From 1e60e4f0aa8e9dc5f03d58c8651d98742fdc36b7 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Mon, 8 Dec 2014 13:00:14 -0600 Subject: bump kernel to 3.14.26 --- .../solidrun-imx6/patches/3.14.22/solidrun.patch | 236547 ----------------- .../solidrun-imx6/patches/3.14.26/solidrun.patch | 236576 ++++++++++++++++++ 2 files changed, 236576 insertions(+), 236547 deletions(-) delete mode 100644 target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch create mode 100644 target/arm/solidrun-imx6/patches/3.14.26/solidrun.patch (limited to 'target/arm/solidrun-imx6/patches') diff --git a/target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch b/target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch deleted file mode 100644 index 0d9621760..000000000 --- a/target/arm/solidrun-imx6/patches/3.14.22/solidrun.patch +++ /dev/null @@ -1,236547 +0,0 @@ -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/clcd-panels.dtsi linux-3.14.22/arch/arm/boot/dts/clcd-panels.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/clcd-panels.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/clcd-panels.dtsi 2014-10-22 14:55:49.026220001 -0500 -@@ -0,0 +1,52 @@ -+/* -+ * ARM Ltd. Versatile Express -+ * -+ */ -+ -+/ { -+ panels { -+ panel@0 { -+ compatible = "panel"; -+ mode = "VGA"; -+ refresh = <60>; -+ xres = <640>; -+ yres = <480>; -+ pixclock = <39721>; -+ left_margin = <40>; -+ right_margin = <24>; -+ upper_margin = <32>; -+ lower_margin = <11>; -+ hsync_len = <96>; -+ vsync_len = <2>; -+ sync = <0>; -+ vmode = "FB_VMODE_NONINTERLACED"; -+ -+ tim2 = "TIM2_BCD", "TIM2_IPC"; -+ cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; -+ caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; -+ bpp = <16>; -+ }; -+ -+ panel@1 { -+ compatible = "panel"; -+ mode = "XVGA"; -+ refresh = <60>; -+ xres = <1024>; -+ yres = <768>; -+ pixclock = <15748>; -+ left_margin = <152>; -+ right_margin = <48>; -+ upper_margin = <23>; -+ lower_margin = <3>; -+ hsync_len = <104>; -+ vsync_len = <4>; -+ sync = <0>; -+ vmode = "FB_VMODE_NONINTERLACED"; -+ -+ tim2 = "TIM2_BCD", "TIM2_IPC"; -+ cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; -+ caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; -+ bpp = <16>; -+ }; -+ }; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/efm32gg-dk3750.dts linux-3.14.22/arch/arm/boot/dts/efm32gg-dk3750.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/efm32gg-dk3750.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/efm32gg-dk3750.dts 2014-10-22 14:55:49.030220001 -0500 -@@ -26,7 +26,7 @@ - }; - - i2c@4000a000 { -- location = <3>; -+ efm32,location = <3>; - status = "ok"; - - temp@48 { -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx23.dtsi linux-3.14.22/arch/arm/boot/dts/imx23.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx23.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx23.dtsi 2014-10-22 14:55:49.030220001 -0500 -@@ -363,7 +363,8 @@ - compatible = "fsl,imx23-lcdif"; - reg = <0x80030000 2000>; - interrupts = <46 45>; -- clocks = <&clks 38>; -+ clocks = <&clks 38>, <&clks 38>; -+ clock-names = "pix", "axi"; - status = "disabled"; - }; - -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx25.dtsi linux-3.14.22/arch/arm/boot/dts/imx25.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx25.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx25.dtsi 2014-10-22 14:55:49.030220001 -0500 -@@ -13,6 +13,7 @@ - - / { - aliases { -+ ethernet0 = &fec; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -56,6 +57,7 @@ - - osc { - compatible = "fsl,imx-osc", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx25-karo-tx25.dts linux-3.14.22/arch/arm/boot/dts/imx25-karo-tx25.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx25-karo-tx25.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx25-karo-tx25.dts 2014-10-22 14:55:49.030220001 -0500 -@@ -16,6 +16,10 @@ - model = "Ka-Ro TX25"; - compatible = "karo,imx25-tx25", "fsl,imx25"; - -+ chosen { -+ stdout-path = &uart1; -+ }; -+ - memory { - reg = <0x80000000 0x02000000 0x90000000 0x02000000>; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx27-apf27.dts linux-3.14.22/arch/arm/boot/dts/imx27-apf27.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx27-apf27.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx27-apf27.dts 2014-10-22 14:55:49.030220001 -0500 -@@ -29,6 +29,7 @@ - - osc26m { - compatible = "fsl,imx-osc26m", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <0>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx27.dtsi linux-3.14.22/arch/arm/boot/dts/imx27.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx27.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx27.dtsi 2014-10-22 14:55:49.030220001 -0500 -@@ -13,6 +13,7 @@ - - / { - aliases { -+ ethernet0 = &fec; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -46,6 +47,7 @@ - - osc26m { - compatible = "fsl,imx-osc26m", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <26000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts linux-3.14.22/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts 2014-10-22 14:55:49.142220001 -0500 -@@ -15,6 +15,10 @@ - model = "Phytec pca100 rapid development kit"; - compatible = "phytec,imx27-pca100-rdk", "phytec,imx27-pca100", "fsl,imx27"; - -+ chosen { -+ stdout-path = &uart1; -+ }; -+ - display: display { - model = "Primeview-PD050VL1"; - native-mode = <&timing0>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx28.dtsi linux-3.14.22/arch/arm/boot/dts/imx28.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx28.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx28.dtsi 2014-10-22 14:55:49.146220001 -0500 -@@ -840,7 +840,8 @@ - compatible = "fsl,imx28-lcdif"; - reg = <0x80030000 0x2000>; - interrupts = <38>; -- clocks = <&clks 55>; -+ clocks = <&clks 55>, <&clks 55>; -+ clock-names = "pix", "axi"; - dmas = <&dma_apbh 13>; - dma-names = "rx"; - status = "disabled"; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx51-babbage.dts linux-3.14.22/arch/arm/boot/dts/imx51-babbage.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx51-babbage.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx51-babbage.dts 2014-10-22 14:55:49.146220001 -0500 -@@ -17,6 +17,10 @@ - model = "Freescale i.MX51 Babbage Board"; - compatible = "fsl,imx51-babbage", "fsl,imx51"; - -+ chosen { -+ stdout-path = &uart1; -+ }; -+ - memory { - reg = <0x90000000 0x20000000>; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx51.dtsi linux-3.14.22/arch/arm/boot/dts/imx51.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx51.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx51.dtsi 2014-10-22 14:55:49.226220001 -0500 -@@ -15,6 +15,7 @@ - - / { - aliases { -+ ethernet0 = &fec; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -43,21 +44,25 @@ - - ckil { - compatible = "fsl,imx-ckil", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <32768>; - }; - - ckih1 { - compatible = "fsl,imx-ckih1", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <0>; - }; - - ckih2 { - compatible = "fsl,imx-ckih2", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <0>; - }; - - osc { - compatible = "fsl,imx-osc", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx53.dtsi linux-3.14.22/arch/arm/boot/dts/imx53.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx53.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx53.dtsi 2014-10-22 14:55:49.342220001 -0500 -@@ -15,6 +15,7 @@ - - / { - aliases { -+ ethernet0 = &fec; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -59,21 +60,25 @@ - - ckil { - compatible = "fsl,imx-ckil", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <32768>; - }; - - ckih1 { - compatible = "fsl,imx-ckih1", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <22579200>; - }; - - ckih2 { - compatible = "fsl,imx-ckih2", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <0>; - }; - - osc { - compatible = "fsl,imx-osc", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx53-mba53.dts linux-3.14.22/arch/arm/boot/dts/imx53-mba53.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx53-mba53.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx53-mba53.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -25,6 +25,10 @@ - enable-active-low; - }; - -+ chosen { -+ stdout-path = &uart2; -+ }; -+ - backlight { - compatible = "pwm-backlight"; - pwms = <&pwm2 0 50000>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2013 Sascha Hauer -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef __DTS_V1__ -+#define __DTS_V1__ -+/dts-v1/; -+#endif -+ -+#include "imx6dl.dtsi" -+#include "imx6qdl-dfi-fs700-m60.dtsi" -+ -+/ { -+ model = "DFI FS700-M60-6DL i.MX6dl Q7 Board"; -+ compatible = "dfi,fs700-m60-6dl", "dfi,fs700e-m60", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl.dtsi linux-3.14.22/arch/arm/boot/dts/imx6dl.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl.dtsi 2014-10-22 14:55:49.342220001 -0500 -@@ -8,6 +8,7 @@ - * - */ - -+#include - #include "imx6dl-pinfunc.h" - #include "imx6qdl.dtsi" - -@@ -21,6 +22,26 @@ - device_type = "cpu"; - reg = <0>; - next-level-cache = <&L2>; -+ operating-points = < -+ /* kHz uV */ -+ 996000 1275000 -+ 792000 1175000 -+ 396000 1075000 -+ >; -+ fsl,soc-operating-points = < -+ /* ARM kHz SOC-PU uV */ -+ 996000 1175000 -+ 792000 1175000 -+ 396000 1175000 -+ >; -+ clock-latency = <61036>; /* two CLK32 periods */ -+ clocks = <&clks 104>, <&clks 6>, <&clks 16>, -+ <&clks 17>, <&clks 170>; -+ clock-names = "arm", "pll2_pfd2_396m", "step", -+ "pll1_sw", "pll1_sys"; -+ arm-supply = <®_arm>; -+ pu-supply = <®_pu>; -+ soc-supply = <®_soc>; - }; - - cpu@1 { -@@ -32,40 +53,124 @@ - }; - - soc { -+ -+ busfreq { /* BUSFREQ */ -+ compatible = "fsl,imx6_busfreq"; -+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>, -+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>, <&clks 22> , <&clks 8>; -+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", -+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "axi_sel", "pll3_pfd1_540m"; -+ interrupts = <0 107 0x04>, <0 112 0x4>; -+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1"; -+ fsl,max_ddr_freq = <400000000>; -+ }; -+ -+ gpu@00130000 { -+ compatible = "fsl,imx6dl-gpu", "fsl,imx6q-gpu"; -+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>, -+ <0x0 0x0>; -+ reg-names = "iobase_3d", "iobase_2d", -+ "phys_baseaddr"; -+ interrupts = <0 9 0x04>, <0 10 0x04>; -+ interrupt-names = "irq_3d", "irq_2d"; -+ clocks = <&clks 143>, <&clks 27>, -+ <&clks 121>, <&clks 122>, -+ <&clks 0>; -+ clock-names = "gpu2d_axi_clk", "gpu3d_axi_clk", -+ "gpu2d_clk", "gpu3d_clk", -+ "gpu3d_shader_clk"; -+ resets = <&src 0>, <&src 3>; -+ reset-names = "gpu3d", "gpu2d"; -+ pu-supply = <®_pu>; -+ }; -+ - ocram: sram@00900000 { - compatible = "mmio-sram"; - reg = <0x00900000 0x20000>; - clocks = <&clks 142>; - }; - -+ hdmi_core: hdmi_core@00120000 { -+ compatible = "fsl,imx6dl-hdmi-core"; -+ reg = <0x00120000 0x9000>; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ status = "disabled"; -+ }; -+ -+ hdmi_video: hdmi_video@020e0000 { -+ compatible = "fsl,imx6dl-hdmi-video"; -+ reg = <0x020e0000 0x1000>; -+ reg-names = "hdmi_gpr"; -+ interrupts = <0 115 0x04>; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ status = "disabled"; -+ }; -+ -+ hdmi_audio: hdmi_audio@00120000 { -+ compatible = "fsl,imx6dl-hdmi-audio"; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ dmas = <&sdma 2 23 0>; -+ dma-names = "tx"; -+ status = "disabled"; -+ }; -+ -+ hdmi_cec: hdmi_cec@00120000 { -+ compatible = "fsl,imx6dl-hdmi-cec"; -+ interrupts = <0 115 0x04>; -+ status = "disabled"; -+ }; -+ - aips1: aips-bus@02000000 { -+ vpu@02040000 { -+ iramsize = <0>; -+ status = "okay"; -+ }; -+ - iomuxc: iomuxc@020e0000 { - compatible = "fsl,imx6dl-iomuxc"; - }; - - pxp: pxp@020f0000 { -+ compatible = "fsl,imx6dl-pxp-dma"; - reg = <0x020f0000 0x4000>; -- interrupts = <0 98 0x04>; -+ interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 133>; -+ clock-names = "pxp-axi"; -+ status = "disabled"; - }; - - epdc: epdc@020f4000 { - reg = <0x020f4000 0x4000>; -- interrupts = <0 97 0x04>; -+ interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>; - }; - - lcdif: lcdif@020f8000 { - reg = <0x020f8000 0x4000>; -- interrupts = <0 39 0x04>; -+ interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; - }; - }; - - aips2: aips-bus@02100000 { -+ mipi_dsi: mipi@021e0000 { -+ compatible = "fsl,imx6dl-mipi-dsi"; -+ reg = <0x021e0000 0x4000>; -+ interrupts = <0 102 0x04>; -+ gpr = <&gpr>; -+ clocks = <&clks 138>, <&clks 209>; -+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk"; -+ status = "disabled"; -+ }; -+ - i2c4: i2c@021f8000 { - #address-cells = <1>; - #size-cells = <0>; -- compatible = "fsl,imx1-i2c"; -+ compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; - reg = <0x021f8000 0x4000>; -- interrupts = <0 35 0x04>; -+ interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 116>; - status = "disabled"; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw51xx.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-gw51xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw51xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-gw51xx.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-gw51xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 DualLite GW51XX"; -+ compatible = "gw,imx6dl-gw51xx", "gw,ventana", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw52xx.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-gw52xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw52xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-gw52xx.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-gw52xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 DualLite GW52XX"; -+ compatible = "gw,imx6dl-gw52xx", "gw,ventana", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw53xx.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-gw53xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw53xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-gw53xx.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-gw53xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 DualLite GW53XX"; -+ compatible = "gw,imx6dl-gw53xx", "gw,ventana", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw54xx.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-gw54xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-gw54xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-gw54xx.dts 2014-10-22 14:55:49.342220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-gw54xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 DualLite GW54XX"; -+ compatible = "gw,imx6dl-gw54xx", "gw,ventana", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-hummingboard.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-hummingboard.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-hummingboard.dts 2014-10-22 14:55:49.346220001 -0500 -@@ -1,163 +1,13 @@ - /* -- * Copyright (C) 2013,2014 Russell King -+ * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com) -+ * Based on work by Russell King - */ - /dts-v1/; - - #include "imx6dl.dtsi" --#include "imx6qdl-microsom.dtsi" --#include "imx6qdl-microsom-ar8035.dtsi" -+#include "imx6qdl-hummingboard.dtsi" - - / { -- model = "SolidRun HummingBoard DL/Solo"; -- compatible = "solidrun,hummingboard", "fsl,imx6dl"; -- -- ir_recv: ir-receiver { -- compatible = "gpio-ir-receiver"; -- gpios = <&gpio1 2 1>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_gpio1_2>; -- }; -- -- regulators { -- compatible = "simple-bus"; -- -- reg_3p3v: 3p3v { -- compatible = "regulator-fixed"; -- regulator-name = "3P3V"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- -- reg_usbh1_vbus: usb-h1-vbus { -- compatible = "regulator-fixed"; -- enable-active-high; -- gpio = <&gpio1 0 0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_usbh1_vbus>; -- regulator-name = "usb_h1_vbus"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- }; -- -- reg_usbotg_vbus: usb-otg-vbus { -- compatible = "regulator-fixed"; -- enable-active-high; -- gpio = <&gpio3 22 0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_usbotg_vbus>; -- regulator-name = "usb_otg_vbus"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- }; -- }; -- -- sound-spdif { -- compatible = "fsl,imx-audio-spdif"; -- model = "imx-spdif"; -- /* IMX6 doesn't implement this yet */ -- spdif-controller = <&spdif>; -- spdif-out; -- }; --}; -- --&can1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_flexcan1>; -- status = "okay"; --}; -- --&i2c1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_i2c1>; -- -- /* -- * Not fitted on Carrier-1 board... yet -- status = "okay"; -- -- rtc: pcf8523@68 { -- compatible = "nxp,pcf8523"; -- reg = <0x68>; -- }; -- */ --}; -- --&iomuxc { -- hummingboard { -- pinctrl_hummingboard_flexcan1: hummingboard-flexcan1 { -- fsl,pins = < -- MX6QDL_PAD_SD3_CLK__FLEXCAN1_RX 0x80000000 -- MX6QDL_PAD_SD3_CMD__FLEXCAN1_TX 0x80000000 -- >; -- }; -- -- pinctrl_hummingboard_gpio1_2: hummingboard-gpio1_2 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 -- >; -- }; -- -- pinctrl_hummingboard_i2c1: hummingboard-i2c1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_hummingboard_spdif: hummingboard-spdif { -- fsl,pins = ; -- }; -- -- pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { -- fsl,pins = ; -- }; -- -- pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus { -- fsl,pins = ; -- }; -- -- pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-aux { -- fsl,pins = < -- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071 -- >; -- }; -- -- pinctrl_hummingboard_usdhc2: hummingboard-usdhc2 { -- fsl,pins = < -- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 -- >; -- }; -- }; --}; -- --&spdif { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hummingboard_spdif>; -- status = "okay"; --}; -- --&usbh1 { -- vbus-supply = <®_usbh1_vbus>; -- status = "okay"; --}; -- --&usbotg { -- vbus-supply = <®_usbotg_vbus>; -- status = "okay"; --}; -- --&usdhc2 { -- pinctrl-names = "default"; -- pinctrl-0 = < -- &pinctrl_hummingboard_usdhc2_aux -- &pinctrl_hummingboard_usdhc2 -- >; -- vmmc-supply = <®_3p3v>; -- cd-gpios = <&gpio1 4 0>; -- status = "okay"; -+ model = "SolidRun HummingBoard Solo/DualLite"; -+ compatible = "solidrun,hummingboard/dl", "fsl,imx6dl"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-nitrogen6x.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-nitrogen6x.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-nitrogen6x.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-nitrogen6x.dts 2014-10-22 14:55:49.346220001 -0500 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright 2013 Boundary Devices, Inc. -+ * Copyright 2012 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-nitrogen6x.dtsi" -+ -+/ { -+ model = "Freescale i.MX6 DualLite Nitrogen6x Board"; -+ compatible = "fsl,imx6dl-nitrogen6x", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-phytec-pbab01.dts 2014-10-22 14:55:49.346220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl-phytec-pfla02.dtsi" -+#include "imx6qdl-phytec-pbab01.dtsi" -+ -+/ { -+ model = "Phytec phyFLEX-i.MX6 DualLite/Solo Carrier-Board"; -+ compatible = "phytec,imx6dl-pbab01", "phytec,imx6dl-pfla02", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi linux-3.14.22/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-phytec-pfla02.dtsi 2014-10-22 14:55:49.346220001 -0500 -@@ -0,0 +1,22 @@ -+/* -+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "imx6dl.dtsi" -+#include "imx6qdl-phytec-pfla02.dtsi" -+ -+/ { -+ model = "Phytec phyFLEX-i.MX6 DualLite/Solo"; -+ compatible = "phytec,imx6dl-pfla02", "fsl,imx6dl"; -+ -+ memory { -+ reg = <0x10000000 0x20000000>; -+ }; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-pinfunc.h linux-3.14.22/arch/arm/boot/dts/imx6dl-pinfunc.h ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-pinfunc.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-pinfunc.h 2014-10-22 14:55:49.346220001 -0500 -@@ -755,6 +755,7 @@ - #define MX6QDL_PAD_GPIO_5__I2C3_SCL 0x230 0x600 0x878 0x6 0x2 - #define MX6QDL_PAD_GPIO_5__ARM_EVENTI 0x230 0x600 0x000 0x7 0x0 - #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK 0x234 0x604 0x840 0x0 0x1 -+#define MX6QDL_PAD_GPIO_6__ENET_IRQ 0x234 0x604 0x03c 0x11 0xff000609 - #define MX6QDL_PAD_GPIO_6__I2C3_SDA 0x234 0x604 0x87c 0x2 0x2 - #define MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x234 0x604 0x000 0x5 0x0 - #define MX6QDL_PAD_GPIO_6__SD2_LCTL 0x234 0x604 0x000 0x6 0x0 -@@ -950,6 +951,7 @@ - #define MX6QDL_PAD_RGMII_TXC__GPIO6_IO19 0x2d8 0x6c0 0x000 0x5 0x0 - #define MX6QDL_PAD_RGMII_TXC__XTALOSC_REF_CLK_24M 0x2d8 0x6c0 0x000 0x7 0x0 - #define MX6QDL_PAD_SD1_CLK__SD1_CLK 0x2dc 0x6c4 0x928 0x0 0x1 -+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x2dc 0x6c4 0x000 0x2 0x0 - #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN 0x2dc 0x6c4 0x000 0x3 0x0 - #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x2dc 0x6c4 0x000 0x5 0x0 - #define MX6QDL_PAD_SD1_CMD__SD1_CMD 0x2e0 0x6c8 0x000 0x0 0x0 -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabreauto.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-sabreauto.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabreauto.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-sabreauto.dts 2014-10-22 14:55:49.498220001 -0500 -@@ -15,3 +15,16 @@ - model = "Freescale i.MX6 DualLite/Solo SABRE Automotive Board"; - compatible = "fsl,imx6dl-sabreauto", "fsl,imx6dl"; - }; -+ -+&ldb { -+ ipu_id = <0>; -+ sec_ipu_id = <0>; -+}; -+ -+&mxcfb1 { -+ status = "okay"; -+}; -+ -+&mxcfb2 { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabrelite.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-sabrelite.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabrelite.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-sabrelite.dts 2014-10-22 14:55:49.498220001 -0500 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright 2011 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6dl.dtsi" -+#include "imx6qdl-sabrelite.dtsi" -+ -+/ { -+ model = "Freescale i.MX6 DualLite SABRE Lite Board"; -+ compatible = "fsl,imx6dl-sabrelite", "fsl,imx6dl"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabresd.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-sabresd.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabresd.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-sabresd.dts 2014-10-22 14:55:49.498220001 -0500 -@@ -15,3 +15,20 @@ - model = "Freescale i.MX6 DualLite SABRE Smart Device Board"; - compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl"; - }; -+ -+&ldb { -+ ipu_id = <0>; -+ sec_ipu_id = <0>; -+}; -+ -+&pxp { -+ status = "okay"; -+}; -+ -+&mxcfb1 { -+ status = "okay"; -+}; -+ -+&mxcfb2 { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts linux-3.14.22/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6dl-sabresd-hdcp.dts 2014-10-22 14:55:49.498220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include "imx6dl-sabresd.dts" -+ -+&hdmi_video { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hdmi_hdcp>; -+ fsl,hdcp; -+}; -+ -+&i2c2 { -+ status = "disable"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-arm2.dts linux-3.14.22/arch/arm/boot/dts/imx6q-arm2.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-arm2.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-arm2.dts 2014-10-22 14:55:49.502220001 -0500 -@@ -23,14 +23,27 @@ - - regulators { - compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; - -- reg_3p3v: 3p3v { -+ reg_3p3v: regulator@0 { - compatible = "regulator-fixed"; -+ reg = <0>; - regulator-name = "3P3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; -+ -+ reg_usb_otg_vbus: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; - }; - - leds { -@@ -46,7 +59,7 @@ - - &gpmi { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_gpmi_nand_1>; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; - status = "disabled"; /* gpmi nand conflicts with SD */ - }; - -@@ -54,28 +67,131 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - -- hog { -+ imx6q-arm2 { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000 - >; - }; -- }; - -- arm2 { -- pinctrl_usdhc3_arm2: usdhc3grp-arm2 { -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1 -+ MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059 -+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059 -+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059 -+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3_cdwp: usdhc3cdwp { - fsl,pins = < - MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000 - MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000 - >; - }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 -+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 -+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 -+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 -+ >; -+ }; - }; - }; - - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_2>; -+ pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; -+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; - status = "okay"; - }; - -@@ -84,8 +200,8 @@ - wp-gpios = <&gpio6 14 0>; - vmmc-supply = <®_3p3v>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_1 -- &pinctrl_usdhc3_arm2>; -+ pinctrl-0 = <&pinctrl_usdhc3 -+ &pinctrl_usdhc3_cdwp>; - status = "okay"; - }; - -@@ -93,13 +209,13 @@ - non-removable; - vmmc-supply = <®_3p3v>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc4_1>; -+ pinctrl-0 = <&pinctrl_usdhc4>; - status = "okay"; - }; - - &uart2 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart2_2>; -+ pinctrl-0 = <&pinctrl_uart2>; - fsl,dte-mode; - fsl,uart-has-rtscts; - status = "okay"; -@@ -107,6 +223,6 @@ - - &uart4 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart4_1>; -+ pinctrl-0 = <&pinctrl_uart4>; - status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-arm2-hsic.dts linux-3.14.22/arch/arm/boot/dts/imx6q-arm2-hsic.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-arm2-hsic.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-arm2-hsic.dts 2014-10-22 14:55:49.502220001 -0500 -@@ -0,0 +1,32 @@ -+/* -+ * Copyright 2013 Freescale Semiconductor, Inc. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "imx6q-arm2.dts" -+ -+&fec { -+ status = "disabled"; -+}; -+ -+&usbh2 { -+ pinctrl-names = "idle", "active"; -+ pinctrl-0 = <&pinctrl_usbh2_1>; -+ pinctrl-1 = <&pinctrl_usbh2_2>; -+ osc-clkgate-delay = <0x3>; -+ status = "okay"; -+}; -+ -+&usbh3 { -+ pinctrl-names = "idle", "active"; -+ pinctrl-0 = <&pinctrl_usbh3_1>; -+ pinctrl-1 = <&pinctrl_usbh3_2>; -+ osc-clkgate-delay = <0x3>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-cm-fx6.dts linux-3.14.22/arch/arm/boot/dts/imx6q-cm-fx6.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-cm-fx6.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-cm-fx6.dts 2014-10-22 14:55:49.502220001 -0500 -@@ -0,0 +1,107 @@ -+/* -+ * Copyright 2013 CompuLab Ltd. -+ * -+ * Author: Valentin Raevsky -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+ -+/ { -+ model = "CompuLab CM-FX6"; -+ compatible = "compulab,cm-fx6", "fsl,imx6q"; -+ -+ memory { -+ reg = <0x10000000 0x80000000>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ heartbeat-led { -+ label = "Heartbeat"; -+ gpios = <&gpio2 31 0>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ status = "okay"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&iomuxc { -+ imx6q-cm-fx6 { -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 -+ >; -+ }; -+ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -+ >; -+ }; -+ }; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart4>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-cubox-i.dts linux-3.14.22/arch/arm/boot/dts/imx6q-cubox-i.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-cubox-i.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-cubox-i.dts 2014-10-22 14:55:49.502220001 -0500 -@@ -13,4 +13,8 @@ - - &sata { - status = "okay"; -+ fsl,transmit-level-mV = <1104>; -+ fsl,transmit-boost-mdB = <0>; -+ fsl,transmit-atten-16ths = <9>; -+ fsl,no-spread-spectrum; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts linux-3.14.22/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-dfi-fs700-m60.dts 2014-10-22 14:55:49.502220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2013 Sascha Hauer -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#ifndef __DTS_V1__ -+#define __DTS_V1__ -+/dts-v1/; -+#endif -+ -+#include "imx6q.dtsi" -+#include "imx6qdl-dfi-fs700-m60.dtsi" -+ -+/ { -+ model = "DFI FS700-M60-6QD i.MX6qd Q7 Board"; -+ compatible = "dfi,fs700-m60-6qd", "dfi,fs700e-m60", "fsl,imx6q"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi 2014-10-22 14:55:49.502220001 -0500 -@@ -5,11 +5,33 @@ - #include "imx6qdl-microsom-ar8035.dtsi" - - / { -+ chosen { -+ bootargs = "quiet console=ttymxc0,115200 root=/dev/mmcblk0p2 rw"; -+ }; -+ -+ aliases { -+ mxcfb0 = &mxcfb1; -+ }; -+ - ir_recv: ir-receiver { - compatible = "gpio-ir-receiver"; - gpios = <&gpio3 9 1>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cubox_i_ir>; -+ linux,rc-map-name = "rc-rc6-mce"; -+ }; -+ -+ pwmleds { -+ compatible = "pwm-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_cubox_i_pwm1>; -+ -+ front { -+ active-low; -+ label = "imx6:red:front"; -+ max-brightness = <248>; -+ pwms = <&pwm1 0 50000>; -+ }; - }; - - regulators { -@@ -49,10 +71,62 @@ - sound-spdif { - compatible = "fsl,imx-audio-spdif"; - model = "imx-spdif"; -- /* IMX6 doesn't implement this yet */ - spdif-controller = <&spdif>; - spdif-out; - }; -+ -+ sound-hdmi { -+ compatible = "fsl,imx6q-audio-hdmi", -+ "fsl,imx-audio-hdmi"; -+ model = "imx-audio-hdmi"; -+ hdmi-controller = <&hdmi_audio>; -+ }; -+ -+ mxcfb1: fb@0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "hdmi"; -+ interface_pix_fmt = "RGB24"; -+ mode_str ="1920x1080M@60"; -+ default_bpp = <32>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "okay"; -+ }; -+}; -+ -+&hdmi_core { -+ ipu_id = <0>; -+ disp_id = <0>; -+ status = "okay"; -+}; -+ -+&hdmi_video { -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ status = "okay"; -+}; -+ -+&hdmi_audio { -+ status = "okay"; -+}; -+ -+&hdmi_cec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_cubox_i_hdmi>; -+ status = "okay"; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_cubox_i_i2c2>; -+ -+ status = "okay"; -+ -+ ddc: imx6_hdmi_i2c@50 { -+ compatible = "fsl,imx6-hdmi-i2c"; -+ reg = <0x50>; -+ }; - }; - - &i2c3 { -@@ -69,6 +143,19 @@ - - &iomuxc { - cubox_i { -+ pinctrl_cubox_i_hdmi: cubox-i-hdmi { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0 -+ >; -+ }; -+ -+ pinctrl_cubox_i_i2c2: cubox-i-i2c2 { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ - pinctrl_cubox_i_i2c3: cubox-i-i2c3 { - fsl,pins = < - MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 -@@ -82,16 +169,35 @@ - >; - }; - -+ pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led { -+ fsl,pins = ; -+ }; -+ - pinctrl_cubox_i_spdif: cubox-i-spdif { - fsl,pins = ; - }; - -+ pinctrl_cubox_i_usbh1: cubox-i-usbh1 { -+ fsl,pins = ; -+ }; -+ - pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus { -- fsl,pins = ; -+ fsl,pins = ; -+ }; -+ -+ pinctrl_cubox_i_usbotg: cubox-i-usbotg { -+ /* -+ * The Cubox-i pulls ID low, but as it's pointless -+ * leaving it as a pull-up, even if it is just 10uA. -+ */ -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059 -+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0 -+ >; - }; - - pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus { -- fsl,pins = ; -+ fsl,pins = ; - }; - - pinctrl_cubox_i_usdhc2_aux: cubox-i-usdhc2-aux { -@@ -111,29 +217,76 @@ - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 - >; - }; -+ -+ pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9 -+ >; -+ }; -+ -+ pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9 -+ >; -+ }; - }; - }; - - &spdif { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_cubox_i_spdif>; -+ clocks = <&clks 197>, <&clks 0>, -+ <&clks 197>, <&clks 0>, -+ <&clks 0>, <&clks 0>, -+ <&clks 0>, <&clks 0>, -+ <&clks 0>; -+ clock-names = "core", "rxtx0", -+ "rxtx1", "rxtx2", -+ "rxtx3", "rxtx4", -+ "rxtx5", "rxtx6", -+ "rxtx7"; - status = "okay"; - }; - - &usbh1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_cubox_i_usbh1>; - vbus-supply = <®_usbh1_vbus>; - status = "okay"; - }; - - &usbotg { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_cubox_i_usbotg>; - vbus-supply = <®_usbotg_vbus>; - status = "okay"; - }; - - &usdhc2 { -- pinctrl-names = "default"; -+ pinctrl-names = "default", "state_100mhz", "state_200mhz"; - pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>; -+ pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>; -+ pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>; - vmmc-supply = <®_3p3v>; - cd-gpios = <&gpio1 4 0>; -+ no-1-8-v; - status = "okay"; - }; -+ -+ -+&gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi 2014-10-22 14:55:49.502220001 -0500 -@@ -0,0 +1,199 @@ -+/ { -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ dummy_reg: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "dummy-supply"; -+ }; -+ -+ reg_usb_otg_vbus: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ chosen { -+ stdout-path = &uart1; -+ }; -+}; -+ -+&ecspi3 { -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio4 24 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi3>; -+ status = "okay"; -+ -+ flash: m25p80@0 { -+ #address-cells = <1>; -+ #size-cells = <1>; -+ compatible = "sst,sst25vf040b", "m25p80"; -+ spi-max-frequency = <20000000>; -+ reg = <0>; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ status = "okay"; -+ phy-mode = "rgmii"; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6qdl-dfi-fs700-m60 { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000 -+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000 /* PMIC irq */ -+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000 /* MAX11801 irq */ -+ MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x000030b0 /* Backlight enable */ -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc2: usdhc2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 /* card detect */ -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 -+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 -+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 -+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_ecspi3: ecspi3grp { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1 -+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1 -+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1 -+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */ -+ >; -+ }; -+ }; -+}; -+ -+&i2c2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usdhc2 { /* module slot */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc2>; -+ cd-gpios = <&gpio2 2 0>; -+ status = "okay"; -+}; -+ -+&usdhc3 { /* baseboard slot */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+}; -+ -+&usdhc4 { /* eMMC */ -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ bus-width = <8>; -+ non-removable; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl.dtsi 2014-10-22 14:55:49.506220001 -0500 -@@ -10,10 +10,16 @@ - * http://www.gnu.org/copyleft/gpl.html - */ - -+#include -+ - #include "skeleton.dtsi" -+#include - - / { - aliases { -+ ethernet0 = &fec; -+ can0 = &can1; -+ can1 = &can2; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -24,6 +30,11 @@ - i2c0 = &i2c1; - i2c1 = &i2c2; - i2c2 = &i2c3; -+ ipu0 = &ipu1; -+ mmc0 = &usdhc1; -+ mmc1 = &usdhc2; -+ mmc2 = &usdhc3; -+ mmc3 = &usdhc4; - serial0 = &uart1; - serial1 = &uart2; - serial2 = &uart3; -@@ -33,13 +44,13 @@ - spi1 = &ecspi2; - spi2 = &ecspi3; - spi3 = &ecspi4; -+ usbphy0 = &usbphy1; -+ usbphy1 = &usbphy2; - }; - - intc: interrupt-controller@00a01000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; -- #address-cells = <1>; -- #size-cells = <1>; - interrupt-controller; - reg = <0x00a01000 0x1000>, - <0x00a00100 0x100>; -@@ -51,20 +62,27 @@ - - ckil { - compatible = "fsl,imx-ckil", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <32768>; - }; - - ckih1 { - compatible = "fsl,imx-ckih1", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <0>; - }; - - osc { - compatible = "fsl,imx-osc", "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; - -+ pu_dummy: pudummy_reg { -+ compatible = "fsl,imx6-dummy-pureg"; /* only used in ldo-bypass */ -+ }; -+ - soc { - #address-cells = <1>; - #size-cells = <1>; -@@ -75,7 +93,10 @@ - dma_apbh: dma-apbh@00110000 { - compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh"; - reg = <0x00110000 0x2000>; -- interrupts = <0 13 0x04>, <0 13 0x04>, <0 13 0x04>, <0 13 0x04>; -+ interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>, -+ <0 13 IRQ_TYPE_LEVEL_HIGH>, -+ <0 13 IRQ_TYPE_LEVEL_HIGH>, -+ <0 13 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3"; - #dma-cells = <1>; - dma-channels = <4>; -@@ -88,7 +109,7 @@ - #size-cells = <1>; - reg = <0x00112000 0x2000>, <0x00114000 0x2000>; - reg-names = "gpmi-nand", "bch"; -- interrupts = <0 15 0x04>; -+ interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "bch"; - clocks = <&clks 152>, <&clks 153>, <&clks 151>, - <&clks 150>, <&clks 149>; -@@ -109,11 +130,13 @@ - L2: l2-cache@00a02000 { - compatible = "arm,pl310-cache"; - reg = <0x00a02000 0x1000>; -- interrupts = <0 92 0x04>; -+ interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>; - cache-unified; - cache-level = <2>; - arm,tag-latency = <4 2 3>; - arm,data-latency = <4 2 3>; -+ arm,dynamic-clk-gating; -+ arm,standby-mode; - }; - - pcie: pcie@0x01000000 { -@@ -126,15 +149,22 @@ - 0x81000000 0 0 0x01f80000 0 0x00010000 /* downstream I/O */ - 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */ - num-lanes = <1>; -- interrupts = <0 123 0x04>; -- clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>; -- clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi"; -+ interrupts = ; -+ interrupt-names = "pme"; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 0x7>; -+ interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, -+ <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 144>, <&clks 221>, <&clks 189>, <&clks 187>; -+ clock-names = "pcie_axi", "lvds_gate", "pcie_ref_125m", "sata_ref_100m"; - status = "disabled"; - }; - - pmu { - compatible = "arm,cortex-a9-pmu"; -- interrupts = <0 94 0x04>; -+ interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>; - }; - - aips-bus@02000000 { /* AIPS1 */ -@@ -154,7 +184,7 @@ - spdif: spdif@02004000 { - compatible = "fsl,imx35-spdif"; - reg = <0x02004000 0x4000>; -- interrupts = <0 52 0x04>; -+ interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>; - dmas = <&sdma 14 18 0>, - <&sdma 15 18 0>; - dma-names = "rx", "tx"; -@@ -176,9 +206,11 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; - reg = <0x02008000 0x4000>; -- interrupts = <0 31 0x04>; -+ interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 112>, <&clks 112>; - clock-names = "ipg", "per"; -+ dmas = <&sdma 3 7 1>, <&sdma 4 7 2>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - -@@ -187,9 +219,11 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; - reg = <0x0200c000 0x4000>; -- interrupts = <0 32 0x04>; -+ interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 113>, <&clks 113>; - clock-names = "ipg", "per"; -+ dmas = <&sdma 5 7 1>, <&sdma 6 7 2>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - -@@ -198,9 +232,11 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; - reg = <0x02010000 0x4000>; -- interrupts = <0 33 0x04>; -+ interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 114>, <&clks 114>; - clock-names = "ipg", "per"; -+ dmas = <&sdma 7 7 1>, <&sdma 8 7 2>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - -@@ -209,16 +245,18 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; - reg = <0x02014000 0x4000>; -- interrupts = <0 34 0x04>; -+ interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 115>, <&clks 115>; - clock-names = "ipg", "per"; -+ dmas = <&sdma 9 7 1>, <&sdma 10 7 2>; -+ dma-names = "rx", "tx"; - status = "disabled"; - }; - - uart1: serial@02020000 { - compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02020000 0x4000>; -- interrupts = <0 26 0x04>; -+ interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 160>, <&clks 161>; - clock-names = "ipg", "per"; - dmas = <&sdma 25 4 0>, <&sdma 26 4 0>; -@@ -227,15 +265,23 @@ - }; - - esai: esai@02024000 { -+ compatible = "fsl,imx6q-esai"; - reg = <0x02024000 0x4000>; -- interrupts = <0 51 0x04>; -+ interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 118>; -+ fsl,esai-dma-events = <24 23>; -+ fsl,flags = <1>; -+ status = "disabled"; - }; - - ssi1: ssi@02028000 { -- compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6q-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x02028000 0x4000>; -- interrupts = <0 46 0x04>; -- clocks = <&clks 178>; -+ interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 178>, <&clks 157>; -+ clock-names = "ipg", "baud"; - dmas = <&sdma 37 1 0>, - <&sdma 38 1 0>; - dma-names = "rx", "tx"; -@@ -245,10 +291,13 @@ - }; - - ssi2: ssi@0202c000 { -- compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6q-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x0202c000 0x4000>; -- interrupts = <0 47 0x04>; -- clocks = <&clks 179>; -+ interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 179>, <&clks 158>; -+ clock-names = "ipg", "baud"; - dmas = <&sdma 41 1 0>, - <&sdma 42 1 0>; - dma-names = "rx", "tx"; -@@ -258,10 +307,13 @@ - }; - - ssi3: ssi@02030000 { -- compatible = "fsl,imx6q-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6q-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x02030000 0x4000>; -- interrupts = <0 48 0x04>; -- clocks = <&clks 180>; -+ interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 180>, <&clks 159>; -+ clock-names = "ipg", "baud"; - dmas = <&sdma 45 1 0>, - <&sdma 46 1 0>; - dma-names = "rx", "tx"; -@@ -271,8 +323,25 @@ - }; - - asrc: asrc@02034000 { -+ compatible = "fsl,imx53-asrc"; - reg = <0x02034000 0x4000>; -- interrupts = <0 50 0x04>; -+ interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 107>, <&clks 156>; -+ clock-names = "core", "dma"; -+ dmas = <&sdma 17 20 1>, <&sdma 18 20 1>, <&sdma 19 20 1>, -+ <&sdma 20 20 1>, <&sdma 21 20 1>, <&sdma 22 20 1>; -+ dma-names = "rxa", "rxb", "rxc", -+ "txa", "txb", "txc"; -+ status = "okay"; -+ }; -+ -+ asrc_p2p: asrc_p2p { -+ compatible = "fsl,imx6q-asrc-p2p"; -+ fsl,output-rate = <48000>; -+ fsl,output-width = <16>; -+ fsl,asrc-dma-rx-events = <17 18 19>; -+ fsl,asrc-dma-tx-events = <20 21 22>; -+ status = "okay"; - }; - - spba@0203c000 { -@@ -281,8 +350,19 @@ - }; - - vpu: vpu@02040000 { -+ compatible = "fsl,imx6-vpu"; - reg = <0x02040000 0x3c000>; -- interrupts = <0 3 0x04 0 12 0x04>; -+ reg-names = "vpu_regs"; -+ interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>, -+ <0 12 IRQ_TYPE_LEVEL_HIGH>; -+ interrupt-names = "vpu_jpu_irq", "vpu_ipi_irq"; -+ clocks = <&clks 168>, <&clks 140>, <&clks 142>; -+ clock-names = "vpu_clk", "mmdc_ch0_axi", "ocram"; -+ iramsize = <0x21000>; -+ iram = <&ocram>; -+ resets = <&src 1>; -+ pu-supply = <®_pu>; -+ status = "disabled"; - }; - - aipstz@0207c000 { /* AIPSTZ1 */ -@@ -293,7 +373,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; - reg = <0x02080000 0x4000>; -- interrupts = <0 83 0x04>; -+ interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 62>, <&clks 145>; - clock-names = "ipg", "per"; - }; -@@ -302,7 +382,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; - reg = <0x02084000 0x4000>; -- interrupts = <0 84 0x04>; -+ interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 62>, <&clks 146>; - clock-names = "ipg", "per"; - }; -@@ -311,7 +391,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; - reg = <0x02088000 0x4000>; -- interrupts = <0 85 0x04>; -+ interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 62>, <&clks 147>; - clock-names = "ipg", "per"; - }; -@@ -320,7 +400,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm"; - reg = <0x0208c000 0x4000>; -- interrupts = <0 86 0x04>; -+ interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 62>, <&clks 148>; - clock-names = "ipg", "per"; - }; -@@ -328,23 +408,25 @@ - can1: flexcan@02090000 { - compatible = "fsl,imx6q-flexcan"; - reg = <0x02090000 0x4000>; -- interrupts = <0 110 0x04>; -+ interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 108>, <&clks 109>; - clock-names = "ipg", "per"; -+ status = "disabled"; - }; - - can2: flexcan@02094000 { - compatible = "fsl,imx6q-flexcan"; - reg = <0x02094000 0x4000>; -- interrupts = <0 111 0x04>; -+ interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 110>, <&clks 111>; - clock-names = "ipg", "per"; -+ status = "disabled"; - }; - - gpt: gpt@02098000 { - compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt"; - reg = <0x02098000 0x4000>; -- interrupts = <0 55 0x04>; -+ interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 119>, <&clks 120>; - clock-names = "ipg", "per"; - }; -@@ -352,7 +434,8 @@ - gpio1: gpio@0209c000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x0209c000 0x4000>; -- interrupts = <0 66 0x04 0 67 0x04>; -+ interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>, -+ <0 67 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -362,7 +445,8 @@ - gpio2: gpio@020a0000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020a0000 0x4000>; -- interrupts = <0 68 0x04 0 69 0x04>; -+ interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>, -+ <0 69 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -372,7 +456,8 @@ - gpio3: gpio@020a4000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020a4000 0x4000>; -- interrupts = <0 70 0x04 0 71 0x04>; -+ interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>, -+ <0 71 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -382,7 +467,8 @@ - gpio4: gpio@020a8000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020a8000 0x4000>; -- interrupts = <0 72 0x04 0 73 0x04>; -+ interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>, -+ <0 73 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -392,7 +478,8 @@ - gpio5: gpio@020ac000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020ac000 0x4000>; -- interrupts = <0 74 0x04 0 75 0x04>; -+ interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>, -+ <0 75 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -402,7 +489,8 @@ - gpio6: gpio@020b0000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020b0000 0x4000>; -- interrupts = <0 76 0x04 0 77 0x04>; -+ interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>, -+ <0 77 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -412,7 +500,8 @@ - gpio7: gpio@020b4000 { - compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio"; - reg = <0x020b4000 0x4000>; -- interrupts = <0 78 0x04 0 79 0x04>; -+ interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>, -+ <0 79 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -421,20 +510,20 @@ - - kpp: kpp@020b8000 { - reg = <0x020b8000 0x4000>; -- interrupts = <0 82 0x04>; -+ interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>; - }; - - wdog1: wdog@020bc000 { - compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; - reg = <0x020bc000 0x4000>; -- interrupts = <0 80 0x04>; -+ interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 0>; - }; - - wdog2: wdog@020c0000 { - compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt"; - reg = <0x020c0000 0x4000>; -- interrupts = <0 81 0x04>; -+ interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 0>; - status = "disabled"; - }; -@@ -442,14 +531,17 @@ - clks: ccm@020c4000 { - compatible = "fsl,imx6q-ccm"; - reg = <0x020c4000 0x4000>; -- interrupts = <0 87 0x04 0 88 0x04>; -+ interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>, -+ <0 88 IRQ_TYPE_LEVEL_HIGH>; - #clock-cells = <1>; - }; - - anatop: anatop@020c8000 { - compatible = "fsl,imx6q-anatop", "syscon", "simple-bus"; - reg = <0x020c8000 0x1000>; -- interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>; -+ interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>, -+ <0 54 IRQ_TYPE_LEVEL_HIGH>, -+ <0 127 IRQ_TYPE_LEVEL_HIGH>; - - regulator-1p1@110 { - compatible = "fsl,anatop-regulator"; -@@ -495,7 +587,7 @@ - - reg_arm: regulator-vddcore@140 { - compatible = "fsl,anatop-regulator"; -- regulator-name = "cpu"; -+ regulator-name = "vddarm"; - regulator-min-microvolt = <725000>; - regulator-max-microvolt = <1450000>; - regulator-always-on; -@@ -515,7 +607,6 @@ - regulator-name = "vddpu"; - regulator-min-microvolt = <725000>; - regulator-max-microvolt = <1450000>; -- regulator-always-on; - anatop-reg-offset = <0x140>; - anatop-vol-bit-shift = <9>; - anatop-vol-bit-width = <5>; -@@ -547,23 +638,38 @@ - - tempmon: tempmon { - compatible = "fsl,imx6q-tempmon"; -- interrupts = <0 49 0x04>; -+ interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>; - fsl,tempmon = <&anatop>; - fsl,tempmon-data = <&ocotp>; -+ clocks = <&clks 172>; - }; - - usbphy1: usbphy@020c9000 { - compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; - reg = <0x020c9000 0x1000>; -- interrupts = <0 44 0x04>; -+ interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 182>; -+ fsl,anatop = <&anatop>; - }; - - usbphy2: usbphy@020ca000 { - compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; - reg = <0x020ca000 0x1000>; -- interrupts = <0 45 0x04>; -+ interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 183>; -+ fsl,anatop = <&anatop>; -+ }; -+ -+ usbphy_nop1: usbphy_nop1 { -+ compatible = "usb-nop-xceiv"; -+ clocks = <&clks 182>; -+ clock-names = "main_clk"; -+ }; -+ -+ usbphy_nop2: usbphy_nop2 { -+ compatible = "usb-nop-xceiv"; -+ clocks = <&clks 182>; -+ clock-names = "main_clk"; - }; - - snvs@020cc000 { -@@ -575,31 +681,39 @@ - snvs-rtc-lp@34 { - compatible = "fsl,sec-v4.0-mon-rtc-lp"; - reg = <0x34 0x58>; -- interrupts = <0 19 0x04 0 20 0x04>; -+ interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>, -+ <0 20 IRQ_TYPE_LEVEL_HIGH>; - }; - }; - - epit1: epit@020d0000 { /* EPIT1 */ - reg = <0x020d0000 0x4000>; -- interrupts = <0 56 0x04>; -+ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; - }; - - epit2: epit@020d4000 { /* EPIT2 */ - reg = <0x020d4000 0x4000>; -- interrupts = <0 57 0x04>; -+ interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; - }; - - src: src@020d8000 { - compatible = "fsl,imx6q-src", "fsl,imx51-src"; - reg = <0x020d8000 0x4000>; -- interrupts = <0 91 0x04 0 96 0x04>; -+ interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>, -+ <0 96 IRQ_TYPE_LEVEL_HIGH>; - #reset-cells = <1>; - }; - - gpc: gpc@020dc000 { - compatible = "fsl,imx6q-gpc"; - reg = <0x020dc000 0x4000>; -- interrupts = <0 89 0x04 0 90 0x04>; -+ interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>, -+ <0 90 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 122>, <&clks 74>, <&clks 121>, -+ <&clks 26>, <&clks 143>, <&clks 168>, <&clks 62>; -+ clock-names = "gpu3d_core", "gpu3d_shader", "gpu2d_core", -+ "gpu2d_axi", "openvg_axi", "vpu_axi", "ipg"; -+ pu-supply = <®_pu>; - }; - - gpr: iomuxc-gpr@020e0000 { -@@ -610,778 +724,40 @@ - iomuxc: iomuxc@020e0000 { - compatible = "fsl,imx6dl-iomuxc", "fsl,imx6q-iomuxc"; - reg = <0x020e0000 0x4000>; -- -- audmux { -- pinctrl_audmux_1: audmux-1 { -- fsl,pins = < -- MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x80000000 -- MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x80000000 -- MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x80000000 -- MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x80000000 -- >; -- }; -- -- pinctrl_audmux_2: audmux-2 { -- fsl,pins = < -- MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x80000000 -- MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x80000000 -- MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x80000000 -- MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x80000000 -- >; -- }; -- -- pinctrl_audmux_3: audmux-3 { -- fsl,pins = < -- MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x80000000 -- MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x80000000 -- MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x80000000 -- >; -- }; -- }; -- -- ecspi1 { -- pinctrl_ecspi1_1: ecspi1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 -- MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 -- MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 -- >; -- }; -- -- pinctrl_ecspi1_2: ecspi1grp-2 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1 -- MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1 -- MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1 -- >; -- }; -- }; -- -- ecspi3 { -- pinctrl_ecspi3_1: ecspi3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1 -- MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1 -- MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1 -- >; -- }; -- }; -- -- enet { -- pinctrl_enet_1: enetgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -- MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -- >; -- }; -- -- pinctrl_enet_2: enetgrp-2 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0 -- MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0 -- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -- >; -- }; -- -- pinctrl_enet_3: enetgrp-3 { -- fsl,pins = < -- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -- MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -- MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -- MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -- MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 -- >; -- }; -- }; -- -- esai { -- pinctrl_esai_1: esaigrp-1 { -- fsl,pins = < -- MX6QDL_PAD_ENET_RXD0__ESAI_TX_HF_CLK 0x1b030 -- MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030 -- MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030 -- MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030 -- MX6QDL_PAD_ENET_TXD1__ESAI_TX2_RX3 0x1b030 -- MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030 -- MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030 -- MX6QDL_PAD_NANDF_CS2__ESAI_TX0 0x1b030 -- MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030 -- >; -- }; -- -- pinctrl_esai_2: esaigrp-2 { -- fsl,pins = < -- MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030 -- MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030 -- MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030 -- MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030 -- MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030 -- MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030 -- MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030 -- MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030 -- MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030 -- MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030 -- >; -- }; -- }; -- -- flexcan1 { -- pinctrl_flexcan1_1: flexcan1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000 -- MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000 -- >; -- }; -- -- pinctrl_flexcan1_2: flexcan1grp-2 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x80000000 -- MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000 -- >; -- }; -- }; -- -- flexcan2 { -- pinctrl_flexcan2_1: flexcan2grp-1 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000 -- MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000 -- >; -- }; -- }; -- -- gpmi-nand { -- pinctrl_gpmi_nand_1: gpmi-nand-1 { -- fsl,pins = < -- MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -- MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -- MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -- MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -- MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -- MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -- MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -- MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -- MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -- MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -- MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -- MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -- MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -- MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -- MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -- MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -- MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 -- >; -- }; -- }; -- -- hdmi_hdcp { -- pinctrl_hdmi_hdcp_1: hdmihdcpgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1 -- MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_hdmi_hdcp_2: hdmihdcpgrp-2 { -- fsl,pins = < -- MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D16__HDMI_TX_DDC_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_hdmi_hdcp_3: hdmihdcpgrp-3 { -- fsl,pins = < -- MX6QDL_PAD_EIM_EB2__HDMI_TX_DDC_SCL 0x4001b8b1 -- MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1 -- >; -- }; -- }; -- -- hdmi_cec { -- pinctrl_hdmi_cec_1: hdmicecgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_A25__HDMI_TX_CEC_LINE 0x1f8b0 -- >; -- }; -- -- pinctrl_hdmi_cec_2: hdmicecgrp-2 { -- fsl,pins = < -- MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0 -- >; -- }; -- }; -- -- i2c1 { -- pinctrl_i2c1_1: i2c1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c1_2: i2c1grp-2 { -- fsl,pins = < -- MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 -- MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 -- >; -- }; -- }; -- -- i2c2 { -- pinctrl_i2c2_1: i2c2grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c2_2: i2c2grp-2 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c2_3: i2c2grp-3 { -- fsl,pins = < -- MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -- MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -- >; -- }; -- }; -- -- i2c3 { -- pinctrl_i2c3_1: i2c3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c3_2: i2c3grp-2 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -- MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c3_3: i2c3grp-3 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 -- MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1 -- >; -- }; -- -- pinctrl_i2c3_4: i2c3grp-4 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -- MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 -- >; -- }; -- }; -- -- ipu1 { -- pinctrl_ipu1_1: ipu1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 -- MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 -- MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 -- MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 -- MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000 -- MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10 -- MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 -- MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 -- MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 -- MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 -- MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 -- MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 -- MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 -- MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 -- MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 -- MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 -- MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 -- MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 -- MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 -- MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 -- MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 -- MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 -- MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 -- MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 -- MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 -- MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 -- MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 -- MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 -- MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 -- >; -- }; -- -- pinctrl_ipu1_2: ipu1grp-2 { /* parallel camera */ -- fsl,pins = < -- MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000 -- MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000 -- MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000 -- MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000 -- MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000 -- MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000 -- MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000 -- MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000 -- MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000 -- MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000 -- MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000 -- MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000 -- >; -- }; -- -- pinctrl_ipu1_3: ipu1grp-3 { /* parallel port 16-bit */ -- fsl,pins = < -- MX6QDL_PAD_CSI0_DAT4__IPU1_CSI0_DATA04 0x80000000 -- MX6QDL_PAD_CSI0_DAT5__IPU1_CSI0_DATA05 0x80000000 -- MX6QDL_PAD_CSI0_DAT6__IPU1_CSI0_DATA06 0x80000000 -- MX6QDL_PAD_CSI0_DAT7__IPU1_CSI0_DATA07 0x80000000 -- MX6QDL_PAD_CSI0_DAT8__IPU1_CSI0_DATA08 0x80000000 -- MX6QDL_PAD_CSI0_DAT9__IPU1_CSI0_DATA09 0x80000000 -- MX6QDL_PAD_CSI0_DAT10__IPU1_CSI0_DATA10 0x80000000 -- MX6QDL_PAD_CSI0_DAT11__IPU1_CSI0_DATA11 0x80000000 -- MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000 -- MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13 0x80000000 -- MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14 0x80000000 -- MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15 0x80000000 -- MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16 0x80000000 -- MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17 0x80000000 -- MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18 0x80000000 -- MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19 0x80000000 -- MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK 0x80000000 -- MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC 0x80000000 -- MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC 0x80000000 -- >; -- }; -- }; -- -- mlb { -- pinctrl_mlb_1: mlbgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_3__MLB_CLK 0x71 -- MX6QDL_PAD_GPIO_6__MLB_SIG 0x71 -- MX6QDL_PAD_GPIO_2__MLB_DATA 0x71 -- >; -- }; -- -- pinctrl_mlb_2: mlbgrp-2 { -- fsl,pins = < -- MX6QDL_PAD_ENET_TXD1__MLB_CLK 0x71 -- MX6QDL_PAD_GPIO_6__MLB_SIG 0x71 -- MX6QDL_PAD_GPIO_2__MLB_DATA 0x71 -- >; -- }; -- }; -- -- pwm0 { -- pinctrl_pwm0_1: pwm0grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -- >; -- }; -- }; -- -- pwm3 { -- pinctrl_pwm3_1: pwm3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1 -- >; -- }; -- }; -- -- spdif { -- pinctrl_spdif_1: spdifgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0 -- >; -- }; -- -- pinctrl_spdif_2: spdifgrp-2 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_16__SPDIF_IN 0x1b0b0 -- MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0 -- >; -- }; -- -- pinctrl_spdif_3: spdifgrp-3 { -- fsl,pins = < -- MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0 -- >; -- }; -- }; -- -- uart1 { -- pinctrl_uart1_1: uart1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -- MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 -- >; -- }; -- }; -- -- uart2 { -- pinctrl_uart2_1: uart2grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 -- >; -- }; -- -- pinctrl_uart2_2: uart2grp-2 { /* DTE mode */ -- fsl,pins = < -- MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1 -- MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1 -- >; -- }; -- }; -- -- uart3 { -- pinctrl_uart3_1: uart3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1 -- MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1 -- MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1 -- >; -- }; -- -- pinctrl_uart3_2: uart3grp-2 { -- fsl,pins = < -- MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 -- MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1 -- MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1 -- >; -- }; -- }; -- -- uart4 { -- pinctrl_uart4_1: uart4grp-1 { -- fsl,pins = < -- MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -- MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -- >; -- }; -- }; -- -- usbotg { -- pinctrl_usbotg_1: usbotggrp-1 { -- fsl,pins = < -- MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -- >; -- }; -- -- pinctrl_usbotg_2: usbotggrp-2 { -- fsl,pins = < -- MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 -- >; -- }; -- }; -- -- usbh2 { -- pinctrl_usbh2_1: usbh2grp-1 { -- fsl,pins = < -- MX6QDL_PAD_RGMII_TXC__USB_H2_DATA 0x40013030 -- MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40013030 -- >; -- }; -- -- pinctrl_usbh2_2: usbh2grp-2 { -- fsl,pins = < -- MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x40017030 -- >; -- }; -- }; -- -- usbh3 { -- pinctrl_usbh3_1: usbh3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_RGMII_RX_CTL__USB_H3_DATA 0x40013030 -- MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40013030 -- >; -- }; -- -- pinctrl_usbh3_2: usbh3grp-2 { -- fsl,pins = < -- MX6QDL_PAD_RGMII_RXC__USB_H3_STROBE 0x40017030 -- >; -- }; -- }; -- -- usdhc1 { -- pinctrl_usdhc1_1: usdhc1grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 -- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 -- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -- MX6QDL_PAD_NANDF_D0__SD1_DATA4 0x17059 -- MX6QDL_PAD_NANDF_D1__SD1_DATA5 0x17059 -- MX6QDL_PAD_NANDF_D2__SD1_DATA6 0x17059 -- MX6QDL_PAD_NANDF_D3__SD1_DATA7 0x17059 -- >; -- }; -- -- pinctrl_usdhc1_2: usdhc1grp-2 { -- fsl,pins = < -- MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 -- MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 -- MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -- MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -- MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -- MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -- >; -- }; -- }; -- -- usdhc2 { -- pinctrl_usdhc2_1: usdhc2grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -- MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059 -- MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059 -- MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059 -- MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059 -- >; -- }; -- -- pinctrl_usdhc2_2: usdhc2grp-2 { -- fsl,pins = < -- MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -- MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -- MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -- MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -- MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -- MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -- >; -- }; -- }; -- -- usdhc3 { -- pinctrl_usdhc3_1: usdhc3grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059 -- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059 -- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059 -- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059 -- >; -- }; -- -- pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { /* 100Mhz */ -- fsl,pins = < -- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 -- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 -- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9 -- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9 -- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9 -- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9 -- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9 -- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9 -- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9 -- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9 -- >; -- }; -- -- pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { /* 200Mhz */ -- fsl,pins = < -- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 -- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 -- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9 -- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9 -- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9 -- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9 -- MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9 -- MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9 -- MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9 -- MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9 -- >; -- }; -- -- pinctrl_usdhc3_2: usdhc3grp-2 { -- fsl,pins = < -- MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -- MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -- MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -- MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -- MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -- MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -- >; -- }; -- }; -- -- usdhc4 { -- pinctrl_usdhc4_1: usdhc4grp-1 { -- fsl,pins = < -- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -- MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 -- MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 -- MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 -- MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 -- >; -- }; -- -- pinctrl_usdhc4_2: usdhc4grp-2 { -- fsl,pins = < -- MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -- MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -- MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -- MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -- MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -- MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -- >; -- }; -- }; -- -- weim { -- pinctrl_weim_cs0_1: weim_cs0grp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1 -- >; -- }; -- -- pinctrl_weim_nor_1: weim_norgrp-1 { -- fsl,pins = < -- MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1 -- MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1 -- MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060 -- /* data */ -- MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0 -- MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0 -- MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0 -- MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0 -- MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0 -- MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0 -- MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0 -- MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0 -- MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0 -- MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0 -- MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0 -- MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0 -- MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0 -- MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0 -- MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0 -- MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0 -- /* address */ -- MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1 -- MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1 -- MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1 -- MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1 -- MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1 -- MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1 -- MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1 -- MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1 -- MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1 -- MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1 -- MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1 -- MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1 -- MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1 -- MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1 -- MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1 -- MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1 -- MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1 -- MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1 -- MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1 -- MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1 -- MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1 -- MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1 -- MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1 -- MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1 -- >; -- }; -- }; - }; - - ldb: ldb@020e0008 { -- #address-cells = <1>; -- #size-cells = <0>; - compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb"; -- gpr = <&gpr>; -+ reg = <0x020e0000 0x4000>; -+ clocks = <&clks 135>, <&clks 136>, -+ <&clks 39>, <&clks 40>, -+ <&clks 41>, <&clks 42>, -+ <&clks 184>, <&clks 185>, -+ <&clks 210>, <&clks 211>, -+ <&clks 212>, <&clks 213>; -+ clock-names = "ldb_di0", "ldb_di1", -+ "ipu1_di0_sel", "ipu1_di1_sel", -+ "ipu2_di0_sel", "ipu2_di1_sel", -+ "di0_div_3_5", "di1_div_3_5", -+ "di0_div_7", "di1_div_7", -+ "di0_div_sel", "di1_div_sel"; - status = "disabled"; -- -- lvds-channel@0 { -- reg = <0>; -- status = "disabled"; -- }; -- -- lvds-channel@1 { -- reg = <1>; -- status = "disabled"; -- }; - }; - - dcic1: dcic@020e4000 { - reg = <0x020e4000 0x4000>; -- interrupts = <0 124 0x04>; -+ interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>; - }; - - dcic2: dcic@020e8000 { - reg = <0x020e8000 0x4000>; -- interrupts = <0 125 0x04>; -+ interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>; - }; - - sdma: sdma@020ec000 { - compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; - reg = <0x020ec000 0x4000>; -- interrupts = <0 2 0x04>; -+ interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 155>, <&clks 155>; - clock-names = "ipg", "ahb"; - #dma-cells = <3>; -@@ -1396,9 +772,29 @@ - reg = <0x02100000 0x100000>; - ranges; - -- caam@02100000 { -- reg = <0x02100000 0x40000>; -- interrupts = <0 105 0x04 0 106 0x04>; -+ crypto: caam@02100000 { -+ compatible = "fsl,sec-v4.0"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0x2100000 0x40000>; -+ ranges = <0 0x2100000 0x40000>; -+ interrupt-parent = <&intc>; /* interrupts = <0 92 0x4>; */ -+ clocks = <&clks 214>, <&clks 215>, <&clks 216>, <&clks 196>; -+ clock-names = "caam_mem", "caam_aclk", "caam_ipg", "caam_emi_slow"; -+ -+ sec_jr0: jr0@1000 { -+ compatible = "fsl,sec-v4.0-job-ring"; -+ reg = <0x1000 0x1000>; -+ interrupt-parent = <&intc>; -+ interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ sec_jr1: jr1@2000 { -+ compatible = "fsl,sec-v4.0-job-ring"; -+ reg = <0x2000 0x1000>; -+ interrupt-parent = <&intc>; -+ interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; -+ }; - }; - - aipstz@0217c000 { /* AIPSTZ2 */ -@@ -1408,7 +804,7 @@ - usbotg: usb@02184000 { - compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; - reg = <0x02184000 0x200>; -- interrupts = <0 43 0x04>; -+ interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 162>; - fsl,usbphy = <&usbphy1>; - fsl,usbmisc = <&usbmisc 0>; -@@ -1418,7 +814,7 @@ - usbh1: usb@02184200 { - compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; - reg = <0x02184200 0x200>; -- interrupts = <0 40 0x04>; -+ interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 162>; - fsl,usbphy = <&usbphy2>; - fsl,usbmisc = <&usbmisc 1>; -@@ -1428,18 +824,24 @@ - usbh2: usb@02184400 { - compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; - reg = <0x02184400 0x200>; -- interrupts = <0 41 0x04>; -+ interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 162>; - fsl,usbmisc = <&usbmisc 2>; -+ phy_type = "hsic"; -+ fsl,usbphy = <&usbphy_nop1>; -+ fsl,anatop = <&anatop>; - status = "disabled"; - }; - - usbh3: usb@02184600 { - compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; - reg = <0x02184600 0x200>; -- interrupts = <0 42 0x04>; -+ interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 162>; - fsl,usbmisc = <&usbmisc 3>; -+ phy_type = "hsic"; -+ fsl,usbphy = <&usbphy_nop2>; -+ fsl,anatop = <&anatop>; - status = "disabled"; - }; - -@@ -1453,7 +855,9 @@ - fec: ethernet@02188000 { - compatible = "fsl,imx6q-fec"; - reg = <0x02188000 0x4000>; -- interrupts = <0 118 0x04 0 119 0x04>; -+ interrupts-extended = -+ <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 117>, <&clks 117>, <&clks 190>; - clock-names = "ipg", "ahb", "ptp"; - status = "disabled"; -@@ -1461,13 +865,15 @@ - - mlb@0218c000 { - reg = <0x0218c000 0x4000>; -- interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>; -+ interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>, -+ <0 117 IRQ_TYPE_LEVEL_HIGH>, -+ <0 126 IRQ_TYPE_LEVEL_HIGH>; - }; - - usdhc1: usdhc@02190000 { - compatible = "fsl,imx6q-usdhc"; - reg = <0x02190000 0x4000>; -- interrupts = <0 22 0x04>; -+ interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 163>, <&clks 163>, <&clks 163>; - clock-names = "ipg", "ahb", "per"; - bus-width = <4>; -@@ -1477,7 +883,7 @@ - usdhc2: usdhc@02194000 { - compatible = "fsl,imx6q-usdhc"; - reg = <0x02194000 0x4000>; -- interrupts = <0 23 0x04>; -+ interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 164>, <&clks 164>, <&clks 164>; - clock-names = "ipg", "ahb", "per"; - bus-width = <4>; -@@ -1487,7 +893,7 @@ - usdhc3: usdhc@02198000 { - compatible = "fsl,imx6q-usdhc"; - reg = <0x02198000 0x4000>; -- interrupts = <0 24 0x04>; -+ interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 165>, <&clks 165>, <&clks 165>; - clock-names = "ipg", "ahb", "per"; - bus-width = <4>; -@@ -1497,7 +903,7 @@ - usdhc4: usdhc@0219c000 { - compatible = "fsl,imx6q-usdhc"; - reg = <0x0219c000 0x4000>; -- interrupts = <0 25 0x04>; -+ interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 166>, <&clks 166>, <&clks 166>; - clock-names = "ipg", "ahb", "per"; - bus-width = <4>; -@@ -1509,7 +915,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; - reg = <0x021a0000 0x4000>; -- interrupts = <0 36 0x04>; -+ interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 125>; - status = "disabled"; - }; -@@ -1519,7 +925,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; - reg = <0x021a4000 0x4000>; -- interrupts = <0 37 0x04>; -+ interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 126>; - status = "disabled"; - }; -@@ -1529,7 +935,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c"; - reg = <0x021a8000 0x4000>; -- interrupts = <0 38 0x04>; -+ interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 127>; - status = "disabled"; - }; -@@ -1538,6 +944,11 @@ - reg = <0x021ac000 0x4000>; - }; - -+ mmdc0-1@021b0000 { /* MMDC0-1 */ -+ compatible = "fsl,imx6q-mmdc-combine"; -+ reg = <0x021b0000 0x8000>; -+ }; -+ - mmdc0: mmdc@021b0000 { /* MMDC0 */ - compatible = "fsl,imx6q-mmdc"; - reg = <0x021b0000 0x4000>; -@@ -1550,23 +961,29 @@ - weim: weim@021b8000 { - compatible = "fsl,imx6q-weim"; - reg = <0x021b8000 0x4000>; -- interrupts = <0 14 0x04>; -+ interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 196>; - }; - -- ocotp: ocotp@021bc000 { -- compatible = "fsl,imx6q-ocotp", "syscon"; -+ ocotp: ocotp-ctrl@021bc000 { -+ compatible = "syscon"; - reg = <0x021bc000 0x4000>; - }; - -+ ocotp-fuse@021bc000 { -+ compatible = "fsl,imx6q-ocotp"; -+ reg = <0x021bc000 0x4000>; -+ clocks = <&clks 128>; -+ }; -+ - tzasc@021d0000 { /* TZASC1 */ - reg = <0x021d0000 0x4000>; -- interrupts = <0 108 0x04>; -+ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; - }; - - tzasc@021d4000 { /* TZASC2 */ - reg = <0x021d4000 0x4000>; -- interrupts = <0 109 0x04>; -+ interrupts = <0 109 IRQ_TYPE_LEVEL_HIGH>; - }; - - audmux: audmux@021d8000 { -@@ -1575,23 +992,32 @@ - status = "disabled"; - }; - -- mipi@021dc000 { /* MIPI-CSI */ -+ mipi_csi: mipi_csi@021dc000 { -+ compatible = "fsl,imx6q-mipi-csi2"; - reg = <0x021dc000 0x4000>; -- }; -- -- mipi@021e0000 { /* MIPI-DSI */ -- reg = <0x021e0000 0x4000>; -+ interrupts = <0 100 0x04>, <0 101 0x04>; -+ clocks = <&clks 138>, <&clks 53>, <&clks 204>; -+ /* Note: clks 138 is hsi_tx, however, the dphy_c -+ * hsi_tx and pll_refclk use the same clk gate. -+ * In current clk driver, open/close clk gate do -+ * use hsi_tx for a temporary debug purpose. -+ */ -+ clock-names = "dphy_clk", "pixel_clk", "cfg_clk"; -+ status = "disabled"; - }; - - vdoa@021e4000 { -+ compatible = "fsl,imx6q-vdoa"; - reg = <0x021e4000 0x4000>; -- interrupts = <0 18 0x04>; -+ interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 202>; -+ iram = <&ocram>; - }; - - uart2: serial@021e8000 { - compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x021e8000 0x4000>; -- interrupts = <0 27 0x04>; -+ interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 160>, <&clks 161>; - clock-names = "ipg", "per"; - dmas = <&sdma 27 4 0>, <&sdma 28 4 0>; -@@ -1602,7 +1028,7 @@ - uart3: serial@021ec000 { - compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x021ec000 0x4000>; -- interrupts = <0 28 0x04>; -+ interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 160>, <&clks 161>; - clock-names = "ipg", "per"; - dmas = <&sdma 29 4 0>, <&sdma 30 4 0>; -@@ -1613,7 +1039,7 @@ - uart4: serial@021f0000 { - compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x021f0000 0x4000>; -- interrupts = <0 29 0x04>; -+ interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 160>, <&clks 161>; - clock-names = "ipg", "per"; - dmas = <&sdma 31 4 0>, <&sdma 32 4 0>; -@@ -1624,7 +1050,7 @@ - uart5: serial@021f4000 { - compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x021f4000 0x4000>; -- interrupts = <0 30 0x04>; -+ interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 160>, <&clks 161>; - clock-names = "ipg", "per"; - dmas = <&sdma 33 4 0>, <&sdma 34 4 0>; -@@ -1634,13 +1060,18 @@ - }; - - ipu1: ipu@02400000 { -- #crtc-cells = <1>; - compatible = "fsl,imx6q-ipu"; - reg = <0x02400000 0x400000>; -- interrupts = <0 6 0x4 0 5 0x4>; -- clocks = <&clks 130>, <&clks 131>, <&clks 132>; -- clock-names = "bus", "di0", "di1"; -+ interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>, -+ <0 5 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 130>, <&clks 131>, <&clks 132>, -+ <&clks 39>, <&clks 40>, -+ <&clks 135>, <&clks 136>; -+ clock-names = "bus", "di0", "di1", -+ "di0_sel", "di1_sel", -+ "ldb_di0", "ldb_di1"; - resets = <&src 2>; -+ bypass_reset = <0>; - }; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi 2014-10-22 14:55:49.510220001 -0500 -@@ -0,0 +1,374 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/ { -+ /* these are used by bootloader for disabling nodes */ -+ aliases { -+ can0 = &can1; -+ ethernet0 = &fec; -+ led0 = &led0; -+ led1 = &led1; -+ nand = &gpmi; -+ usb0 = &usbh1; -+ usb1 = &usbotg; -+ }; -+ -+ chosen { -+ bootargs = "console=ttymxc1,115200"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led0: user1 { -+ label = "user1"; -+ gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */ -+ default-state = "on"; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led1: user2 { -+ label = "user2"; -+ gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */ -+ default-state = "off"; -+ }; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x20000000>; -+ }; -+ -+ pps { -+ compatible = "pps-gpio"; -+ gpios = <&gpio1 26 0>; -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_3p3v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_5p0v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "5P0V"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 30 0>; -+ status = "okay"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom1: eeprom@50 { -+ compatible = "atmel,24c02"; -+ reg = <0x50>; -+ pagesize = <16>; -+ }; -+ -+ eeprom2: eeprom@51 { -+ compatible = "atmel,24c02"; -+ reg = <0x51>; -+ pagesize = <16>; -+ }; -+ -+ eeprom3: eeprom@52 { -+ compatible = "atmel,24c02"; -+ reg = <0x52>; -+ pagesize = <16>; -+ }; -+ -+ eeprom4: eeprom@53 { -+ compatible = "atmel,24c02"; -+ reg = <0x53>; -+ pagesize = <16>; -+ }; -+ -+ gpio: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ reg = <0x23>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ hwmon: gsc@29 { -+ compatible = "gw,gsp"; -+ reg = <0x29>; -+ }; -+ -+ rtc: ds1672@68 { -+ compatible = "dallas,ds1672"; -+ reg = <0x68>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ pmic: ltc3676@3c { -+ compatible = "ltc,ltc3676"; -+ reg = <0x3c>; -+ -+ regulators { -+ sw1_reg: ltc3676__sw1 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw2_reg: ltc3676__sw2 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3_reg: ltc3676__sw3 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: ltc3676__sw4 { -+ regulator-min-microvolt = <1500000>; -+ regulator-max-microvolt = <1500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo2_reg: ltc3676__ldo2 { -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo4_reg: ltc3676__ldo4 { -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ status = "okay"; -+ -+ videoin: adv7180@20 { -+ compatible = "adi,adv7180"; -+ reg = <0x20>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6qdl-gw51xx { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* MEZZ_DIO0 */ -+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* MEZZ_DIO1 */ -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */ -+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */ -+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */ -+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x80000000 /* PCIE_RST# */ -+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */ -+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */ -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart3: uart3grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart5: uart5grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&pcie { -+ reset-gpio = <&gpio1 0 0>; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&uart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart3>; -+ status = "okay"; -+}; -+ -+&uart5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart5>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi 2014-10-22 14:55:49.510220001 -0500 -@@ -0,0 +1,527 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/ { -+ /* these are used by bootloader for disabling nodes */ -+ aliases { -+ ethernet0 = &fec; -+ led0 = &led0; -+ led1 = &led1; -+ led2 = &led2; -+ nand = &gpmi; -+ ssi0 = &ssi1; -+ usb0 = &usbh1; -+ usb1 = &usbotg; -+ usdhc2 = &usdhc3; -+ }; -+ -+ chosen { -+ bootargs = "console=ttymxc1,115200"; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm4 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led0: user1 { -+ label = "user1"; -+ gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */ -+ default-state = "on"; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led1: user2 { -+ label = "user2"; -+ gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */ -+ default-state = "off"; -+ }; -+ -+ led2: user3 { -+ label = "user3"; -+ gpios = <&gpio4 15 1>; /* 111 - MX6_LOCLED# */ -+ default-state = "off"; -+ }; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x20000000>; -+ }; -+ -+ pps { -+ compatible = "pps-gpio"; -+ gpios = <&gpio1 26 0>; -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_1p0v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "1P0V"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ }; -+ -+ /* remove this fixed regulator once ltc3676__sw2 driver available */ -+ reg_1p8v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "1P8V"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_5p0v: regulator@3 { -+ compatible = "regulator-fixed"; -+ reg = <3>; -+ regulator-name = "5P0V"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@4 { -+ compatible = "regulator-fixed"; -+ reg = <4>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-sabrelite-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-sabrelite-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <4>; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; -+ status = "okay"; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 30 0>; -+ status = "okay"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom1: eeprom@50 { -+ compatible = "atmel,24c02"; -+ reg = <0x50>; -+ pagesize = <16>; -+ }; -+ -+ eeprom2: eeprom@51 { -+ compatible = "atmel,24c02"; -+ reg = <0x51>; -+ pagesize = <16>; -+ }; -+ -+ eeprom3: eeprom@52 { -+ compatible = "atmel,24c02"; -+ reg = <0x52>; -+ pagesize = <16>; -+ }; -+ -+ eeprom4: eeprom@53 { -+ compatible = "atmel,24c02"; -+ reg = <0x53>; -+ pagesize = <16>; -+ }; -+ -+ gpio: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ reg = <0x23>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ hwmon: gsc@29 { -+ compatible = "gw,gsp"; -+ reg = <0x29>; -+ }; -+ -+ rtc: ds1672@68 { -+ compatible = "dallas,ds1672"; -+ reg = <0x68>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ pciswitch: pex8609@3f { -+ compatible = "plx,pex8609"; -+ reg = <0x3f>; -+ }; -+ -+ pmic: ltc3676@3c { -+ compatible = "ltc,ltc3676"; -+ reg = <0x3c>; -+ -+ regulators { -+ sw1_reg: ltc3676__sw1 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw2_reg: ltc3676__sw2 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3_reg: ltc3676__sw3 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: ltc3676__sw4 { -+ regulator-min-microvolt = <1500000>; -+ regulator-max-microvolt = <1500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo2_reg: ltc3676__ldo2 { -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo3_reg: ltc3676__ldo3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo4_reg: ltc3676__ldo4 { -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ status = "okay"; -+ -+ accelerometer: fxos8700@1e { -+ compatible = "fsl,fxos8700"; -+ reg = <0x13>; -+ }; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 169>; -+ VDDA-supply = <®_1p8v>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+ -+ touchscreen: egalax_ts@04 { -+ compatible = "eeti,egalax_ts"; -+ reg = <0x04>; -+ interrupt-parent = <&gpio7>; -+ interrupts = <12 2>; /* gpio7_12 active low */ -+ wakeup-gpios = <&gpio7 12 0>; -+ }; -+ -+ videoin: adv7180@20 { -+ compatible = "adi,adv7180"; -+ reg = <0x20>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6qdl-gw52xx { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* MEZZ_DIO0 */ -+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* MEZZ_DIO1 */ -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */ -+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x80000000 /* VIDDEC_PDN# */ -+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* PHY Reset */ -+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE_RST# */ -+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_PWDN */ -+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */ -+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* USB_SEL_PCI */ -+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */ -+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */ -+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */ -+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */ -+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x80000000 /* LVDS_TCH# */ -+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 /* SD3_CD# */ -+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000 /* UART2_EN# */ -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0 -+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0 -+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0 -+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm4: pwm4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart5: uart5grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@0 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; -+ }; -+}; -+ -+&pcie { -+ reset-gpio = <&gpio1 29 0>; -+ status = "okay"; -+}; -+ -+&pwm4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm4>; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&uart5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart5>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi 2014-10-22 14:55:49.510220001 -0500 -@@ -0,0 +1,572 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/ { -+ /* these are used by bootloader for disabling nodes */ -+ aliases { -+ can0 = &can1; -+ ethernet0 = &fec; -+ ethernet1 = ð1; -+ led0 = &led0; -+ led1 = &led1; -+ led2 = &led2; -+ nand = &gpmi; -+ sky2 = ð1; -+ ssi0 = &ssi1; -+ usb0 = &usbh1; -+ usb1 = &usbotg; -+ usdhc2 = &usdhc3; -+ }; -+ -+ chosen { -+ bootargs = "console=ttymxc1,115200"; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm4 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led0: user1 { -+ label = "user1"; -+ gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */ -+ default-state = "on"; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led1: user2 { -+ label = "user2"; -+ gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */ -+ default-state = "off"; -+ }; -+ -+ led2: user3 { -+ label = "user3"; -+ gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */ -+ default-state = "off"; -+ }; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ pps { -+ compatible = "pps-gpio"; -+ gpios = <&gpio1 26 0>; -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_1p0v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "1P0V"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ }; -+ -+ /* remove when pmic 1p8 regulator available */ -+ reg_1p8v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "1P8V"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_h1_vbus: regulator@3 { -+ compatible = "regulator-fixed"; -+ reg = <3>; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@4 { -+ compatible = "regulator-fixed"; -+ reg = <4>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-sabrelite-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-sabrelite-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <4>; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; -+ status = "okay"; -+}; -+ -+&can1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_flexcan1>; -+ status = "okay"; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 30 0>; -+ status = "okay"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom1: eeprom@50 { -+ compatible = "atmel,24c02"; -+ reg = <0x50>; -+ pagesize = <16>; -+ }; -+ -+ eeprom2: eeprom@51 { -+ compatible = "atmel,24c02"; -+ reg = <0x51>; -+ pagesize = <16>; -+ }; -+ -+ eeprom3: eeprom@52 { -+ compatible = "atmel,24c02"; -+ reg = <0x52>; -+ pagesize = <16>; -+ }; -+ -+ eeprom4: eeprom@53 { -+ compatible = "atmel,24c02"; -+ reg = <0x53>; -+ pagesize = <16>; -+ }; -+ -+ gpio: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ reg = <0x23>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ hwmon: gsc@29 { -+ compatible = "gw,gsp"; -+ reg = <0x29>; -+ }; -+ -+ rtc: ds1672@68 { -+ compatible = "dallas,ds1672"; -+ reg = <0x68>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ pciclkgen: si53156@6b { -+ compatible = "sil,si53156"; -+ reg = <0x6b>; -+ }; -+ -+ pciswitch: pex8606@3f { -+ compatible = "plx,pex8606"; -+ reg = <0x3f>; -+ }; -+ -+ pmic: ltc3676@3c { -+ compatible = "ltc,ltc3676"; -+ reg = <0x3c>; -+ -+ regulators { -+ /* VDD_SOC */ -+ sw1_reg: ltc3676__sw1 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_1P8 */ -+ sw2_reg: ltc3676__sw2 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_ARM */ -+ sw3_reg: ltc3676__sw3 { -+ regulator-min-microvolt = <1175000>; -+ regulator-max-microvolt = <1175000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_DDR */ -+ sw4_reg: ltc3676__sw4 { -+ regulator-min-microvolt = <1500000>; -+ regulator-max-microvolt = <1500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_2P5 */ -+ ldo2_reg: ltc3676__ldo2 { -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_1P8 */ -+ ldo3_reg: ltc3676__ldo3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ /* VDD_HIGH */ -+ ldo4_reg: ltc3676__ldo4 { -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; -+ }; -+ }; -+ }; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ status = "okay"; -+ -+ accelerometer: fxos8700@1e { -+ compatible = "fsl,fxos8700"; -+ reg = <0x1e>; -+ }; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 201>; -+ VDDA-supply = <®_1p8v>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+ -+ hdmiin: adv7611@4c { -+ compatible = "adi,adv7611"; -+ reg = <0x4c>; -+ }; -+ -+ touchscreen: egalax_ts@04 { -+ compatible = "eeti,egalax_ts"; -+ reg = <0x04>; -+ interrupt-parent = <&gpio1>; -+ interrupts = <11 2>; /* gpio1_11 active low */ -+ wakeup-gpios = <&gpio1 11 0>; -+ }; -+ -+ videoout: adv7393@2a { -+ compatible = "adi,adv7393"; -+ reg = <0x2a>; -+ }; -+ -+ videoin: adv7180@20 { -+ compatible = "adi,adv7180"; -+ reg = <0x20>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6qdl-gw53xx { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000 /* PCIE6EXP_DIO0 */ -+ MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000 /* PCIE6EXP_DIO1 */ -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */ -+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 /* GPS_SHDN */ -+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */ -+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */ -+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */ -+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* CAN_STBY */ -+ MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x80000000 /* PMIC_IRQ# */ -+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000 /* HUB_RST# */ -+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* PCIE_WDIS# */ -+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x80000000 /* ACCEL_IRQ# */ -+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */ -+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x80000000 /* USBOTG_OC# */ -+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */ -+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */ -+ MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x80000000 /* TOUCH_IRQ# */ -+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 /* SD3_DET# */ -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0 -+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0 -+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0 -+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_flexcan1: flexcan1grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000 -+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm4: pwm4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart5: uart5grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@1 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; -+ }; -+}; -+ -+&pcie { -+ reset-gpio = <&gpio1 29 0>; -+ status = "okay"; -+ -+ eth1: sky2@8 { /* MAC/PHY on bus 8 */ -+ compatible = "marvell,sky2"; -+ }; -+}; -+ -+&pwm4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm4>; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&uart5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart5>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ vbus-supply = <®_usb_h1_vbus>; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi 2014-10-22 14:55:49.510220001 -0500 -@@ -0,0 +1,599 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/ { -+ /* these are used by bootloader for disabling nodes */ -+ aliases { -+ can0 = &can1; -+ ethernet0 = &fec; -+ ethernet1 = ð1; -+ led0 = &led0; -+ led1 = &led1; -+ led2 = &led2; -+ nand = &gpmi; -+ sky2 = ð1; -+ ssi0 = &ssi1; -+ usb0 = &usbh1; -+ usb1 = &usbotg; -+ usdhc2 = &usdhc3; -+ }; -+ -+ chosen { -+ bootargs = "console=ttymxc1,115200"; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm4 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led0: user1 { -+ label = "user1"; -+ gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */ -+ default-state = "on"; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led1: user2 { -+ label = "user2"; -+ gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */ -+ default-state = "off"; -+ }; -+ -+ led2: user3 { -+ label = "user3"; -+ gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */ -+ default-state = "off"; -+ }; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ pps { -+ compatible = "pps-gpio"; -+ gpios = <&gpio1 26 0>; -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_1p0v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "1P0V"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_h1_vbus: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@3 { -+ compatible = "regulator-fixed"; -+ reg = <3>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-sabrelite-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-sabrelite-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <4>; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; /* AUD4<->sgtl5000 */ -+ status = "okay"; -+}; -+ -+&can1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_flexcan1>; -+ status = "okay"; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 30 0>; -+ status = "okay"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom1: eeprom@50 { -+ compatible = "atmel,24c02"; -+ reg = <0x50>; -+ pagesize = <16>; -+ }; -+ -+ eeprom2: eeprom@51 { -+ compatible = "atmel,24c02"; -+ reg = <0x51>; -+ pagesize = <16>; -+ }; -+ -+ eeprom3: eeprom@52 { -+ compatible = "atmel,24c02"; -+ reg = <0x52>; -+ pagesize = <16>; -+ }; -+ -+ eeprom4: eeprom@53 { -+ compatible = "atmel,24c02"; -+ reg = <0x53>; -+ pagesize = <16>; -+ }; -+ -+ gpio: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ reg = <0x23>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ hwmon: gsc@29 { -+ compatible = "gw,gsp"; -+ reg = <0x29>; -+ }; -+ -+ rtc: ds1672@68 { -+ compatible = "dallas,ds1672"; -+ reg = <0x68>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3950000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ pciswitch: pex8609@3f { -+ compatible = "plx,pex8609"; -+ reg = <0x3f>; -+ }; -+ -+ pciclkgen: si52147@6b { -+ compatible = "sil,si52147"; -+ reg = <0x6b>; -+ }; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ status = "okay"; -+ -+ accelerometer: fxos8700@1e { -+ compatible = "fsl,fxos8700"; -+ reg = <0x1e>; -+ }; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 201>; -+ VDDA-supply = <&sw4_reg>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+ -+ hdmiin: adv7611@4c { -+ compatible = "adi,adv7611"; -+ reg = <0x4c>; -+ }; -+ -+ touchscreen: egalax_ts@04 { -+ compatible = "eeti,egalax_ts"; -+ reg = <0x04>; -+ interrupt-parent = <&gpio7>; -+ interrupts = <12 2>; /* gpio7_12 active low */ -+ wakeup-gpios = <&gpio7 12 0>; -+ }; -+ -+ videoout: adv7393@2a { -+ compatible = "adi,adv7393"; -+ reg = <0x2a>; -+ }; -+ -+ videoin: adv7180@20 { -+ compatible = "adi,adv7180"; -+ reg = <0x20>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6qdl-gw54xx { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */ -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 /* SPINOR_CS0# */ -+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x80000000 /* GPS_PPS */ -+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */ -+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */ -+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* CAN_STBY */ -+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */ -+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */ -+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */ -+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */ -+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x80000000 /* USBHUB_RST# */ -+ MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x80000000 /* MIPI_DIO */ -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0 -+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0 -+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0 -+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_flexcan1: flexcan1grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x80000000 -+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x80000000 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm4: pwm4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart5: uart5grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@1 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; -+ }; -+}; -+ -+&pcie { -+ reset-gpio = <&gpio1 29 0>; -+ status = "okay"; -+ -+ eth1: sky2@8 { /* MAC/PHY on bus 8 */ -+ compatible = "marvell,sky2"; -+ }; -+}; -+ -+&pwm4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm4>; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&ssi2 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&uart5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart5>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ vbus-supply = <®_usb_h1_vbus>; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi 2014-10-22 14:55:49.514220001 -0500 -@@ -0,0 +1,341 @@ -+/* -+ * Copyright (C) 2013,2014 Russell King -+ */ -+#include "imx6qdl-microsom.dtsi" -+#include "imx6qdl-microsom-ar8035.dtsi" -+ -+/ { -+ chosen { -+ bootargs = "quiet console=ttymxc0,115200 root=/dev/mmcblk0p2 rw"; -+ }; -+ -+ aliases { -+ mxcfb0 = &mxcfb1; -+ }; -+ -+ ir_recv: ir-receiver { -+ compatible = "gpio-ir-receiver"; -+ gpios = <&gpio3 5 1>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_gpio3_5>; -+ linux,rc-map-name = "rc-rc6-mce"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_3p3v: 3p3v { -+ compatible = "regulator-fixed"; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usbh1_vbus: usb-h1-vbus { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio1 0 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_usbh1_vbus>; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ -+ reg_usbotg_vbus: usb-otg-vbus { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 22 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_usbotg_vbus>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ }; -+ }; -+ -+ sound-sgtl5000 { -+ audio-codec = <&sgtl5000>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ compatible = "fsl,imx-audio-sgtl5000"; -+ model = "On-board Codec"; -+ mux-ext-port = <5>; -+ mux-int-port = <1>; -+ ssi-controller = <&ssi1>; -+ }; -+ -+ sound-spdif { -+ compatible = "fsl,imx-audio-spdif"; -+ model = "imx-spdif"; -+ spdif-controller = <&spdif>; -+ spdif-out; -+ }; -+ -+ sound-hdmi { -+ compatible = "fsl,imx6q-audio-hdmi", -+ "fsl,imx-audio-hdmi"; -+ model = "imx-audio-hdmi"; -+ hdmi-controller = <&hdmi_audio>; -+ }; -+ -+ mxcfb1: fb@0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "hdmi"; -+ interface_pix_fmt = "RGB24"; -+ mode_str ="1920x1080M@60"; -+ default_bpp = <32>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "okay"; -+ }; -+}; -+ -+&hdmi_core { -+ ipu_id = <0>; -+ disp_id = <0>; -+ status = "okay"; -+}; -+ -+&hdmi_video { -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ status = "okay"; -+}; -+ -+&hdmi_audio { -+ status = "okay"; -+}; -+ -+&hdmi_cec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_hdmi>; -+ status = "okay"; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_i2c2>; -+ status = "okay"; -+ -+ ddc: imx6_hdmi_i2c@50 { -+ compatible = "fsl,imx6-hdmi-i2c"; -+ reg = <0x50>; -+ }; -+}; -+ -+&audmux { -+ status = "okay"; -+}; -+ -+&can1 { -+ pinctrl-names = "default"; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_i2c1>; -+ status = "okay"; -+ -+ /* Pro model */ -+ rtc: pcf8523@68 { -+ compatible = "nxp,pcf8523"; -+ reg = <0x68>; -+ }; -+ -+ /* Pro model */ -+ sgtl5000: sgtl5000@0a { -+ clocks = <&clks 201>; -+ compatible = "fsl,sgtl5000"; -+ pinctrl-0 = <&pinctrl_hummingboard_sgtl5000>; -+ pinctrl-names = "default"; -+ reg = <0x0a>; -+ VDDA-supply = <®_3p3v>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ hummingboard { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ /* -+ * 26 pin header GPIO description. The pins -+ * numbering as following - -+ * GPIO number | GPIO (bank,num) | PIN number -+ * ------------+-----------------+------------ -+ * gpio1 | (1,1) | IO7 -+ * gpio73 | (3,9) | IO11 -+ * gpio72 | (3,8) | IO12 -+ * gpio71 | (3,7) | IO13 -+ * gpio70 | (3,6) | IO15 -+ * gpio194 | (7,2) | IO16 -+ * gpio195 | (7,3) | IO18 -+ * gpio67 | (3,3) | IO22 -+ * -+ * Notice the gpioX and GPIO (Y,Z) mapping forumla : -+ * X = (Y-1) * 32 + Z -+ */ -+ MX6QDL_PAD_GPIO_1__GPIO1_IO01 0x400130b1 -+ MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x400130b1 -+ MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x400130b1 -+ MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x400130b1 -+ MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x400130b1 -+ MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x400130b1 -+ MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x400130b1 -+ MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x400130b1 -+ >; -+ }; -+ -+ pinctrl_hummingboard_gpio3_5: hummingboard-gpio3_5 { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x80000000 -+ >; -+ }; -+ -+ pinctrl_hummingboard_hdmi: hummingboard-hdmi { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0 -+ >; -+ }; -+ -+ pinctrl_hummingboard_i2c1: hummingboard-i2c1 { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_hummingboard_i2c2: hummingboard-i2c2 { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_hummingboard_sgtl5000: hummingboard-sgtl5000 { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0 /*brk*/ -+ MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /*ok*/ -+ MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /*brk*/ -+ MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /*ok*/ -+ MX6QDL_PAD_GPIO_5__CCM_CLKO1 0x130b0 -+ >; -+ }; -+ -+ pinctrl_hummingboard_spdif: hummingboard-spdif { -+ fsl,pins = ; -+ }; -+ -+ pinctrl_hummingboard_usbh1_vbus: hummingboard-usbh1-vbus { -+ fsl,pins = ; -+ }; -+ -+ pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-id { -+ /* -+ * Similar to pinctrl_usbotg_2, but we want it -+ * pulled down for a fixed host connection. -+ */ -+ fsl,pins = ; -+ }; -+ -+ pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus { -+ fsl,pins = ; -+ }; -+ -+ pinctrl_hummingboard_usdhc2_aux: hummingboard-usdhc2-aux { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071 -+ >; -+ }; -+ -+ pinctrl_hummingboard_usdhc2: hummingboard-usdhc2 { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 -+ >; -+ }; -+ -+ pinctrl_hummingboard_pcie_reset: hummingboard-pcie-reset { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x80000000 -+ >; -+ }; -+ }; -+}; -+ -+&spdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_spdif>; -+ clocks = <&clks 197>, <&clks 0>, -+ <&clks 197>, <&clks 0>, -+ <&clks 0>, <&clks 0>, -+ <&clks 0>, <&clks 0>, -+ <&clks 0>; -+ clock-names = "core", "rxtx0", -+ "rxtx1", "rxtx2", -+ "rxtx3", "rxtx4", -+ "rxtx5", "rxtx6", -+ "rxtx7"; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ disable-over-current; -+ vbus-supply = <®_usbh1_vbus>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ disable-over-current; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>; -+ vbus-supply = <®_usbotg_vbus>; -+ status = "okay"; -+}; -+ -+&usdhc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = < -+ &pinctrl_hummingboard_usdhc2_aux -+ &pinctrl_hummingboard_usdhc2 -+ >; -+ vmmc-supply = <®_3p3v>; -+ cd-gpios = <&gpio1 4 0>; -+ status = "okay"; -+}; -+ -+&gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+}; -+ -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = < -+ &pinctrl_hummingboard_pcie_reset -+ >; -+ reset-gpio = <&gpio3 4 0>; -+ status = "okay"; -+ no-msi; -+}; -+ -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi 2014-10-22 14:55:49.514220001 -0500 -@@ -17,7 +17,7 @@ - enet { - pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 { - fsl,pins = < -- MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b8b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - /* AR8035 reset */ - MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0 -@@ -26,25 +26,25 @@ - /* GPIO16 -> AR8035 25MHz */ - MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0xc0000000 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x80000000 -- MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -- MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -- MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -- MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -- MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b030 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b030 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b030 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b030 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b030 - /* AR8035 CLK_25M --> ENET_REF_CLK (V22) */ - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x0a0b1 - /* AR8035 pin strapping: IO voltage: pull up */ -- MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b030 - /* AR8035 pin strapping: PHYADDR#0: pull down */ -- MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x130b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x13030 - /* AR8035 pin strapping: PHYADDR#1: pull down */ -- MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x130b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x13030 - /* AR8035 pin strapping: MODE#1: pull up */ -- MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b030 - /* AR8035 pin strapping: MODE#3: pull up */ -- MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b030 - /* AR8035 pin strapping: MODE#0: pull down */ -- MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x130b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x13030 - - /* - * As the RMII pins are also connected to RGMII -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-microsom.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-microsom.dtsi 2014-10-22 14:55:49.514220001 -0500 -@@ -1,9 +1,69 @@ - /* - * Copyright (C) 2013,2014 Russell King - */ -+#include -+/ { -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_brcm_osc: brcm-osc-reg { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio5 5 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_osc_reg>; -+ regulator-name = "brcm_osc_reg"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ regulator-boot-on; -+ }; -+ -+ reg_brcm: brcm-reg { -+ compatible = "regulator-fixed"; -+ enable-active-high; -+ gpio = <&gpio3 19 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_reg>; -+ regulator-name = "brcm_reg"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <200000>; -+ }; -+ }; -+}; - - &iomuxc { - microsom { -+ pinctrl_microsom_brcm_bt: microsom-brcm-bt { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x40013070 -+ MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x40013070 -+ MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_osc_reg: microsom-brcm-osc-reg { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_reg: microsom-brcm-reg { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40013070 -+ >; -+ }; -+ -+ pinctrl_microsom_brcm_wifi: microsom-brcm-wifi { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_8__XTALOSC_REF_CLK_32K 0x1b0b0 -+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x40013070 -+ MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x40013070 -+ MX6QDL_PAD_CSI0_DAT9__GPIO5_IO27 0x40013070 -+ >; -+ }; -+ - pinctrl_microsom_uart1: microsom-uart1 { - fsl,pins = < - MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -@@ -11,12 +71,24 @@ - >; - }; - -- pinctrl_microsom_usbotg: microsom-usbotg { -- /* -- * Similar to pinctrl_usbotg_2, but we want it -- * pulled down for a fixed host connection. -- */ -- fsl,pins = ; -+ pinctrl_microsom_uart4_1: microsom-uart4 { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_microsom_usdhc1: microsom-usdhc1 { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 -+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 -+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -+ >; - }; - }; - }; -@@ -27,7 +99,23 @@ - status = "okay"; - }; - --&usbotg { -+/* UART4 - Connected to optional BRCM Wifi/BT/FM */ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_microsom_brcm_bt &pinctrl_microsom_uart4_1>; -+ fsl,uart-has-rtscts; -+ status = "okay"; -+}; -+ -+/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */ -+&usdhc1 { -+ card-external-vcc-supply = <®_brcm>; -+ card-reset-gpios = <&gpio5 26 GPIO_ACTIVE_LOW>, <&gpio6 0 GPIO_ACTIVE_LOW>; -+ keep-power-in-suspend; -+ non-removable; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_microsom_usbotg>; -+ pinctrl-0 = <&pinctrl_microsom_brcm_wifi &pinctrl_microsom_usdhc1>; -+ vmmc-supply = <®_brcm>; -+ status = "okay"; - }; -+ -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi 2014-10-22 14:55:49.514220001 -0500 -@@ -0,0 +1,426 @@ -+/* -+ * Copyright 2013 Boundary Devices, Inc. -+ * Copyright 2011 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+#include -+#include -+ -+/ { -+ chosen { -+ stdout-path = &uart2; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_2p5v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "2P5V"; -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpio_keys>; -+ -+ power { -+ label = "Power Button"; -+ gpios = <&gpio2 3 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ gpio-key,wakeup; -+ }; -+ -+ menu { -+ label = "Menu"; -+ gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ home { -+ label = "Home"; -+ gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ back { -+ label = "Back"; -+ gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ volume-up { -+ label = "Volume Up"; -+ gpios = <&gpio7 13 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ volume-down { -+ label = "Volume Down"; -+ gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-nitrogen6x-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-nitrogen6x-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <3>; -+ }; -+ -+ backlight_lcd { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm1 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ power-supply = <®_3p3v>; -+ status = "okay"; -+ }; -+ -+ backlight_lvds { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm4 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ power-supply = <®_3p3v>; -+ status = "okay"; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; -+ status = "okay"; -+}; -+ -+&ecspi1 { -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio3 19 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi1>; -+ status = "okay"; -+ -+ flash: m25p80@0 { -+ compatible = "sst,sst25vf016b"; -+ spi-max-frequency = <20000000>; -+ reg = <0>; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 27 0>; -+ txen-skew-ps = <0>; -+ txc-skew-ps = <3000>; -+ rxdv-skew-ps = <0>; -+ rxc-skew-ps = <3000>; -+ rxd0-skew-ps = <0>; -+ rxd1-skew-ps = <0>; -+ rxd2-skew-ps = <0>; -+ rxd3-skew-ps = <0>; -+ txd0-skew-ps = <0>; -+ txd1-skew-ps = <0>; -+ txd2-skew-ps = <0>; -+ txd3-skew-ps = <0>; -+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 201>; -+ VDDA-supply = <®_2p5v>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-nitrogen6x { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ /* SGTL5000 sys_mclk */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0 -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 -+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 -+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 -+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 -+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 -+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */ -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ /* Phy reset */ -+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x000b0 -+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 -+ >; -+ }; -+ -+ pinctrl_gpio_keys: gpio_keysgrp { -+ fsl,pins = < -+ /* Power Button */ -+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0 -+ /* Menu Button */ -+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0 -+ /* Home Button */ -+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0 -+ /* Back Button */ -+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0 -+ /* Volume Up Button */ -+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0 -+ /* Volume Down Button */ -+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm1: pwm1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_pwm3: pwm3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_pwm4: pwm4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0 -+ /* power enable, high active */ -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */ -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */ -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@0 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; -+ }; -+}; -+ -+&pcie { -+ status = "okay"; -+}; -+ -+&pwm1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm1>; -+ status = "okay"; -+}; -+ -+&pwm3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm3>; -+ status = "okay"; -+}; -+ -+&pwm4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm4>; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -+ -+&usdhc4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ cd-gpios = <&gpio2 6 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-phytec-pbab01.dtsi 2014-10-22 14:55:49.514220001 -0500 -@@ -0,0 +1,98 @@ -+/* -+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/ { -+ chosen { -+ linux,stdout-path = &uart4; -+ }; -+}; -+ -+&fec { -+ status = "okay"; -+}; -+ -+&gpmi { -+ status = "okay"; -+}; -+ -+&i2c2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ clock-frequency = <100000>; -+ status = "okay"; -+ -+ tlv320@18 { -+ compatible = "ti,tlv320aic3x"; -+ reg = <0x18>; -+ }; -+ -+ stmpe@41 { -+ compatible = "st,stmpe811"; -+ reg = <0x41>; -+ }; -+ -+ rtc@51 { -+ compatible = "nxp,rtc8564"; -+ reg = <0x51>; -+ }; -+ -+ adc@64 { -+ compatible = "maxim,max1037"; -+ reg = <0x64>; -+ }; -+}; -+ -+&i2c3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ clock-frequency = <100000>; -+ status = "okay"; -+}; -+ -+&uart3 { -+ status = "okay"; -+}; -+ -+&uart4 { -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -+ -+&usbotg { -+ status = "okay"; -+}; -+ -+&usdhc2 { -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ status = "okay"; -+}; -+ -+&iomuxc { -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi 2014-10-22 14:55:49.518220001 -0500 -@@ -0,0 +1,356 @@ -+/* -+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+ -+/ { -+ model = "Phytec phyFLEX-i.MX6 Ouad"; -+ compatible = "phytec,imx6q-pfla02", "fsl,imx6q"; -+ -+ memory { -+ reg = <0x10000000 0x80000000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_usb_otg_vbus: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio4 15 0>; -+ }; -+ -+ reg_usb_h1_vbus: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio1 0 0>; -+ }; -+ }; -+ -+ gpio_leds: leds { -+ compatible = "gpio-leds"; -+ -+ green { -+ label = "phyflex:green"; -+ gpios = <&gpio1 30 0>; -+ }; -+ -+ red { -+ label = "phyflex:red"; -+ gpios = <&gpio2 31 0>; -+ }; -+ }; -+}; -+ -+&ecspi3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi3>; -+ status = "okay"; -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio4 24 0>; -+ -+ flash@0 { -+ compatible = "m25p80"; -+ spi-max-frequency = <20000000>; -+ reg = <0>; -+ }; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom@50 { -+ compatible = "atmel,24c32"; -+ reg = <0x50>; -+ }; -+ -+ pmic@58 { -+ compatible = "dialog,da9063"; -+ reg = <0x58>; -+ interrupt-parent = <&gpio4>; -+ interrupts = <17 0x8>; /* active-low GPIO4_17 */ -+ -+ regulators { -+ vddcore_reg: bcore1 { -+ regulator-min-microvolt = <730000>; -+ regulator-max-microvolt = <1380000>; -+ regulator-always-on; -+ }; -+ -+ vddsoc_reg: bcore2 { -+ regulator-min-microvolt = <730000>; -+ regulator-max-microvolt = <1380000>; -+ regulator-always-on; -+ }; -+ -+ vdd_ddr3_reg: bpro { -+ regulator-min-microvolt = <1500000>; -+ regulator-max-microvolt = <1500000>; -+ regulator-always-on; -+ }; -+ -+ vdd_3v3_reg: bperi { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vdd_buckmem_reg: bmem { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vdd_eth_reg: bio { -+ regulator-min-microvolt = <1200000>; -+ regulator-max-microvolt = <1200000>; -+ regulator-always-on; -+ }; -+ -+ vdd_eth_io_reg: ldo4 { -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-always-on; -+ }; -+ -+ vdd_mx6_snvs_reg: ldo5 { -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-always-on; -+ }; -+ -+ vdd_3v3_pmic_io_reg: ldo6 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vdd_sd0_reg: ldo9 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vdd_sd1_reg: ldo10 { -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vdd_mx6_high_reg: ldo11 { -+ regulator-min-microvolt = <3000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-phytec-pfla02 { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 -+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */ -+ MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */ -+ MX6QDL_PAD_ENET_TXD0__GPIO1_IO30 0x80000000 /* Green LED */ -+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000 /* Red LED */ -+ >; -+ }; -+ -+ pinctrl_ecspi3: ecspi3grp { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1 -+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1 -+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_uart3: uart3grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D30__UART3_RTS_B 0x1b0b1 -+ MX6QDL_PAD_EIM_D31__UART3_CTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbh1: usbh1grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_0__USB_H1_PWR 0x80000000 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0 -+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 -+ >; -+ }; -+ -+ pinctrl_usdhc2: usdhc2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3_cdwp: usdhc3cdwp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 -+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 -+ >; -+ }; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; -+ status = "disabled"; -+}; -+ -+&gpmi { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ nand-on-flash-bbt; -+ status = "disabled"; -+}; -+ -+&uart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart3>; -+ status = "disabled"; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart4>; -+ status = "disabled"; -+}; -+ -+&usbh1 { -+ vbus-supply = <®_usb_h1_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbh1>; -+ status = "disabled"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "disabled"; -+}; -+ -+&usdhc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc2>; -+ cd-gpios = <&gpio1 4 0>; -+ wp-gpios = <&gpio1 2 0>; -+ status = "disabled"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3 -+ &pinctrl_usdhc3_cdwp>; -+ cd-gpios = <&gpio1 27 0>; -+ wp-gpios = <&gpio1 29 0>; -+ status = "disabled"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi 2014-10-22 14:55:49.518220001 -0500 -@@ -10,17 +10,146 @@ - * http://www.gnu.org/copyleft/gpl.html - */ - -+#include -+ - / { -+ aliases { -+ mxcfb0 = &mxcfb1; -+ mxcfb1 = &mxcfb2; -+ mxcfb2 = &mxcfb3; -+ mxcfb3 = &mxcfb4; -+ }; -+ - memory { - reg = <0x10000000 0x80000000>; - }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpio_leds>; -+ -+ user { -+ label = "debug"; -+ gpios = <&gpio5 15 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ sound-spdif { -+ compatible = "fsl,imx-audio-spdif", -+ "fsl,imx-sabreauto-spdif"; -+ model = "imx-spdif"; -+ spdif-controller = <&spdif>; -+ spdif-in; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm3 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ status = "okay"; -+ }; -+ -+ max7310_reset: max7310-reset { -+ compatible = "gpio-reset"; -+ reset-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; -+ reset-delay-us = <1>; -+ #reset-cells = <0>; -+ }; -+ -+ mxcfb1: fb@0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "ldb"; -+ interface_pix_fmt = "RGB666"; -+ mode_str ="LDB-XGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb2: fb@1 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "hdmi"; -+ interface_pix_fmt = "RGB24"; -+ mode_str ="1920x1080M@60"; -+ default_bpp = <24>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb3: fb@2 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "lcd"; -+ interface_pix_fmt = "RGB565"; -+ mode_str ="CLAA-WVGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb4: fb@3 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "ldb"; -+ interface_pix_fmt = "RGB666"; -+ mode_str ="LDB-XGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm3 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ reg_audio: cs42888_supply { -+ compatible = "regulator-fixed"; -+ regulator-name = "cs42888_supply"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ -+ sound-cs42888 { -+ compatible = "fsl,imx6-sabreauto-cs42888", -+ "fsl,imx-audio-cs42888"; -+ model = "imx-cs42888"; -+ esai-controller = <&esai>; -+ asrc-controller = <&asrc_p2p>; -+ audio-codec = <&codec>; -+ }; -+ -+ sound-hdmi { -+ compatible = "fsl,imx6q-audio-hdmi", -+ "fsl,imx-audio-hdmi"; -+ model = "imx-audio-hdmi"; -+ hdmi-controller = <&hdmi_audio>; -+ }; -+ -+ clocks { -+ codec_osc: anaclk2 { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24576000>; -+ }; -+ }; - }; - - &ecspi1 { - fsl,spi-num-chipselects = <1>; - cs-gpios = <&gpio3 19 0>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_ecspi1_1 &pinctrl_ecspi1_sabreauto>; -+ pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1_cs>; - status = "disabled"; /* pin conflict with WEIM NOR */ - - flash: m25p80@0 { -@@ -34,51 +163,481 @@ - - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_2>; -+ pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; -+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; - status = "okay"; - }; - - &gpmi { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_gpmi_nand_1>; -+ pinctrl-0 = <&pinctrl_gpmi_nand>; -+ status = "okay"; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ egalax_ts@04 { -+ compatible = "eeti,egalax_ts"; -+ reg = <0x04>; -+ interrupt-parent = <&gpio2>; -+ interrupts = <28 2>; -+ wakeup-gpios = <&gpio2 28 0>; -+ }; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ codec: cs42888@048 { -+ compatible = "cirrus,cs42888"; -+ reg = <0x048>; -+ clocks = <&codec_osc 0>; -+ clock-names = "codec_osc"; -+ VA-supply = <®_audio>; -+ VD-supply = <®_audio>; -+ VLS-supply = <®_audio>; -+ VLC-supply = <®_audio>; -+ }; -+ -+ hdmi: edid@50 { -+ compatible = "fsl,imx6-hdmi-i2c"; -+ reg = <0x50>; -+ }; -+}; -+ -+&i2c3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>; - status = "okay"; -+ -+ max7310_a: gpio@30 { -+ compatible = "maxim,max7310"; -+ reg = <0x30>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ resets = <&max7310_reset>; -+ }; -+ -+ max7310_b: gpio@32 { -+ compatible = "maxim,max7310"; -+ reg = <0x32>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ max7310_c: gpio@34 { -+ compatible = "maxim,max7310"; -+ reg = <0x34>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; - }; - - &iomuxc { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - -- hog { -+ imx6qdl-sabreauto { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000 - MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x80000000 -+ MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x80000000 -+ MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x80000000 - MX6QDL_PAD_GPIO_18__SD3_VSELECT 0x17059 - >; - }; -- }; - -- ecspi1 { -- pinctrl_ecspi1_sabreauto: ecspi1-sabreauto { -+ pinctrl_esai1: esai1grp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_CRS_DV__ESAI_TX_CLK 0x1b030 -+ MX6QDL_PAD_ENET_RXD1__ESAI_TX_FS 0x1b030 -+ MX6QDL_PAD_ENET_TX_EN__ESAI_TX3_RX2 0x1b030 -+ MX6QDL_PAD_GPIO_5__ESAI_TX2_RX3 0x1b030 -+ MX6QDL_PAD_ENET_TXD0__ESAI_TX4_RX1 0x1b030 -+ MX6QDL_PAD_ENET_MDC__ESAI_TX5_RX0 0x1b030 -+ MX6QDL_PAD_GPIO_17__ESAI_TX0 0x1b030 -+ MX6QDL_PAD_NANDF_CS3__ESAI_TX1 0x1b030 -+ MX6QDL_PAD_ENET_MDIO__ESAI_RX_CLK 0x1b030 -+ MX6QDL_PAD_GPIO_9__ESAI_RX_FS 0x1b030 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 -+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 -+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 -+ >; -+ }; -+ -+ pinctrl_ecspi1_cs: ecspi1cs { - fsl,pins = < - MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 - >; - }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_KEY_COL2__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 -+ >; -+ }; -+ -+ pinctrl_gpio_leds: gpioledsgrp { -+ fsl,pins = < -+ MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000 -+ >; -+ }; -+ -+ pinctrl_gpmi_nand: gpminandgrp { -+ fsl,pins = < -+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 -+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 -+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 -+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 -+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 -+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 -+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 -+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 -+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 -+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 -+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 -+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 -+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 -+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 -+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 -+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 -+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 -+ >; -+ }; -+ -+ pinctrl_hdmi_cec_2: hdmicecgrp-2 { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm1: pwm1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_spdif: spdifgrp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__SPDIF_IN 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_uart3: uart3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CLK__UART3_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_CMD__UART3_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1 -+ MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059 -+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059 -+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059 -+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170b9 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100b9 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9 -+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9 -+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9 -+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9 -+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9 -+ >; -+ }; -+ -+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x170f9 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x100f9 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9 -+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9 -+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9 -+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9 -+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9 -+ >; -+ }; -+ -+ pinctrl_weim_cs0: weimcs0grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_CS0__EIM_CS0_B 0xb0b1 -+ >; -+ }; -+ -+ pinctrl_weim_nor: weimnorgrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_OE__EIM_OE_B 0xb0b1 -+ MX6QDL_PAD_EIM_RW__EIM_RW 0xb0b1 -+ MX6QDL_PAD_EIM_WAIT__EIM_WAIT_B 0xb060 -+ MX6QDL_PAD_EIM_D16__EIM_DATA16 0x1b0b0 -+ MX6QDL_PAD_EIM_D17__EIM_DATA17 0x1b0b0 -+ MX6QDL_PAD_EIM_D18__EIM_DATA18 0x1b0b0 -+ MX6QDL_PAD_EIM_D19__EIM_DATA19 0x1b0b0 -+ MX6QDL_PAD_EIM_D20__EIM_DATA20 0x1b0b0 -+ MX6QDL_PAD_EIM_D21__EIM_DATA21 0x1b0b0 -+ MX6QDL_PAD_EIM_D22__EIM_DATA22 0x1b0b0 -+ MX6QDL_PAD_EIM_D23__EIM_DATA23 0x1b0b0 -+ MX6QDL_PAD_EIM_D24__EIM_DATA24 0x1b0b0 -+ MX6QDL_PAD_EIM_D25__EIM_DATA25 0x1b0b0 -+ MX6QDL_PAD_EIM_D26__EIM_DATA26 0x1b0b0 -+ MX6QDL_PAD_EIM_D27__EIM_DATA27 0x1b0b0 -+ MX6QDL_PAD_EIM_D28__EIM_DATA28 0x1b0b0 -+ MX6QDL_PAD_EIM_D29__EIM_DATA29 0x1b0b0 -+ MX6QDL_PAD_EIM_D30__EIM_DATA30 0x1b0b0 -+ MX6QDL_PAD_EIM_D31__EIM_DATA31 0x1b0b0 -+ MX6QDL_PAD_EIM_A23__EIM_ADDR23 0xb0b1 -+ MX6QDL_PAD_EIM_A22__EIM_ADDR22 0xb0b1 -+ MX6QDL_PAD_EIM_A21__EIM_ADDR21 0xb0b1 -+ MX6QDL_PAD_EIM_A20__EIM_ADDR20 0xb0b1 -+ MX6QDL_PAD_EIM_A19__EIM_ADDR19 0xb0b1 -+ MX6QDL_PAD_EIM_A18__EIM_ADDR18 0xb0b1 -+ MX6QDL_PAD_EIM_A17__EIM_ADDR17 0xb0b1 -+ MX6QDL_PAD_EIM_A16__EIM_ADDR16 0xb0b1 -+ MX6QDL_PAD_EIM_DA15__EIM_AD15 0xb0b1 -+ MX6QDL_PAD_EIM_DA14__EIM_AD14 0xb0b1 -+ MX6QDL_PAD_EIM_DA13__EIM_AD13 0xb0b1 -+ MX6QDL_PAD_EIM_DA12__EIM_AD12 0xb0b1 -+ MX6QDL_PAD_EIM_DA11__EIM_AD11 0xb0b1 -+ MX6QDL_PAD_EIM_DA10__EIM_AD10 0xb0b1 -+ MX6QDL_PAD_EIM_DA9__EIM_AD09 0xb0b1 -+ MX6QDL_PAD_EIM_DA8__EIM_AD08 0xb0b1 -+ MX6QDL_PAD_EIM_DA7__EIM_AD07 0xb0b1 -+ MX6QDL_PAD_EIM_DA6__EIM_AD06 0xb0b1 -+ MX6QDL_PAD_EIM_DA5__EIM_AD05 0xb0b1 -+ MX6QDL_PAD_EIM_DA4__EIM_AD04 0xb0b1 -+ MX6QDL_PAD_EIM_DA3__EIM_AD03 0xb0b1 -+ MX6QDL_PAD_EIM_DA2__EIM_AD02 0xb0b1 -+ MX6QDL_PAD_EIM_DA1__EIM_AD01 0xb0b1 -+ MX6QDL_PAD_EIM_DA0__EIM_AD00 0xb0b1 -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@0 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; - }; - }; - -+&pcie { -+ status = "okay"; -+}; -+ -+&pwm3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm1>; -+ status = "okay"; -+}; -+ -+&spdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_spdif>; -+ status = "okay"; -+}; -+ -+&uart3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart3>; -+ pinctrl-assert-gpios = <&max7310_b 4 GPIO_ACTIVE_HIGH>, /* CTS */ -+ <&max7310_c 3 GPIO_ACTIVE_HIGH>; /* RXD and TXD */ -+ fsl,uart-has-rtscts; -+ status = "okay"; -+}; -+ - &uart4 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart4_1>; -+ pinctrl-0 = <&pinctrl_uart4>; - status = "okay"; - }; - - &usdhc3 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; -- pinctrl-0 = <&pinctrl_usdhc3_1>; -- pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>; -- pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>; -+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - cd-gpios = <&gpio6 15 0>; - wp-gpios = <&gpio1 13 0>; - status = "okay"; -@@ -86,7 +645,7 @@ - - &weim { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_weim_nor_1 &pinctrl_weim_cs0_1>; -+ pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>; - #address-cells = <2>; - #size-cells = <1>; - ranges = <0 0 0x08000000 0x08000000>; -@@ -102,3 +661,48 @@ - 0x0000c000 0x1404a38e 0x00000000>; - }; - }; -+ -+&ldb { -+ ipu_id = <1>; -+ disp_id = <0>; -+ ext_ref = <1>; -+ mode = "sep0"; -+ sec_ipu_id = <1>; -+ sec_disp_id = <1>; -+ status = "okay"; -+}; -+ -+&esai { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_esai1>; -+ status = "okay"; -+}; -+ -+&hdmi_core { -+ ipu_id = <0>; -+ disp_id = <1>; -+ status = "okay"; -+}; -+ -+&hdmi_video { -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ status = "okay"; -+}; -+ -+&hdmi_audio { -+ status = "okay"; -+}; -+ -+&hdmi_cec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hdmi_cec_2>; -+ status = "okay"; -+}; -+ -+&gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi 2014-10-22 14:55:49.518220001 -0500 -@@ -0,0 +1,427 @@ -+/* -+ * Copyright 2011 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+#include -+#include -+ -+/ { -+ chosen { -+ stdout-path = &uart2; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_2p5v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "2P5V"; -+ regulator-min-microvolt = <2500000>; -+ regulator-max-microvolt = <2500000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpio_keys>; -+ -+ power { -+ label = "Power Button"; -+ gpios = <&gpio2 3 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ gpio-key,wakeup; -+ }; -+ -+ menu { -+ label = "Menu"; -+ gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ home { -+ label = "Home"; -+ gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ back { -+ label = "Back"; -+ gpios = <&gpio2 2 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ volume-up { -+ label = "Volume Up"; -+ gpios = <&gpio7 13 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ -+ volume-down { -+ label = "Volume Down"; -+ gpios = <&gpio4 5 GPIO_ACTIVE_LOW>; -+ linux,code = ; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-sabrelite-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-sabrelite-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <4>; -+ }; -+ -+ backlight_lcd { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm1 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ power-supply = <®_3p3v>; -+ status = "okay"; -+ }; -+ -+ backlight_lvds { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm4 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ power-supply = <®_3p3v>; -+ status = "okay"; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; -+ status = "okay"; -+}; -+ -+&ecspi1 { -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio3 19 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi1>; -+ status = "okay"; -+ -+ flash: m25p80@0 { -+ compatible = "sst,sst25vf016b"; -+ spi-max-frequency = <20000000>; -+ reg = <0>; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>; -+ txen-skew-ps = <0>; -+ txc-skew-ps = <3000>; -+ rxdv-skew-ps = <0>; -+ rxc-skew-ps = <3000>; -+ rxd0-skew-ps = <0>; -+ rxd1-skew-ps = <0>; -+ rxd2-skew-ps = <0>; -+ rxd3-skew-ps = <0>; -+ txd0-skew-ps = <0>; -+ txd1-skew-ps = <0>; -+ txd2-skew-ps = <0>; -+ txd3-skew-ps = <0>; -+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 201>; -+ VDDA-supply = <®_2p5v>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-sabrelite { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ /* SGTL5000 sys_mclk */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x030b0 -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0 -+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0 -+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0 -+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 -+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 -+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x000b1 /* CS */ -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ /* Phy reset */ -+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x000b0 -+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 -+ >; -+ }; -+ -+ pinctrl_gpio_keys: gpio_keysgrp { -+ fsl,pins = < -+ /* Power Button */ -+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x1b0b0 -+ /* Menu Button */ -+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x1b0b0 -+ /* Home Button */ -+ MX6QDL_PAD_NANDF_D4__GPIO2_IO04 0x1b0b0 -+ /* Back Button */ -+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x1b0b0 -+ /* Volume Up Button */ -+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0 -+ /* Volume Down Button */ -+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pwm1: pwm1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_pwm3: pwm3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT1__PWM3_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_pwm4: pwm4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__PWM4_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0 -+ /* power enable, high active */ -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x000b0 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b0b0 /* CD */ -+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* WP */ -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x1b0b0 /* CD */ -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+ -+ lvds-channel@0 { -+ fsl,data-mapping = "spwg"; -+ fsl,data-width = <18>; -+ status = "okay"; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: hsd100pxn1 { -+ clock-frequency = <65000000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hback-porch = <220>; -+ hfront-porch = <40>; -+ vback-porch = <21>; -+ vfront-porch = <7>; -+ hsync-len = <60>; -+ vsync-len = <10>; -+ }; -+ }; -+ }; -+}; -+ -+&pcie { -+ status = "okay"; -+}; -+ -+&pwm1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm1>; -+ status = "okay"; -+}; -+ -+&pwm3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm3>; -+ status = "okay"; -+}; -+ -+&pwm4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm4>; -+ status = "okay"; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ wp-gpios = <&gpio7 1 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -+ -+&usdhc4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ cd-gpios = <&gpio2 6 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabresd.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabresd.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 2014-10-22 14:55:49.566220001 -0500 -@@ -10,16 +10,33 @@ - * http://www.gnu.org/copyleft/gpl.html - */ - -+#include -+#include -+ - / { -+ aliases { -+ mxcfb0 = &mxcfb1; -+ mxcfb1 = &mxcfb2; -+ mxcfb2 = &mxcfb3; -+ mxcfb3 = &mxcfb4; -+ }; -+ -+ chosen { -+ stdout-path = &uart1; -+ }; -+ - memory { - reg = <0x10000000 0x40000000>; - }; - - regulators { - compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; - -- reg_usb_otg_vbus: usb_otg_vbus { -+ reg_usb_otg_vbus: regulator@0 { - compatible = "regulator-fixed"; -+ reg = <0>; - regulator-name = "usb_otg_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; -@@ -27,8 +44,9 @@ - enable-active-high; - }; - -- reg_usb_h1_vbus: usb_h1_vbus { -+ reg_usb_h1_vbus: regulator@1 { - compatible = "regulator-fixed"; -+ reg = <1>; - regulator-name = "usb_h1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; -@@ -36,29 +54,46 @@ - enable-active-high; - }; - -- reg_audio: wm8962_supply { -+ reg_audio: regulator@2 { - compatible = "regulator-fixed"; -+ reg = <2>; - regulator-name = "wm8962-supply"; - gpio = <&gpio4 10 0>; - enable-active-high; - }; -+ -+ reg_mipi_dsi_pwr_on: mipi_dsi_pwr_on { -+ compatible = "regulator-fixed"; -+ regulator-name = "mipi_dsi_pwr_on"; -+ gpio = <&gpio6 14 0>; -+ enable-active-high; -+ }; - }; - - gpio-keys { - compatible = "gpio-keys"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpio_keys>; -+ -+ power { -+ label = "Power Button"; -+ gpios = <&gpio3 29 GPIO_ACTIVE_LOW>; -+ gpio-key,wakeup; -+ linux,code = ; -+ }; - - volume-up { - label = "Volume Up"; -- gpios = <&gpio1 4 0>; -+ gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; - gpio-key,wakeup; -- linux,code = <115>; /* KEY_VOLUMEUP */ -+ linux,code = ; - }; - - volume-down { - label = "Volume Down"; -- gpios = <&gpio1 5 0>; -+ gpios = <&gpio1 5 GPIO_ACTIVE_LOW>; - gpio-key,wakeup; -- linux,code = <114>; /* KEY_VOLUMEDOWN */ -+ linux,code = ; - }; - }; - -@@ -88,11 +123,107 @@ - default-brightness-level = <7>; - status = "okay"; - }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_gpio_leds>; -+ -+ red { -+ gpios = <&gpio1 2 0>; -+ default-state = "on"; -+ }; -+ }; -+ -+ sound-hdmi { -+ compatible = "fsl,imx6q-audio-hdmi", -+ "fsl,imx-audio-hdmi"; -+ model = "imx-audio-hdmi"; -+ hdmi-controller = <&hdmi_audio>; -+ }; -+ -+ mxcfb1: fb@0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "ldb"; -+ interface_pix_fmt = "RGB666"; -+ mode_str ="LDB-XGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb2: fb@1 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "hdmi"; -+ interface_pix_fmt = "RGB24"; -+ mode_str ="1920x1080M@60"; -+ default_bpp = <24>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb3: fb@2 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "lcd"; -+ interface_pix_fmt = "RGB565"; -+ mode_str ="CLAA-WVGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ mxcfb4: fb@3 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "ldb"; -+ interface_pix_fmt = "RGB666"; -+ mode_str ="LDB-XGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "disabled"; -+ }; -+ -+ lcd@0 { -+ compatible = "fsl,lcd"; -+ ipu_id = <0>; -+ disp_id = <0>; -+ default_ifmt = "RGB565"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ipu1>; -+ status = "okay"; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm1 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <7>; -+ }; -+ -+ v4l2_out { -+ compatible = "fsl,mxc_v4l2_output"; -+ status = "okay"; -+ }; -+ -+ lvds_cabc_ctrl { -+ lvds0-gpios = <&gpio6 15 0>; -+ lvds1-gpios = <&gpio6 16 0>; -+ }; -+ -+ mipi_dsi_reset: mipi-dsi-reset { -+ compatible = "gpio-reset"; -+ reset-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>; -+ reset-delay-us = <50>; -+ #reset-cells = <0>; -+ }; - }; - - &audmux { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_audmux_2>; -+ pinctrl-0 = <&pinctrl_audmux>; - status = "okay"; - }; - -@@ -100,7 +231,7 @@ - fsl,spi-num-chipselects = <1>; - cs-gpios = <&gpio4 9 0>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_ecspi1_2>; -+ pinctrl-0 = <&pinctrl_ecspi1>; - status = "okay"; - - flash: m25p80@0 { -@@ -114,7 +245,7 @@ - - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_1>; -+ pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - phy-reset-gpios = <&gpio1 25 0>; - status = "okay"; -@@ -123,7 +254,7 @@ - &i2c1 { - clock-frequency = <100000>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2c1_2>; -+ pinctrl-0 = <&pinctrl_i2c1>; - status = "okay"; - - codec: wm8962@1a { -@@ -149,10 +280,121 @@ - }; - }; - -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ hdmi: edid@50 { -+ compatible = "fsl,imx6-hdmi-i2c"; -+ reg = <0x50>; -+ }; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+}; -+ - &i2c3 { - clock-frequency = <100000>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2c3_2>; -+ pinctrl-0 = <&pinctrl_i2c3>; - status = "okay"; - - egalax_ts@04 { -@@ -168,11 +410,9 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - -- hog { -+ imx6qdl-sabresd { - pinctrl_hog: hoggrp { - fsl,pins = < -- MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000 -- MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000 - MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000 - MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000 - MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 -@@ -182,6 +422,202 @@ - MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 - MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 - MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000 -+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000 -+ MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000 -+ MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000 -+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000 -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 -+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 -+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 -+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1 -+ MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1 -+ MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_gpio_keys: gpio_keysgrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 -+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000 -+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000 -+ >; -+ }; -+ -+ pinctrl_hdmi_cec: hdmi_cecgrp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE 0x1f8b0 -+ >; -+ }; -+ -+ pinctrl_hdmi_hdcp: hdmi_hdcpgrp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 -+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_ipu1: ipu1grp { -+ fsl,pins = < -+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 -+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 -+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 -+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 -+ MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000 -+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10 -+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 -+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 -+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 -+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 -+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 -+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 -+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 -+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 -+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 -+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 -+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 -+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 -+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 -+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 -+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 -+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 -+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 -+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 -+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 -+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 -+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 -+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 -+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 -+ >; -+ }; -+ -+ pinctrl_pcie: pciegrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 -+ >; -+ }; -+ -+ pinctrl_pwm1: pwm1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc2: usdhc2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -+ MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059 -+ MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059 -+ MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059 -+ MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x17059 -+ MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x17059 -+ MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x17059 -+ MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 -+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 -+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 -+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 -+ >; -+ }; -+ }; -+ -+ gpio_leds { -+ pinctrl_gpio_leds: gpioledsgrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 - >; - }; - }; -@@ -212,9 +648,33 @@ - }; - }; - -+&pcie { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pcie>; -+ reset-gpio = <&gpio7 12 0>; -+ status = "okay"; -+}; -+ -+&pcie { -+ power-on-gpio = <&gpio3 19 0>; -+ reset-gpio = <&gpio7 12 0>; -+ status = "okay"; -+}; -+ -+ - &pwm1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_pwm0_1>; -+ pinctrl-0 = <&pinctrl_pwm1>; -+ status = "okay"; -+}; -+ -+&ldb { -+ ipu_id = <1>; -+ disp_id = <1>; -+ ext_ref = <1>; -+ mode = "sep1"; -+ sec_ipu_id = <1>; -+ sec_disp_id = <0>; - status = "okay"; - }; - -@@ -225,7 +685,16 @@ - - &uart1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart1_1>; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&mipi_dsi { -+ dev_id = <0>; -+ disp_id = <0>; -+ lcd_panel = "TRULY-WVGA"; -+ disp-power-on-supply = <®_mipi_dsi_pwr_on>; -+ resets = <&mipi_dsi_reset>; - status = "okay"; - }; - -@@ -237,14 +706,14 @@ - &usbotg { - vbus-supply = <®_usb_otg_vbus>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usbotg_2>; -+ pinctrl-0 = <&pinctrl_usbotg>; - disable-over-current; - status = "okay"; - }; - - &usdhc2 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc2_1>; -+ pinctrl-0 = <&pinctrl_usdhc2>; - bus-width = <8>; - cd-gpios = <&gpio2 2 0>; - wp-gpios = <&gpio2 3 0>; -@@ -253,9 +722,47 @@ - - &usdhc3 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_1>; -+ pinctrl-0 = <&pinctrl_usdhc3>; - bus-width = <8>; - cd-gpios = <&gpio2 0 0>; - wp-gpios = <&gpio2 1 0>; - status = "okay"; - }; -+ -+&usdhc4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ bus-width = <8>; -+ non-removable; -+ no-1-8-v; -+ status = "okay"; -+}; -+ -+&hdmi_core { -+ ipu_id = <0>; -+ disp_id = <0>; -+ status = "okay"; -+}; -+ -+&hdmi_video { -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ status = "okay"; -+}; -+ -+&hdmi_audio { -+ status = "okay"; -+}; -+ -+&hdmi_cec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hdmi_cec>; -+ status = "okay"; -+}; -+ -+&gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-wandboard.dtsi linux-3.14.22/arch/arm/boot/dts/imx6qdl-wandboard.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6qdl-wandboard.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6qdl-wandboard.dtsi 2014-10-22 14:55:49.570220001 -0500 -@@ -12,17 +12,21 @@ - / { - regulators { - compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; - -- reg_2p5v: 2p5v { -+ reg_2p5v: regulator@0 { - compatible = "regulator-fixed"; -+ reg = <0>; - regulator-name = "2P5V"; - regulator-min-microvolt = <2500000>; - regulator-max-microvolt = <2500000>; - regulator-always-on; - }; - -- reg_3p3v: 3p3v { -+ reg_3p3v: regulator@1 { - compatible = "regulator-fixed"; -+ reg = <1>; - regulator-name = "3P3V"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; -@@ -54,14 +58,14 @@ - - &audmux { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_audmux_2>; -+ pinctrl-0 = <&pinctrl_audmux>; - status = "okay"; - }; - - &i2c2 { - clock-frequency = <100000>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2c2_2>; -+ pinctrl-0 = <&pinctrl_i2c2>; - status = "okay"; - - codec: sgtl5000@0a { -@@ -77,7 +81,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - -- hog { -+ imx6qdl-wandboard { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 -@@ -91,20 +95,121 @@ - MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 - >; - }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 -+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 -+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 -+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ MX6QDL_PAD_GPIO_6__ENET_IRQ 0x000b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_spdif: spdifgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart3: uart3grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1 -+ MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc1: usdhc1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 -+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 -+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc2: usdhc2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; - }; - }; - - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_1>; -+ pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - phy-reset-gpios = <&gpio3 29 0>; -+ interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, -+ <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; - status = "okay"; - }; - - &spdif { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_spdif_3>; -+ pinctrl-0 = <&pinctrl_spdif>; - status = "okay"; - }; - -@@ -115,13 +220,13 @@ - - &uart1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart1_1>; -+ pinctrl-0 = <&pinctrl_uart1>; - status = "okay"; - }; - - &uart3 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart3_2>; -+ pinctrl-0 = <&pinctrl_uart3>; - fsl,uart-has-rtscts; - status = "okay"; - }; -@@ -132,7 +237,7 @@ - - &usbotg { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usbotg_1>; -+ pinctrl-0 = <&pinctrl_usbotg>; - disable-over-current; - dr_mode = "peripheral"; - status = "okay"; -@@ -140,21 +245,21 @@ - - &usdhc1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc1_2>; -+ pinctrl-0 = <&pinctrl_usdhc1>; - cd-gpios = <&gpio1 2 0>; - status = "okay"; - }; - - &usdhc2 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc2_2>; -+ pinctrl-0 = <&pinctrl_usdhc2>; - non-removable; - status = "okay"; - }; - - &usdhc3 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_2>; -+ pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio3 9 0>; - status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts linux-3.14.22/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-dmo-edmqmx6.dts 2014-10-22 14:55:49.570220001 -0500 -@@ -0,0 +1,432 @@ -+/* -+ * Copyright 2013 Data Modul AG -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+ -+#include -+#include "imx6q.dtsi" -+ -+/ { -+ model = "Data Modul eDM-QMX6 Board"; -+ compatible = "dmo,imx6q-edmqmx6", "fsl,imx6q"; -+ -+ chosen { -+ stdout-path = &uart2; -+ }; -+ -+ aliases { -+ gpio7 = &stmpe_gpio1; -+ gpio8 = &stmpe_gpio2; -+ stmpe-i2c0 = &stmpe1; -+ stmpe-i2c1 = &stmpe2; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x80000000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_3p3v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_switch: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "usb_otg_switch"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio7 12 0>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ reg_usb_host1: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_host1_en"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ gpio = <&gpio3 31 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ gpio-leds { -+ compatible = "gpio-leds"; -+ -+ led-blue { -+ label = "blue"; -+ gpios = <&stmpe_gpio1 8 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led-green { -+ label = "green"; -+ gpios = <&stmpe_gpio1 9 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-pink { -+ label = "pink"; -+ gpios = <&stmpe_gpio1 10 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ led-red { -+ label = "red"; -+ gpios = <&stmpe_gpio1 11 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+}; -+ -+&ecspi5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi5>; -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio1 12 0>; -+ status = "okay"; -+ -+ flash: m25p80@0 { -+ compatible = "m25p80"; -+ spi-max-frequency = <40000000>; -+ reg = <0>; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio3 23 0>; -+ phy-supply = <&vgen2_1v2_eth>; -+ status = "okay"; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2 -+ &pinctrl_stmpe1 -+ &pinctrl_stmpe2 -+ &pinctrl_pfuze>; -+ status = "okay"; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ interrupt-parent = <&gpio3>; -+ interrupts = <20 8>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-always-on; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ regulator-always-on; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_1v2_eth: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vdd_high_in: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ stmpe1: stmpe1601@40 { -+ compatible = "st,stmpe1601"; -+ reg = <0x40>; -+ interrupts = <30 0>; -+ interrupt-parent = <&gpio3>; -+ vcc-supply = <&sw2_reg>; -+ vio-supply = <&sw2_reg>; -+ -+ stmpe_gpio1: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ }; -+ }; -+ -+ stmpe2: stmpe1601@44 { -+ compatible = "st,stmpe1601"; -+ reg = <0x44>; -+ interrupts = <2 0>; -+ interrupt-parent = <&gpio5>; -+ vcc-supply = <&sw2_reg>; -+ vio-supply = <&sw2_reg>; -+ -+ stmpe_gpio2: stmpe_gpio { -+ #gpio-cells = <2>; -+ compatible = "st,stmpe-gpio"; -+ }; -+ }; -+ -+ temp1: ad7414@4c { -+ compatible = "ad,ad7414"; -+ reg = <0x4c>; -+ }; -+ -+ temp2: ad7414@4d { -+ compatible = "ad,ad7414"; -+ reg = <0x4d>; -+ }; -+ -+ rtc: m41t62@68 { -+ compatible = "stm,m41t62"; -+ reg = <0x68>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-dmo-edmqmx6 { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000 -+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000 -+ >; -+ }; -+ -+ pinctrl_ecspi5: ecspi5rp-1 { -+ fsl,pins = < -+ MX6QDL_PAD_SD1_DAT0__ECSPI5_MISO 0x80000000 -+ MX6QDL_PAD_SD1_CMD__ECSPI5_MOSI 0x80000000 -+ MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x80000000 -+ MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x80000000 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_pfuze: pfuze100grp1 { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000 -+ >; -+ }; -+ -+ pinctrl_stmpe1: stmpe1grp { -+ fsl,pins = ; -+ }; -+ -+ pinctrl_stmpe2: stmpe2grp { -+ fsl,pins = ; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 -+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 -+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 -+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&sata { -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ vbus-supply = <®_usb_host1>; -+ disable-over-current; -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ -+&usbotg { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -+ -+&usdhc4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ vmmc-supply = <®_3p3v>; -+ non-removable; -+ bus-width = <8>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q.dtsi linux-3.14.22/arch/arm/boot/dts/imx6q.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q.dtsi 2014-10-22 14:55:49.570220001 -0500 -@@ -8,10 +8,16 @@ - * - */ - -+#include - #include "imx6q-pinfunc.h" - #include "imx6qdl.dtsi" - - / { -+ aliases { -+ ipu1 = &ipu2; -+ spi4 = &ecspi5; -+ }; -+ - cpus { - #address-cells = <1>; - #size-cells = <0>; -@@ -25,8 +31,17 @@ - /* kHz uV */ - 1200000 1275000 - 996000 1250000 -+ 852000 1250000 - 792000 1150000 -- 396000 950000 -+ 396000 975000 -+ >; -+ fsl,soc-operating-points = < -+ /* ARM kHz SOC-PU uV */ -+ 1200000 1275000 -+ 996000 1250000 -+ 852000 1250000 -+ 792000 1175000 -+ 396000 1175000 - >; - clock-latency = <61036>; /* two CLK32 periods */ - clocks = <&clks 104>, <&clks 6>, <&clks 16>, -@@ -61,12 +76,77 @@ - }; - - soc { -+ -+ busfreq { /* BUSFREQ */ -+ compatible = "fsl,imx6_busfreq"; -+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>, -+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>; -+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", -+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc"; -+ interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>; -+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3"; -+ fsl,max_ddr_freq = <528000000>; -+ }; -+ -+ gpu@00130000 { -+ compatible = "fsl,imx6q-gpu"; -+ reg = <0x00130000 0x4000>, <0x00134000 0x4000>, -+ <0x02204000 0x4000>, <0x0 0x0>; -+ reg-names = "iobase_3d", "iobase_2d", -+ "iobase_vg", "phys_baseaddr"; -+ interrupts = <0 9 0x04>, <0 10 0x04>,<0 11 0x04>; -+ interrupt-names = "irq_3d", "irq_2d", "irq_vg"; -+ clocks = <&clks 26>, <&clks 143>, -+ <&clks 27>, <&clks 121>, -+ <&clks 122>, <&clks 74>; -+ clock-names = "gpu2d_axi_clk", "openvg_axi_clk", -+ "gpu3d_axi_clk", "gpu2d_clk", -+ "gpu3d_clk", "gpu3d_shader_clk"; -+ resets = <&src 0>, <&src 3>, <&src 3>; -+ reset-names = "gpu3d", "gpu2d", "gpuvg"; -+ pu-supply = <®_pu>; -+ }; -+ - ocram: sram@00900000 { - compatible = "mmio-sram"; - reg = <0x00900000 0x40000>; - clocks = <&clks 142>; - }; - -+ hdmi_core: hdmi_core@00120000 { -+ compatible = "fsl,imx6q-hdmi-core"; -+ reg = <0x00120000 0x9000>; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ status = "disabled"; -+ }; -+ -+ hdmi_video: hdmi_video@020e0000 { -+ compatible = "fsl,imx6q-hdmi-video"; -+ reg = <0x020e0000 0x1000>; -+ reg-names = "hdmi_gpr"; -+ interrupts = <0 115 0x04>; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ status = "disabled"; -+ }; -+ -+ hdmi_audio: hdmi_audio@00120000 { -+ compatible = "fsl,imx6q-hdmi-audio"; -+ clocks = <&clks 124>, <&clks 123>; -+ clock-names = "hdmi_isfr", "hdmi_iahb"; -+ dmas = <&sdma 2 23 0>; -+ dma-names = "tx"; -+ status = "disabled"; -+ }; -+ -+ hdmi_cec: hdmi_cec@00120000 { -+ compatible = "fsl,imx6q-hdmi-cec"; -+ interrupts = <0 115 0x04>; -+ status = "disabled"; -+ }; -+ -+ - aips-bus@02000000 { /* AIPS1 */ - spba-bus@02000000 { - ecspi5: ecspi@02018000 { -@@ -74,13 +154,17 @@ - #size-cells = <0>; - compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi"; - reg = <0x02018000 0x4000>; -- interrupts = <0 35 0x04>; -+ interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 116>, <&clks 116>; - clock-names = "ipg", "per"; - status = "disabled"; - }; - }; - -+ vpu@02040000 { -+ status = "okay"; -+ }; -+ - iomuxc: iomuxc@020e0000 { - compatible = "fsl,imx6q-iomuxc"; - -@@ -122,40 +206,40 @@ - }; - }; - -+ aips-bus@02100000 { /* AIPS2 */ -+ mipi_dsi: mipi@021e0000 { -+ compatible = "fsl,imx6q-mipi-dsi"; -+ reg = <0x021e0000 0x4000>; -+ interrupts = <0 102 0x04>; -+ gpr = <&gpr>; -+ clocks = <&clks 138>, <&clks 209>; -+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk"; -+ status = "disabled"; -+ }; -+ }; -+ - sata: sata@02200000 { - compatible = "fsl,imx6q-ahci"; - reg = <0x02200000 0x4000>; -- interrupts = <0 39 0x04>; -+ interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks 154>, <&clks 187>, <&clks 105>; - clock-names = "sata", "sata_ref", "ahb"; - status = "disabled"; - }; - - ipu2: ipu@02800000 { -- #crtc-cells = <1>; - compatible = "fsl,imx6q-ipu"; - reg = <0x02800000 0x400000>; -- interrupts = <0 8 0x4 0 7 0x4>; -- clocks = <&clks 133>, <&clks 134>, <&clks 137>; -- clock-names = "bus", "di0", "di1"; -+ interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>, -+ <0 7 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 133>, <&clks 134>, <&clks 137>, -+ <&clks 41>, <&clks 42>, -+ <&clks 135>, <&clks 136>; -+ clock-names = "bus", "di0", "di1", -+ "di0_sel", "di1_sel", -+ "ldb_di0", "ldb_di1"; - resets = <&src 4>; -+ bypass_reset = <0>; - }; - }; - }; -- --&ldb { -- clocks = <&clks 33>, <&clks 34>, -- <&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>, -- <&clks 135>, <&clks 136>; -- clock-names = "di0_pll", "di1_pll", -- "di0_sel", "di1_sel", "di2_sel", "di3_sel", -- "di0", "di1"; -- -- lvds-channel@0 { -- crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>; -- }; -- -- lvds-channel@1 { -- crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>; -- }; --}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gk802.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gk802.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gk802.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gk802.dts 2014-10-22 14:55:49.570220001 -0500 -@@ -0,0 +1,229 @@ -+/* -+ * Copyright (C) 2013 Philipp Zabel -+ * -+ * This file is licensed under the terms of the GNU General Public License -+ * version 2. This program is licensed "as is" without any warranty of any -+ * kind, whether express or implied. -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+ -+/ { -+ model = "Zealz GK802"; -+ compatible = "zealz,imx6q-gk802", "fsl,imx6q"; -+ -+ aliases { -+ mxcfb0 = &mxcfb1; -+ }; -+ -+ chosen { -+ stdout-path = &uart4; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_3p3v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_h1_vbus: usb_h1_vbus { -+ compatible = "regulator-fixed"; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio2 0 0>; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ -+ recovery-button { -+ label = "recovery"; -+ gpios = <&gpio3 16 1>; -+ linux,code = <0x198>; /* KEY_RESTART */ -+ gpio-key,wakeup; -+ }; -+ -+ }; -+ -+ sound-hdmi { -+ compatible = "fsl,imx6q-audio-hdmi", -+ "fsl,imx-audio-hdmi"; -+ model = "imx-audio-hdmi"; -+ hdmi-controller = <&hdmi_audio>; -+ }; -+ -+ mxcfb1: fb@0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "hdmi"; -+ interface_pix_fmt = "RGB24"; -+ mode_str ="1920x1080M@60"; -+ default_bpp = <32>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "okay"; -+ }; -+}; -+ -+&hdmi_core { -+ ipu_id = <0>; -+ disp_id = <0>; -+ status = "okay"; -+}; -+ -+&hdmi_video { -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ status = "okay"; -+}; -+ -+&hdmi_audio { -+ status = "okay"; -+}; -+ -+ -+/* Internal I2C */ -+&i2c2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ clock-frequency = <100000>; -+ status = "okay"; -+ -+ /* SDMC DM2016 1024 bit EEPROM + 128 bit OTP */ -+ eeprom: dm2016@51 { -+ compatible = "sdmc,dm2016"; -+ reg = <0x51>; -+ }; -+}; -+ -+/* External I2C via HDMI */ -+&i2c3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ clock-frequency = <100000>; -+ status = "okay"; -+ -+ ddc: imx6_hdmi_i2c@50 { -+ compatible = "fsl,imx6-hdmi-i2c"; -+ reg = <0x50>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-gk802 { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ /* Recovery button, active-low */ -+ MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x100b1 -+ /* RTL8192CU enable GPIO, active-low */ -+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x1b0b0 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_uart4: uart4grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc4: usdhc4grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 -+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 -+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 -+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 -+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 -+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&uart2 { -+ status = "okay"; -+}; -+ -+&uart4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart4>; -+ status = "okay"; -+}; -+ -+/* External USB-A port (USBOTG) */ -+&usbotg { -+ phy_type = "utmi"; -+ dr_mode = "host"; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+/* Internal USB port (USBH1), connected to RTL8192CU */ -+&usbh1 { -+ phy_type = "utmi"; -+ dr_mode = "host"; -+ vbus-supply = <®_usb_h1_vbus>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+/* External microSD */ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ bus-width = <4>; -+ cd-gpios = <&gpio6 11 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -+ -+/* Internal microSD */ -+&usdhc4 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc4>; -+ bus-width = <4>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw51xx.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gw51xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw51xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gw51xx.dts 2014-10-22 14:55:49.570220001 -0500 -@@ -0,0 +1,19 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+#include "imx6qdl-gw54xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 Quad GW51XX"; -+ compatible = "gw,imx6q-gw51xx", "gw,ventana", "fsl,imx6q"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw52xx.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gw52xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw52xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gw52xx.dts 2014-10-22 14:55:49.570220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+#include "imx6qdl-gw52xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 Quad GW52XX"; -+ compatible = "gw,imx6q-gw52xx", "gw,ventana", "fsl,imx6q"; -+}; -+ -+&sata { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw53xx.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gw53xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw53xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gw53xx.dts 2014-10-22 14:55:49.570220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+#include "imx6qdl-gw53xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 Quad GW53XX"; -+ compatible = "gw,imx6q-gw53xx", "gw,ventana", "fsl,imx6q"; -+}; -+ -+&sata { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw5400-a.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gw5400-a.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw5400-a.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gw5400-a.dts 2014-10-22 14:55:49.574220001 -0500 -@@ -0,0 +1,543 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+ -+/ { -+ model = "Gateworks Ventana GW5400-A"; -+ compatible = "gw,imx6q-gw5400-a", "gw,ventana", "fsl,imx6q"; -+ -+ /* these are used by bootloader for disabling nodes */ -+ aliases { -+ ethernet0 = &fec; -+ ethernet1 = ð1; -+ i2c0 = &i2c1; -+ i2c1 = &i2c2; -+ i2c2 = &i2c3; -+ led0 = &led0; -+ led1 = &led1; -+ led2 = &led2; -+ sky2 = ð1; -+ ssi0 = &ssi1; -+ spi0 = &ecspi1; -+ usb0 = &usbh1; -+ usb1 = &usbotg; -+ usdhc2 = &usdhc3; -+ }; -+ -+ chosen { -+ bootargs = "console=ttymxc1,115200"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led0: user1 { -+ label = "user1"; -+ gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */ -+ default-state = "on"; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ led1: user2 { -+ label = "user2"; -+ gpios = <&gpio4 10 0>; /* 106 -> MX6_PANLEDR */ -+ default-state = "off"; -+ }; -+ -+ led2: user3 { -+ label = "user3"; -+ gpios = <&gpio4 15 1>; /* 111 -> MX6_LOCLED# */ -+ default-state = "off"; -+ }; -+ }; -+ -+ memory { -+ reg = <0x10000000 0x40000000>; -+ }; -+ -+ pps { -+ compatible = "pps-gpio"; -+ gpios = <&gpio1 5 0>; -+ status = "okay"; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ reg_1p0v: regulator@0 { -+ compatible = "regulator-fixed"; -+ reg = <0>; -+ regulator-name = "1P0V"; -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <1000000>; -+ regulator-always-on; -+ }; -+ -+ reg_3p3v: regulator@1 { -+ compatible = "regulator-fixed"; -+ reg = <1>; -+ regulator-name = "3P3V"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_h1_vbus: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "usb_h1_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ regulator-always-on; -+ }; -+ -+ reg_usb_otg_vbus: regulator@3 { -+ compatible = "regulator-fixed"; -+ reg = <3>; -+ regulator-name = "usb_otg_vbus"; -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5000000>; -+ gpio = <&gpio3 22 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ sound { -+ compatible = "fsl,imx6q-sabrelite-sgtl5000", -+ "fsl,imx-audio-sgtl5000"; -+ model = "imx6q-sabrelite-sgtl5000"; -+ ssi-controller = <&ssi1>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "MIC_IN", "Mic Jack", -+ "Mic Jack", "Mic Bias", -+ "Headphone Jack", "HP_OUT"; -+ mux-int-port = <1>; -+ mux-ext-port = <4>; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux>; -+ status = "okay"; -+}; -+ -+&ecspi1 { -+ fsl,spi-num-chipselects = <1>; -+ cs-gpios = <&gpio3 19 0>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ecspi1>; -+ status = "okay"; -+ -+ flash: m25p80@0 { -+ compatible = "sst,w25q256"; -+ spi-max-frequency = <30000000>; -+ reg = <0>; -+ }; -+}; -+ -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ phy-reset-gpios = <&gpio1 30 0>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ eeprom1: eeprom@50 { -+ compatible = "atmel,24c02"; -+ reg = <0x50>; -+ pagesize = <16>; -+ }; -+ -+ eeprom2: eeprom@51 { -+ compatible = "atmel,24c02"; -+ reg = <0x51>; -+ pagesize = <16>; -+ }; -+ -+ eeprom3: eeprom@52 { -+ compatible = "atmel,24c02"; -+ reg = <0x52>; -+ pagesize = <16>; -+ }; -+ -+ eeprom4: eeprom@53 { -+ compatible = "atmel,24c02"; -+ reg = <0x53>; -+ pagesize = <16>; -+ }; -+ -+ gpio: pca9555@23 { -+ compatible = "nxp,pca9555"; -+ reg = <0x23>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ hwmon: gsc@29 { -+ compatible = "gw,gsp"; -+ reg = <0x29>; -+ }; -+ -+ rtc: ds1672@68 { -+ compatible = "dallas,ds1672"; -+ reg = <0x68>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3950000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ pciswitch: pex8609@3f { -+ compatible = "plx,pex8609"; -+ reg = <0x3f>; -+ }; -+ -+ pciclkgen: si52147@6b { -+ compatible = "sil,si52147"; -+ reg = <0x6b>; -+ }; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3>; -+ status = "okay"; -+ -+ accelerometer: mma8450@1c { -+ compatible = "fsl,mma8450"; -+ reg = <0x1c>; -+ }; -+ -+ codec: sgtl5000@0a { -+ compatible = "fsl,sgtl5000"; -+ reg = <0x0a>; -+ clocks = <&clks 201>; -+ VDDA-supply = <&sw4_reg>; -+ VDDIO-supply = <®_3p3v>; -+ }; -+ -+ hdmiin: adv7611@4c { -+ compatible = "adi,adv7611"; -+ reg = <0x4c>; -+ }; -+ -+ touchscreen: egalax_ts@04 { -+ compatible = "eeti,egalax_ts"; -+ reg = <0x04>; -+ interrupt-parent = <&gpio7>; -+ interrupts = <12 2>; /* gpio7_12 active low */ -+ wakeup-gpios = <&gpio7 12 0>; -+ }; -+ -+ videoout: adv7393@2a { -+ compatible = "adi,adv7393"; -+ reg = <0x2a>; -+ }; -+ -+ videoin: adv7180@20 { -+ compatible = "adi,adv7180"; -+ reg = <0x20>; -+ }; -+}; -+ -+&iomuxc { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hog>; -+ -+ imx6q-gw5400-a { -+ pinctrl_hog: hoggrp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* OTG_PWR_EN */ -+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 /* SPINOR_CS0# */ -+ MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000 /* PCIE IRQ */ -+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE RST */ -+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000130b0 /* AUD4_MCK */ -+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x80000000 /* GPS_PPS */ -+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* TOUCH_IRQ# */ -+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */ -+ MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x80000000 /* user2 led */ -+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */ -+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x80000000 /* USBHUB_RST# */ -+ MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x80000000 /* MIPI_DIO */ -+ >; -+ }; -+ -+ pinctrl_audmux: audmuxgrp { -+ fsl,pins = < -+ MX6QDL_PAD_SD2_DAT0__AUD4_RXD 0x130b0 -+ MX6QDL_PAD_SD2_DAT3__AUD4_TXC 0x130b0 -+ MX6QDL_PAD_SD2_DAT2__AUD4_TXD 0x110b0 -+ MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x130b0 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 -+ MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 -+ MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 -+ >; -+ }; -+ -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1 -+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 -+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_i2c3: i2c3grp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 -+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_uart5: uart5grp { -+ fsl,pins = < -+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ -+&ldb { -+ status = "okay"; -+}; -+ -+&pcie { -+ reset-gpio = <&gpio1 29 0>; -+ status = "okay"; -+ -+ eth1: sky2@8 { /* MAC/PHY on bus 8 */ -+ compatible = "marvell,sky2"; -+ }; -+}; -+ -+&ssi1 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart1>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart2>; -+ status = "okay"; -+}; -+ -+&uart5 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_uart5>; -+ status = "okay"; -+}; -+ -+&usbotg { -+ vbus-supply = <®_usb_otg_vbus>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usbotg>; -+ disable-over-current; -+ status = "okay"; -+}; -+ -+&usbh1 { -+ vbus-supply = <®_usb_h1_vbus>; -+ status = "okay"; -+}; -+ -+&usdhc3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ cd-gpios = <&gpio7 0 0>; -+ vmmc-supply = <®_3p3v>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw54xx.dts linux-3.14.22/arch/arm/boot/dts/imx6q-gw54xx.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-gw54xx.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-gw54xx.dts 2014-10-22 14:55:49.574220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2013 Gateworks Corporation -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+#include "imx6qdl-gw54xx.dtsi" -+ -+/ { -+ model = "Gateworks Ventana i.MX6 Quad GW54XX"; -+ compatible = "gw,imx6q-gw54xx", "gw,ventana", "fsl,imx6q"; -+}; -+ -+&sata { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-hummingboard.dts linux-3.14.22/arch/arm/boot/dts/imx6q-hummingboard.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-hummingboard.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-hummingboard.dts 2014-10-22 14:55:49.574220001 -0500 -@@ -0,0 +1,21 @@ -+/* -+ * Copyright (C) 2014 Rabeeh Khoury (rabeeh@solid-run.com) -+ * Based on work by Russell King -+ */ -+/dts-v1/; -+ -+#include "imx6q.dtsi" -+#include "imx6qdl-hummingboard.dtsi" -+ -+/ { -+ model = "SolidRun HummingBoard Dual/Quad"; -+ compatible = "solidrun,hummingboard/q", "fsl,imx6q"; -+}; -+ -+&sata { -+ status = "okay"; -+ fsl,transmit-level-mV = <1104>; -+ fsl,transmit-boost-mdB = <0>; -+ fsl,transmit-atten-16ths = <9>; -+ fsl,no-spread-spectrum; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-nitrogen6x.dts linux-3.14.22/arch/arm/boot/dts/imx6q-nitrogen6x.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-nitrogen6x.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-nitrogen6x.dts 2014-10-22 14:55:49.574220001 -0500 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright 2013 Boundary Devices, Inc. -+ * Copyright 2012 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/dts-v1/; -+#include "imx6q.dtsi" -+#include "imx6qdl-nitrogen6x.dtsi" -+ -+/ { -+ model = "Freescale i.MX6 Quad Nitrogen6x Board"; -+ compatible = "fsl,imx6q-nitrogen6x", "fsl,imx6q"; -+}; -+ -+&sata { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-phytec-pbab01.dts linux-3.14.22/arch/arm/boot/dts/imx6q-phytec-pbab01.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-phytec-pbab01.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-phytec-pbab01.dts 2014-10-22 14:55:49.574220001 -0500 -@@ -11,24 +11,17 @@ - - /dts-v1/; - #include "imx6q-phytec-pfla02.dtsi" -+#include "imx6qdl-phytec-pbab01.dtsi" - - / { - model = "Phytec phyFLEX-i.MX6 Quad Carrier-Board"; - compatible = "phytec,imx6q-pbab01", "phytec,imx6q-pfla02", "fsl,imx6q"; --}; -- --&fec { -- status = "okay"; --}; -- --&uart4 { -- status = "okay"; --}; - --&usdhc2 { -- status = "okay"; -+ chosen { -+ stdout-path = &uart4; -+ }; - }; - --&usdhc3 { -- status = "okay"; -+&sata { -+ status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi linux-3.14.22/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-phytec-pfla02.dtsi 2014-10-22 14:55:49.574220001 -0500 -@@ -10,171 +10,13 @@ - */ - - #include "imx6q.dtsi" -+#include "imx6qdl-phytec-pfla02.dtsi" - - / { -- model = "Phytec phyFLEX-i.MX6 Ouad"; -+ model = "Phytec phyFLEX-i.MX6 Quad"; - compatible = "phytec,imx6q-pfla02", "fsl,imx6q"; - - memory { - reg = <0x10000000 0x80000000>; - }; - }; -- --&ecspi3 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_ecspi3_1>; -- status = "okay"; -- fsl,spi-num-chipselects = <1>; -- cs-gpios = <&gpio4 24 0>; -- -- flash@0 { -- compatible = "m25p80"; -- spi-max-frequency = <20000000>; -- reg = <0>; -- }; --}; -- --&i2c1 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2c1_1>; -- status = "okay"; -- -- eeprom@50 { -- compatible = "atmel,24c32"; -- reg = <0x50>; -- }; -- -- pmic@58 { -- compatible = "dialog,da9063"; -- reg = <0x58>; -- interrupt-parent = <&gpio4>; -- interrupts = <17 0x8>; /* active-low GPIO4_17 */ -- -- regulators { -- vddcore_reg: bcore1 { -- regulator-min-microvolt = <730000>; -- regulator-max-microvolt = <1380000>; -- regulator-always-on; -- }; -- -- vddsoc_reg: bcore2 { -- regulator-min-microvolt = <730000>; -- regulator-max-microvolt = <1380000>; -- regulator-always-on; -- }; -- -- vdd_ddr3_reg: bpro { -- regulator-min-microvolt = <1500000>; -- regulator-max-microvolt = <1500000>; -- regulator-always-on; -- }; -- -- vdd_3v3_reg: bperi { -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- -- vdd_buckmem_reg: bmem { -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- -- vdd_eth_reg: bio { -- regulator-min-microvolt = <1200000>; -- regulator-max-microvolt = <1200000>; -- regulator-always-on; -- }; -- -- vdd_eth_io_reg: ldo4 { -- regulator-min-microvolt = <2500000>; -- regulator-max-microvolt = <2500000>; -- regulator-always-on; -- }; -- -- vdd_mx6_snvs_reg: ldo5 { -- regulator-min-microvolt = <3000000>; -- regulator-max-microvolt = <3000000>; -- regulator-always-on; -- }; -- -- vdd_3v3_pmic_io_reg: ldo6 { -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- -- vdd_sd0_reg: ldo9 { -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- }; -- -- vdd_sd1_reg: ldo10 { -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- }; -- -- vdd_mx6_high_reg: ldo11 { -- regulator-min-microvolt = <3000000>; -- regulator-max-microvolt = <3000000>; -- regulator-always-on; -- }; -- }; -- }; --}; -- --&iomuxc { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hog>; -- -- hog { -- pinctrl_hog: hoggrp { -- fsl,pins = < -- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 -- MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */ -- MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */ -- >; -- }; -- }; -- -- pfla02 { -- pinctrl_usdhc3_pfla02: usdhc3grp-pfla02 { -- fsl,pins = < -- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 -- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 -- >; -- }; -- }; --}; -- --&fec { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_3>; -- phy-mode = "rgmii"; -- phy-reset-gpios = <&gpio3 23 0>; -- status = "disabled"; --}; -- --&uart4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart4_1>; -- status = "disabled"; --}; -- --&usdhc2 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc2_2>; -- cd-gpios = <&gpio1 4 0>; -- wp-gpios = <&gpio1 2 0>; -- status = "disabled"; --}; -- --&usdhc3 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_2 -- &pinctrl_usdhc3_pfla02>; -- cd-gpios = <&gpio1 27 0>; -- wp-gpios = <&gpio1 29 0>; -- status = "disabled"; --}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-pinfunc.h linux-3.14.22/arch/arm/boot/dts/imx6q-pinfunc.h ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-pinfunc.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-pinfunc.h 2014-10-22 14:55:49.578220001 -0500 -@@ -673,6 +673,7 @@ - #define MX6QDL_PAD_GPIO_3__USB_H1_OC 0x22c 0x5fc 0x948 0x6 0x1 - #define MX6QDL_PAD_GPIO_3__MLB_CLK 0x22c 0x5fc 0x900 0x7 0x1 - #define MX6QDL_PAD_GPIO_6__ESAI_TX_CLK 0x230 0x600 0x870 0x0 0x1 -+#define MX6QDL_PAD_GPIO_6__ENET_IRQ 0x230 0x600 0x03c 0x11 0xff000609 - #define MX6QDL_PAD_GPIO_6__I2C3_SDA 0x230 0x600 0x8ac 0x2 0x1 - #define MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x230 0x600 0x000 0x5 0x0 - #define MX6QDL_PAD_GPIO_6__SD2_LCTL 0x230 0x600 0x000 0x6 0x0 -@@ -1024,6 +1025,7 @@ - #define MX6QDL_PAD_SD1_DAT2__WDOG1_RESET_B_DEB 0x34c 0x734 0x000 0x6 0x0 - #define MX6QDL_PAD_SD1_CLK__SD1_CLK 0x350 0x738 0x000 0x0 0x0 - #define MX6QDL_PAD_SD1_CLK__ECSPI5_SCLK 0x350 0x738 0x828 0x1 0x0 -+#define MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT 0x350 0x738 0x000 0x2 0x0 - #define MX6QDL_PAD_SD1_CLK__GPT_CLKIN 0x350 0x738 0x000 0x3 0x0 - #define MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x350 0x738 0x000 0x5 0x0 - #define MX6QDL_PAD_SD2_CLK__SD2_CLK 0x354 0x73c 0x000 0x0 0x0 -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabreauto.dts linux-3.14.22/arch/arm/boot/dts/imx6q-sabreauto.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabreauto.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-sabreauto.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -20,6 +20,22 @@ - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q"; - }; - -+&mxcfb1 { -+ status = "okay"; -+}; -+ -+&mxcfb2 { -+ status = "okay"; -+}; -+ -+&mxcfb3 { -+ status = "okay"; -+}; -+ -+&mxcfb4 { -+ status = "okay"; -+}; -+ - &sata { - status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabrelite.dts linux-3.14.22/arch/arm/boot/dts/imx6q-sabrelite.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabrelite.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-sabrelite.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -12,189 +12,13 @@ - - /dts-v1/; - #include "imx6q.dtsi" -+#include "imx6qdl-sabrelite.dtsi" - - / { - model = "Freescale i.MX6 Quad SABRE Lite Board"; - compatible = "fsl,imx6q-sabrelite", "fsl,imx6q"; -- -- memory { -- reg = <0x10000000 0x40000000>; -- }; -- -- regulators { -- compatible = "simple-bus"; -- -- reg_2p5v: 2p5v { -- compatible = "regulator-fixed"; -- regulator-name = "2P5V"; -- regulator-min-microvolt = <2500000>; -- regulator-max-microvolt = <2500000>; -- regulator-always-on; -- }; -- -- reg_3p3v: 3p3v { -- compatible = "regulator-fixed"; -- regulator-name = "3P3V"; -- regulator-min-microvolt = <3300000>; -- regulator-max-microvolt = <3300000>; -- regulator-always-on; -- }; -- -- reg_usb_otg_vbus: usb_otg_vbus { -- compatible = "regulator-fixed"; -- regulator-name = "usb_otg_vbus"; -- regulator-min-microvolt = <5000000>; -- regulator-max-microvolt = <5000000>; -- gpio = <&gpio3 22 0>; -- enable-active-high; -- }; -- }; -- -- sound { -- compatible = "fsl,imx6q-sabrelite-sgtl5000", -- "fsl,imx-audio-sgtl5000"; -- model = "imx6q-sabrelite-sgtl5000"; -- ssi-controller = <&ssi1>; -- audio-codec = <&codec>; -- audio-routing = -- "MIC_IN", "Mic Jack", -- "Mic Jack", "Mic Bias", -- "Headphone Jack", "HP_OUT"; -- mux-int-port = <1>; -- mux-ext-port = <4>; -- }; --}; -- --&audmux { -- status = "okay"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_audmux_1>; --}; -- --&ecspi1 { -- fsl,spi-num-chipselects = <1>; -- cs-gpios = <&gpio3 19 0>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_ecspi1_1>; -- status = "okay"; -- -- flash: m25p80@0 { -- compatible = "sst,sst25vf016b"; -- spi-max-frequency = <20000000>; -- reg = <0>; -- }; --}; -- --&fec { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_1>; -- phy-mode = "rgmii"; -- phy-reset-gpios = <&gpio3 23 0>; -- status = "okay"; --}; -- --&i2c1 { -- status = "okay"; -- clock-frequency = <100000>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_i2c1_1>; -- -- codec: sgtl5000@0a { -- compatible = "fsl,sgtl5000"; -- reg = <0x0a>; -- clocks = <&clks 201>; -- VDDA-supply = <®_2p5v>; -- VDDIO-supply = <®_3p3v>; -- }; --}; -- --&iomuxc { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_hog>; -- -- hog { -- pinctrl_hog: hoggrp { -- fsl,pins = < -- MX6QDL_PAD_NANDF_D6__GPIO2_IO06 0x80000000 -- MX6QDL_PAD_NANDF_D7__GPIO2_IO07 0x80000000 -- MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 -- MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 -- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 -- MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x80000000 -- MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 -- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x80000000 -- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 -- >; -- }; -- }; --}; -- --&ldb { -- status = "okay"; -- -- lvds-channel@0 { -- fsl,data-mapping = "spwg"; -- fsl,data-width = <18>; -- status = "okay"; -- -- display-timings { -- native-mode = <&timing0>; -- timing0: hsd100pxn1 { -- clock-frequency = <65000000>; -- hactive = <1024>; -- vactive = <768>; -- hback-porch = <220>; -- hfront-porch = <40>; -- vback-porch = <21>; -- vfront-porch = <7>; -- hsync-len = <60>; -- vsync-len = <10>; -- }; -- }; -- }; - }; - - &sata { - status = "okay"; - }; -- --&ssi1 { -- fsl,mode = "i2s-slave"; -- status = "okay"; --}; -- --&uart2 { -- status = "okay"; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart2_1>; --}; -- --&usbh1 { -- status = "okay"; --}; -- --&usbotg { -- vbus-supply = <®_usb_otg_vbus>; -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usbotg_1>; -- disable-over-current; -- status = "okay"; --}; -- --&usdhc3 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_2>; -- cd-gpios = <&gpio7 0 0>; -- wp-gpios = <&gpio7 1 0>; -- vmmc-supply = <®_3p3v>; -- status = "okay"; --}; -- --&usdhc4 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc4_2>; -- cd-gpios = <&gpio2 6 0>; -- wp-gpios = <&gpio2 7 0>; -- vmmc-supply = <®_3p3v>; -- status = "okay"; --}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabresd.dts linux-3.14.22/arch/arm/boot/dts/imx6q-sabresd.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabresd.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-sabresd.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -23,3 +23,19 @@ - &sata { - status = "okay"; - }; -+ -+&mxcfb1 { -+ status = "okay"; -+}; -+ -+&mxcfb2 { -+ status = "okay"; -+}; -+ -+&mxcfb3 { -+ status = "okay"; -+}; -+ -+&mxcfb4 { -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts linux-3.14.22/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-sabresd-hdcp.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -0,0 +1,23 @@ -+/* -+ * Copyright 2012-2013 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include "imx6q-sabresd.dts" -+ -+&hdmi_video { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_hdmi_hdcp>; -+ fsl,hdcp; -+}; -+ -+&i2c2 { -+ status = "disable"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sbc6x.dts linux-3.14.22/arch/arm/boot/dts/imx6q-sbc6x.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-sbc6x.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-sbc6x.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -17,28 +17,78 @@ - }; - }; - -+ - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_enet_1>; -+ pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - status = "okay"; - }; - -+&iomuxc { -+ imx6q-sbc6x { -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg: usbotggrp { -+ fsl,pins = < -+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ - &uart1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart1_1>; -+ pinctrl-0 = <&pinctrl_uart1>; - status = "okay"; - }; - - &usbotg { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usbotg_1>; -+ pinctrl-0 = <&pinctrl_usbotg>; - disable-over-current; - status = "okay"; - }; - - &usdhc3 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_2>; -+ pinctrl-0 = <&pinctrl_usdhc3>; - status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6q-udoo.dts linux-3.14.22/arch/arm/boot/dts/imx6q-udoo.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6q-udoo.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6q-udoo.dts 2014-10-22 14:55:49.578220001 -0500 -@@ -16,24 +16,78 @@ - model = "Udoo i.MX6 Quad Board"; - compatible = "udoo,imx6q-udoo", "fsl,imx6q"; - -+ chosen { -+ stdout-path = &uart2; -+ }; -+ - memory { - reg = <0x10000000 0x40000000>; - }; - }; - -+&fec { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_enet>; -+ phy-mode = "rgmii"; -+ status = "okay"; -+}; -+ -+&iomuxc { -+ imx6q-udoo { -+ pinctrl_enet: enetgrp { -+ fsl,pins = < -+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 -+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 -+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 -+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 -+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 -+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 -+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 -+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_uart2: uart2grp { -+ fsl,pins = < -+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 -+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ }; -+}; -+ - &sata { - status = "okay"; - }; - - &uart2 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart2_1>; -+ pinctrl-0 = <&pinctrl_uart2>; - status = "okay"; - }; - - &usdhc3 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usdhc3_2>; -+ pinctrl-0 = <&pinctrl_usdhc3>; - non-removable; - status = "okay"; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6sl.dtsi linux-3.14.22/arch/arm/boot/dts/imx6sl.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6sl.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6sl.dtsi 2014-10-22 14:55:49.582220001 -0500 -@@ -7,12 +7,14 @@ - * - */ - -+#include - #include "skeleton.dtsi" - #include "imx6sl-pinfunc.h" - #include - - / { - aliases { -+ ethernet0 = &fec; - gpio0 = &gpio1; - gpio1 = &gpio2; - gpio2 = &gpio3; -@@ -27,25 +29,46 @@ - spi1 = &ecspi2; - spi2 = &ecspi3; - spi3 = &ecspi4; -+ usbphy0 = &usbphy1; -+ usbphy1 = &usbphy2; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - -- cpu@0 { -+ cpu0: cpu@0 { - compatible = "arm,cortex-a9"; - device_type = "cpu"; - reg = <0x0>; - next-level-cache = <&L2>; -+ operating-points = < -+ /* kHz uV */ -+ 996000 1275000 -+ 792000 1175000 -+ 396000 975000 -+ >; -+ fsl,soc-operating-points = < -+ /* ARM kHz SOC-PU uV */ -+ 996000 1225000 -+ 792000 1175000 -+ 396000 1175000 -+ >; -+ clock-latency = <61036>; /* two CLK32 periods */ -+ clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>, -+ <&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_CLK_PLL1_SW>, -+ <&clks IMX6SL_CLK_PLL1_SYS>; -+ clock-names = "arm", "pll2_pfd2_396m", "step", -+ "pll1_sw", "pll1_sys"; -+ arm-supply = <®_arm>; -+ pu-supply = <®_pu>; -+ soc-supply = <®_soc>; - }; - }; - - intc: interrupt-controller@00a01000 { - compatible = "arm,cortex-a9-gic"; - #interrupt-cells = <3>; -- #address-cells = <1>; -- #size-cells = <1>; - interrupt-controller; - reg = <0x00a01000 0x1000>, - <0x00a00100 0x100>; -@@ -57,15 +80,21 @@ - - ckil { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <32768>; - }; - - osc { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; - -+ pu_dummy: pudummy_reg { -+ compatible = "fsl,imx6-dummy-pureg"; /* only used in ldo-bypass */ -+ }; -+ - soc { - #address-cells = <1>; - #size-cells = <1>; -@@ -73,19 +102,45 @@ - interrupt-parent = <&intc>; - ranges; - -+ ocram: sram@00900000 { -+ compatible = "mmio-sram"; -+ reg = <0x00900000 0x20000>; -+ clocks = <&clks IMX6SL_CLK_OCRAM>; -+ }; -+ -+ busfreq { /* BUSFREQ */ -+ compatible = "fsl,imx6_busfreq"; -+ clocks = <&clks IMX6SL_CLK_PLL2_BUS>, <&clks IMX6SL_CLK_PLL2_PFD2>, -+ <&clks IMX6SL_CLK_PLL2_198M>, <&clks IMX6SL_CLK_ARM>, -+ <&clks IMX6SL_CLK_PLL3_USB_OTG>, <&clks IMX6SL_CLK_PERIPH>, -+ <&clks IMX6SL_CLK_PRE_PERIPH_SEL>, <&clks IMX6SL_CLK_PERIPH_CLK2>, -+ <&clks IMX6SL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6SL_CLK_OSC>, -+ <&clks IMX6SL_CLK_PLL1_SYS>, <&clks IMX6SL_CLK_PERIPH2>, -+ <&clks IMX6SL_CLK_AHB>, <&clks IMX6SL_CLK_OCRAM>, -+ <&clks IMX6SL_CLK_PLL1_SW>, <&clks IMX6SL_CLK_PRE_PERIPH2_SEL>, -+ <&clks IMX6SL_CLK_PERIPH2_CLK2_SEL>, <&clks IMX6SL_CLK_PERIPH2_CLK2>, -+ <&clks IMX6SL_CLK_STEP>; -+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", -+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc", "pll1_sys", "periph2", "ahb", "ocram", "pll1_sw", -+ "periph2_pre", "periph2_clk2_sel", "periph2_clk2", "step"; -+ fsl,max_ddr_freq = <400000000>; -+ }; -+ - L2: l2-cache@00a02000 { - compatible = "arm,pl310-cache"; - reg = <0x00a02000 0x1000>; -- interrupts = <0 92 0x04>; -+ interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>; - cache-unified; - cache-level = <2>; - arm,tag-latency = <4 2 3>; - arm,data-latency = <4 2 3>; -+ arm,dynamic-clk-gating; -+ arm,standby-mode; - }; - - pmu { - compatible = "arm,cortex-a9-pmu"; -- interrupts = <0 94 0x04>; -+ interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>; - }; - - aips1: aips-bus@02000000 { -@@ -104,7 +159,7 @@ - - spdif: spdif@02004000 { - reg = <0x02004000 0x4000>; -- interrupts = <0 52 0x04>; -+ interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>; - }; - - ecspi1: ecspi@02008000 { -@@ -112,7 +167,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; - reg = <0x02008000 0x4000>; -- interrupts = <0 31 0x04>; -+ interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ECSPI1>, - <&clks IMX6SL_CLK_ECSPI1>; - clock-names = "ipg", "per"; -@@ -124,7 +179,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; - reg = <0x0200c000 0x4000>; -- interrupts = <0 32 0x04>; -+ interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ECSPI2>, - <&clks IMX6SL_CLK_ECSPI2>; - clock-names = "ipg", "per"; -@@ -136,7 +191,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; - reg = <0x02010000 0x4000>; -- interrupts = <0 33 0x04>; -+ interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ECSPI3>, - <&clks IMX6SL_CLK_ECSPI3>; - clock-names = "ipg", "per"; -@@ -148,7 +203,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-ecspi", "fsl,imx51-ecspi"; - reg = <0x02014000 0x4000>; -- interrupts = <0 34 0x04>; -+ interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ECSPI4>, - <&clks IMX6SL_CLK_ECSPI4>; - clock-names = "ipg", "per"; -@@ -159,7 +214,7 @@ - compatible = "fsl,imx6sl-uart", - "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02018000 0x4000>; -- interrupts = <0 30 0x04>; -+ interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_UART>, - <&clks IMX6SL_CLK_UART_SERIAL>; - clock-names = "ipg", "per"; -@@ -172,7 +227,7 @@ - compatible = "fsl,imx6sl-uart", - "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02020000 0x4000>; -- interrupts = <0 26 0x04>; -+ interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_UART>, - <&clks IMX6SL_CLK_UART_SERIAL>; - clock-names = "ipg", "per"; -@@ -185,7 +240,7 @@ - compatible = "fsl,imx6sl-uart", - "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02024000 0x4000>; -- interrupts = <0 27 0x04>; -+ interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_UART>, - <&clks IMX6SL_CLK_UART_SERIAL>; - clock-names = "ipg", "per"; -@@ -195,9 +250,11 @@ - }; - - ssi1: ssi@02028000 { -- compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6sl-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x02028000 0x4000>; -- interrupts = <0 46 0x04>; -+ interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_SSI1>; - dmas = <&sdma 37 1 0>, - <&sdma 38 1 0>; -@@ -207,9 +264,11 @@ - }; - - ssi2: ssi@0202c000 { -- compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6sl-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x0202c000 0x4000>; -- interrupts = <0 47 0x04>; -+ interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_SSI2>; - dmas = <&sdma 41 1 0>, - <&sdma 42 1 0>; -@@ -219,9 +278,11 @@ - }; - - ssi3: ssi@02030000 { -- compatible = "fsl,imx6sl-ssi","fsl,imx21-ssi"; -+ compatible = "fsl,imx6sl-ssi", -+ "fsl,imx51-ssi", -+ "fsl,imx21-ssi"; - reg = <0x02030000 0x4000>; -- interrupts = <0 48 0x04>; -+ interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_SSI3>; - dmas = <&sdma 45 1 0>, - <&sdma 46 1 0>; -@@ -234,7 +295,7 @@ - compatible = "fsl,imx6sl-uart", - "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02034000 0x4000>; -- interrupts = <0 28 0x04>; -+ interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_UART>, - <&clks IMX6SL_CLK_UART_SERIAL>; - clock-names = "ipg", "per"; -@@ -247,7 +308,7 @@ - compatible = "fsl,imx6sl-uart", - "fsl,imx6q-uart", "fsl,imx21-uart"; - reg = <0x02038000 0x4000>; -- interrupts = <0 29 0x04>; -+ interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_UART>, - <&clks IMX6SL_CLK_UART_SERIAL>; - clock-names = "ipg", "per"; -@@ -261,7 +322,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm"; - reg = <0x02080000 0x4000>; -- interrupts = <0 83 0x04>; -+ interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_PWM1>, - <&clks IMX6SL_CLK_PWM1>; - clock-names = "ipg", "per"; -@@ -271,7 +332,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm"; - reg = <0x02084000 0x4000>; -- interrupts = <0 84 0x04>; -+ interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_PWM2>, - <&clks IMX6SL_CLK_PWM2>; - clock-names = "ipg", "per"; -@@ -281,7 +342,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm"; - reg = <0x02088000 0x4000>; -- interrupts = <0 85 0x04>; -+ interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_PWM3>, - <&clks IMX6SL_CLK_PWM3>; - clock-names = "ipg", "per"; -@@ -291,7 +352,7 @@ - #pwm-cells = <2>; - compatible = "fsl,imx6sl-pwm", "fsl,imx27-pwm"; - reg = <0x0208c000 0x4000>; -- interrupts = <0 86 0x04>; -+ interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_PWM4>, - <&clks IMX6SL_CLK_PWM4>; - clock-names = "ipg", "per"; -@@ -300,7 +361,7 @@ - gpt: gpt@02098000 { - compatible = "fsl,imx6sl-gpt"; - reg = <0x02098000 0x4000>; -- interrupts = <0 55 0x04>; -+ interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_GPT>, - <&clks IMX6SL_CLK_GPT_SERIAL>; - clock-names = "ipg", "per"; -@@ -309,7 +370,8 @@ - gpio1: gpio@0209c000 { - compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio"; - reg = <0x0209c000 0x4000>; -- interrupts = <0 66 0x04 0 67 0x04>; -+ interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>, -+ <0 67 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -319,7 +381,8 @@ - gpio2: gpio@020a0000 { - compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio"; - reg = <0x020a0000 0x4000>; -- interrupts = <0 68 0x04 0 69 0x04>; -+ interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>, -+ <0 69 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -329,7 +392,8 @@ - gpio3: gpio@020a4000 { - compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio"; - reg = <0x020a4000 0x4000>; -- interrupts = <0 70 0x04 0 71 0x04>; -+ interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>, -+ <0 71 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -339,7 +403,8 @@ - gpio4: gpio@020a8000 { - compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio"; - reg = <0x020a8000 0x4000>; -- interrupts = <0 72 0x04 0 73 0x04>; -+ interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>, -+ <0 73 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -349,7 +414,8 @@ - gpio5: gpio@020ac000 { - compatible = "fsl,imx6sl-gpio", "fsl,imx35-gpio"; - reg = <0x020ac000 0x4000>; -- interrupts = <0 74 0x04 0 75 0x04>; -+ interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>, -+ <0 75 IRQ_TYPE_LEVEL_HIGH>; - gpio-controller; - #gpio-cells = <2>; - interrupt-controller; -@@ -357,21 +423,23 @@ - }; - - kpp: kpp@020b8000 { -+ compatible = "fsl,imx6sl-kpp", "fsl,imx21-kpp"; - reg = <0x020b8000 0x4000>; -- interrupts = <0 82 0x04>; -+ interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks IMX6SL_CLK_DUMMY>; - }; - - wdog1: wdog@020bc000 { - compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt"; - reg = <0x020bc000 0x4000>; -- interrupts = <0 80 0x04>; -+ interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_DUMMY>; - }; - - wdog2: wdog@020c0000 { - compatible = "fsl,imx6sl-wdt", "fsl,imx21-wdt"; - reg = <0x020c0000 0x4000>; -- interrupts = <0 81 0x04>; -+ interrupts = <0 81 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_DUMMY>; - status = "disabled"; - }; -@@ -379,7 +447,8 @@ - clks: ccm@020c4000 { - compatible = "fsl,imx6sl-ccm"; - reg = <0x020c4000 0x4000>; -- interrupts = <0 87 0x04 0 88 0x04>; -+ interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>, -+ <0 88 IRQ_TYPE_LEVEL_HIGH>; - #clock-cells = <1>; - }; - -@@ -388,7 +457,9 @@ - "fsl,imx6q-anatop", - "syscon", "simple-bus"; - reg = <0x020c8000 0x1000>; -- interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>; -+ interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>, -+ <0 54 IRQ_TYPE_LEVEL_HIGH>, -+ <0 127 IRQ_TYPE_LEVEL_HIGH>; - - regulator-1p1@110 { - compatible = "fsl,anatop-regulator"; -@@ -434,7 +505,7 @@ - - reg_arm: regulator-vddcore@140 { - compatible = "fsl,anatop-regulator"; -- regulator-name = "cpu"; -+ regulator-name = "vddarm"; - regulator-min-microvolt = <725000>; - regulator-max-microvolt = <1450000>; - regulator-always-on; -@@ -454,7 +525,6 @@ - regulator-name = "vddpu"; - regulator-min-microvolt = <725000>; - regulator-max-microvolt = <1450000>; -- regulator-always-on; - anatop-reg-offset = <0x140>; - anatop-vol-bit-shift = <9>; - anatop-vol-bit-width = <5>; -@@ -484,18 +554,34 @@ - }; - }; - -+ tempmon: tempmon { -+ compatible = "fsl,imx6sl-tempmon", "fsl,imx6q-tempmon"; -+ interrupts = <0 49 0x04>; -+ fsl,tempmon = <&anatop>; -+ fsl,tempmon-data = <&ocotp>; -+ clocks = <&clks IMX6SL_CLK_PLL3_USB_OTG>; -+ }; -+ - usbphy1: usbphy@020c9000 { - compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy"; - reg = <0x020c9000 0x1000>; -- interrupts = <0 44 0x04>; -+ interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USBPHY1>; -+ fsl,anatop = <&anatop>; - }; - - usbphy2: usbphy@020ca000 { - compatible = "fsl,imx6sl-usbphy", "fsl,imx23-usbphy"; - reg = <0x020ca000 0x1000>; -- interrupts = <0 45 0x04>; -+ interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USBPHY2>; -+ fsl,anatop = <&anatop>; -+ }; -+ -+ usbphy_nop1: usbphy_nop1 { -+ compatible = "usb-nop-xceiv"; -+ clocks = <&clks IMX6SL_CLK_USBPHY1>; -+ clock-names = "main_clk"; - }; - - snvs@020cc000 { -@@ -507,271 +593,165 @@ - snvs-rtc-lp@34 { - compatible = "fsl,sec-v4.0-mon-rtc-lp"; - reg = <0x34 0x58>; -- interrupts = <0 19 0x04 0 20 0x04>; -+ interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>, -+ <0 20 IRQ_TYPE_LEVEL_HIGH>; - }; -- }; -- -- epit1: epit@020d0000 { -- reg = <0x020d0000 0x4000>; -- interrupts = <0 56 0x04>; -- }; - -- epit2: epit@020d4000 { -- reg = <0x020d4000 0x4000>; -- interrupts = <0 57 0x04>; -- }; -- -- src: src@020d8000 { -- compatible = "fsl,imx6sl-src", "fsl,imx51-src"; -- reg = <0x020d8000 0x4000>; -- interrupts = <0 91 0x04 0 96 0x04>; -- #reset-cells = <1>; -- }; -- -- gpc: gpc@020dc000 { -- compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc"; -- reg = <0x020dc000 0x4000>; -- interrupts = <0 89 0x04>; -- }; -- -- gpr: iomuxc-gpr@020e0000 { -- compatible = "fsl,imx6sl-iomuxc-gpr", -- "fsl,imx6q-iomuxc-gpr", "syscon"; -- reg = <0x020e0000 0x38>; -- }; -- -- iomuxc: iomuxc@020e0000 { -- compatible = "fsl,imx6sl-iomuxc"; -- reg = <0x020e0000 0x4000>; -- -- ecspi1 { -- pinctrl_ecspi1_1: ecspi1grp-1 { -+ csi { -+ pinctrl_csi_0: csigrp-0 { - fsl,pins = < -- MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1 -- MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1 -- MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1 -+ MX6SL_PAD_EPDC_GDRL__CSI_MCLK 0x110b0 -+ MX6SL_PAD_EPDC_GDCLK__CSI_PIXCLK 0x110b0 -+ MX6SL_PAD_EPDC_GDSP__CSI_VSYNC 0x110b0 -+ MX6SL_PAD_EPDC_GDOE__CSI_HSYNC 0x110b0 -+ MX6SL_PAD_EPDC_SDLE__CSI_DATA09 0x110b0 -+ MX6SL_PAD_EPDC_SDCLK__CSI_DATA08 0x110b0 -+ MX6SL_PAD_EPDC_D7__CSI_DATA07 0x110b0 -+ MX6SL_PAD_EPDC_D6__CSI_DATA06 0x110b0 -+ MX6SL_PAD_EPDC_D5__CSI_DATA05 0x110b0 -+ MX6SL_PAD_EPDC_D4__CSI_DATA04 0x110b0 -+ MX6SL_PAD_EPDC_D3__CSI_DATA03 0x110b0 -+ MX6SL_PAD_EPDC_D2__CSI_DATA02 0x110b0 -+ MX6SL_PAD_EPDC_D1__CSI_DATA01 0x110b0 -+ MX6SL_PAD_EPDC_D0__CSI_DATA00 0x110b0 -+ MX6SL_PAD_EPDC_SDSHR__GPIO1_IO26 0x80000000 -+ MX6SL_PAD_EPDC_SDOE__GPIO1_IO25 0x80000000 - >; - }; - }; - -- fec { -- pinctrl_fec_1: fecgrp-1 { -+ i2c1 { -+ pinctrl_i2c1_1: i2c1grp-1 { - fsl,pins = < -- MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0 -- MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0 -- MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0 -- MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0 -- MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0 -- MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0 -- MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0 -- MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0 -- MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8 -+ MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1 -+ MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1 - >; - }; - }; - -- uart1 { -- pinctrl_uart1_1: uart1grp-1 { -+ i2c2 { -+ pinctrl_i2c2_1: i2c2grp-1 { - fsl,pins = < -- MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1 -- MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1 -+ MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1 -+ MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1 - >; - }; - }; - -- usbotg1 { -- pinctrl_usbotg1_1: usbotg1grp-1 { -- fsl,pins = < -- MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059 -- >; -- }; -- -- pinctrl_usbotg1_2: usbotg1grp-2 { -+ i2c3 { -+ pinctrl_i2c3_1: i2c3grp-1 { - fsl,pins = < -- MX6SL_PAD_FEC_RXD0__USB_OTG1_ID 0x17059 -- >; -- }; -- -- pinctrl_usbotg1_3: usbotg1grp-3 { -- fsl,pins = < -- MX6SL_PAD_LCD_DAT1__USB_OTG1_ID 0x17059 -- >; -- }; -- -- pinctrl_usbotg1_4: usbotg1grp-4 { -- fsl,pins = < -- MX6SL_PAD_REF_CLK_32K__USB_OTG1_ID 0x17059 -- >; -- }; -- -- pinctrl_usbotg1_5: usbotg1grp-5 { -- fsl,pins = < -- MX6SL_PAD_SD3_DAT0__USB_OTG1_ID 0x17059 -+ MX6SL_PAD_EPDC_SDCE2__I2C3_SCL 0x4001b8b1 -+ MX6SL_PAD_EPDC_SDCE3__I2C3_SDA 0x4001b8b1 - >; - }; - }; - -- usbotg2 { -- pinctrl_usbotg2_1: usbotg2grp-1 { -- fsl,pins = < -- MX6SL_PAD_ECSPI1_SCLK__USB_OTG2_OC 0x17059 -- >; -- }; -- -- pinctrl_usbotg2_2: usbotg2grp-2 { -+ lcdif { -+ pinctrl_lcdif_dat_0: lcdifdatgrp-0 { - fsl,pins = < -- MX6SL_PAD_ECSPI2_SCLK__USB_OTG2_OC 0x17059 -+ MX6SL_PAD_LCD_DAT0__LCD_DATA00 0x1b0b0 -+ MX6SL_PAD_LCD_DAT1__LCD_DATA01 0x1b0b0 -+ MX6SL_PAD_LCD_DAT2__LCD_DATA02 0x1b0b0 -+ MX6SL_PAD_LCD_DAT3__LCD_DATA03 0x1b0b0 -+ MX6SL_PAD_LCD_DAT4__LCD_DATA04 0x1b0b0 -+ MX6SL_PAD_LCD_DAT5__LCD_DATA05 0x1b0b0 -+ MX6SL_PAD_LCD_DAT6__LCD_DATA06 0x1b0b0 -+ MX6SL_PAD_LCD_DAT7__LCD_DATA07 0x1b0b0 -+ MX6SL_PAD_LCD_DAT8__LCD_DATA08 0x1b0b0 -+ MX6SL_PAD_LCD_DAT9__LCD_DATA09 0x1b0b0 -+ MX6SL_PAD_LCD_DAT10__LCD_DATA10 0x1b0b0 -+ MX6SL_PAD_LCD_DAT11__LCD_DATA11 0x1b0b0 -+ MX6SL_PAD_LCD_DAT12__LCD_DATA12 0x1b0b0 -+ MX6SL_PAD_LCD_DAT13__LCD_DATA13 0x1b0b0 -+ MX6SL_PAD_LCD_DAT14__LCD_DATA14 0x1b0b0 -+ MX6SL_PAD_LCD_DAT15__LCD_DATA15 0x1b0b0 -+ MX6SL_PAD_LCD_DAT16__LCD_DATA16 0x1b0b0 -+ MX6SL_PAD_LCD_DAT17__LCD_DATA17 0x1b0b0 -+ MX6SL_PAD_LCD_DAT18__LCD_DATA18 0x1b0b0 -+ MX6SL_PAD_LCD_DAT19__LCD_DATA19 0x1b0b0 -+ MX6SL_PAD_LCD_DAT20__LCD_DATA20 0x1b0b0 -+ MX6SL_PAD_LCD_DAT21__LCD_DATA21 0x1b0b0 -+ MX6SL_PAD_LCD_DAT22__LCD_DATA22 0x1b0b0 -+ MX6SL_PAD_LCD_DAT23__LCD_DATA23 0x1b0b0 - >; - }; - -- pinctrl_usbotg2_3: usbotg2grp-3 { -+ pinctrl_lcdif_ctrl_0: lcdifctrlgrp-0 { - fsl,pins = < -- MX6SL_PAD_KEY_ROW5__USB_OTG2_OC 0x17059 -- >; -- }; -- -- pinctrl_usbotg2_4: usbotg2grp-4 { -- fsl,pins = < -- MX6SL_PAD_SD3_DAT2__USB_OTG2_OC 0x17059 -+ MX6SL_PAD_LCD_CLK__LCD_CLK 0x1b0b0 -+ MX6SL_PAD_LCD_ENABLE__LCD_ENABLE 0x1b0b0 -+ MX6SL_PAD_LCD_HSYNC__LCD_HSYNC 0x1b0b0 -+ MX6SL_PAD_LCD_VSYNC__LCD_VSYNC 0x1b0b0 -+ MX6SL_PAD_LCD_RESET__LCD_RESET 0x1b0b0 - >; - }; - }; - -- usdhc1 { -- pinctrl_usdhc1_1: usdhc1grp-1 { -+ pwm1 { -+ pinctrl_pwm1_0: pwm1grp-0 { - fsl,pins = < -- MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059 -- MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059 -- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059 -- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059 -- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059 -- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059 -+ MX6SL_PAD_PWM1__PWM1_OUT 0x110b0 - >; - }; -- -- pinctrl_usdhc1_1_100mhz: usdhc1grp-1-100mhz { -- fsl,pins = < -- MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9 -- MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9 -- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9 -- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9 -- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9 -- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9 -- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9 -- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9 -- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9 -- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9 -- >; -- }; -- -- pinctrl_usdhc1_1_200mhz: usdhc1grp-1-200mhz { -- fsl,pins = < -- MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9 -- MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9 -- MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9 -- MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9 -- MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9 -- MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9 -- MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9 -- MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9 -- MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9 -- MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9 -- >; -- }; -- -- - }; -+ }; - -- usdhc2 { -- pinctrl_usdhc2_1: usdhc2grp-1 { -- fsl,pins = < -- MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059 -- MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059 -- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -- >; -- }; -- -- pinctrl_usdhc2_1_100mhz: usdhc2grp-1-100mhz { -- fsl,pins = < -- MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9 -- MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9 -- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 -- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 -- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 -- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9 -- >; -- }; -+ epit1: epit@020d0000 { -+ reg = <0x020d0000 0x4000>; -+ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; -+ }; - -- pinctrl_usdhc2_1_200mhz: usdhc2grp-1-200mhz { -- fsl,pins = < -- MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9 -- MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9 -- MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 -- MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 -- MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 -- MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9 -- >; -- }; -+ epit2: epit@020d4000 { -+ reg = <0x020d4000 0x4000>; -+ interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; -+ }; - -- }; -+ src: src@020d8000 { -+ compatible = "fsl,imx6sl-src", "fsl,imx51-src"; -+ reg = <0x020d8000 0x4000>; -+ interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>, -+ <0 96 IRQ_TYPE_LEVEL_HIGH>; -+ #reset-cells = <1>; -+ }; - -- usdhc3 { -- pinctrl_usdhc3_1: usdhc3grp-1 { -- fsl,pins = < -- MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059 -- MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059 -- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -- >; -- }; -+ gpc: gpc@020dc000 { -+ compatible = "fsl,imx6sl-gpc", "fsl,imx6q-gpc"; -+ reg = <0x020dc000 0x4000>; -+ interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks IMX6SL_CLK_GPU2D_PODF>, <&clks IMX6SL_CLK_GPU2D_OVG>, -+ <&clks IMX6SL_CLK_IPG>; -+ clock-names = "gpu2d_podf", "gpu2d_ovg", "ipg"; -+ pu-supply = <®_pu>; -+ }; - -- pinctrl_usdhc3_1_100mhz: usdhc3grp-1-100mhz { -- fsl,pins = < -- MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9 -- MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9 -- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9 -- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9 -- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9 -- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9 -- >; -- }; -+ gpr: iomuxc-gpr@020e0000 { -+ compatible = "fsl,imx6sl-iomuxc-gpr", -+ "fsl,imx6q-iomuxc-gpr", "syscon"; -+ reg = <0x020e0000 0x38>; -+ }; - -- pinctrl_usdhc3_1_200mhz: usdhc3grp-1-200mhz { -- fsl,pins = < -- MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9 -- MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9 -- MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9 -- MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9 -- MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9 -- MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9 -- >; -- }; -- }; -+ iomuxc: iomuxc@020e0000 { -+ compatible = "fsl,imx6sl-iomuxc"; -+ reg = <0x020e0000 0x4000>; - }; - - csi: csi@020e4000 { -+ compatible = "fsl,imx6sl-csi"; - reg = <0x020e4000 0x4000>; -- interrupts = <0 7 0x04>; -+ interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; -+ status = "disabled"; - }; - - spdc: spdc@020e8000 { - reg = <0x020e8000 0x4000>; -- interrupts = <0 6 0x04>; -+ interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>; - }; - - sdma: sdma@020ec000 { - compatible = "fsl,imx6sl-sdma", "fsl,imx35-sdma"; - reg = <0x020ec000 0x4000>; -- interrupts = <0 2 0x04>; -+ interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_SDMA>, - <&clks IMX6SL_CLK_SDMA>; - clock-names = "ipg", "ahb"; -@@ -781,23 +761,32 @@ - }; - - pxp: pxp@020f0000 { -+ compatible = "fsl,imx6sl-pxp-dma", "fsl,imx6dl-pxp-dma"; - reg = <0x020f0000 0x4000>; -- interrupts = <0 98 0x04>; -+ interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks 111>; -+ clock-names = "pxp-axi"; -+ status = "disabled"; - }; - - epdc: epdc@020f4000 { - reg = <0x020f4000 0x4000>; -- interrupts = <0 97 0x04>; -+ interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>; - }; - - lcdif: lcdif@020f8000 { -+ compatible = "fsl,imx6sl-lcdif", "fsl,imx28-lcdif"; - reg = <0x020f8000 0x4000>; -- interrupts = <0 39 0x04>; -+ interrupts = <0 39 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clks IMX6SL_CLK_LCDIF_PIX>, -+ <&clks IMX6SL_CLK_LCDIF_AXI>; -+ clock-names = "pix", "axi"; -+ status = "disabled"; - }; - - dcp: dcp@020fc000 { - reg = <0x020fc000 0x4000>; -- interrupts = <0 99 0x04>; -+ interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>; - }; - }; - -@@ -811,7 +800,7 @@ - usbotg1: usb@02184000 { - compatible = "fsl,imx6sl-usb", "fsl,imx27-usb"; - reg = <0x02184000 0x200>; -- interrupts = <0 43 0x04>; -+ interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USBOH3>; - fsl,usbphy = <&usbphy1>; - fsl,usbmisc = <&usbmisc 0>; -@@ -821,7 +810,7 @@ - usbotg2: usb@02184200 { - compatible = "fsl,imx6sl-usb", "fsl,imx27-usb"; - reg = <0x02184200 0x200>; -- interrupts = <0 42 0x04>; -+ interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USBOH3>; - fsl,usbphy = <&usbphy2>; - fsl,usbmisc = <&usbmisc 1>; -@@ -831,9 +820,12 @@ - usbh: usb@02184400 { - compatible = "fsl,imx6sl-usb", "fsl,imx27-usb"; - reg = <0x02184400 0x200>; -- interrupts = <0 40 0x04>; -+ interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USBOH3>; - fsl,usbmisc = <&usbmisc 2>; -+ phy_type = "hsic"; -+ fsl,usbphy = <&usbphy_nop1>; -+ fsl,anatop = <&anatop>; - status = "disabled"; - }; - -@@ -847,7 +839,7 @@ - fec: ethernet@02188000 { - compatible = "fsl,imx6sl-fec", "fsl,imx25-fec"; - reg = <0x02188000 0x4000>; -- interrupts = <0 114 0x04>; -+ interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ENET_REF>, - <&clks IMX6SL_CLK_ENET_REF>; - clock-names = "ipg", "ahb"; -@@ -857,7 +849,7 @@ - usdhc1: usdhc@02190000 { - compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc"; - reg = <0x02190000 0x4000>; -- interrupts = <0 22 0x04>; -+ interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USDHC1>, - <&clks IMX6SL_CLK_USDHC1>, - <&clks IMX6SL_CLK_USDHC1>; -@@ -869,7 +861,7 @@ - usdhc2: usdhc@02194000 { - compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc"; - reg = <0x02194000 0x4000>; -- interrupts = <0 23 0x04>; -+ interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USDHC2>, - <&clks IMX6SL_CLK_USDHC2>, - <&clks IMX6SL_CLK_USDHC2>; -@@ -881,7 +873,7 @@ - usdhc3: usdhc@02198000 { - compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc"; - reg = <0x02198000 0x4000>; -- interrupts = <0 24 0x04>; -+ interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USDHC3>, - <&clks IMX6SL_CLK_USDHC3>, - <&clks IMX6SL_CLK_USDHC3>; -@@ -893,7 +885,7 @@ - usdhc4: usdhc@0219c000 { - compatible = "fsl,imx6sl-usdhc", "fsl,imx6q-usdhc"; - reg = <0x0219c000 0x4000>; -- interrupts = <0 25 0x04>; -+ interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_USDHC4>, - <&clks IMX6SL_CLK_USDHC4>, - <&clks IMX6SL_CLK_USDHC4>; -@@ -907,7 +899,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c"; - reg = <0x021a0000 0x4000>; -- interrupts = <0 36 0x04>; -+ interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_I2C1>; - status = "disabled"; - }; -@@ -917,7 +909,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c"; - reg = <0x021a4000 0x4000>; -- interrupts = <0 37 0x04>; -+ interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_I2C2>; - status = "disabled"; - }; -@@ -927,7 +919,7 @@ - #size-cells = <0>; - compatible = "fsl,imx6sl-i2c", "fsl,imx21-i2c"; - reg = <0x021a8000 0x4000>; -- interrupts = <0 38 0x04>; -+ interrupts = <0 38 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_I2C3>; - status = "disabled"; - }; -@@ -939,17 +931,23 @@ - - rngb: rngb@021b4000 { - reg = <0x021b4000 0x4000>; -- interrupts = <0 5 0x04>; -+ interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>; - }; - - weim: weim@021b8000 { - reg = <0x021b8000 0x4000>; -- interrupts = <0 14 0x04>; -+ interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>; -+ }; -+ -+ ocotp: ocotp-ctrl@021bc000 { -+ compatible = "syscon"; -+ reg = <0x021bc000 0x4000>; - }; - -- ocotp: ocotp@021bc000 { -- compatible = "fsl,imx6sl-ocotp"; -+ ocotp-fuse@021bc000 { -+ compatible = "fsl,imx6sl-ocotp", "fsl,imx6q-ocotp"; - reg = <0x021bc000 0x4000>; -+ clocks = <&clks IMX6SL_CLK_OCOTP>; - }; - - audmux: audmux@021d8000 { -@@ -957,6 +955,25 @@ - reg = <0x021d8000 0x4000>; - status = "disabled"; - }; -+ -+ gpu: gpu@02200000 { -+ compatible = "fsl,imx6sl-gpu", "fsl,imx6q-gpu"; -+ reg = <0x02200000 0x4000>, <0x02204000 0x4000>, -+ <0x80000000 0x0>; -+ reg-names = "iobase_2d", "iobase_vg", -+ "phys_baseaddr"; -+ interrupts = <0 10 0x04>, <0 11 0x04>; -+ interrupt-names = "irq_2d", "irq_vg"; -+ clocks = <&clks IMX6SL_CLK_MMDC_ROOT>, -+ <&clks IMX6SL_CLK_MMDC_ROOT>, -+ <&clks IMX6SL_CLK_GPU2D_OVG>; -+ clock-names = "gpu2d_axi_clk", "openvg_axi_clk", -+ "gpu2d_clk"; -+ resets = <&src 3>, <&src 3>; -+ reset-names = "gpu2d", "gpuvg"; -+ pu-supply = <®_pu>; -+ }; -+ - }; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6sl-evk-csi.dts linux-3.14.22/arch/arm/boot/dts/imx6sl-evk-csi.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6sl-evk-csi.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/imx6sl-evk-csi.dts 2014-10-22 14:55:49.682220001 -0500 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include "imx6sl-evk.dts" -+ -+/ { -+ csi_v4l2_cap { -+ status = "okay"; -+ }; -+}; -+ -+&csi { -+ status = "okay"; -+}; -+ -+&i2c3 { -+ status = "okay"; -+}; -+ -+&epdc { -+ status = "disabled"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/imx6sl-evk.dts linux-3.14.22/arch/arm/boot/dts/imx6sl-evk.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/imx6sl-evk.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/imx6sl-evk.dts 2014-10-22 14:55:49.682220001 -0500 -@@ -8,6 +8,8 @@ - - /dts-v1/; - -+#include -+#include - #include "imx6sl.dtsi" - - / { -@@ -18,11 +20,26 @@ - reg = <0x80000000 0x40000000>; - }; - -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_led>; -+ -+ user { -+ label = "debug"; -+ gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ }; -+ - regulators { - compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <0>; - -- reg_usb_otg1_vbus: usb_otg1_vbus { -+ reg_usb_otg1_vbus: regulator@0 { - compatible = "regulator-fixed"; -+ reg = <0>; - regulator-name = "usb_otg1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; -@@ -30,22 +47,63 @@ - enable-active-high; - }; - -- reg_usb_otg2_vbus: usb_otg2_vbus { -+ reg_usb_otg2_vbus: regulator@1 { - compatible = "regulator-fixed"; -+ reg = <1>; - regulator-name = "usb_otg2_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio4 2 0>; - enable-active-high; - }; -+ -+ reg_aud3v: regulator@2 { -+ compatible = "regulator-fixed"; -+ reg = <2>; -+ regulator-name = "wm8962-supply-3v15"; -+ regulator-min-microvolt = <3150000>; -+ regulator-max-microvolt = <3150000>; -+ regulator-boot-on; -+ }; -+ -+ reg_aud4v: regulator@3 { -+ compatible = "regulator-fixed"; -+ reg = <3>; -+ regulator-name = "wm8962-supply-4v2"; -+ regulator-min-microvolt = <4325000>; -+ regulator-max-microvolt = <4325000>; -+ regulator-boot-on; -+ }; - }; -+ -+ sound { -+ compatible = "fsl,imx6sl-evk-wm8962", "fsl,imx-audio-wm8962"; -+ model = "wm8962-audio"; -+ ssi-controller = <&ssi2>; -+ audio-codec = <&codec>; -+ audio-routing = -+ "Headphone Jack", "HPOUTL", -+ "Headphone Jack", "HPOUTR", -+ "Ext Spk", "SPKOUTL", -+ "Ext Spk", "SPKOUTR", -+ "AMIC", "MICBIAS", -+ "IN3R", "AMIC"; -+ mux-int-port = <2>; -+ mux-ext-port = <3>; -+ }; -+}; -+ -+&audmux { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_audmux3>; -+ status = "okay"; - }; - - &ecspi1 { - fsl,spi-num-chipselects = <1>; - cs-gpios = <&gpio4 11 0>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_ecspi1_1>; -+ pinctrl-0 = <&pinctrl_ecspi1>; - status = "okay"; - - flash: m25p80@0 { -@@ -57,18 +115,326 @@ - }; - }; - -+&csi { -+ status = "okay"; -+}; -+ -+&cpu0 { -+ arm-supply = <&sw1a_reg>; -+ soc-supply = <&sw1c_reg>; -+ pu-supply = <&pu_dummy>; /* use pu_dummy if VDDSOC share with VDDPU */ -+}; -+ - &fec { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_fec_1>; -+ pinctrl-0 = <&pinctrl_fec>; - phy-mode = "rmii"; - status = "okay"; - }; - -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1>; -+ status = "okay"; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ regulator-always-on; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ regulators { -+ compatible = "simple-bus"; -+ -+ reg_lcd_3v3: lcd-3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "lcd-3v3"; -+ gpio = <&gpio4 3 0>; -+ enable-active-high; -+ }; -+ }; -+ -+ backlight { -+ compatible = "pwm-backlight"; -+ pwms = <&pwm1 0 5000000>; -+ brightness-levels = <0 4 8 16 32 64 128 255>; -+ default-brightness-level = <6>; -+ }; -+ -+ csi_v4l2_cap { -+ compatible = "fsl,imx6sl-csi-v4l2"; -+ status = "okay"; -+ }; -+ -+ pxp_v4l2_out { -+ compatible = "fsl,imx6sl-pxp-v4l2"; -+ status = "okay"; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2>; -+ status = "okay"; -+ -+ codec: wm8962@1a { -+ compatible = "wlf,wm8962"; -+ reg = <0x1a>; -+ clocks = <&clks IMX6SL_CLK_EXTERN_AUDIO>; -+ DCVDD-supply = <&vgen3_reg>; -+ DBVDD-supply = <®_aud3v>; -+ AVDD-supply = <&vgen3_reg>; -+ CPVDD-supply = <&vgen3_reg>; -+ MICVDD-supply = <®_aud3v>; -+ PLLVDD-supply = <&vgen3_reg>; -+ SPKVDD1-supply = <®_aud4v>; -+ SPKVDD2-supply = <®_aud4v>; -+ }; -+}; -+ -+&i2c1 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c1_1>; -+ status = "okay"; -+ -+ pmic: pfuze100@08 { -+ compatible = "fsl,pfuze100"; -+ reg = <0x08>; -+ -+ regulators { -+ sw1a_reg: sw1ab { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw1c_reg: sw1c { -+ regulator-min-microvolt = <300000>; -+ regulator-max-microvolt = <1875000>; -+ regulator-boot-on; -+ regulator-always-on; -+ regulator-ramp-delay = <6250>; -+ }; -+ -+ sw2_reg: sw2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3a_reg: sw3a { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw3b_reg: sw3b { -+ regulator-min-microvolt = <400000>; -+ regulator-max-microvolt = <1975000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ sw4_reg: sw4 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+ swbst_reg: swbst { -+ regulator-min-microvolt = <5000000>; -+ regulator-max-microvolt = <5150000>; -+ }; -+ -+ snvs_reg: vsnvs { -+ regulator-min-microvolt = <1000000>; -+ regulator-max-microvolt = <3000000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vref_reg: vrefddr { -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ vgen1_reg: vgen1 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen2_reg: vgen2 { -+ regulator-min-microvolt = <800000>; -+ regulator-max-microvolt = <1550000>; -+ }; -+ -+ vgen3_reg: vgen3 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen4_reg: vgen4 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen5_reg: vgen5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ vgen6_reg: vgen6 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ }; -+ }; -+ -+ mma8450@1c { -+ compatible = "fsl,mma8450"; -+ reg = <0x1c>; -+ }; -+}; -+ -+&i2c2 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c2_1>; -+ status = "okay"; -+}; -+ -+&i2c3 { -+ clock-frequency = <100000>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_i2c3_1>; -+ status = "okay"; -+ -+ ov564x: ov564x@3c { -+ compatible = "ovti,ov564x"; -+ reg = <0x3c>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_csi_0>; -+ clocks = <&clks IMX6SL_CLK_CSI>; -+ clock-names = "csi_mclk"; -+ AVDD-supply = <&vgen6_reg>; /* 2.8v */ -+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/ -+ pwn-gpios = <&gpio1 25 1>; -+ rst-gpios = <&gpio1 26 0>; -+ csi_id = <0>; -+ mclk = <24000000>; -+ mclk_source = <0>; -+ }; -+}; -+ - &iomuxc { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - -- hog { -+ imx6sl-evk { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6SL_PAD_KEY_ROW7__GPIO4_IO07 0x17059 -@@ -78,21 +444,270 @@ - MX6SL_PAD_REF_CLK_32K__GPIO3_IO22 0x17059 - MX6SL_PAD_KEY_COL4__GPIO4_IO00 0x80000000 - MX6SL_PAD_KEY_COL5__GPIO4_IO02 0x80000000 -+ MX6SL_PAD_AUD_MCLK__AUDIO_CLK_OUT 0x4130b0 -+ >; -+ }; -+ -+ pinctrl_audmux3: audmux3grp { -+ fsl,pins = < -+ MX6SL_PAD_AUD_RXD__AUD3_RXD 0x4130b0 -+ MX6SL_PAD_AUD_TXC__AUD3_TXC 0x4130b0 -+ MX6SL_PAD_AUD_TXD__AUD3_TXD 0x4110b0 -+ MX6SL_PAD_AUD_TXFS__AUD3_TXFS 0x4130b0 -+ >; -+ }; -+ -+ pinctrl_ecspi1: ecspi1grp { -+ fsl,pins = < -+ MX6SL_PAD_ECSPI1_MISO__ECSPI1_MISO 0x100b1 -+ MX6SL_PAD_ECSPI1_MOSI__ECSPI1_MOSI 0x100b1 -+ MX6SL_PAD_ECSPI1_SCLK__ECSPI1_SCLK 0x100b1 -+ MX6SL_PAD_ECSPI1_SS0__GPIO4_IO11 0x80000000 -+ >; -+ }; -+ -+ pinctrl_fec: fecgrp { -+ fsl,pins = < -+ MX6SL_PAD_FEC_MDC__FEC_MDC 0x1b0b0 -+ MX6SL_PAD_FEC_MDIO__FEC_MDIO 0x1b0b0 -+ MX6SL_PAD_FEC_CRS_DV__FEC_RX_DV 0x1b0b0 -+ MX6SL_PAD_FEC_RXD0__FEC_RX_DATA0 0x1b0b0 -+ MX6SL_PAD_FEC_RXD1__FEC_RX_DATA1 0x1b0b0 -+ MX6SL_PAD_FEC_TX_EN__FEC_TX_EN 0x1b0b0 -+ MX6SL_PAD_FEC_TXD0__FEC_TX_DATA0 0x1b0b0 -+ MX6SL_PAD_FEC_TXD1__FEC_TX_DATA1 0x1b0b0 -+ MX6SL_PAD_FEC_REF_CLK__FEC_REF_OUT 0x4001b0a8 -+ >; -+ }; -+ -+ pinctrl_i2c1: i2c1grp { -+ fsl,pins = < -+ MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001b8b1 -+ MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ -+ pinctrl_i2c2: i2c2grp { -+ fsl,pins = < -+ MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001b8b1 -+ MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001b8b1 -+ >; -+ }; -+ -+ pinctrl_led: ledgrp { -+ fsl,pins = < -+ MX6SL_PAD_HSIC_STROBE__GPIO3_IO20 0x17059 -+ >; -+ }; -+ -+ pinctrl_kpp: kppgrp { -+ fsl,pins = < -+ MX6SL_PAD_KEY_ROW0__KEY_ROW0 0x1b010 -+ MX6SL_PAD_KEY_ROW1__KEY_ROW1 0x1b010 -+ MX6SL_PAD_KEY_ROW2__KEY_ROW2 0x1b0b0 -+ MX6SL_PAD_KEY_COL0__KEY_COL0 0x110b0 -+ MX6SL_PAD_KEY_COL1__KEY_COL1 0x110b0 -+ MX6SL_PAD_KEY_COL2__KEY_COL2 0x110b0 -+ >; -+ }; -+ -+ pinctrl_uart1: uart1grp { -+ fsl,pins = < -+ MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1 -+ MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1 -+ >; -+ }; -+ -+ pinctrl_usbotg1: usbotg1grp { -+ fsl,pins = < -+ MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc1: usdhc1grp { -+ fsl,pins = < -+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x17059 -+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x10059 -+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x17059 -+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x17059 -+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x17059 -+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x17059 -+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x17059 -+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x17059 -+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x17059 -+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x170b9 -+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x100b9 -+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170b9 -+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170b9 -+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170b9 -+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170b9 -+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170b9 -+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170b9 -+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170b9 -+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170b9 -+ >; -+ }; -+ -+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD1_CMD__SD1_CMD 0x170f9 -+ MX6SL_PAD_SD1_CLK__SD1_CLK 0x100f9 -+ MX6SL_PAD_SD1_DAT0__SD1_DATA0 0x170f9 -+ MX6SL_PAD_SD1_DAT1__SD1_DATA1 0x170f9 -+ MX6SL_PAD_SD1_DAT2__SD1_DATA2 0x170f9 -+ MX6SL_PAD_SD1_DAT3__SD1_DATA3 0x170f9 -+ MX6SL_PAD_SD1_DAT4__SD1_DATA4 0x170f9 -+ MX6SL_PAD_SD1_DAT5__SD1_DATA5 0x170f9 -+ MX6SL_PAD_SD1_DAT6__SD1_DATA6 0x170f9 -+ MX6SL_PAD_SD1_DAT7__SD1_DATA7 0x170f9 -+ >; -+ }; -+ -+ pinctrl_usdhc2: usdhc2grp { -+ fsl,pins = < -+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059 -+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x10059 -+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059 -+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059 -+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059 -+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9 -+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x100b9 -+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 -+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 -+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 -+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9 -+ >; -+ }; -+ -+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9 -+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x100f9 -+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 -+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 -+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 -+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9 -+ >; -+ }; -+ -+ pinctrl_usdhc3: usdhc3grp { -+ fsl,pins = < -+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x17059 -+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x10059 -+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x17059 -+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x17059 -+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x17059 -+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x17059 -+ >; -+ }; -+ -+ pinctrl_usdhc3_100mhz: usdhc3grp100mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9 -+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x100b9 -+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9 -+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9 -+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9 -+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9 -+ >; -+ }; -+ -+ pinctrl_usdhc3_200mhz: usdhc3grp200mhz { -+ fsl,pins = < -+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9 -+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x100f9 -+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9 -+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9 -+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9 -+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9 - >; - }; - }; - }; - -+&kpp { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_kpp>; -+ linux,keymap = < -+ MATRIX_KEY(0x0, 0x0, KEY_UP) /* ROW0, COL0 */ -+ MATRIX_KEY(0x0, 0x1, KEY_DOWN) /* ROW0, COL1 */ -+ MATRIX_KEY(0x0, 0x2, KEY_ENTER) /* ROW0, COL2 */ -+ MATRIX_KEY(0x1, 0x0, KEY_HOME) /* ROW1, COL0 */ -+ MATRIX_KEY(0x1, 0x1, KEY_RIGHT) /* ROW1, COL1 */ -+ MATRIX_KEY(0x1, 0x2, KEY_LEFT) /* ROW1, COL2 */ -+ MATRIX_KEY(0x2, 0x0, KEY_VOLUMEDOWN) /* ROW2, COL0 */ -+ MATRIX_KEY(0x2, 0x1, KEY_VOLUMEUP) /* ROW2, COL1 */ -+ >; -+ status = "okay"; -+}; -+ -+&ssi2 { -+ fsl,mode = "i2s-slave"; -+ status = "okay"; -+}; -+ -+&lcdif { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_lcdif_dat_0 -+ &pinctrl_lcdif_ctrl_0>; -+ lcd-supply = <®_lcd_3v3>; -+ display = <&display>; -+ status = "okay"; -+ -+ display: display { -+ bits-per-pixel = <16>; -+ bus-width = <24>; -+ -+ display-timings { -+ native-mode = <&timing0>; -+ timing0: timing0 { -+ clock-frequency = <33500000>; -+ hactive = <800>; -+ vactive = <480>; -+ hback-porch = <89>; -+ hfront-porch = <164>; -+ vback-porch = <23>; -+ vfront-porch = <10>; -+ hsync-len = <10>; -+ vsync-len = <10>; -+ hsync-active = <0>; -+ vsync-active = <0>; -+ de-active = <1>; -+ pixelclk-active = <0>; -+ }; -+ }; -+ }; -+}; -+ -+&pwm1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_pwm1_0>; -+ status = "okay"; -+}; -+ - &uart1 { - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_uart1_1>; -+ pinctrl-0 = <&pinctrl_uart1>; - status = "okay"; - }; - - &usbotg1 { - vbus-supply = <®_usb_otg1_vbus>; - pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_usbotg1_1>; -+ pinctrl-0 = <&pinctrl_usbotg1>; - disable-over-current; - status = "okay"; - }; -@@ -106,9 +721,9 @@ - - &usdhc1 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; -- pinctrl-0 = <&pinctrl_usdhc1_1>; -- pinctrl-1 = <&pinctrl_usdhc1_1_100mhz>; -- pinctrl-2 = <&pinctrl_usdhc1_1_200mhz>; -+ pinctrl-0 = <&pinctrl_usdhc1>; -+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>; -+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>; - bus-width = <8>; - cd-gpios = <&gpio4 7 0>; - wp-gpios = <&gpio4 6 0>; -@@ -117,9 +732,9 @@ - - &usdhc2 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; -- pinctrl-0 = <&pinctrl_usdhc2_1>; -- pinctrl-1 = <&pinctrl_usdhc2_1_100mhz>; -- pinctrl-2 = <&pinctrl_usdhc2_1_200mhz>; -+ pinctrl-0 = <&pinctrl_usdhc2>; -+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>; -+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>; - cd-gpios = <&gpio5 0 0>; - wp-gpios = <&gpio4 29 0>; - status = "okay"; -@@ -127,9 +742,26 @@ - - &usdhc3 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; -- pinctrl-0 = <&pinctrl_usdhc3_1>; -- pinctrl-1 = <&pinctrl_usdhc3_1_100mhz>; -- pinctrl-2 = <&pinctrl_usdhc3_1_200mhz>; -+ pinctrl-0 = <&pinctrl_usdhc3>; -+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>; -+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>; - cd-gpios = <&gpio3 22 0>; - status = "okay"; - }; -+ -+&pxp { -+ status = "okay"; -+}; -+ -+&gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+ fsl,ldo-bypass; /* use ldo-bypass, u-boot will check it and configure */ -+ pu-supply = <&pu_dummy>; /* ldo-bypass:use pu_dummy if VDDSOC share with VDDPU */ -+}; -+ -+&gpu { -+ pu-supply = <&pu_dummy>; /* ldo-bypass:use pu_dummy if VDDSOC share with VDDPU */ -+}; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/Makefile linux-3.14.22/arch/arm/boot/dts/Makefile ---- linux-3.14.22.orig/arch/arm/boot/dts/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/Makefile 2014-10-22 14:55:49.682220001 -0500 -@@ -154,16 +154,37 @@ - imx53-qsb.dtb \ - imx53-smd.dtb \ - imx6dl-cubox-i.dtb \ -+ imx6dl-dfi-fs700-m60.dtb \ -+ imx6dl-gw51xx.dtb \ -+ imx6dl-gw52xx.dtb \ -+ imx6dl-gw53xx.dtb \ -+ imx6dl-gw54xx.dtb \ - imx6dl-hummingboard.dtb \ -+ imx6dl-nitrogen6x.dtb \ -+ imx6dl-phytec-pbab01.dtb \ - imx6dl-sabreauto.dtb \ -+ imx6dl-sabrelite.dtb \ - imx6dl-sabresd.dtb \ -+ imx6dl-sabresd-hdcp.dtb \ - imx6dl-wandboard.dtb \ - imx6q-arm2.dtb \ -+ imx6q-cm-fx6.dtb \ - imx6q-cubox-i.dtb \ -+ imx6q-hummingboard.dtb \ -+ imx6q-dfi-fs700-m60.dtb \ -+ imx6q-dmo-edmqmx6.dtb \ -+ imx6q-gk802.dtb \ -+ imx6q-gw51xx.dtb \ -+ imx6q-gw52xx.dtb \ -+ imx6q-gw53xx.dtb \ -+ imx6q-gw5400-a.dtb \ -+ imx6q-gw54xx.dtb \ -+ imx6q-nitrogen6x.dtb \ - imx6q-phytec-pbab01.dtb \ - imx6q-sabreauto.dtb \ - imx6q-sabrelite.dtb \ - imx6q-sabresd.dtb \ -+ imx6q-sabresd-hdcp.dtb \ - imx6q-sbc6x.dtb \ - imx6q-udoo.dtb \ - imx6q-wandboard.dtb \ -@@ -312,7 +333,14 @@ - dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ - vexpress-v2p-ca9.dtb \ - vexpress-v2p-ca15-tc1.dtb \ -- vexpress-v2p-ca15_a7.dtb -+ vexpress-v2p-ca15_a7.dtb \ -+ rtsm_ve-cortex_a9x2.dtb \ -+ rtsm_ve-cortex_a9x4.dtb \ -+ rtsm_ve-cortex_a15x1.dtb \ -+ rtsm_ve-cortex_a15x2.dtb \ -+ rtsm_ve-cortex_a15x4.dtb \ -+ rtsm_ve-v2p-ca15x1-ca7x1.dtb \ -+ rtsm_ve-v2p-ca15x4-ca7x4.dtb - dtb-$(CONFIG_ARCH_VIRT) += xenvm-4.2.dtb - dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ - wm8505-ref.dtb \ -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/marco.dtsi linux-3.14.22/arch/arm/boot/dts/marco.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/marco.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/marco.dtsi 2014-10-22 14:55:49.682220001 -0500 -@@ -36,7 +36,7 @@ - ranges = <0x40000000 0x40000000 0xa0000000>; - - l2-cache-controller@c0030000 { -- compatible = "sirf,marco-pl310-cache", "arm,pl310-cache"; -+ compatible = "arm,pl310-cache"; - reg = <0xc0030000 0x1000>; - interrupts = <0 59 0>; - arm,tag-latency = <1 1 1>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/prima2.dtsi linux-3.14.22/arch/arm/boot/dts/prima2.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/prima2.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/prima2.dtsi 2014-10-22 14:55:49.686220001 -0500 -@@ -48,7 +48,7 @@ - ranges = <0x40000000 0x40000000 0x80000000>; - - l2-cache-controller@80040000 { -- compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache"; -+ compatible = "arm,pl310-cache"; - reg = <0x80040000 0x1000>; - interrupts = <59>; - arm,tag-latency = <1 1 1>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x1.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,159 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA15x1CT -+ * -+ * RTSM_VE_Cortex_A15x1.lisa -+ */ -+ -+/dts-v1/; -+ -+/ { -+ model = "RTSM_VE_CortexA15x1"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a15x1", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0 0x80000000 0 0x80000000>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0 0x2c001000 0 0x1000>, -+ <0 0x2c002000 0 0x1000>, -+ <0 0x2c004000 0 0x2000>, -+ <0 0x2c006000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 13 0xf08>, -+ <1 14 0xf08>, -+ <1 11 0xf08>, -+ <1 10 0xf08>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x2.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,165 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA15x2CT -+ * -+ * RTSM_VE_Cortex_A15x2.lisa -+ */ -+ -+/dts-v1/; -+ -+/ { -+ model = "RTSM_VE_CortexA15x2"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a15x2", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <1>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0 0x80000000 0 0x80000000>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0 0x2c001000 0 0x1000>, -+ <0 0x2c002000 0 0x1000>, -+ <0 0x2c004000 0 0x2000>, -+ <0 0x2c006000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 13 0xf08>, -+ <1 14 0xf08>, -+ <1 11 0xf08>, -+ <1 10 0xf08>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a15x4.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,177 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA15x4CT -+ * -+ * RTSM_VE_Cortex_A15x4.lisa -+ */ -+ -+/dts-v1/; -+ -+/ { -+ model = "RTSM_VE_CortexA15x4"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a15x4", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <1>; -+ }; -+ -+ cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <2>; -+ }; -+ -+ cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <3>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0 0x80000000 0 0x80000000>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0 0x2c001000 0 0x1000>, -+ <0 0x2c002000 0 0x1000>, -+ <0 0x2c004000 0 0x2000>, -+ <0 0x2c006000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 13 0xf08>, -+ <1 14 0xf08>, -+ <1 11 0xf08>, -+ <1 10 0xf08>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a9x2.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,171 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA9MPx2CT -+ * -+ * RTSM_VE_Cortex_A9x2.lisa -+ */ -+ -+/dts-v1/; -+ -+/ { -+ model = "RTSM_VE_CortexA9x2"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a9x2", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <1>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x80000000 0x80000000>; -+ }; -+ -+ scu@2c000000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x2c000000 0x58>; -+ }; -+ -+ timer@2c000600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x2c000600 0x20>; -+ interrupts = <1 13 0xf04>; -+ }; -+ -+ watchdog@2c000620 { -+ compatible = "arm,cortex-a9-twd-wdt"; -+ reg = <0x2c000620 0x20>; -+ interrupts = <1 14 0xf04>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x2c001000 0x1000>, -+ <0x2c000100 0x100>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0x08000000 0x04000000>, -+ <1 0 0x14000000 0x04000000>, -+ <2 0 0x18000000 0x04000000>, -+ <3 0 0x1c000000 0x04000000>, -+ <4 0 0x0c000000 0x04000000>, -+ <5 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-cortex_a9x4.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,183 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA9MPx4CT -+ * -+ * RTSM_VE_Cortex_A9x4.lisa -+ */ -+ -+/dts-v1/; -+ -+/ { -+ model = "RTSM_VE_CortexA9x4"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a9x4", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <1>; -+ }; -+ -+ cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <2>; -+ }; -+ -+ cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ reg = <3>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x80000000 0x80000000>; -+ }; -+ -+ scu@2c000000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x2c000000 0x58>; -+ }; -+ -+ timer@2c000600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x2c000600 0x20>; -+ interrupts = <1 13 0xf04>; -+ }; -+ -+ watchdog@2c000620 { -+ compatible = "arm,cortex-a9-twd-wdt"; -+ reg = <0x2c000620 0x20>; -+ interrupts = <1 14 0xf04>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x2c001000 0x1000>, -+ <0x2c000100 0x100>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0x08000000 0x04000000>, -+ <1 0 0x14000000 0x04000000>, -+ <2 0 0x18000000 0x04000000>, -+ <3 0 0x1c000000 0x04000000>, -+ <4 0 0x0c000000 0x04000000>, -+ <5 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi linux-3.14.22/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-motherboard.dtsi 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,231 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * Motherboard component -+ * -+ * VEMotherBoard.lisa -+ */ -+ -+ motherboard { -+ compatible = "arm,vexpress,v2m-p1", "simple-bus"; -+ arm,hbi = <0x190>; -+ arm,vexpress,site = <0>; -+ arm,v2m-memory-map = "rs1"; -+ #address-cells = <2>; /* SMB chipselect number and offset */ -+ #size-cells = <1>; -+ #interrupt-cells = <1>; -+ ranges; -+ -+ flash@0,00000000 { -+ compatible = "arm,vexpress-flash", "cfi-flash"; -+ reg = <0 0x00000000 0x04000000>, -+ <4 0x00000000 0x04000000>; -+ bank-width = <4>; -+ }; -+ -+ vram@2,00000000 { -+ compatible = "arm,vexpress-vram"; -+ reg = <2 0x00000000 0x00800000>; -+ }; -+ -+ ethernet@2,02000000 { -+ compatible = "smsc,lan91c111"; -+ reg = <2 0x02000000 0x10000>; -+ interrupts = <15>; -+ }; -+ -+ iofpga@3,00000000 { -+ compatible = "arm,amba-bus", "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 3 0 0x200000>; -+ -+ v2m_sysreg: sysreg@010000 { -+ compatible = "arm,vexpress-sysreg"; -+ reg = <0x010000 0x1000>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ -+ v2m_sysctl: sysctl@020000 { -+ compatible = "arm,sp810", "arm,primecell"; -+ reg = <0x020000 0x1000>; -+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>; -+ clock-names = "refclk", "timclk", "apb_pclk"; -+ #clock-cells = <1>; -+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; -+ }; -+ -+ aaci@040000 { -+ compatible = "arm,pl041", "arm,primecell"; -+ reg = <0x040000 0x1000>; -+ interrupts = <11>; -+ clocks = <&smbclk>; -+ clock-names = "apb_pclk"; -+ }; -+ -+ mmci@050000 { -+ compatible = "arm,pl180", "arm,primecell"; -+ reg = <0x050000 0x1000>; -+ interrupts = <9 10>; -+ cd-gpios = <&v2m_sysreg 0 0>; -+ wp-gpios = <&v2m_sysreg 1 0>; -+ max-frequency = <12000000>; -+ vmmc-supply = <&v2m_fixed_3v3>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "mclk", "apb_pclk"; -+ }; -+ -+ kmi@060000 { -+ compatible = "arm,pl050", "arm,primecell"; -+ reg = <0x060000 0x1000>; -+ interrupts = <12>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "KMIREFCLK", "apb_pclk"; -+ }; -+ -+ kmi@070000 { -+ compatible = "arm,pl050", "arm,primecell"; -+ reg = <0x070000 0x1000>; -+ interrupts = <13>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "KMIREFCLK", "apb_pclk"; -+ }; -+ -+ v2m_serial0: uart@090000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x090000 0x1000>; -+ interrupts = <5>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "uartclk", "apb_pclk"; -+ }; -+ -+ v2m_serial1: uart@0a0000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x0a0000 0x1000>; -+ interrupts = <6>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "uartclk", "apb_pclk"; -+ }; -+ -+ v2m_serial2: uart@0b0000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x0b0000 0x1000>; -+ interrupts = <7>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "uartclk", "apb_pclk"; -+ }; -+ -+ v2m_serial3: uart@0c0000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x0c0000 0x1000>; -+ interrupts = <8>; -+ clocks = <&v2m_clk24mhz>, <&smbclk>; -+ clock-names = "uartclk", "apb_pclk"; -+ }; -+ -+ wdt@0f0000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = <0x0f0000 0x1000>; -+ interrupts = <0>; -+ clocks = <&v2m_refclk32khz>, <&smbclk>; -+ clock-names = "wdogclk", "apb_pclk"; -+ }; -+ -+ v2m_timer01: timer@110000 { -+ compatible = "arm,sp804", "arm,primecell"; -+ reg = <0x110000 0x1000>; -+ interrupts = <2>; -+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>; -+ clock-names = "timclken1", "timclken2", "apb_pclk"; -+ }; -+ -+ v2m_timer23: timer@120000 { -+ compatible = "arm,sp804", "arm,primecell"; -+ reg = <0x120000 0x1000>; -+ interrupts = <3>; -+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>; -+ clock-names = "timclken1", "timclken2", "apb_pclk"; -+ }; -+ -+ rtc@170000 { -+ compatible = "arm,pl031", "arm,primecell"; -+ reg = <0x170000 0x1000>; -+ interrupts = <4>; -+ clocks = <&smbclk>; -+ clock-names = "apb_pclk"; -+ }; -+ -+ clcd@1f0000 { -+ compatible = "arm,pl111", "arm,primecell"; -+ reg = <0x1f0000 0x1000>; -+ interrupts = <14>; -+ clocks = <&v2m_oscclk1>, <&smbclk>; -+ clock-names = "v2m:oscclk1", "apb_pclk"; -+ mode = "VGA"; -+ use_dma = <0>; -+ framebuffer = <0x18000000 0x00180000>; -+ }; -+ -+ virtio_block@0130000 { -+ compatible = "virtio,mmio"; -+ reg = <0x130000 0x200>; -+ interrupts = <42>; -+ }; -+ -+ }; -+ -+ v2m_fixed_3v3: fixedregulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "3V3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ v2m_clk24mhz: clk24mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ clock-output-names = "v2m:clk24mhz"; -+ }; -+ -+ v2m_refclk1mhz: refclk1mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <1000000>; -+ clock-output-names = "v2m:refclk1mhz"; -+ }; -+ -+ v2m_refclk32khz: refclk32khz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <32768>; -+ clock-output-names = "v2m:refclk32khz"; -+ }; -+ -+ mcc { -+ compatible = "simple-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ v2m_oscclk1: osc@1 { -+ /* CLCD clock */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <23750000 63500000>; -+ #clock-cells = <0>; -+ clock-output-names = "v2m:oscclk1"; -+ }; -+ -+ muxfpga@0 { -+ compatible = "arm,vexpress-muxfpga"; -+ arm,vexpress-sysreg,func = <7 0>; -+ }; -+ -+ shutdown@0 { -+ compatible = "arm,vexpress-shutdown"; -+ arm,vexpress-sysreg,func = <8 0>; -+ }; -+ }; -+ }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-v2p-ca15x1-ca7x1.dts 2014-10-22 14:55:49.686220001 -0500 -@@ -0,0 +1,233 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA15x4CT -+ * ARMCortexA7x4CT -+ * RTSM_VE_Cortex_A15x1_A7x1.lisa -+ */ -+ -+/dts-v1/; -+ -+/memreserve/ 0xff000000 0x01000000; -+ -+/ { -+ model = "RTSM_VE_CortexA15x1-A7x1"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a15x1_a7x1", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ clusters { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cluster0: cluster@0 { -+ reg = <0>; -+// freqs = <500000000 600000000 700000000 800000000 900000000 1000000000 1100000000 1200000000>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core0: core@0 { -+ reg = <0>; -+ }; -+ -+ }; -+ }; -+ -+ cluster1: cluster@1 { -+ reg = <1>; -+// freqs = <350000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core1: core@0 { -+ reg = <0>; -+ }; -+ -+ }; -+ }; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ cluster = <&cluster0>; -+ core = <&core0>; -+// clock-frequency = <1000000000>; -+ cci-control-port = <&cci_control1>; -+ }; -+ -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0x100>; -+ cluster = <&cluster1>; -+ core = <&core1>; -+// clock-frequency = <800000000>; -+ cci-control-port = <&cci_control2>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0 0x80000000 0 0x80000000>; -+ }; -+ -+ cci@2c090000 { -+ compatible = "arm,cci-400", "arm,cci"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0 0x2c090000 0 0x1000>; -+ ranges = <0x0 0x0 0x2c090000 0x10000>; -+ -+ cci_control1: slave-if@4000 { -+ compatible = "arm,cci-400-ctrl-if"; -+ interface-type = "ace"; -+ reg = <0x4000 0x1000>; -+ }; -+ -+ cci_control2: slave-if@5000 { -+ compatible = "arm,cci-400-ctrl-if"; -+ interface-type = "ace"; -+ reg = <0x5000 0x1000>; -+ }; -+ }; -+ -+ dcscb@60000000 { -+ compatible = "arm,rtsm,dcscb"; -+ reg = <0 0x60000000 0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0 0x2c001000 0 0x1000>, -+ <0 0x2c002000 0 0x1000>, -+ <0 0x2c004000 0 0x2000>, -+ <0 0x2c006000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 13 0xf08>, -+ <1 14 0xf08>, -+ <1 11 0xf08>, -+ <1 10 0xf08>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts linux-3.14.22/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/boot/dts/rtsm_ve-v2p-ca15x4-ca7x4.dts 2014-10-22 14:55:49.690220001 -0500 -@@ -0,0 +1,317 @@ -+/* -+ * ARM Ltd. Fast Models -+ * -+ * Versatile Express (VE) system model -+ * ARMCortexA15x4CT -+ * ARMCortexA7x4CT -+ * RTSM_VE_Cortex_A15x4_A7x4.lisa -+ */ -+ -+/dts-v1/; -+ -+/memreserve/ 0xff000000 0x01000000; -+ -+/ { -+ model = "RTSM_VE_CortexA15x4-A7x4"; -+ arm,vexpress,site = <0xf>; -+ compatible = "arm,rtsm_ve,cortex_a15x4_a7x4", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ clusters { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cluster0: cluster@0 { -+ reg = <0>; -+// freqs = <500000000 600000000 700000000 800000000 900000000 1000000000 1100000000 1200000000>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core0: core@0 { -+ reg = <0>; -+ }; -+ -+ core1: core@1 { -+ reg = <1>; -+ }; -+ -+ core2: core@2 { -+ reg = <2>; -+ }; -+ -+ core3: core@3 { -+ reg = <3>; -+ }; -+ -+ }; -+ }; -+ -+ cluster1: cluster@1 { -+ reg = <1>; -+// freqs = <350000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core4: core@0 { -+ reg = <0>; -+ }; -+ -+ core5: core@1 { -+ reg = <1>; -+ }; -+ -+ core6: core@2 { -+ reg = <2>; -+ }; -+ -+ core7: core@3 { -+ reg = <3>; -+ }; -+ -+ }; -+ }; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ cluster = <&cluster0>; -+ core = <&core0>; -+// clock-frequency = <1000000000>; -+ cci-control-port = <&cci_control1>; -+ }; -+ -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <1>; -+ cluster = <&cluster0>; -+ core = <&core1>; -+// clock-frequency = <1000000000>; -+ cci-control-port = <&cci_control1>; -+ }; -+ -+ cpu2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <2>; -+ cluster = <&cluster0>; -+ core = <&core2>; -+// clock-frequency = <1000000000>; -+ cci-control-port = <&cci_control1>; -+ }; -+ -+ cpu3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <3>; -+ cluster = <&cluster0>; -+ core = <&core3>; -+// clock-frequency = <1000000000>; -+ cci-control-port = <&cci_control1>; -+ }; -+ -+ cpu4: cpu@4 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0x100>; -+ cluster = <&cluster1>; -+ core = <&core4>; -+// clock-frequency = <800000000>; -+ cci-control-port = <&cci_control2>; -+ }; -+ -+ cpu5: cpu@5 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0x101>; -+ cluster = <&cluster1>; -+ core = <&core5>; -+// clock-frequency = <800000000>; -+ cci-control-port = <&cci_control2>; -+ }; -+ -+ cpu6: cpu@6 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0x102>; -+ cluster = <&cluster1>; -+ core = <&core6>; -+// clock-frequency = <800000000>; -+ cci-control-port = <&cci_control2>; -+ }; -+ -+ cpu7: cpu@7 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a7"; -+ reg = <0x103>; -+ cluster = <&cluster1>; -+ core = <&core7>; -+// clock-frequency = <800000000>; -+ cci-control-port = <&cci_control2>; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0 0x80000000 0 0x80000000>; -+ }; -+ -+ cci@2c090000 { -+ compatible = "arm,cci-400", "arm,cci"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ reg = <0 0x2c090000 0 0x1000>; -+ ranges = <0x0 0x0 0x2c090000 0x10000>; -+ -+ cci_control1: slave-if@4000 { -+ compatible = "arm,cci-400-ctrl-if"; -+ interface-type = "ace"; -+ reg = <0x4000 0x1000>; -+ }; -+ -+ cci_control2: slave-if@5000 { -+ compatible = "arm,cci-400-ctrl-if"; -+ interface-type = "ace"; -+ reg = <0x5000 0x1000>; -+ }; -+ }; -+ -+ dcscb@60000000 { -+ compatible = "arm,rtsm,dcscb"; -+ reg = <0 0x60000000 0 0x1000>; -+ }; -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0 0x2c001000 0 0x1000>, -+ <0 0x2c002000 0 0x1000>, -+ <0 0x2c004000 0 0x2000>, -+ <0 0x2c006000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv7-timer"; -+ interrupts = <1 13 0xf08>, -+ <1 14 0xf08>, -+ <1 11 0xf08>, -+ <1 10 0xf08>; -+ }; -+ -+ dcc { -+ compatible = "arm,vexpress,config-bus"; -+ arm,vexpress,config-bridge = <&v2m_sysreg>; -+ -+ osc@0 { -+ /* ACLK clock to the AXI master port on the test chip */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 0>; -+ freq-range = <30000000 50000000>; -+ #clock-cells = <0>; -+ clock-output-names = "extsaxiclk"; -+ }; -+ -+ oscclk1: osc@1 { -+ /* Reference clock for the CLCD */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 1>; -+ freq-range = <10000000 80000000>; -+ #clock-cells = <0>; -+ clock-output-names = "clcdclk"; -+ }; -+ -+ smbclk: oscclk2: osc@2 { -+ /* Reference clock for the test chip internal PLLs */ -+ compatible = "arm,vexpress-osc"; -+ arm,vexpress-sysreg,func = <1 2>; -+ freq-range = <33000000 100000000>; -+ #clock-cells = <0>; -+ clock-output-names = "tcrefclk"; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2m.dtsi linux-3.14.22/arch/arm/boot/dts/vexpress-v2m.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2m.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2m.dtsi 2014-10-22 14:55:49.690220001 -0500 -@@ -227,6 +227,7 @@ - }; - - clcd@1f000 { -+ status = "disabled"; - compatible = "arm,pl111", "arm,primecell"; - reg = <0x1f000 0x1000>; - interrupts = <14>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi linux-3.14.22/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi 2014-10-22 14:55:49.690220001 -0500 -@@ -228,6 +228,7 @@ - }; - - clcd@1f0000 { -+ status = "disabled"; - compatible = "arm,pl111", "arm,primecell"; - reg = <0x1f0000 0x1000>; - interrupts = <14>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts 2014-10-22 14:55:49.690220001 -0500 -@@ -9,6 +9,8 @@ - - /dts-v1/; - -+/memreserve/ 0xff000000 0x01000000; -+ - / { - model = "V2P-CA15_CA7"; - arm,hbi = <0x249>; -@@ -29,29 +31,60 @@ - i2c1 = &v2m_i2c_pcie; - }; - -- cpus { -+ clusters { - #address-cells = <1>; - #size-cells = <0>; - -- cpu0: cpu@0 { -- device_type = "cpu"; -- compatible = "arm,cortex-a15"; -+ cluster0: cluster@0 { - reg = <0>; -- cci-control-port = <&cci_control1>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core0: core@0 { -+ reg = <0>; -+ }; -+ -+ core1: core@1 { -+ reg = <1>; -+ }; -+ -+ }; - }; - -- cpu1: cpu@1 { -- device_type = "cpu"; -- compatible = "arm,cortex-a15"; -+ cluster1: cluster@1 { - reg = <1>; -- cci-control-port = <&cci_control1>; -+ cores { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ core2: core@0 { -+ reg = <0>; -+ }; -+ -+ core3: core@1 { -+ reg = <1>; -+ }; -+ -+ core4: core@2 { -+ reg = <2>; -+ }; -+ }; - }; -+ }; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; - - cpu2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x100>; - cci-control-port = <&cci_control2>; -+ cluster = <&cluster1>; -+ core = <&core2>; -+ clock-frequency = <800000000>; - }; - - cpu3: cpu@3 { -@@ -59,6 +92,9 @@ - compatible = "arm,cortex-a7"; - reg = <0x101>; - cci-control-port = <&cci_control2>; -+ cluster = <&cluster1>; -+ core = <&core3>; -+ clock-frequency = <800000000>; - }; - - cpu4: cpu@4 { -@@ -66,12 +102,35 @@ - compatible = "arm,cortex-a7"; - reg = <0x102>; - cci-control-port = <&cci_control2>; -+ cluster = <&cluster1>; -+ core = <&core4>; -+ clock-frequency = <800000000>; -+ }; -+ -+ cpu0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <0>; -+ cci-control-port = <&cci_control1>; -+ cluster = <&cluster0>; -+ core = <&core0>; -+ clock-frequency = <1000000000>; -+ }; -+ -+ cpu1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a15"; -+ reg = <1>; -+ cci-control-port = <&cci_control1>; -+ cluster = <&cluster0>; -+ core = <&core1>; -+ clock-frequency = <1000000000>; - }; - }; - - memory@80000000 { - device_type = "memory"; -- reg = <0 0x80000000 0 0x40000000>; -+ reg = <0 0x80000000 0 0x80000000>; - }; - - wdt@2a490000 { -@@ -86,6 +145,8 @@ - compatible = "arm,hdlcd"; - reg = <0 0x2b000000 0 0x1000>; - interrupts = <0 85 4>; -+ mode = "1024x768-16@60"; -+ framebuffer = <0 0xff000000 0 0x01000000>; - clocks = <&oscclk5>; - clock-names = "pxlclk"; - }; -@@ -127,6 +188,16 @@ - interface-type = "ace"; - reg = <0x5000 0x1000>; - }; -+ -+ pmu@9000 { -+ compatible = "arm,cci-400-pmu"; -+ reg = <0x9000 0x5000>; -+ interrupts = <0 101 4>, -+ <0 102 4>, -+ <0 103 4>, -+ <0 104 4>, -+ <0 105 4>; -+ }; - }; - - memory-controller@7ffd0000 { -@@ -164,12 +235,21 @@ - <1 10 0xf08>; - }; - -- pmu { -+ pmu_a15 { - compatible = "arm,cortex-a15-pmu"; -+ cluster = <&cluster0>; - interrupts = <0 68 4>, - <0 69 4>; - }; - -+ pmu_a7 { -+ compatible = "arm,cortex-a7-pmu"; -+ cluster = <&cluster1>; -+ interrupts = <0 128 4>, -+ <0 129 4>, -+ <0 130 4>; -+ }; -+ - oscclk6a: oscclk6a { - /* Reference 24MHz clock */ - compatible = "fixed-clock"; -@@ -178,6 +258,19 @@ - clock-output-names = "oscclk6a"; - }; - -+/* PSCI requires support from firmware and is not present in the normal TC2 -+ * distribution, so this node is commented out by default... -+ -+ psci { -+ compatible = "arm,psci"; -+ method = "smc"; -+ cpu_suspend = <0x80100001>; -+ cpu_off = <0x80100002>; -+ cpu_on = <0x80100003>; -+ migrate = <0x80100004>; -+ }; -+*/ -+ - dcc { - compatible = "arm,vexpress,config-bus"; - arm,vexpress,config-bridge = <&v2m_sysreg>; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts 2014-10-22 14:55:49.690220001 -0500 -@@ -9,6 +9,8 @@ - - /dts-v1/; - -+/memreserve/ 0xbf000000 0x01000000; -+ - / { - model = "V2P-CA15"; - arm,hbi = <0x237>; -@@ -57,6 +59,8 @@ - interrupts = <0 85 4>; - clocks = <&oscclk5>; - clock-names = "pxlclk"; -+ mode = "1024x768-16@60"; -+ framebuffer = <0 0xbf000000 0 0x01000000>; - }; - - memory-controller@2b0a0000 { -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca5s.dts linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca5s.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca5s.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca5s.dts 2014-10-22 14:55:49.690220001 -0500 -@@ -9,6 +9,8 @@ - - /dts-v1/; - -+/memreserve/ 0xbf000000 0x01000000; -+ - / { - model = "V2P-CA5s"; - arm,hbi = <0x225>; -@@ -59,6 +61,8 @@ - interrupts = <0 85 4>; - clocks = <&oscclk3>; - clock-names = "pxlclk"; -+ mode = "640x480-16@60"; -+ framebuffer = <0xbf000000 0x01000000>; - }; - - memory-controller@2a150000 { -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca9.dts linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca9.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/vexpress-v2p-ca9.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vexpress-v2p-ca9.dts 2014-10-22 14:55:49.690220001 -0500 -@@ -9,6 +9,8 @@ - - /dts-v1/; - -+/include/ "clcd-panels.dtsi" -+ - / { - model = "V2P-CA9"; - arm,hbi = <0x191>; -@@ -73,6 +75,8 @@ - interrupts = <0 44 4>; - clocks = <&oscclk1>, <&oscclk2>; - clock-names = "clcdclk", "apb_pclk"; -+ mode = "XVGA"; -+ use_dma = <1>; - }; - - memory-controller@100e0000 { -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vf610.dtsi linux-3.14.22/arch/arm/boot/dts/vf610.dtsi ---- linux-3.14.22.orig/arch/arm/boot/dts/vf610.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vf610.dtsi 2014-10-22 14:55:49.694220001 -0500 -@@ -44,11 +44,13 @@ - - sxosc { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <32768>; - }; - - fxosc { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/boot/dts/vf610-twr.dts linux-3.14.22/arch/arm/boot/dts/vf610-twr.dts ---- linux-3.14.22.orig/arch/arm/boot/dts/vf610-twr.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/boot/dts/vf610-twr.dts 2014-10-22 14:55:49.694220001 -0500 -@@ -25,11 +25,13 @@ - clocks { - audio_ext { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <24576000>; - }; - - enet_ext { - compatible = "fixed-clock"; -+ #clock-cells = <0>; - clock-frequency = <50000000>; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm/common/Makefile linux-3.14.22/arch/arm/common/Makefile ---- linux-3.14.22.orig/arch/arm/common/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/common/Makefile 2014-10-22 14:55:49.694220001 -0500 -@@ -13,6 +13,7 @@ - obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o - obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o - obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o -+CFLAGS_REMOVE_mcpm_entry.o = -pg - AFLAGS_mcpm_head.o := -march=armv7-a - AFLAGS_vlock.o := -march=armv7-a - obj-$(CONFIG_TI_PRIV_EDMA) += edma.o -diff -Nur linux-3.14.22.orig/arch/arm/configs/imx_v6_v7_defconfig linux-3.14.22/arch/arm/configs/imx_v6_v7_defconfig ---- linux-3.14.22.orig/arch/arm/configs/imx_v6_v7_defconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/configs/imx_v6_v7_defconfig 2014-10-22 14:55:49.694220001 -0500 -@@ -45,6 +45,9 @@ - CONFIG_AEABI=y - CONFIG_HIGHMEM=y - CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CPU_FREQ=y -+CONFIG_ARM_IMX6Q_CPUFREQ=y -+CONFIG_CPU_IDLE=y - CONFIG_VFP=y - CONFIG_NEON=y - CONFIG_BINFMT_MISC=m -@@ -70,6 +73,8 @@ - CONFIG_DEVTMPFS=y - CONFIG_DEVTMPFS_MOUNT=y - # CONFIG_STANDALONE is not set -+CONFIG_CMA=y -+CONFIG_CMA_SIZE_MBYTES=256 - CONFIG_IMX_WEIM=y - CONFIG_CONNECTOR=y - CONFIG_MTD=y -@@ -154,7 +159,12 @@ - CONFIG_SPI_IMX=y - CONFIG_GPIO_SYSFS=y - CONFIG_GPIO_MC9S08DZ60=y -+CONFIG_GPIO_PCA953X=y - # CONFIG_HWMON is not set -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_IMX_THERMAL=y -+CONFIG_DEVICE_THERMAL=y - CONFIG_WATCHDOG=y - CONFIG_IMX2_WDT=y - CONFIG_MFD_DA9052_I2C=y -@@ -170,32 +180,44 @@ - CONFIG_REGULATOR_PFUZE100=y - CONFIG_MEDIA_SUPPORT=y - CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m - CONFIG_MEDIA_RC_SUPPORT=y - CONFIG_RC_DEVICES=y - CONFIG_IR_GPIO_CIR=y - CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_MXC_OUTPUT=y -+CONFIG_VIDEO_MXC_IPU_OUTPUT=y - CONFIG_SOC_CAMERA=y - CONFIG_VIDEO_MX3=y - CONFIG_V4L_MEM2MEM_DRIVERS=y - CONFIG_VIDEO_CODA=y - CONFIG_SOC_CAMERA_OV2640=y - CONFIG_DRM=y -+CONFIG_DRM_VIVANTE=y - CONFIG_BACKLIGHT_LCD_SUPPORT=y - CONFIG_LCD_CLASS_DEVICE=y - CONFIG_LCD_L4F00242T03=y - CONFIG_LCD_PLATFORM=y - CONFIG_BACKLIGHT_CLASS_DEVICE=y - CONFIG_BACKLIGHT_PWM=y -+CONFIG_FB_MXC_SYNC_PANEL=y -+CONFIG_FB_MXC_LDB=y -+CONFIG_FB_MXC_HDMI=y -+CONFIG_FB_MXC_MIPI_DSI=y -+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_LOGO=y - CONFIG_SOUND=y - CONFIG_SND=y -+CONFIG_SND_USB_AUDIO=m - CONFIG_SND_SOC=y - CONFIG_SND_IMX_SOC=y - CONFIG_SND_SOC_PHYCORE_AC97=y - CONFIG_SND_SOC_EUKREA_TLV320=y - CONFIG_SND_SOC_IMX_WM8962=y - CONFIG_SND_SOC_IMX_SGTL5000=y -+CONFIG_SND_SOC_IMX_CS42888=y - CONFIG_SND_SOC_IMX_SPDIF=y - CONFIG_SND_SOC_IMX_MC13783=y - CONFIG_USB=y -@@ -208,12 +230,18 @@ - CONFIG_NOP_USB_XCEIV=y - CONFIG_USB_MXS_PHY=y - CONFIG_USB_GADGET=y -+CONFIG_USB_ZERO=m - CONFIG_USB_ETH=m - CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m - CONFIG_MMC=y -+CONFIG_MMC_UNSAFE_RESUME=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_ESDHC_IMX=y -+CONFIG_MXC_IPU=y -+CONFIG_MXC_GPU_VIV=y -+CONFIG_MXC_ASRC=y - CONFIG_NEW_LEDS=y - CONFIG_LEDS_CLASS=y - CONFIG_LEDS_GPIO=y -@@ -229,16 +257,10 @@ - CONFIG_RTC_DRV_MXC=y - CONFIG_RTC_DRV_SNVS=y - CONFIG_DMADEVICES=y -+CONFIG_MXC_PXP_V2=y - CONFIG_IMX_SDMA=y - CONFIG_MXS_DMA=y - CONFIG_STAGING=y --CONFIG_DRM_IMX=y --CONFIG_DRM_IMX_FB_HELPER=y --CONFIG_DRM_IMX_PARALLEL_DISPLAY=y --CONFIG_DRM_IMX_TVE=y --CONFIG_DRM_IMX_LDB=y --CONFIG_DRM_IMX_IPUV3_CORE=y --CONFIG_DRM_IMX_IPUV3=y - CONFIG_COMMON_CLK_DEBUG=y - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_PWM=y -diff -Nur linux-3.14.22.orig/arch/arm/configs/imx_v7_cbi_hb_base_defconfig linux-3.14.22/arch/arm/configs/imx_v7_cbi_hb_base_defconfig ---- linux-3.14.22.orig/arch/arm/configs/imx_v7_cbi_hb_base_defconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/configs/imx_v7_cbi_hb_base_defconfig 2014-10-22 14:55:49.694220001 -0500 -@@ -0,0 +1,367 @@ -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_KERNEL_LZO=y -+CONFIG_SYSVIPC=y -+CONFIG_FHANDLE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_LOG_BUF_SHIFT=18 -+CONFIG_CGROUPS=y -+CONFIG_RELAY=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EXPERT=y -+CONFIG_PERF_EVENTS=y -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_ZSWAP=y -+CONFIG_ZSMALLOC=y -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+# CONFIG_BLK_DEV_BSG is not set -+CONFIG_GPIO_PCA953X=y -+CONFIG_ARCH_MXC=y -+CONFIG_MXC_DEBUG_BOARD=y -+CONFIG_SOC_IMX6Q=y -+CONFIG_SOC_IMX6SL=y -+# CONFIG_SWP_EMULATE is not set -+CONFIG_PCI=y -+CONFIG_PCIE_DW=y -+CONFIG_PCI_IMX6=y -+CONFIG_SMP=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+# CONFIG_OABI_COMPAT is not set -+CONFIG_HIGHMEM=y -+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_ARM_IMX6_CPUFREQ=y -+CONFIG_CPU_IDLE=y -+CONFIG_VFP=y -+CONFIG_VFPv3=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_PM_RUNTIME=y -+CONFIG_PM_DEBUG=y -+CONFIG_PM_TEST_SUSPEND=y -+CONFIG_IOSCHED_BFQ=y -+CONFIG_CGROUP_BFQIO=y -+CONFIG_DEFAULT_BFQ=y -+CONFIG_DEFAULT_IOSCHED="bfq" -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_INET=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+CONFIG_IPV6=y -+CONFIG_NETFILTER=y -+CONFIG_VLAN_8021Q=y -+CONFIG_WIRELESS=y -+CONFIG_WIRELESS_EXT=y -+CONFIG_WEXT_CORE=y -+CONFIG_WEXT_PROC=y -+CONFIG_WEXT_SPY=y -+CONFIG_WEXT_PRIV=y -+CONFIG_CFG80211=y -+CONFIG_ETHERNET=y -+# CONFIG_NET_VENDOR_BROADCOM is not set -+# CONFIG_NET_VENDOR_CIRRUS is not set -+# CONFIG_NET_VENDOR_FARADAY -+# CONFIG_NET_VENDOR_INTEL -+# CONFIG_NET_VENDOR_I825XX -+# CONFIG_NET_VENDOR_MARVELL -+# CONFIG_NET_VENDOR_MICROCHIP -+# CONFIG_NET_VENDOR_MICROCHIP=y -+# CONFIG_ENC28J60 is not set -+# CONFIG_NET_VENDOR_NATSEMI=y -+# CONFIG_NET_VENDOR_8390=y -+# CONFIG_AX88796 is not set -+# CONFIG_ETHOC is not set -+# CONFIG_SH_ETH is not set -+# CONFIG_NET_VENDOR_SEEQ=y -+# CONFIG_NET_VENDOR_SMSC=y -+# CONFIG_SMC91X is not set -+# CONFIG_SMC911X is not set -+# CONFIG_SMSC911X is not set -+# CONFIG_NET_VENDOR_STMICRO=y -+# CONFIG_STMMAC_ETH is not set -+# CONFIG_NET_VENDOR_VIA=y -+# CONFIG_VIA_VELOCITY is not set -+# CONFIG_NET_VENDOR_WIZNET=y -+CONFIG_NET_VENDOR_FREESCALE=y -+CONFIG_FEC=y -+CONFIG_PHYLIB=y -+CONFIG_AT803X_PHY=y -+CONFIG_WLAN=y -+CONFIG_BRCMUTIL=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_SDIO=y -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+# CONFIG_STANDALONE is not set -+CONFIG_DMA_CMA=y -+CONFIG_CMA=y -+CONFIG_CMA_SIZE_MBYTES=256 -+CONFIG_CONNECTOR=y -+# CONFIG_MTD is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=65536 -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_MULTI_LUN=y -+CONFIG_SCSI_CONSTANTS=y -+CONFIG_SCSI_LOGGING=y -+CONFIG_SCSI_SCAN_ASYNC=y -+# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_ATA=y -+CONFIG_SATA_AHCI_PLATFORM=y -+CONFIG_AHCI_IMX=y -+CONFIG_NETDEVICES=y -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_EVBUG is not set -+CONFIG_KEYBOARD_GPIO=y -+CONFIG_KEYBOARD_IMX=y -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+CONFIG_INPUT_MISC=y -+CONFIG_SERIO_SERPORT=m -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_IMX=y -+CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_FSL_LPUART=y -+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -+CONFIG_FSL_OTP=y -+CONFIG_GPIO_MXC=y -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_CHARDEV=y -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_I2C_ALGOPCF=m -+CONFIG_I2C_ALGOPCA=m -+CONFIG_I2C_IMX=y -+CONFIG_SPI=y -+CONFIG_SPI_IMX=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_POWER_SUPPLY=y -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_IMX_THERMAL=y -+CONFIG_DEVICE_THERMAL=y -+CONFIG_WATCHDOG=y -+CONFIG_IMX2_WDT=y -+CONFIG_MFD_DA9052_I2C=y -+CONFIG_MFD_MC13XXX_SPI=y -+CONFIG_MFD_MC13XXX_I2C=y -+CONFIG_MFD_SI476X_CORE=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+CONFIG_REGULATOR_ANATOP=y -+CONFIG_REGULATOR_PFUZE100=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+# CONFIG_MEDIA_RADIO_SUPPORT is not set -+CONFIG_VIDEO_V4L2_INT_DEVICE=y -+# CONFIG_MEDIA_USB_SUPPORT isnot set -+# CONFIG_USB_VIDEO_CLASS is not set -+# CONFIG_RADIO_ADAPTERS is not set -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_MXC_OUTPUT=y -+CONFIG_VIDEO_MXC_CAPTURE=m -+CONFIG_VIDEO_MXC_CSI_CAMERA=m -+CONFIG_MXC_CAMERA_OV5640=m -+CONFIG_MXC_CAMERA_OV5642=m -+CONFIG_MXC_CAMERA_OV5640_MIPI=m -+CONFIG_MXC_TVIN_ADV7180=m -+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m -+CONFIG_VIDEO_MXC_IPU_OUTPUT=y -+CONFIG_VIDEO_MXC_PXP_V4L2=y -+CONFIG_SOC_CAMERA=y -+CONFIG_SOC_CAMERA_OV2640=y -+CONFIG_DRM=y -+CONFIG_DRM_VIVANTE=y -+CONFIG_FB=y -+# CONFIG_FB_MX3 is not set -+CONFIG_FB_MXC_SYNC_PANEL=y -+CONFIG_FB_MXC_LDB=y -+CONFIG_FB_MXC_HDMI=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_FONTS=y -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+CONFIG_LOGO=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_SOC=y -+CONFIG_SND_IMX_SOC=y -+CONFIG_SND_SOC_IMX_SGTL5000=y -+CONFIG_SND_SOC_IMX_SPDIF=y -+CONFIG_SND_SOC_IMX_HDMI=y -+CONFIG_USB=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_STORAGE=y -+CONFIG_USB_CHIPIDEA=y -+CONFIG_USB_CHIPIDEA_UDC=y -+CONFIG_USB_CHIPIDEA_HOST=y -+CONFIG_USB_PHY=y -+CONFIG_NOP_USB_XCEIV=y -+CONFIG_USB_MXS_PHY=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_ZERO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_MMC=y -+CONFIG_MMC_UNSAFE_RESUME=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_ESDHC_IMX=y -+CONFIG_MXC_IPU=y -+CONFIG_MXC_GPU_VIV=y -+CONFIG_MXC_ASRC=y -+CONFIG_MXC_HDMI_CEC=y -+CONFIG_MXC_MIPI_CSI2=y -+CONFIG_MXC_MLB150=m -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_DRV_MXC=y -+CONFIG_RTC_DRV_SNVS=y -+CONFIG_RTC_DRV_PCF8523=y -+CONFIG_DMADEVICES=y -+CONFIG_MXC_PXP_V2=y -+CONFIG_IMX_SDMA=y -+CONFIG_MXS_DMA=y -+CONFIG_SRAM=y -+CONFIG_STAGING=y -+CONFIG_COMMON_CLK_DEBUG=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_PWM=y -+CONFIG_PWM_SYSFS=y -+CONFIG_PWM_IMX=y -+CONFIG_IRQCHIP=y -+CONFIG_ARM_GIC=y -+# CONFIG_IPACK_BUS is not set -+CONFIG_ARCH_HAS_RESET_CONTROLLER=y -+CONFIG_RESET_CONTROLLER=y -+CONFIG_RESET_GPIO=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_USE_FOR_EXT23=y -+CONFIG_EXT4_FS_XATTR=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_QUOTA=y -+CONFIG_QUOTA_NETLINK_INTERFACE=y -+# CONFIG_PRINT_QUOTA_WARNING is not set -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=m -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_JFFS2_FS=y -+CONFIG_UBIFS_FS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_ROOT_NFS=y -+CONFIG_NLS_DEFAULT="cp437" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_UTF8=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_SCHED_DEBUG is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+# CONFIG_FTRACE is not set -+CONFIG_SECURITYFS=y -+CONFIG_CRYPTO_USER=y -+CONFIG_CRYPTO_TEST=m -+CONFIG_CRYPTO_CCM=y -+CONFIG_CRYPTO_GCM=y -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=y -+CONFIG_CRYPTO_ECB=y -+CONFIG_CRYPTO_LRW=y -+CONFIG_CRYPTO_XTS=y -+CONFIG_CRYPTO_MD4=y -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_MICHAEL_MIC=y -+CONFIG_CRYPTO_RMD128=y -+CONFIG_CRYPTO_RMD160=y -+CONFIG_CRYPTO_RMD256=y -+CONFIG_CRYPTO_RMD320=y -+CONFIG_CRYPTO_SHA1=y -+CONFIG_CRYPTO_SHA256=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_TGR192=y -+CONFIG_CRYPTO_WP512=y -+CONFIG_CRYPTO_BLOWFISH=y -+CONFIG_CRYPTO_CAMELLIA=y -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_TWOFISH=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y -+CONFIG_CRYPTO_AES_ARM_BS=y -+CONFIG_CRC_CCITT=m -+CONFIG_CRC_T10DIF=y -+CONFIG_CRC7=m -+CONFIG_LIBCRC32C=m -+# CONFIG_MXC_MMA8451 is not set -+CONFIG_RC_CORE=m -+CONFIG_RC_DECODERS=y -+CONFIG_LIRC=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_RC_MAP=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_NEC_DECODER=m -+CONFIG_IR_RC5_DECODER=m -+CONFIG_IR_RC6_DECODER=m -+CONFIG_IR_JVC_DECODER=m -+CONFIG_IR_SONY_DECODER=m -+CONFIG_IR_RC5_SZ_DECODER=m -+CONFIG_IR_SANYO_DECODER=m -+CONFIG_IR_MCE_KBD_DECODER=m -+CONFIG_IR_LIRC_CODEC=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_ITE_CIR=m -+CONFIG_IR_NUVOTON=m -+CONFIG_IR_FINTEK=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_ENE=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_WINBOND_CIR=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_IR_GPIO_CIR=m -diff -Nur linux-3.14.22.orig/arch/arm/configs/imx_v7_cbi_hb_defconfig linux-3.14.22/arch/arm/configs/imx_v7_cbi_hb_defconfig ---- linux-3.14.22.orig/arch/arm/configs/imx_v7_cbi_hb_defconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/configs/imx_v7_cbi_hb_defconfig 2014-10-22 14:55:49.702220001 -0500 -@@ -0,0 +1,5138 @@ -+# -+# Automatically generated make config: don't edit -+# -+CONFIG_MMU=y -+CONFIG_HOTPLUG_CPU=y -+# CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set -+# CONFIG_DEBUG_HOTPLUG_CPU0 is not set -+CONFIG_LOCALVERSION="" -+CONFIG_CROSS_COMPILE="" -+CONFIG_DEFAULT_HOSTNAME="(none)" -+ -+# -+# Code maturity level options -+# -+CONFIG_EXPERIMENTAL=y -+CONFIG_HOTPLUG=y -+CONFIG_UEVENT_HELPER_PATH="" -+CONFIG_PREVENT_FIRMWARE_BUILD=y -+ -+CONFIG_BUILD_DOCSRC=y -+ -+# -+# General setup -+# -+CONFIG_KERNEL_LZO=y -+# CONFIG_KERNEL_BZIP2 is not set -+# CONFIG_KERNEL_LZMA is not set -+CONFIG_SWAP=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+# CONFIG_COMPILE_TEST is not set -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_SYSCTL=y -+# CONFIG_IKCONFIG is not set -+# CONFIG_EMBEDDED is not set -+CONFIG_KALLSYMS=y -+CONFIG_KALLSYMS_ALL=y -+CONFIG_FUTEX=y -+CONFIG_EPOLL=y -+CONFIG_IOSCHED_NOOP=y -+CONFIG_IOSCHED_DEADLINE=y -+CONFIG_IOSCHED_CFQ=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_IOSCHED_BFQ=y -+CONFIG_CGROUP_BFQIO=y -+CONFIG_DEFAULT_BFQ=y -+CONFIG_DEFAULT_IOSCHED="bfq" -+# CONFIG_CHECKPOINT_RESTORE is not set -+CONFIG_NAMESPACES=y -+CONFIG_PID_NS=y -+CONFIG_UTS_NS=y -+CONFIG_IPC_NS=y -+CONFIG_NET_NS=y -+CONFIG_USER_NS=y -+# CONFIG_UIDGID_STRICT_TYPE_CHECKS is not set -+CONFIG_SYSVIPC=y -+CONFIG_FHANDLE=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_LOG_BUF_SHIFT=18 -+CONFIG_CGROUPS=y -+CONFIG_RELAY=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EXPERT=y -+CONFIG_PERF_EVENTS=y -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+ -+CONFIG_POSIX_MQUEUE=y -+CONFIG_PREEMPT_VOLUNTARY=y -+ -+CONFIG_SLUB=y -+CONFIG_SLUB_CPU_PARTIAL=y -+# CONFIG_SLUB_STATS is not set -+# CONFIG_SLUB_DEBUG_ON is not set -+ -+# CONFIG_AD525X_DPOT is not set -+# CONFIG_ATMEL_PWM is not set -+# CONFIG_IWMC3200TOP is not set -+# CONFIG_BLK_DEV_BSG is not set -+ -+# MX6 specific kernel configuration -+CONFIG_GPIO_PCA953X=y -+CONFIG_ARCH_MXC=y -+CONFIG_MXC_DEBUG_BOARD=y -+CONFIG_SOC_IMX6Q=y -+CONFIG_SOC_IMX6SL=y -+# CONFIG_SWP_EMULATE is not set -+CONFIG_PCI=y -+CONFIG_PCIE_DW=y -+CONFIG_PCI_IMX6=y -+CONFIG_SMP=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_AEABI=y -+# CONFIG_OABI_COMPAT is not set -+CONFIG_HIGHMEM=y -+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_ARM_IMX6_CPUFREQ=y -+CONFIG_CPU_IDLE=y -+CONFIG_VFP=y -+CONFIG_VFPv3=y -+CONFIG_NEON=y -+CONFIG_KERNEL_MODE_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_PM_RUNTIME=y -+CONFIG_PM_DEBUG=y -+CONFIG_PM_TEST_SUSPEND=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_INET=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+CONFIG_IPV6=y -+CONFIG_NETFILTER=y -+CONFIG_VLAN_8021Q=y -+CONFIG_WIRELESS=y -+CONFIG_WIRELESS_EXT=y -+CONFIG_WEXT_CORE=y -+CONFIG_WEXT_PROC=y -+CONFIG_WEXT_SPY=y -+CONFIG_WEXT_PRIV=y -+CONFIG_CFG80211=y -+CONFIG_ETHERNET=y -+# CONFIG_NET_VENDOR_BROADCOM is not set -+# CONFIG_NET_VENDOR_CIRRUS is not set -+# CONFIG_NET_VENDOR_FARADAY -+# CONFIG_NET_VENDOR_INTEL -+# CONFIG_NET_VENDOR_I825XX -+# CONFIG_NET_VENDOR_MARVELL -+# CONFIG_NET_VENDOR_MICROCHIP -+# CONFIG_NET_VENDOR_MICROCHIP=y -+# CONFIG_ENC28J60 is not set -+# CONFIG_NET_VENDOR_NATSEMI=y -+# CONFIG_NET_VENDOR_8390=y -+# CONFIG_AX88796 is not set -+# CONFIG_ETHOC is not set -+# CONFIG_SH_ETH is not set -+# CONFIG_NET_VENDOR_SEEQ=y -+# CONFIG_NET_VENDOR_SMSC=y -+# CONFIG_SMC91X is not set -+# CONFIG_SMC911X is not set -+# CONFIG_SMSC911X is not set -+# CONFIG_NET_VENDOR_STMICRO=y -+# CONFIG_STMMAC_ETH is not set -+# CONFIG_NET_VENDOR_VIA=y -+# CONFIG_VIA_VELOCITY is not set -+# CONFIG_NET_VENDOR_WIZNET=y -+CONFIG_NET_VENDOR_FREESCALE=y -+CONFIG_FEC=y -+CONFIG_PHYLIB=y -+CONFIG_AT803X_PHY=y -+CONFIG_WLAN=y -+CONFIG_BRCMUTIL=m -+CONFIG_BRCMFMAC=m -+CONFIG_BRCMFMAC_SDIO=y -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+# CONFIG_STANDALONE is not set -+CONFIG_DMA_CMA=y -+CONFIG_CMA=y -+CONFIG_CMA_SIZE_MBYTES=256 -+CONFIG_CONNECTOR=y -+# CONFIG_MTD is not set -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=65536 -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_MULTI_LUN=y -+CONFIG_SCSI_CONSTANTS=y -+CONFIG_SCSI_LOGGING=y -+CONFIG_SCSI_SCAN_ASYNC=y -+# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_ATA=y -+CONFIG_SATA_AHCI_PLATFORM=y -+CONFIG_AHCI_IMX=y -+CONFIG_NETDEVICES=y -+CONFIG_INPUT_EVDEV=y -+# CONFIG_INPUT_EVBUG is not set -+CONFIG_KEYBOARD_GPIO=y -+CONFIG_KEYBOARD_IMX=y -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+# CONFIG_KEYBOARD_ATKBD is not set -+# CONFIG_MOUSE_PS2 is not set -+CONFIG_INPUT_MISC=y -+CONFIG_SERIO_SERPORT=m -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_IMX=y -+CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_FSL_LPUART=y -+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -+CONFIG_FSL_OTP=y -+CONFIG_GPIO_MXC=y -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_CHARDEV=y -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_I2C_ALGOPCF=m -+CONFIG_I2C_ALGOPCA=m -+CONFIG_I2C_IMX=y -+CONFIG_SPI=y -+CONFIG_SPI_IMX=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_POWER_SUPPLY=y -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_IMX_THERMAL=y -+CONFIG_DEVICE_THERMAL=y -+CONFIG_WATCHDOG=y -+CONFIG_IMX2_WDT=y -+CONFIG_MFD_DA9052_I2C=y -+CONFIG_MFD_MC13XXX_SPI=y -+CONFIG_MFD_MC13XXX_I2C=y -+CONFIG_MFD_SI476X_CORE=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+CONFIG_REGULATOR_ANATOP=y -+CONFIG_REGULATOR_PFUZE100=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+# CONFIG_MEDIA_RADIO_SUPPORT is not set -+CONFIG_VIDEO_V4L2_INT_DEVICE=y -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+# CONFIG_RADIO_ADAPTERS is not set -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_MXC_OUTPUT=y -+CONFIG_VIDEO_MXC_CAPTURE=m -+CONFIG_VIDEO_MXC_CSI_CAMERA=m -+CONFIG_MXC_CAMERA_OV5640=m -+CONFIG_MXC_CAMERA_OV5642=m -+CONFIG_MXC_CAMERA_OV5640_MIPI=m -+CONFIG_MXC_TVIN_ADV7180=m -+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m -+CONFIG_VIDEO_MXC_IPU_OUTPUT=y -+CONFIG_VIDEO_MXC_PXP_V4L2=y -+CONFIG_SOC_CAMERA=y -+CONFIG_SOC_CAMERA_OV2640=y -+CONFIG_DRM=y -+CONFIG_DRM_VIVANTE=y -+CONFIG_FB=y -+# CONFIG_FB_MX3 is not set -+CONFIG_FB_MXC_SYNC_PANEL=y -+CONFIG_FB_MXC_LDB=y -+CONFIG_FB_MXC_HDMI=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_FONTS=y -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+CONFIG_LOGO=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_SOC=y -+CONFIG_SND_IMX_SOC=y -+CONFIG_SND_SOC_IMX_SGTL5000=y -+CONFIG_SND_SOC_IMX_SPDIF=y -+CONFIG_SND_SOC_IMX_HDMI=y -+CONFIG_USB=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_STORAGE=y -+CONFIG_USB_CHIPIDEA=y -+CONFIG_USB_CHIPIDEA_UDC=y -+CONFIG_USB_CHIPIDEA_HOST=y -+CONFIG_USB_PHY=y -+CONFIG_NOP_USB_XCEIV=y -+CONFIG_USB_MXS_PHY=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_ZERO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_MMC=y -+CONFIG_MMC_UNSAFE_RESUME=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_ESDHC_IMX=y -+CONFIG_MXC_IPU=y -+CONFIG_MXC_GPU_VIV=y -+CONFIG_MXC_ASRC=y -+CONFIG_MXC_HDMI_CEC=y -+CONFIG_MXC_MIPI_CSI2=y -+CONFIG_MXC_MLB150=m -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_DRV_MXC=y -+CONFIG_RTC_DRV_SNVS=y -+CONFIG_RTC_DRV_PCF8523=y -+CONFIG_DMADEVICES=y -+CONFIG_MXC_PXP_V2=y -+CONFIG_IMX_SDMA=y -+CONFIG_MXS_DMA=y -+CONFIG_SRAM=y -+CONFIG_STAGING=y -+CONFIG_COMMON_CLK_DEBUG=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_PWM=y -+CONFIG_PWM_SYSFS=y -+CONFIG_PWM_IMX=y -+CONFIG_IRQCHIP=y -+CONFIG_ARM_GIC=y -+CONFIG_ARCH_HAS_RESET_CONTROLLER=y -+CONFIG_RESET_CONTROLLER=y -+CONFIG_RESET_GPIO=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_USE_FOR_EXT23=y -+CONFIG_EXT4_FS_XATTR=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_QUOTA=y -+CONFIG_QUOTA_NETLINK_INTERFACE=y -+# CONFIG_PRINT_QUOTA_WARNING is not set -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=m -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_JFFS2_FS=y -+CONFIG_UBIFS_FS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_ROOT_NFS=y -+CONFIG_NLS_DEFAULT="cp437" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_UTF8=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_SCHED_DEBUG is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+# CONFIG_FTRACE is not set -+CONFIG_SECURITYFS=y -+CONFIG_CRYPTO_USER=y -+CONFIG_CRYPTO_TEST=m -+CONFIG_CRYPTO_CCM=y -+CONFIG_CRYPTO_GCM=y -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=y -+CONFIG_CRYPTO_ECB=y -+CONFIG_CRYPTO_LRW=y -+CONFIG_CRYPTO_XTS=y -+CONFIG_CRYPTO_MD4=y -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_MICHAEL_MIC=y -+CONFIG_CRYPTO_RMD128=y -+CONFIG_CRYPTO_RMD160=y -+CONFIG_CRYPTO_RMD256=y -+CONFIG_CRYPTO_RMD320=y -+CONFIG_CRYPTO_SHA1=y -+CONFIG_CRYPTO_SHA256=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_TGR192=y -+CONFIG_CRYPTO_WP512=y -+CONFIG_CRYPTO_BLOWFISH=y -+CONFIG_CRYPTO_CAMELLIA=y -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_TWOFISH=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y -+CONFIG_CRYPTO_AES_ARM_BS=y -+CONFIG_CRC_CCITT=m -+CONFIG_CRC_T10DIF=y -+CONFIG_CRC7=m -+CONFIG_LIBCRC32C=m -+# CONFIG_MXC_MMA8451 is not set -+ -+# -+# Loadable module support -+# -+# CONFIG_MODULE_FORCE_LOAD is not set -+# -- MODULE_FORCE_UNLOAD is controlled by config-debug/nodebug -+ -+# CONFIG_PCI_DEBUG is not set -+CONFIG_PCI_STUB=y -+CONFIG_PCI_IOV=y -+CONFIG_PCI_PRI=y -+CONFIG_PCI_PASID=y -+CONFIG_HT_IRQ=y -+CONFIG_PCI_MSI=y -+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -+CONFIG_PCIEPORTBUS=y -+CONFIG_PCIEAER=y -+CONFIG_PCIEASPM=y -+# CONFIG_PCIEASPM_DEBUG is not set -+CONFIG_PCIE_ECRC=y -+CONFIG_PCIEAER_INJECT=m -+CONFIG_HOTPLUG_PCI_PCIE=y -+CONFIG_HOTPLUG_PCI_FAKE=m -+ -+# CONFIG_SGI_IOC4 is not set -+ -+# CONFIG_ISA is not set -+# CONFIG_SCx200 is not set -+ -+# -+# PCMCIA/CardBus support -+# FIXME: Deprecate Cardbus ? -+# -+CONFIG_PCMCIA=y -+CONFIG_PCMCIA_LOAD_CIS=y -+# CONFIG_PCMCIA_DEBUG is not set -+CONFIG_YENTA=m -+CONFIG_CARDBUS=y -+CONFIG_I82092=m -+CONFIG_PD6729=m -+ -+CONFIG_PCCARD=y -+CONFIG_SDIO_UART=m -+# CONFIG_MMC_TEST is not set -+# CONFIG_MMC_DEBUG is not set -+# https://lists.fedoraproject.org/pipermail/kernel/2014-February/004889.html -+# CONFIG_MMC_CLKGATE is not set -+CONFIG_MMC_BLOCK=y -+CONFIG_MMC_BLOCK_MINORS=8 -+CONFIG_MMC_BLOCK_BOUNCE=y -+CONFIG_MMC_SDHCI_PCI=m -+CONFIG_MMC_SDHCI_ACPI=m -+CONFIG_MMC_SDRICOH_CS=m -+CONFIG_MMC_TIFM_SD=m -+CONFIG_MMC_WBSD=m -+CONFIG_MMC_VIA_SDMMC=m -+CONFIG_MMC_CB710=m -+CONFIG_MMC_RICOH_MMC=y -+CONFIG_MMC_USHC=m -+CONFIG_MMC_REALTEK_PCI=m -+CONFIG_MMC_VUB300=m -+# CONFIG_MMC_SDHCI_PXAV2 is not set -+# CONFIG_MMC_SDHCI_PXAV3 is not set -+# CONFIG_MMC_SDHCI_OF_ARASAN is not set -+ -+ -+CONFIG_CB710_CORE=m -+# CONFIG_CB710_DEBUG is not set -+ -+CONFIG_INFINIBAND=m -+CONFIG_INFINIBAND_MTHCA=m -+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set -+CONFIG_INFINIBAND_IPOIB=m -+CONFIG_INFINIBAND_IPOIB_DEBUG=y -+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y -+CONFIG_INFINIBAND_IPOIB_CM=y -+CONFIG_INFINIBAND_SRP=m -+CONFIG_INFINIBAND_SRPT=m -+CONFIG_INFINIBAND_USER_MAD=m -+CONFIG_INFINIBAND_USER_ACCESS=m -+# CONFIG_INFINIBAND_EXPERIMENTAL_UVERBS_FLOW_STEERING is not set #staging -+CONFIG_INFINIBAND_IPATH=m -+CONFIG_INFINIBAND_ISER=m -+CONFIG_INFINIBAND_ISERT=m -+CONFIG_INFINIBAND_AMSO1100=m -+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set -+CONFIG_INFINIBAND_CXGB3=m -+CONFIG_INFINIBAND_CXGB4=m -+CONFIG_SCSI_CXGB3_ISCSI=m -+CONFIG_SCSI_CXGB4_ISCSI=m -+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set -+CONFIG_MLX4_INFINIBAND=m -+CONFIG_MLX5_INFINIBAND=m -+CONFIG_INFINIBAND_NES=m -+# CONFIG_INFINIBAND_NES_DEBUG is not set -+CONFIG_INFINIBAND_QIB=m -+CONFIG_INFINIBAND_QIB_DCA=y -+# CONFIG_INFINIBAND_OCRDMA is not set -+# CONFIG_INFINIBAND_USNIC is not set -+ -+# -+# Executable file formats -+# -+CONFIG_BINFMT_ELF=y -+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -+# CONFIG_BINFMT_AOUT is not set -+CONFIG_BINFMT_SCRIPT=y -+ -+# -+# Device Drivers -+# -+ -+# CONFIG_COMMON_CLK_SI5351 is not set -+ -+# -+# Generic Driver Options -+# -+CONFIG_FW_LOADER=y -+# CONFIG_FIRMWARE_IN_KERNEL is not set -+CONFIG_EXTRA_FIRMWARE="" -+ -+# Give this a try in rawhide for now -+# CONFIG_FW_LOADER_USER_HELPER is not set -+ -+ -+ -+# -+# Memory Technology Devices (MTD) -+# -+# CONFIG_MTD_TESTS is not set -+# CONFIG_MTD_REDBOOT_PARTS is not set -+# CONFIG_MTD_AR7_PARTS is not set -+# CONFIG_MTD_CMDLINE_PARTS is not set -+ -+# -+# User Modules And Translation Layers -+# -+# CONFIG_MTD_CHAR is not set -+# CONFIG_MTD_BLKDEVS is not set -+# CONFIG_MTD_BLOCK is not set -+# CONFIG_MTD_BLOCK_RO is not set -+# CONFIG_FTL is not set -+# CONFIG_NFTL is not set -+# CONFIG_INFTL is not set -+# CONFIG_RFD_FTL is not set -+# CONFIG_SSFDC is not set -+# CONFIG_SM_FTL is not set -+# CONFIG_MTD_OOPS is not set -+# CONFIG_MTD_SWAP is not set -+ -+# -+# RAM/ROM/Flash chip drivers -+# -+# CONFIG_MTD_CFI is not set -+# CONFIG_MTD_JEDECPROBE is not set -+CONFIG_MTD_MAP_BANK_WIDTH_1=y -+CONFIG_MTD_MAP_BANK_WIDTH_2=y -+CONFIG_MTD_MAP_BANK_WIDTH_4=y -+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -+CONFIG_MTD_CFI_I1=y -+CONFIG_MTD_CFI_I2=y -+# CONFIG_MTD_CFI_I4 is not set -+# CONFIG_MTD_CFI_I8 is not set -+# CONFIG_MTD_RAM is not set -+# CONFIG_MTD_ROM is not set -+# CONFIG_MTD_ABSENT is not set -+ -+# -+# Mapping drivers for chip access -+# -+# CONFIG_MTD_COMPLEX_MAPPINGS is not set -+# CONFIG_MTD_TS5500 is not set -+# CONFIG_MTD_INTEL_VR_NOR is not set -+# CONFIG_MTD_PLATRAM is not set -+ -+# Self-contained MTD device drivers -+# CONFIG_MTD_PMC551 is not set -+# CONFIG_MTD_SLRAM is not set -+# CONFIG_MTD_PHRAM is not set -+# CONFIG_MTD_MTDRAM is not set -+# CONFIG_MTD_BLOCK2MTD is not set -+ -+# -+# Disk-On-Chip Device Drivers -+# -+# CONFIG_MTD_DOCG3 is not set -+# CONFIG_MTD_NAND is not set -+# CONFIG_MTD_ONENAND is not set -+# CONFIG_MTD_NAND_VERIFY_WRITE is not set -+# CONFIG_MTD_NAND_ECC_BCH is not set -+# CONFIG_MTD_NAND_MUSEUM_IDS is not set -+# CONFIG_MTD_NAND_DISKONCHIP is not set -+# CONFIG_MTD_LPDDR is not set -+CONFIG_MTD_UBI=m -+CONFIG_MTD_UBI_WL_THRESHOLD=4096 -+CONFIG_MTD_UBI_BEB_LIMIT=20 -+# CONFIG_MTD_UBI_FASTMAP is not set -+# CONFIG_MTD_UBI_GLUEBI is not set -+ -+# -+# Parallel port support -+# -+CONFIG_PARPORT=m -+CONFIG_PARPORT_PC=m -+CONFIG_PARPORT_SERIAL=m -+# CONFIG_PARPORT_PC_FIFO is not set -+# CONFIG_PARPORT_PC_SUPERIO is not set -+CONFIG_PARPORT_PC_PCMCIA=m -+CONFIG_PARPORT_1284=y -+# CONFIG_PARPORT_AX88796 is not set -+ -+CONFIG_ACPI_PCI_SLOT=y -+CONFIG_HOTPLUG_PCI_ACPI=y -+CONFIG_HOTPLUG_PCI_ACPI_IBM=m -+ -+# -+# Block devices -+# -+CONFIG_BLK_DEV=y -+CONFIG_BLK_DEV_NULL_BLK=m -+CONFIG_BLK_DEV_FD=m -+# CONFIG_PARIDE is not set -+CONFIG_ZRAM=m -+# CONFIG_ZRAM_DEBUG is not set -+CONFIG_ENHANCEIO=m -+ -+CONFIG_BLK_CPQ_DA=m -+CONFIG_BLK_CPQ_CISS_DA=m -+CONFIG_CISS_SCSI_TAPE=y -+CONFIG_BLK_DEV_DAC960=m -+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set -+CONFIG_BLK_DEV_DRBD=m -+CONFIG_BLK_DEV_UMEM=m -+CONFIG_BLK_DEV_LOOP_MIN_COUNT=0 -+# Fedora 18 util-linux is the last release that supports cryptoloop devices -+# CONFIG_BLK_DEV_CRYPTOLOOP is not set -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_NVME=m -+CONFIG_BLK_DEV_SKD=m # 64-bit only but easier to put here -+CONFIG_BLK_DEV_OSD=m -+CONFIG_BLK_DEV_RAM_COUNT=16 -+CONFIG_BLK_DEV_IO_TRACE=y -+ -+CONFIG_BLK_DEV_BSGLIB=y -+CONFIG_BLK_DEV_INTEGRITY=y -+CONFIG_BLK_DEV_THROTTLING=y -+# CONFIG_BLK_CMDLINE_PARSER is not set -+ -+ -+# -+# ATA/ATAPI/MFM/RLL support -+# -+# CONFIG_IDE is not set -+ -+# CONFIG_BLK_DEV_HD is not set -+# CONFIG_BLK_DEV_RSXX is not set -+ -+CONFIG_SCSI_VIRTIO=m -+CONFIG_VIRTIO_BLK=m -+CONFIG_VIRTIO_PCI=m -+CONFIG_VIRTIO_BALLOON=m -+CONFIG_VIRTIO_MMIO=m -+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set -+CONFIG_VIRTIO_NET=m -+CONFIG_HW_RANDOM_VIRTIO=m -+CONFIG_VIRTIO_CONSOLE=m -+CONFIG_VHOST_NET=m -+CONFIG_TCM_VHOST=m -+CONFIG_VHOST_SCSI=m -+ -+# -+# SCSI device support -+# -+CONFIG_SCSI=y -+ -+CONFIG_SCSI_ENCLOSURE=m -+CONFIG_SCSI_SRP=m -+CONFIG_SCSI_SRP_ATTRS=m -+CONFIG_SCSI_TGT=m -+CONFIG_SCSI_ISCI=m -+CONFIG_SCSI_CHELSIO_FCOE=m -+ -+CONFIG_SCSI_DH=y -+CONFIG_SCSI_DH_RDAC=m -+CONFIG_SCSI_DH_HP_SW=m -+CONFIG_SCSI_DH_EMC=m -+CONFIG_SCSI_DH_ALUA=m -+ -+# -+# SCSI support type (disk, tape, CD-ROM) -+# -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=y -+CONFIG_BLK_DEV_SR_VENDOR=y -+CONFIG_CHR_DEV_SG=y -+CONFIG_CHR_DEV_SCH=m -+ -+# -+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -+# -+CONFIG_SCSI_SPI_ATTRS=m -+CONFIG_SCSI_FC_ATTRS=m -+CONFIG_SCSI_FC_TGT_ATTRS=y -+CONFIG_SCSI_ISCSI_ATTRS=m -+CONFIG_SCSI_SAS_ATTRS=m -+CONFIG_SCSI_SRP_TGT_ATTRS=y -+CONFIG_SCSI_SAS_LIBSAS=m -+CONFIG_SCSI_SAS_ATA=y -+CONFIG_SCSI_SAS_HOST_SMP=y -+CONFIG_RAID_ATTRS=m -+ -+CONFIG_ISCSI_TCP=m -+CONFIG_ISCSI_BOOT_SYSFS=m -+ -+# -+# SCSI low-level drivers -+# -+CONFIG_BLK_DEV_3W_XXXX_RAID=m -+CONFIG_SCSI_3W_9XXX=m -+CONFIG_SCSI_ACARD=m -+CONFIG_SCSI_AACRAID=m -+CONFIG_SCSI_AIC7XXX=m -+# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004102.html -+# CONFIG_SCSI_AIC7XXX_OLD is not set -+CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 -+CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -+CONFIG_AIC7XXX_DEBUG_MASK=0 -+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set -+CONFIG_SCSI_AIC79XX=m -+CONFIG_AIC79XX_CMDS_PER_DEVICE=4 -+CONFIG_AIC79XX_RESET_DELAY_MS=15000 -+# CONFIG_AIC79XX_BUILD_FIRMWARE is not set -+# CONFIG_AIC79XX_DEBUG_ENABLE is not set -+CONFIG_AIC79XX_DEBUG_MASK=0 -+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -+CONFIG_SCSI_AIC94XX=m -+# CONFIG_AIC94XX_DEBUG is not set -+# CONFIG_SCSI_ADVANSYS is not set -+CONFIG_SCSI_BFA_FC=m -+CONFIG_MEGARAID_NEWGEN=y -+CONFIG_MEGARAID_MM=m -+CONFIG_MEGARAID_MAILBOX=m -+CONFIG_MEGARAID_LEGACY=m -+CONFIG_MEGARAID_SAS=m -+CONFIG_SCSI_ESAS2R=m -+CONFIG_SCSI_MVSAS=m -+# CONFIG_SCSI_MVSAS_DEBUG is not set -+CONFIG_SCSI_MVSAS_TASKLET=y -+CONFIG_SCSI_MPT2SAS=m -+CONFIG_SCSI_MPT2SAS_MAX_SGE=128 -+CONFIG_SCSI_MPT2SAS_LOGGING=y -+CONFIG_SCSI_MPT3SAS=m -+CONFIG_SCSI_MPT3SAS_MAX_SGE=128 -+CONFIG_SCSI_MPT3SAS_LOGGING=y -+ -+CONFIG_SCSI_UFSHCD=m -+CONFIG_SCSI_UFSHCD_PCI=m -+# CONFIG_SCSI_UFSHCD_PLATFORM is not set -+ -+CONFIG_SCSI_MVUMI=m -+ -+CONFIG_SCSI_OSD_INITIATOR=m -+CONFIG_SCSI_OSD_ULD=m -+CONFIG_SCSI_OSD_DPRINT_SENSE=1 -+# CONFIG_SCSI_OSD_DEBUG is not set -+ -+CONFIG_SCSI_BNX2_ISCSI=m -+CONFIG_SCSI_BNX2X_FCOE=m -+CONFIG_BE2ISCSI=m -+CONFIG_SCSI_PMCRAID=m -+ -+CONFIG_SCSI_HPSA=m -+CONFIG_SCSI_3W_SAS=m -+CONFIG_SCSI_PM8001=m -+CONFIG_VMWARE_PVSCSI=m -+CONFIG_VMWARE_BALLOON=m -+ -+CONFIG_SCSI_ARCMSR=m -+CONFIG_SCSI_BUSLOGIC=m -+CONFIG_SCSI_INITIO=m -+CONFIG_SCSI_FLASHPOINT=y -+CONFIG_SCSI_DMX3191D=m -+# CONFIG_SCSI_EATA is not set -+# CONFIG_SCSI_EATA_PIO is not set -+# CONFIG_SCSI_FUTURE_DOMAIN is not set -+CONFIG_SCSI_GDTH=m -+CONFIG_SCSI_HPTIOP=m -+CONFIG_SCSI_IPS=m -+CONFIG_SCSI_INIA100=m -+# CONFIG_SCSI_PPA is not set -+# CONFIG_SCSI_IMM is not set -+# CONFIG_SCSI_IZIP_EPP16 is not set -+# CONFIG_SCSI_IZIP_SLOW_CTR is not set -+CONFIG_SCSI_STEX=m -+CONFIG_SCSI_SYM53C8XX_2=m -+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -+CONFIG_SCSI_SYM53C8XX_MMIO=y -+CONFIG_SCSI_QLOGIC_1280=m -+CONFIG_SCSI_DC395x=m -+# CONFIG_SCSI_NSP32 is not set -+CONFIG_SCSI_DEBUG=m -+CONFIG_SCSI_DC390T=m -+CONFIG_SCSI_QLA_FC=m -+CONFIG_TCM_QLA2XXX=m -+CONFIG_SCSI_QLA_ISCSI=m -+CONFIG_SCSI_IPR=m -+CONFIG_SCSI_IPR_TRACE=y -+CONFIG_SCSI_IPR_DUMP=y -+# CONFIG_SCSI_DPT_I2O is not set -+CONFIG_SCSI_LPFC=m -+# CONFIG_SCSI_LPFC_DEBUG_FS is not set -+ -+# PCMCIA SCSI adapter support -+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -+ -+CONFIG_ATA_BMDMA=y -+CONFIG_ATA_VERBOSE_ERROR=y -+CONFIG_ATA_SFF=y -+CONFIG_ATA_PIIX=y -+# CONFIG_SATA_HIGHBANK is not set -+CONFIG_ATA_ACPI=y -+CONFIG_BLK_DEV_SX8=m -+CONFIG_PDC_ADMA=m -+CONFIG_SATA_AHCI=y -+CONFIG_SATA_INIC162X=m -+CONFIG_SATA_MV=m -+CONFIG_SATA_NV=m -+CONFIG_SATA_PMP=y -+CONFIG_SATA_PROMISE=m -+CONFIG_SATA_QSTOR=m -+CONFIG_SATA_RCAR=m -+CONFIG_SATA_SIL=m -+CONFIG_SATA_SIL24=m -+CONFIG_SATA_SIS=m -+CONFIG_SATA_SVW=m -+CONFIG_SATA_SX4=m -+CONFIG_SATA_ULI=m -+CONFIG_SATA_VIA=m -+CONFIG_SATA_VITESSE=m -+# CONFIG_SATA_ZPODD is not set -+CONFIG_SATA_ACARD_AHCI=m -+ -+# CONFIG_PATA_LEGACY is not set -+CONFIG_PATA_ACPI=m -+CONFIG_PATA_ALI=m -+CONFIG_PATA_AMD=m -+CONFIG_PATA_ARASAN_CF=m -+CONFIG_PATA_ARTOP=m -+CONFIG_PATA_ATIIXP=m -+CONFIG_PATA_CMD640_PCI=m -+CONFIG_PATA_CMD64X=m -+CONFIG_PATA_CS5520=m -+CONFIG_PATA_CS5530=m -+CONFIG_PATA_CS5535=m -+CONFIG_PATA_CS5536=m -+CONFIG_PATA_CYPRESS=m -+CONFIG_PATA_EFAR=m -+CONFIG_ATA_GENERIC=m -+CONFIG_PATA_HPT366=m -+CONFIG_PATA_HPT37X=m -+CONFIG_PATA_HPT3X2N=m -+CONFIG_PATA_HPT3X3=m -+# CONFIG_PATA_HPT3X3_DMA is not set -+CONFIG_PATA_IT821X=m -+CONFIG_PATA_IT8213=m -+CONFIG_PATA_JMICRON=m -+CONFIG_PATA_NINJA32=m -+CONFIG_PATA_MARVELL=m -+CONFIG_PATA_MPIIX=m -+CONFIG_PATA_NETCELL=m -+CONFIG_PATA_NS87410=m -+CONFIG_PATA_NS87415=m -+CONFIG_PATA_OLDPIIX=m -+CONFIG_PATA_OPTI=m -+CONFIG_PATA_OPTIDMA=m -+CONFIG_PATA_PCMCIA=m -+CONFIG_PATA_PDC_OLD=m -+# CONFIG_PATA_RADISYS is not set -+CONFIG_PATA_RDC=m -+# CONFIG_PATA_RZ1000 is not set -+# CONFIG_PATA_SC1200 is not set -+CONFIG_PATA_SERVERWORKS=m -+CONFIG_PATA_PDC2027X=m -+CONFIG_PATA_SCH=m -+CONFIG_PATA_SIL680=m -+CONFIG_PATA_SIS=m -+CONFIG_PATA_TOSHIBA=m -+CONFIG_PATA_TRIFLEX=m -+CONFIG_PATA_VIA=m -+CONFIG_PATA_WINBOND=m -+CONFIG_PATA_ATP867X=m -+ -+ -+# -+# Multi-device support (RAID and LVM) -+# -+CONFIG_MD=y -+CONFIG_BLK_DEV_MD=y -+CONFIG_MD_AUTODETECT=y -+CONFIG_MD_FAULTY=m -+CONFIG_MD_LINEAR=m -+CONFIG_MD_MULTIPATH=m -+CONFIG_MD_RAID0=m -+CONFIG_MD_RAID1=m -+CONFIG_MD_RAID10=m -+CONFIG_MD_RAID456=m -+ -+CONFIG_BCACHE=m -+# CONFIG_BCACHE_DEBUG is not set -+# CONFIG_BCACHE_EDEBUG is not set -+# CONFIG_BCACHE_CLOSURES_DEBUG is not set -+ -+# CONFIG_MULTICORE_RAID456 is not set -+CONFIG_ASYNC_RAID6_TEST=m -+CONFIG_BLK_DEV_DM=y -+CONFIG_DM_CRYPT=m -+CONFIG_DM_DEBUG=y -+CONFIG_DM_DELAY=m -+CONFIG_DM_MIRROR=y -+CONFIG_DM_MULTIPATH=m -+CONFIG_DM_SNAPSHOT=y -+CONFIG_DM_THIN_PROVISIONING=m -+CONFIG_DM_CACHE=m -+CONFIG_DM_CACHE_MQ=m -+CONFIG_DM_CACHE_CLEANER=m -+# CONFIG_DM_DEBUG_BLOCK_STACK_TRACING is not set -+# CONFIG_DM_DEBUG_SPACE_MAPS is not set -+CONFIG_DM_UEVENT=y -+CONFIG_DM_ZERO=y -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_MULTIPATH_QL=m -+CONFIG_DM_MULTIPATH_ST=m -+CONFIG_DM_RAID=m -+CONFIG_DM_FLAKEY=m -+CONFIG_DM_VERITY=m -+CONFIG_DM_SWITCH=m -+ -+# -+# Fusion MPT device support -+# -+CONFIG_FUSION=y -+CONFIG_FUSION_SPI=m -+CONFIG_FUSION_FC=m -+CONFIG_FUSION_MAX_SGE=40 -+CONFIG_FUSION_CTL=m -+CONFIG_FUSION_LAN=m -+CONFIG_FUSION_SAS=m -+CONFIG_FUSION_LOGGING=y -+ -+# -+# IEEE 1394 (FireWire) support (JUJU alternative stack) -+# -+CONFIG_FIREWIRE=m -+CONFIG_FIREWIRE_OHCI=m -+CONFIG_FIREWIRE_SBP2=m -+CONFIG_FIREWIRE_NET=m -+CONFIG_FIREWIRE_OHCI_DEBUG=y -+CONFIG_FIREWIRE_NOSY=m -+# CONFIG_FIREWIRE_SERIAL is not set -+# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set -+ -+# -+# IEEE 1394 (FireWire) support -+# -+ -+# -+# I2O device support -+# -+# CONFIG_I2O is not set -+# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set -+ -+# -+# Virtualization support drivers -+# -+# CONFIG_VIRT_DRIVERS is not set -+ -+# Networking support -+# -+ -+CONFIG_NET_DMA=y -+ -+CONFIG_NETLINK_MMAP=y -+CONFIG_NETLINK_DIAG=m -+ -+CONFIG_TCP_CONG_ADVANCED=y -+CONFIG_TCP_CONG_BIC=m -+CONFIG_TCP_CONG_CUBIC=y -+CONFIG_TCP_CONG_HTCP=m -+CONFIG_TCP_CONG_HSTCP=m -+CONFIG_TCP_CONG_HYBLA=m -+CONFIG_TCP_CONG_ILLINOIS=m -+CONFIG_TCP_CONG_LP=m -+CONFIG_TCP_CONG_SCALABLE=m -+CONFIG_TCP_CONG_VEGAS=m -+CONFIG_TCP_CONG_VENO=m -+CONFIG_TCP_CONG_WESTWOOD=m -+CONFIG_TCP_CONG_YEAH=m -+ -+CONFIG_TCP_MD5SIG=y -+ -+# -+# Networking options -+# -+CONFIG_PACKET_DIAG=m -+CONFIG_UNIX_DIAG=m -+CONFIG_NET_KEY=m -+CONFIG_NET_KEY_MIGRATE=y -+CONFIG_INET_TUNNEL=m -+CONFIG_INET_DIAG=m -+CONFIG_INET_UDP_DIAG=m -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_FIB_TRIE_STATS=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_NF_SECURITY=m -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_NET_IPGRE_BROADCAST=y -+CONFIG_IP_MROUTE=y -+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IP_PIMSM_V1=y -+CONFIG_IP_PIMSM_V2=y -+CONFIG_ARPD=y -+CONFIG_SYN_COOKIES=y -+CONFIG_NET_IPVTI=m -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_NETCONSOLE=m -+CONFIG_NETCONSOLE_DYNAMIC=y -+CONFIG_NETPOLL_TRAP=y -+CONFIG_NET_POLL_CONTROLLER=y -+ -+# -+# IP: Virtual Server Configuration -+# -+CONFIG_IP_VS=m -+# CONFIG_IP_VS_DEBUG is not set -+CONFIG_IP_VS_TAB_BITS=12 -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_IPV6=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+ -+# -+# IPVS SH scheduler -+# -+CONFIG_IP_VS_SH_TAB_BITS=8 -+ -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m -+ -+CONFIG_IPV6_PRIVACY=y -+CONFIG_IPV6_ROUTER_PREF=y -+CONFIG_IPV6_ROUTE_INFO=y -+CONFIG_IPV6_OPTIMISTIC_DAD=y -+CONFIG_INET6_AH=m -+CONFIG_INET6_ESP=m -+CONFIG_INET6_IPCOMP=m -+CONFIG_IPV6_MIP6=y -+CONFIG_IPV6_VTI=m -+CONFIG_IPV6_SIT=m -+CONFIG_IPV6_SIT_6RD=y -+CONFIG_IPV6_TUNNEL=m -+# CONFIG_IPV6_GRE is not set -+CONFIG_IPV6_SUBTREES=y -+CONFIG_IPV6_MULTIPLE_TABLES=y -+CONFIG_IPV6_MROUTE=y -+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y -+CONFIG_IPV6_PIMSM_V2=y -+ -+CONFIG_RDS=m -+# CONFIG_RDS_DEBUG is not set -+CONFIG_RDS_RDMA=m -+CONFIG_RDS_TCP=m -+ -+CONFIG_NET_9P=m -+CONFIG_NET_9P_VIRTIO=m -+# CONFIG_NET_9P_DEBUG is not set -+CONFIG_NET_9P_RDMA=m -+ -+# CONFIG_DECNET is not set -+CONFIG_BRIDGE=m -+CONFIG_BRIDGE_IGMP_SNOOPING=y -+CONFIG_BRIDGE_VLAN_FILTERING=y -+ -+# PHY timestamping adds overhead -+CONFIG_NETWORK_PHY_TIMESTAMPING=y -+ -+CONFIG_NETFILTER_ADVANCED=y -+CONFIG_NF_CONNTRACK=m -+CONFIG_NETFILTER_NETLINK=m -+CONFIG_NETFILTER_NETLINK_ACCT=m -+CONFIG_NETFILTER_NETLINK_QUEUE=m -+CONFIG_NETFILTER_NETLINK_QUEUE_CT=y -+CONFIG_NETFILTER_NETLINK_LOG=m -+CONFIG_NETFILTER_TPROXY=m -+CONFIG_NETFILTER_XTABLES=y -+CONFIG_NETFILTER_XT_SET=m -+CONFIG_NETFILTER_XT_MARK=m -+CONFIG_NETFILTER_XT_CONNMARK=m -+ -+CONFIG_NETFILTER_XT_TARGET_AUDIT=m -+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m -+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m -+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m -+CONFIG_NETFILTER_XT_TARGET_CT=m -+CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m -+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m -+CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m -+CONFIG_NETFILTER_XT_TARGET_MARK=m -+CONFIG_NETFILTER_XT_TARGET_NFLOG=m -+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m -+CONFIG_NETFILTER_XT_TARGET_RATEEST=m -+CONFIG_NETFILTER_XT_TARGET_SECMARK=m -+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m -+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m -+CONFIG_NETFILTER_XT_TARGET_TRACE=m -+CONFIG_NETFILTER_XT_TARGET_TEE=m -+CONFIG_NETFILTER_XT_TARGET_TPROXY=m -+ -+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m -+CONFIG_NETFILTER_XT_MATCH_BPF=m -+CONFIG_NETFILTER_XT_MATCH_CGROUP=m -+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m -+CONFIG_NETFILTER_XT_MATCH_COMMENT=m -+CONFIG_NETFILTER_XT_MATCH_CPU=m -+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m -+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m -+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y -+CONFIG_NETFILTER_XT_MATCH_DCCP=m -+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m -+CONFIG_NETFILTER_XT_MATCH_DSCP=m -+CONFIG_NETFILTER_XT_MATCH_ECN=m -+CONFIG_NETFILTER_XT_MATCH_ESP=m -+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m -+CONFIG_NETFILTER_XT_MATCH_HELPER=m -+CONFIG_NETFILTER_XT_MATCH_HL=m -+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m -+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m -+CONFIG_NETFILTER_XT_MATCH_L2TP=m -+CONFIG_NETFILTER_XT_MATCH_LENGTH=m -+CONFIG_NETFILTER_XT_MATCH_LIMIT=m -+CONFIG_NETFILTER_XT_MATCH_MAC=m -+CONFIG_NETFILTER_XT_MATCH_MARK=m -+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m -+CONFIG_NETFILTER_XT_MATCH_OSF=m -+CONFIG_NETFILTER_XT_MATCH_OWNER=m -+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m -+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -+CONFIG_NETFILTER_XT_MATCH_POLICY=m -+CONFIG_NETFILTER_XT_MATCH_QUOTA=m -+CONFIG_NETFILTER_XT_MATCH_RATEEST=m -+CONFIG_NETFILTER_XT_MATCH_REALM=m -+CONFIG_NETFILTER_XT_MATCH_RECENT=m -+CONFIG_NETFILTER_XT_MATCH_SCTP=m -+CONFIG_NETFILTER_XT_MATCH_SOCKET=m -+CONFIG_NETFILTER_XT_MATCH_STATE=y -+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -+CONFIG_NETFILTER_XT_MATCH_STRING=m -+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m -+CONFIG_NETFILTER_XT_MATCH_TIME=m -+CONFIG_NETFILTER_XT_MATCH_U32=m -+ -+# CONFIG_NETFILTER_DEBUG is not set -+CONFIG_BRIDGE_NETFILTER=y -+ -+# -+# IP: Netfilter Configuration -+# -+ -+CONFIG_NF_CONNTRACK_MARK=y -+CONFIG_NF_CONNTRACK_SECMARK=y -+CONFIG_NF_CONNTRACK_EVENTS=y -+CONFIG_NF_CONNTRACK_ZONES=y -+CONFIG_NF_CONNTRACK_PROCFS=y # check if contrack(8) in f17 supports netlink -+# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set -+CONFIG_NF_CONNTRACK_AMANDA=m -+CONFIG_NF_CONNTRACK_FTP=m -+CONFIG_NF_CONNTRACK_H323=m -+CONFIG_NF_CONNTRACK_IRC=m -+CONFIG_NF_CONNTRACK_NETBIOS_NS=m -+CONFIG_NF_CONNTRACK_PPTP=m -+CONFIG_NF_CONNTRACK_SANE=m -+CONFIG_NF_CONNTRACK_SIP=m -+CONFIG_NF_CONNTRACK_TFTP=m -+CONFIG_NF_CONNTRACK_IPV4=y -+CONFIG_NF_CONNTRACK_IPV6=y -+# CONFIG_NF_CONNTRACK_TIMEOUT is not set -+CONFIG_NF_CONNTRACK_TIMESTAMP=y -+CONFIG_NF_CONNTRACK_SNMP=m -+CONFIG_NF_NAT=m -+CONFIG_NF_NAT_SNMP_BASIC=m -+CONFIG_NF_CT_PROTO_DCCP=m -+CONFIG_NF_CT_PROTO_SCTP=m -+CONFIG_NF_CT_NETLINK=m -+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set -+CONFIG_NF_CT_NETLINK_HELPER=m -+CONFIG_NF_CT_PROTO_UDPLITE=m -+ -+CONFIG_IP_NF_MATCH_AH=m -+CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m -+CONFIG_IP_NF_MATCH_TTL=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m -+CONFIG_IP_NF_TARGET_REDIRECT=m -+CONFIG_IP_NF_TARGET_NETMAP=m -+CONFIG_IP_NF_TARGET_ECN=m -+CONFIG_IP_NF_TARGET_LOG=m -+CONFIG_IP_NF_TARGET_ULOG=m -+CONFIG_IP_NF_TARGET_REJECT=y -+CONFIG_IP_NF_TARGET_SYNPROXY=m -+CONFIG_IP_NF_TARGET_TTL=m -+CONFIG_NF_NAT_IPV4=m -+CONFIG_IP_NF_TARGET_MASQUERADE=m -+CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_ARPTABLES=m -+CONFIG_IP_NF_ARPFILTER=m -+CONFIG_IP_NF_ARP_MANGLE=m -+CONFIG_IP_NF_QUEUE=m -+CONFIG_IP_NF_RAW=m -+ -+CONFIG_IP_NF_IPTABLES=y -+CONFIG_IP_NF_FILTER=y -+ -+# -+# IPv6: Netfilter Configuration -+# -+CONFIG_IP6_NF_FILTER=m -+CONFIG_IP6_NF_IPTABLES=m -+CONFIG_IP6_NF_MANGLE=m -+CONFIG_IP6_NF_MATCH_AH=m -+CONFIG_IP6_NF_MATCH_EUI64=m -+CONFIG_IP6_NF_MATCH_FRAG=m -+CONFIG_IP6_NF_MATCH_HL=m -+CONFIG_IP6_NF_MATCH_IPV6HEADER=m -+CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m -+CONFIG_IP6_NF_MATCH_OPTS=m -+CONFIG_IP6_NF_MATCH_RT=m -+CONFIG_IP6_NF_QUEUE=m -+CONFIG_IP6_NF_RAW=m -+CONFIG_IP6_NF_SECURITY=m -+CONFIG_IP6_NF_TARGET_LOG=m -+CONFIG_IP6_NF_TARGET_REJECT=m -+CONFIG_IP6_NF_TARGET_SYNPROXY=m -+CONFIG_IP6_NF_TARGET_HL=m -+CONFIG_NF_NAT_IPV6=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+# CONFIG_IP6_NF_TARGET_NPT is not set -+ -+# nf_tables support -+CONFIG_NF_TABLES=m -+CONFIG_NF_TABLES_INET=m -+CONFIG_NFT_EXTHDR=m -+CONFIG_NFT_META=m -+CONFIG_NFT_CT=m -+CONFIG_NFT_RBTREE=m -+CONFIG_NFT_HASH=m -+CONFIG_NFT_COUNTER=m -+CONFIG_NFT_LOG=m -+CONFIG_NFT_LIMIT=m -+CONFIG_NFT_NAT=m -+CONFIG_NFT_QUEUE=m -+CONFIG_NFT_REJECT=m -+CONFIG_NFT_COMPAT=m -+ -+CONFIG_NF_TABLES_IPV4=m -+CONFIG_NFT_REJECT_IPV4=m -+CONFIG_NFT_CHAIN_ROUTE_IPV4=m -+CONFIG_NFT_CHAIN_NAT_IPV4=m -+CONFIG_NF_TABLES_ARP=m -+ -+CONFIG_NF_TABLES_IPV6=m -+CONFIG_NFT_CHAIN_ROUTE_IPV6=m -+CONFIG_NFT_CHAIN_NAT_IPV6=m -+ -+CONFIG_NF_TABLES_BRIDGE=m -+# -+# Bridge: Netfilter Configuration -+# -+CONFIG_BRIDGE_NF_EBTABLES=m -+CONFIG_BRIDGE_EBT_802_3=m -+CONFIG_BRIDGE_EBT_AMONG=m -+CONFIG_BRIDGE_EBT_ARP=m -+CONFIG_BRIDGE_EBT_ARPREPLY=m -+CONFIG_BRIDGE_EBT_BROUTE=m -+CONFIG_BRIDGE_EBT_DNAT=m -+CONFIG_BRIDGE_EBT_IP=m -+CONFIG_BRIDGE_EBT_IP6=m -+CONFIG_BRIDGE_EBT_LIMIT=m -+CONFIG_BRIDGE_EBT_LOG=m -+CONFIG_BRIDGE_EBT_MARK=m -+CONFIG_BRIDGE_EBT_MARK_T=m -+CONFIG_BRIDGE_EBT_NFLOG=m -+CONFIG_BRIDGE_EBT_PKTTYPE=m -+CONFIG_BRIDGE_EBT_REDIRECT=m -+CONFIG_BRIDGE_EBT_SNAT=m -+CONFIG_BRIDGE_EBT_STP=m -+CONFIG_BRIDGE_EBT_T_FILTER=m -+CONFIG_BRIDGE_EBT_T_NAT=m -+CONFIG_BRIDGE_EBT_ULOG=m -+CONFIG_BRIDGE_EBT_VLAN=m -+CONFIG_XFRM=y -+CONFIG_XFRM_MIGRATE=y -+CONFIG_XFRM_SUB_POLICY=y -+CONFIG_XFRM_STATISTICS=y -+CONFIG_XFRM_USER=y -+CONFIG_INET6_XFRM_MODE_TRANSPORT=m -+CONFIG_INET6_XFRM_MODE_TUNNEL=m -+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m -+CONFIG_INET6_XFRM_MODE_BEET=m -+ -+CONFIG_IP_SET=m -+CONFIG_IP_SET_MAX=256 -+CONFIG_IP_SET_BITMAP_IP=m -+CONFIG_IP_SET_BITMAP_IPMAC=m -+CONFIG_IP_SET_BITMAP_PORT=m -+CONFIG_IP_SET_HASH_IP=m -+CONFIG_IP_SET_HASH_IPPORT=m -+CONFIG_IP_SET_HASH_IPPORTIP=m -+CONFIG_IP_SET_HASH_IPPORTNET=m -+CONFIG_IP_SET_HASH_NETPORTNET=m -+CONFIG_IP_SET_HASH_NET=m -+CONFIG_IP_SET_HASH_NETNET=m -+CONFIG_IP_SET_HASH_NETPORT=m -+CONFIG_IP_SET_HASH_NETIFACE=m -+CONFIG_IP_SET_LIST_SET=m -+ -+# -+# SCTP Configuration (EXPERIMENTAL) -+# -+CONFIG_IP_SCTP=m -+CONFIG_NET_SCTPPROBE=m -+# CONFIG_SCTP_DBG_MSG is not set -+# CONFIG_SCTP_DBG_OBJCNT is not set -+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y -+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5 is not set -+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set -+CONFIG_SCTP_COOKIE_HMAC_MD5=y -+CONFIG_SCTP_COOKIE_HMAC_SHA1=y -+CONFIG_ATM=m -+CONFIG_VLAN_8021Q_GVRP=y -+CONFIG_VLAN_8021Q_MVRP=y -+CONFIG_LLC=m -+# CONFIG_LLC2 is not set -+CONFIG_IPX=m -+# CONFIG_IPX_INTERN is not set -+CONFIG_ATALK=m -+CONFIG_DEV_APPLETALK=m -+CONFIG_IPDDP=m -+CONFIG_IPDDP_ENCAP=y -+CONFIG_IPDDP_DECAP=y -+# CONFIG_X25 is not set -+# CONFIG_LAPB is not set -+# CONFIG_ECONET is not set -+CONFIG_WAN_ROUTER=m -+CONFIG_IP_DCCP=m -+CONFIG_IP_DCCP_CCID2=m -+# CONFIG_IP_DCCP_CCID2_DEBUG is not set -+CONFIG_IP_DCCP_CCID3=y -+# CONFIG_IP_DCCP_CCID3_DEBUG is not set -+# CONFIG_IP_DCCP_DEBUG is not set -+# CONFIG_NET_DCCPPROBE is not set -+ -+# -+# TIPC Configuration (EXPERIMENTAL) -+# -+CONFIG_TIPC=m -+CONFIG_TIPC_PORTS=8192 -+# CONFIG_TIPC_MEDIA_IB is not set -+# CONFIG_TIPC_ADVANCED is not set -+# CONFIG_TIPC_DEBUG is not set -+ -+CONFIG_NETLABEL=y -+ -+# -+# QoS and/or fair queueing -+# -+CONFIG_NET_SCHED=y -+CONFIG_NET_SCH_CBQ=m -+CONFIG_NET_SCH_DSMARK=m -+CONFIG_NET_SCH_DRR=m -+CONFIG_NET_SCH_GRED=m -+CONFIG_NET_SCH_HFSC=m -+CONFIG_NET_SCH_HTB=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_NETEM=m -+CONFIG_NET_SCH_PRIO=m -+CONFIG_NET_SCH_RED=m -+CONFIG_NET_SCH_SFQ=m -+CONFIG_NET_SCH_TBF=m -+CONFIG_NET_SCH_TEQL=m -+CONFIG_NET_SCH_SFB=m -+CONFIG_NET_SCH_MQPRIO=m -+CONFIG_NET_SCH_MULTIQ=m -+CONFIG_NET_SCH_CHOKE=m -+CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_FQ=m -+CONFIG_NET_SCH_HHF=m -+CONFIG_NET_SCH_PIE=m -+CONFIG_NET_SCH_PLUG=m -+CONFIG_NET_CLS=y -+CONFIG_NET_CLS_ACT=y -+CONFIG_NET_CLS_BASIC=m -+CONFIG_NET_CLS_CGROUP=y -+CONFIG_NET_CLS_BPF=m -+CONFIG_NET_CLS_FLOW=m -+CONFIG_NET_CLS_FW=m -+CONFIG_NET_CLS_IND=y -+CONFIG_NET_CLS_ROUTE4=m -+CONFIG_NET_CLS_ROUTE=y -+CONFIG_NET_CLS_RSVP=m -+CONFIG_NET_CLS_RSVP6=m -+CONFIG_NET_CLS_TCINDEX=m -+CONFIG_NET_CLS_U32=m -+CONFIG_CLS_U32_MARK=y -+CONFIG_CLS_U32_PERF=y -+CONFIG_NET_EMATCH=y -+CONFIG_NET_EMATCH_CMP=m -+CONFIG_NET_EMATCH_META=m -+CONFIG_NET_EMATCH_NBYTE=m -+CONFIG_NET_EMATCH_STACK=32 -+CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m -+CONFIG_NET_EMATCH_U32=m -+ -+CONFIG_NET_ACT_CSUM=m -+CONFIG_NET_ACT_GACT=m -+CONFIG_GACT_PROB=y -+CONFIG_NET_ACT_IPT=m -+CONFIG_NET_ACT_MIRRED=m -+CONFIG_NET_ACT_NAT=m -+CONFIG_NET_ACT_PEDIT=m -+CONFIG_NET_ACT_POLICE=m -+CONFIG_NET_ACT_SIMP=m -+CONFIG_NET_ACT_SKBEDIT=m -+ -+CONFIG_DCB=y -+CONFIG_DNS_RESOLVER=m -+CONFIG_BATMAN_ADV=m -+CONFIG_BATMAN_ADV_BLA=y -+CONFIG_BATMAN_ADV_DAT=y -+CONFIG_BATMAN_ADV_NC=y -+ -+# CONFIG_BATMAN_ADV_DEBUG is not set -+CONFIG_OPENVSWITCH=m -+CONFIG_OPENVSWITCH_GRE=y -+CONFIG_OPENVSWITCH_VXLAN=y -+CONFIG_VSOCKETS=m -+ -+ -+# -+# Network testing -+# -+CONFIG_NET_PKTGEN=m -+# CONFIG_NET_TCPPROBE is not set -+CONFIG_NET_DROP_MONITOR=y -+ -+# disable later --kyle -+ -+# -+# ARCnet devices -+# -+# CONFIG_ARCNET is not set -+CONFIG_IFB=m -+CONFIG_NET_TEAM=m -+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m -+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m -+CONFIG_NET_TEAM_MODE_LOADBALANCE=m -+CONFIG_NET_TEAM_MODE_BROADCAST=m -+CONFIG_NET_TEAM_MODE_RANDOM=m -+CONFIG_DUMMY=m -+CONFIG_BONDING=m -+CONFIG_MACVLAN=m -+CONFIG_MACVTAP=m -+CONFIG_VXLAN=m -+CONFIG_EQUALIZER=m -+CONFIG_TUN=m -+CONFIG_VETH=m -+CONFIG_NLMON=m -+ -+# -+# ATM -+# -+CONFIG_ATM_DRIVERS=y -+# CONFIG_ATM_DUMMY is not set -+CONFIG_ATM_CLIP=m -+CONFIG_ATM_LANE=m -+CONFIG_ATM_BR2684=m -+CONFIG_NET_SCH_ATM=m -+CONFIG_ATM_TCP=m -+# CONFIG_ATM_LANAI is not set -+CONFIG_ATM_ENI=m -+CONFIG_ATM_FIRESTREAM=m -+# CONFIG_ATM_ZATM is not set -+# CONFIG_ATM_IDT77252 is not set -+# CONFIG_ATM_AMBASSADOR is not set -+# CONFIG_ATM_HORIZON is not set -+# CONFIG_ATM_FORE200E is not set -+# CONFIG_ATM_FORE200E_USE_TASKLET is not set -+CONFIG_ATM_FORE200E_TX_RETRY=16 -+CONFIG_ATM_FORE200E_DEBUG=0 -+ -+CONFIG_ATM_HE=m -+CONFIG_PPTP=m -+CONFIG_PPPOATM=m -+CONFIG_PPPOL2TP=m -+CONFIG_ATM_NICSTAR=m -+# CONFIG_ATM_IA is not set -+# CONFIG_ATM_CLIP_NO_ICMP is not set -+# CONFIG_ATM_MPOA is not set -+# CONFIG_ATM_BR2684_IPFILTER is not set -+# CONFIG_ATM_ENI_DEBUG is not set -+# CONFIG_ATM_ENI_TUNE_BURST is not set -+# CONFIG_ATM_ZATM_DEBUG is not set -+# CONFIG_ATM_IDT77252_DEBUG is not set -+# CONFIG_ATM_IDT77252_RCV_ALL is not set -+# CONFIG_ATM_AMBASSADOR_DEBUG is not set -+# CONFIG_ATM_HORIZON_DEBUG is not set -+# CONFIG_ATM_HE_USE_SUNI is not set -+# CONFIG_ATM_NICSTAR_USE_SUNI is not set -+# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set -+# CONFIG_ATM_IA_DEBUG is not set -+CONFIG_ATM_SOLOS=m -+ -+CONFIG_L2TP=m -+CONFIG_L2TP_V3=y -+CONFIG_L2TP_IP=m -+CONFIG_L2TP_ETH=m -+ -+# CONFIG_CAIF is not set -+ -+CONFIG_RFKILL=m -+CONFIG_RFKILL_GPIO=m -+CONFIG_RFKILL_INPUT=y -+ -+ -+# -+# Ethernet (10 or 100Mbit) -+# -+ -+CONFIG_NET_VENDOR_ADAPTEC=y -+CONFIG_ADAPTEC_STARFIRE=m -+ -+CONFIG_NET_VENDOR_ALTEON=y -+CONFIG_ACENIC=m -+# CONFIG_ACENIC_OMIT_TIGON_I is not set -+ -+CONFIG_NET_VENDOR_AMD=y -+CONFIG_PCNET32=m -+CONFIG_AMD8111_ETH=m -+CONFIG_PCMCIA_NMCLAN=m -+ -+CONFIG_NET_VENDOR_ARC=y -+CONFIG_ARC_EMAC=m -+ -+CONFIG_NET_VENDOR_ATHEROS=y -+CONFIG_ALX=m -+CONFIG_ATL2=m -+CONFIG_ATL1=m -+CONFIG_ATL1C=m -+CONFIG_ATL1E=m -+CONFIG_NET_CADENCE=y -+CONFIG_ARM_AT91_ETHER=m -+CONFIG_MACB=m -+ -+CONFIG_NET_VENDOR_BROCADE=y -+CONFIG_BNA=m -+CONFIG_NET_CALXEDA_XGMAC=m -+ -+CONFIG_NET_VENDOR_CHELSIO=y -+CONFIG_CHELSIO_T1=m -+CONFIG_CHELSIO_T1_1G=y -+CONFIG_CHELSIO_T3=m -+CONFIG_CHELSIO_T4=m -+CONFIG_CHELSIO_T4VF=m -+ -+CONFIG_NET_VENDOR_CISCO=y -+CONFIG_ENIC=m -+ -+CONFIG_NET_VENDOR_DEC=y -+# -+# Tulip family network device support -+# -+CONFIG_NET_TULIP=y -+CONFIG_DE2104X=m -+CONFIG_DE2104X_DSL=0 -+CONFIG_TULIP=m -+# CONFIG_TULIP_NAPI is not set -+# CONFIG_TULIP_MWI is not set -+CONFIG_TULIP_MMIO=y -+# CONFIG_NI5010 is not set -+CONFIG_DE4X5=m -+CONFIG_WINBOND_840=m -+CONFIG_DM9102=m -+CONFIG_PCMCIA_XIRCOM=m -+CONFIG_ULI526X=m -+ -+CONFIG_NET_VENDOR_DLINK=y -+CONFIG_DE600=m -+CONFIG_DE620=m -+CONFIG_DL2K=m -+CONFIG_SUNDANCE=m -+# CONFIG_SUNDANCE_MMIO is not set -+ -+CONFIG_NET_VENDOR_EMULEX=y -+CONFIG_BE2NET=m -+ -+CONFIG_NET_VENDOR_EXAR=y -+CONFIG_S2IO=m -+CONFIG_VXGE=m -+# CONFIG_VXGE_DEBUG_TRACE_ALL is not set -+ -+# CONFIG_NET_VENDOR_FARADAY is not set -+# CONFIG_NET_VENDOR_FUJITSU is not set -+# CONFIG_NET_VENDOR_HP is not set -+CONFIG_NET_VENDOR_INTEL=y -+CONFIG_E100=m -+CONFIG_E1000=m -+CONFIG_E1000E=m -+CONFIG_IGB=m -+CONFIG_IGB_HWMON=y -+CONFIG_IGB_DCA=y -+CONFIG_IGB_PTP=y -+CONFIG_IGBVF=m -+CONFIG_IXGB=m -+CONFIG_IXGBEVF=m -+CONFIG_IXGBE=m -+CONFIG_IXGBE_DCA=y -+CONFIG_IXGBE_DCB=y -+CONFIG_IXGBE_HWMON=y -+CONFIG_IXGBE_PTP=y -+CONFIG_I40E=m -+# CONFIG_I40E_VXLAN is not set -+# CONFIG_I40E_DCB is not set -+# CONFIG_I40EVF is not set -+ -+ -+# CONFIG_NET_VENDOR_I825XX is not set -+CONFIG_NET_VENDOR_MARVELL=y -+CONFIG_MVMDIO=m -+CONFIG_SKGE=m -+# CONFIG_SKGE_DEBUG is not set -+CONFIG_SKGE_GENESIS=y -+CONFIG_SKY2=m -+# CONFIG_SKY2_DEBUG is not set -+ -+CONFIG_NET_VENDOR_MICREL=y -+CONFIG_KSZ884X_PCI=m -+# CONFIG_KS8842 is not set -+# CONFIG_KS8851_MLL is not set -+ -+CONFIG_NET_VENDOR_MYRI=y -+CONFIG_MYRI10GE=m -+CONFIG_MYRI10GE_DCA=y -+ -+CONFIG_NATSEMI=m -+CONFIG_NS83820=m -+ -+CONFIG_PCMCIA_AXNET=m -+CONFIG_NE2K_PCI=m -+CONFIG_NE3210=m -+CONFIG_PCMCIA_PCNET=m -+ -+CONFIG_NET_VENDOR_NVIDIA=y -+CONFIG_FORCEDETH=m -+ -+CONFIG_NET_VENDOR_OKI=y -+# CONFIG_PCH_GBE is not set -+# CONFIG_PCH_PTP is not set -+ -+CONFIG_NET_PACKET_ENGINE=y -+CONFIG_HAMACHI=m -+CONFIG_YELLOWFIN=m -+ -+CONFIG_NET_VENDOR_QLOGIC=y -+CONFIG_QLA3XXX=m -+CONFIG_QLCNIC=m -+CONFIG_QLCNIC_SRIOV=y -+CONFIG_QLCNIC_DCB=y -+CONFIG_QLGE=m -+CONFIG_NETXEN_NIC=m -+ -+CONFIG_NET_VENDOR_REALTEK=y -+CONFIG_ATP=m -+CONFIG_8139CP=m -+CONFIG_8139TOO=m -+# CONFIG_8139TOO_PIO is not set -+# CONFIG_8139TOO_TUNE_TWISTER is not set -+CONFIG_8139TOO_8129=y -+# CONFIG_8139_OLD_RX_RESET is not set -+CONFIG_R8169=m -+ -+ -+CONFIG_NET_VENDOR_RDC=y -+CONFIG_R6040=m -+ -+ -+CONFIG_NET_VENDOR_SILAN=y -+CONFIG_SC92031=m -+ -+CONFIG_NET_VENDOR_SIS=y -+CONFIG_SIS900=m -+CONFIG_SIS190=m -+ -+CONFIG_PCMCIA_SMC91C92=m -+CONFIG_EPIC100=m -+CONFIG_SMSC9420=m -+ -+# CONFIG_STMMAC_PLATFORM is not set -+# CONFIG_STMMAC_PCI is not set -+# CONFIG_STMMAC_DA is not set -+# CONFIG_STMMAC_DUAL_MAC is not set -+# CONFIG_STMMAC_TIMER is not set -+# CONFIG_STMMAC_DEBUG_FS is not set -+ -+CONFIG_NET_VENDOR_SUN=y -+CONFIG_HAPPYMEAL=m -+CONFIG_SUNGEM=m -+CONFIG_CASSINI=m -+CONFIG_NIU=m -+ -+CONFIG_NET_VENDOR_TEHUTI=y -+CONFIG_TEHUTI=m -+ -+CONFIG_NET_VENDOR_TI=y -+CONFIG_TLAN=m -+ -+CONFIG_VIA_RHINE=m -+CONFIG_VIA_RHINE_MMIO=y -+ -+CONFIG_WIZNET_W5100=m -+CONFIG_WIZNET_W5300=m -+CONFIG_NET_VENDOR_XIRCOM=y -+CONFIG_PCMCIA_XIRC2PS=m -+ -+CONFIG_AMD_PHY=m -+CONFIG_BROADCOM_PHY=m -+CONFIG_BCM87XX_PHY=m -+CONFIG_CICADA_PHY=m -+CONFIG_DAVICOM_PHY=m -+CONFIG_DP83640_PHY=m -+CONFIG_FIXED_PHY=y -+CONFIG_MDIO_BITBANG=m -+CONFIG_NATIONAL_PHY=m -+CONFIG_ICPLUS_PHY=m -+CONFIG_BCM63XX_PHY=m -+CONFIG_LSI_ET1011C_PHY=m -+CONFIG_LXT_PHY=m -+CONFIG_MARVELL_PHY=m -+CONFIG_QSEMI_PHY=m -+CONFIG_REALTEK_PHY=m -+CONFIG_SMSC_PHY=m -+CONFIG_STE10XP=m -+CONFIG_VITESSE_PHY=m -+CONFIG_MICREL_PHY=m -+ -+CONFIG_MII=m -+CONFIG_NET_CORE=y -+CONFIG_NET_VENDOR_3COM=y -+CONFIG_VORTEX=m -+CONFIG_TYPHOON=m -+CONFIG_DNET=m -+ -+ -+CONFIG_LNE390=m -+CONFIG_ES3210=m -+CONFIG_NET_PCI=y -+CONFIG_B44=m -+CONFIG_B44_PCI=y -+CONFIG_BNX2=m -+CONFIG_BNX2X=m -+CONFIG_BNX2X_SRIOV=y -+CONFIG_CNIC=m -+CONFIG_FEALNX=m -+CONFIG_NET_POCKET=y -+ -+# -+# Ethernet (1000 Mbit) -+# -+CONFIG_TIGON3=m -+CONFIG_JME=m -+ -+# -+# Ethernet (10000 Mbit) -+# -+# CONFIG_IP1000 is not set -+# CONFIG_MLX4_EN is not set -+# CONFIG_SFC is not set -+ -+# CONFIG_FDDI is not set -+# CONFIG_DEFXX is not set -+# CONFIG_SKFP is not set -+# CONFIG_HIPPI is not set -+# CONFIG_PLIP is not set -+CONFIG_PPP=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_IPPP_FILTER=y -+CONFIG_PPP_BSDCOMP=y -+CONFIG_PPPOE=m -+CONFIG_PPP_MPPE=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y -+# CONFIG_SLIP_MODE_SLIP6 is not set -+ -+# -+# Wireless LAN -+# -+# -+# CONFIG_STRIP is not set -+# CONFIG_PCMCIA_RAYCS is not set -+ -+CONFIG_CFG80211_WEXT=y -+# CONFIG_CFG80211_REG_DEBUG is not set -+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set -+CONFIG_CFG80211_DEFAULT_PS=y -+CONFIG_NL80211=y -+# CONFIG_NL80211_TESTMODE is not set -+# CONFIG_WIRELESS_EXT_SYSFS is not set -+CONFIG_LIB80211=m -+CONFIG_LIB80211_CRYPT_WEP=m -+CONFIG_LIB80211_CRYPT_CCMP=m -+CONFIG_LIB80211_CRYPT_TKIP=m -+# CONFIG_LIB80211_DEBUG is not set -+ -+CONFIG_MAC80211=m -+CONFIG_MAC80211_RC_MINSTREL=y -+# CONFIG_MAC80211_RC_DEFAULT_PID is not set -+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -+CONFIG_MAC80211_RC_DEFAULT="minstrel" -+CONFIG_MAC80211_MESH=y -+CONFIG_MAC80211_LEDS=y -+# CONFIG_MAC80211_DEBUG_MENU is not set -+ -+# CONFIG_WIMAX is not set -+ -+# CONFIG_ADM8211 is not set -+CONFIG_ATH_COMMON=m -+CONFIG_ATH_CARDS=m -+CONFIG_ATH5K=m -+CONFIG_ATH5K_DEBUG=y -+# CONFIG_ATH5K_TRACER is not set -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_DEBUG=y -+CONFIG_ATH6KL_SDIO=m -+CONFIG_ATH6KL_USB=m -+# CONFIG_ATH6KL_TRACING is not set -+CONFIG_AR5523=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_PCI=y -+CONFIG_ATH9K_AHB=y -+# CONFIG_ATH9K_DEBUG is not set -+# CONFIG_ATH9K_MAC_DEBUG is not set -+CONFIG_ATH9K_HTC=m -+CONFIG_ATH9K_BTCOEX_SUPPORT=y -+# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set -+# CONFIG_ATH9K_WOW is not set -+# -+CONFIG_ATH10K=m -+CONFIG_ATH10K_PCI=m -+# CONFIG_ATH10K_DEBUG is not set -+# CONFIG_ATH10K_TRACING is not set -+CONFIG_ATH10K_DEBUGFS=y -+CONFIG_WCN36XX=m -+# CONFIG_WCN36XX_DEBUGFS is not set -+CONFIG_WIL6210=m -+CONFIG_WIL6210_ISR_COR=y -+# CONFIG_WIL6210_TRACING is not set -+CONFIG_CARL9170=m -+CONFIG_CARL9170_LEDS=y -+# CONFIG_CARL9170_HWRNG is not set -+CONFIG_AT76C50X_USB=m -+# CONFIG_AIRO is not set -+# CONFIG_AIRO_CS is not set -+# CONFIG_ATMEL is not set -+CONFIG_B43=m -+CONFIG_B43_PCMCIA=y -+CONFIG_B43_SDIO=y -+CONFIG_B43_BCMA=y -+# CONFIG_B43_BCMA_EXTRA is not set -+CONFIG_B43_BCMA_PIO=y -+# CONFIG_B43_DEBUG is not set -+CONFIG_B43_PHY_LP=y -+CONFIG_B43_PHY_N=y -+CONFIG_B43_PHY_HT=y -+# CONFIG_B43_FORCE_PIO is not set -+CONFIG_B43LEGACY=m -+# CONFIG_B43LEGACY_DEBUG is not set -+CONFIG_B43LEGACY_DMA=y -+CONFIG_B43LEGACY_PIO=y -+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y -+# CONFIG_B43LEGACY_DMA_MODE is not set -+# CONFIG_B43LEGACY_PIO_MODE is not set -+CONFIG_BRCMSMAC=m -+# CONFIG_BRCMFMAC_SDIO_OOB is not set -+CONFIG_BRCMFMAC_USB=y -+# CONFIG_BRCM_TRACING is not set -+# CONFIG_BRCMISCAN is not set -+# CONFIG_BRCMDBG is not set -+CONFIG_HERMES=m -+CONFIG_HERMES_CACHE_FW_ON_INIT=y -+# CONFIG_HERMES_PRISM is not set -+CONFIG_NORTEL_HERMES=m -+CONFIG_PCI_HERMES=m -+CONFIG_PLX_HERMES=m -+CONFIG_PCMCIA_HERMES=m -+CONFIG_ORINOCO_USB=m -+# CONFIG_TMD_HERMES is not set -+# CONFIG_PCMCIA_SPECTRUM is not set -+CONFIG_CW1200=m -+CONFIG_CW1200_WLAN_SDIO=m -+CONFIG_CW1200_WLAN_SPI=m -+# CONFIG_HOSTAP is not set -+# CONFIG_IPW2100 is not set -+# CONFIG_IPW2200 is not set -+# CONFIG_IPW2100_DEBUG is not set -+# CONFIG_IPW2200_DEBUG is not set -+# CONFIG_LIBIPW_DEBUG is not set -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_CS=m -+CONFIG_LIBERTAS_SDIO=m -+# CONFIG_LIBERTAS_DEBUG is not set -+# CONFIG_LIBERTAS_THINFIRM is not set -+CONFIG_LIBERTAS_MESH=y -+CONFIG_IWLWIFI=m -+CONFIG_IWLDVM=m -+CONFIG_IWLMVM=m -+CONFIG_IWLWIFI_DEBUG=y -+CONFIG_IWLWIFI_DEVICE_SVTOOL=y -+# CONFIG_IWLWIFI_EXPERIMENTAL_MFP is not set -+CONFIG_IWLWIFI_UCODE16=y -+# CONFIG_IWLWIFI_P2P is not set -+CONFIG_IWLEGACY=m -+CONFIG_IWLEGACY_DEBUG=y -+# CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING is not set -+CONFIG_IWL4965=y -+CONFIG_IWL3945=m -+# CONFIG_IWM is not set -+# CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE is not set -+CONFIG_MAC80211_HWSIM=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_P54_PCI=m -+CONFIG_MWL8K=m -+# CONFIG_PRISM54 is not set -+# CONFIG_PCMCIA_WL3501 is not set -+CONFIG_RT2X00=m -+# CONFIG_RT2X00_DEBUG is not set -+CONFIG_RT2400PCI=m -+CONFIG_RT2500PCI=m -+CONFIG_RT61PCI=m -+CONFIG_RT2500USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT33XX=y -+CONFIG_RT2800USB_RT35XX=y -+CONFIG_RT2800USB_RT3573=y -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_RT55XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_RT2800PCI=m -+CONFIG_RT2800PCI_RT3290=y -+CONFIG_RT2800PCI_RT33XX=y -+CONFIG_RT2800PCI_RT35XX=y -+CONFIG_RT2800PCI_RT53XX=y -+CONFIG_RT73USB=m -+CONFIG_RTL8180=m -+CONFIG_RTL8187=m -+# CONFIG_USB_ZD1201 is not set -+# CONFIG_USB_NET_SR9800 is not set -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_NET_SMSC75XX=m -+# CONFIG_WL_TI is not set -+CONFIG_ZD1211RW=m -+# CONFIG_ZD1211RW_DEBUG is not set -+ -+CONFIG_WL12XX=m -+CONFIG_WL12XX_SPI=m -+CONFIG_WL12XX_SDIO=m -+ -+CONFIG_WL1251=m -+CONFIG_WL1251_SPI=m -+CONFIG_WL1251_SDIO=m -+ -+CONFIG_RTL_CARDS=m -+CONFIG_RTLWIFI=m -+CONFIG_RTL8192CE=m -+CONFIG_RTL8192SE=m -+CONFIG_RTL8192CU=m -+CONFIG_RTL8192DE=m -+CONFIG_RTL8723AE=m -+CONFIG_RTL8188EE=m -+ -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_MWIFIEX_PCIE=m -+CONFIG_MWIFIEX_USB=m -+ -+# -+# Token Ring devices -+# -+# CONFIG_TR is not set -+ -+CONFIG_NET_FC=y -+ -+# -+# Wan interfaces -+# -+# CONFIG_WAN is not set -+ -+# -+# PCMCIA network device support -+# -+CONFIG_NET_PCMCIA=y -+CONFIG_PCMCIA_3C589=m -+CONFIG_PCMCIA_3C574=m -+CONFIG_PCMCIA_FMVJ18X=m -+ -+# -+# Amateur Radio support -+# -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_AX25_DAMA_SLAVE=y -+ -+# CONFIG_CAN is not set -+ -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_BAYCOM_PAR=m -+CONFIG_BAYCOM_EPP=m -+CONFIG_YAM=m -+ -+CONFIG_NFC=m -+CONFIG_NFC_DIGITAL=m -+CONFIG_NFC_NCI=m -+CONFIG_NFC_HCI=m -+CONFIG_NFC_SHDLC=y -+CONFIG_NFC_LLCP=y -+CONFIG_NFC_SIM=m -+CONFIG_NFC_MRVL=m -+CONFIG_NFC_MRVL_USB=m -+ -+# -+# Near Field Communication (NFC) devices -+# -+CONFIG_NFC_PORT100=m -+CONFIG_NFC_PN544=m -+CONFIG_NFC_PN544_I2C=m -+CONFIG_NFC_PN533=m -+CONFIG_NFC_MICROREAD=m -+CONFIG_NFC_MICROREAD_I2C=m -+ -+# -+# IrDA (infrared) support -+# -+CONFIG_IRDA=m -+# CONFIG_IRDA_DEBUG is not set -+CONFIG_IRLAN=m -+CONFIG_IRNET=m -+CONFIG_IRCOMM=m -+# CONFIG_IRDA_ULTRA is not set -+CONFIG_IRDA_CACHE_LAST_LSAP=y -+CONFIG_IRDA_FAST_RR=y -+CONFIG_IRTTY_SIR=m -+CONFIG_DONGLE=y -+CONFIG_ACTISYS_DONGLE=m -+CONFIG_ACT200L_DONGLE=m -+CONFIG_ESI_DONGLE=m -+CONFIG_GIRBIL_DONGLE=m -+CONFIG_KINGSUN_DONGLE=m -+CONFIG_KSDAZZLE_DONGLE=m -+CONFIG_KS959_DONGLE=m -+CONFIG_LITELINK_DONGLE=m -+CONFIG_MA600_DONGLE=m -+CONFIG_MCP2120_DONGLE=m -+CONFIG_OLD_BELKIN_DONGLE=m -+CONFIG_TEKRAM_DONGLE=m -+CONFIG_TOIM3232_DONGLE=m -+ -+CONFIG_ALI_FIR=m -+CONFIG_MCS_FIR=m -+CONFIG_NSC_FIR=m -+CONFIG_SIGMATEL_FIR=m -+CONFIG_SMC_IRCC_FIR=m -+# CONFIG_TOSHIBA_FIR is not set -+CONFIG_USB_IRDA=m -+CONFIG_VLSI_FIR=m -+CONFIG_VIA_FIR=m -+CONFIG_WINBOND_FIR=m -+ -+# -+# Bluetooth support -+# -+CONFIG_BT=m -+CONFIG_BT_L2CAP=y -+CONFIG_BT_SCO=y -+CONFIG_BT_CMTP=m -+CONFIG_BT_RFCOMM=m -+CONFIG_BT_RFCOMM_TTY=y -+CONFIG_BT_BNEP=m -+CONFIG_BT_BNEP_MC_FILTER=y -+CONFIG_BT_BNEP_PROTO_FILTER=y -+CONFIG_BT_HIDP=m -+ -+# -+# Bluetooth device drivers -+# -+CONFIG_BT_HCIBTUSB=m -+# Disable the BT_HCIUSB driver. -+# It sucks more power than BT_HCIBTUSB which has the same functionality. -+CONFIG_BT_HCIUART=m -+CONFIG_BT_HCIUART_H4=y -+CONFIG_BT_HCIUART_BCSP=y -+CONFIG_BT_HCIUART_ATH3K=y -+CONFIG_BT_HCIUART_3WIRE=y -+CONFIG_BT_HCIDTL1=m -+CONFIG_BT_HCIBT3C=m -+CONFIG_BT_HCIBLUECARD=m -+CONFIG_BT_HCIBTUART=m -+CONFIG_BT_HCIVHCI=m -+CONFIG_BT_HCIBCM203X=m -+CONFIG_BT_HCIBFUSB=m -+CONFIG_BT_HCIBPA10X=m -+CONFIG_BT_HCIBTSDIO=m -+CONFIG_BT_HCIUART_LL=y -+CONFIG_BT_MRVL=m -+CONFIG_BT_MRVL_SDIO=m -+CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+ -+# -+# ISDN subsystem -+# -+CONFIG_ISDN=y -+CONFIG_MISDN=m -+CONFIG_MISDN_DSP=m -+CONFIG_MISDN_L1OIP=m -+CONFIG_MISDN_AVMFRITZ=m -+CONFIG_MISDN_SPEEDFAX=m -+CONFIG_MISDN_INFINEON=m -+CONFIG_MISDN_W6692=m -+CONFIG_MISDN_NETJET=m -+ -+# -+# mISDN hardware drivers -+# -+CONFIG_MISDN_HFCPCI=m -+CONFIG_MISDN_HFCMULTI=m -+CONFIG_ISDN_I4L=m -+CONFIG_ISDN_DRV_AVMB1_B1PCI=m -+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m -+CONFIG_ISDN_DRV_AVMB1_T1PCI=m -+CONFIG_ISDN_DRV_AVMB1_C4=m -+ -+CONFIG_MISDN_HFCUSB=m -+ -+CONFIG_ISDN_PPP=y -+CONFIG_ISDN_PPP_VJ=y -+CONFIG_ISDN_MPP=y -+# CONFIG_ISDN_PPP_BSDCOMP is not set -+CONFIG_ISDN_TTY_FAX=y -+CONFIG_DE_AOC=y -+ -+CONFIG_ISDN_AUDIO=y -+ -+CONFIG_ISDN_DRV_HISAX=m -+CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y -+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m -+ -+CONFIG_ISDN_CAPI_CAPIDRV=m -+CONFIG_ISDN_DIVERSION=m -+ -+CONFIG_HISAX_EURO=y -+CONFIG_HISAX_1TR6=y -+CONFIG_HISAX_NI1=y -+CONFIG_HISAX_MAX_CARDS=8 -+CONFIG_HISAX_16_3=y -+CONFIG_HISAX_TELESPCI=y -+CONFIG_HISAX_S0BOX=y -+CONFIG_HISAX_FRITZPCI=y -+CONFIG_HISAX_AVM_A1_PCMCIA=y -+CONFIG_HISAX_ELSA=y -+CONFIG_HISAX_DIEHLDIVA=y -+CONFIG_HISAX_SEDLBAUER=y -+CONFIG_HISAX_NETJET=y -+CONFIG_HISAX_NETJET_U=y -+CONFIG_HISAX_NICCY=y -+CONFIG_HISAX_BKM_A4T=y -+CONFIG_HISAX_SCT_QUADRO=y -+CONFIG_HISAX_GAZEL=y -+CONFIG_HISAX_HFC_PCI=y -+CONFIG_HISAX_W6692=y -+CONFIG_HISAX_HFC_SX=y -+CONFIG_HISAX_ENTERNOW_PCI=y -+# CONFIG_HISAX_DEBUG is not set -+CONFIG_HISAX_AVM_A1_CS=m -+CONFIG_HISAX_ST5481=m -+# CONFIG_HISAX_HFCUSB is not set -+CONFIG_HISAX_FRITZ_PCIPNP=m -+CONFIG_HISAX_NO_SENDCOMPLETE=y -+CONFIG_HISAX_NO_LLC=y -+CONFIG_HISAX_NO_KEYPAD=y -+CONFIG_HISAX_SEDLBAUER_CS=m -+CONFIG_HISAX_ELSA_CS=m -+CONFIG_HISAX_TELES_CS=m -+CONFIG_HISAX_HFC4S8S=m -+ -+CONFIG_ISDN_DRV_LOOP=m -+CONFIG_HYSDN=m -+CONFIG_HYSDN_CAPI=y -+ -+ -+# -+# CAPI subsystem -+# -+CONFIG_ISDN_CAPI=m -+# CONFIG_CAPI_TRACE is not set -+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y -+CONFIG_ISDN_CAPI_MIDDLEWARE=y -+CONFIG_ISDN_CAPI_CAPI20=m -+ -+# -+# CAPI hardware drivers -+# -+ -+# -+# Active AVM cards -+# -+CONFIG_CAPI_AVM=y -+ -+# -+# Active Eicon DIVA Server cards -+# -+# CONFIG_CAPI_EICON is not set -+CONFIG_ISDN_DIVAS=m -+CONFIG_ISDN_DIVAS_BRIPCI=y -+CONFIG_ISDN_DIVAS_PRIPCI=y -+CONFIG_ISDN_DIVAS_DIVACAPI=m -+CONFIG_ISDN_DIVAS_USERIDI=m -+CONFIG_ISDN_DIVAS_MAINT=m -+ -+CONFIG_ISDN_DRV_GIGASET=m -+CONFIG_GIGASET_CAPI=y -+CONFIG_GIGASET_BASE=m -+CONFIG_GIGASET_M101=m -+CONFIG_GIGASET_M105=m -+# CONFIG_GIGASET_DEBUG is not set -+ -+# -+# Telephony Support -+# -+# CONFIG_PHONE is not set -+ -+# -+# Input device support -+# -+CONFIG_INPUT=y -+CONFIG_INPUT_FF_MEMLESS=m -+ -+# -+# Userland interfaces -+# -+CONFIG_INPUT_MOUSEDEV=y -+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -+CONFIG_INPUT_JOYDEV=m -+# CONFIG_INPUT_MATRIXKMAP is not set -+ -+CONFIG_INPUT_TABLET=y -+CONFIG_TABLET_USB_ACECAD=m -+CONFIG_TABLET_USB_AIPTEK=m -+CONFIG_TABLET_USB_GTCO=m -+CONFIG_TABLET_USB_HANWANG=m -+CONFIG_TABLET_USB_KBTAB=m -+CONFIG_TABLET_USB_WACOM=m -+ -+CONFIG_INPUT_POWERMATE=m -+CONFIG_INPUT_YEALINK=m -+CONFIG_INPUT_CM109=m -+CONFIG_INPUT_POLLDEV=m -+CONFIG_INPUT_SPARSEKMAP=m -+# CONFIG_INPUT_ADXL34X is not set -+# CONFIG_INPUT_BMA150 is not set -+# CONFIG_INPUT_IMS_PCU is not set -+CONFIG_INPUT_CMA3000=m -+CONFIG_INPUT_CMA3000_I2C=m -+CONFIG_INPUT_IDEAPAD_SLIDEBAR=m -+ -+# -+# Input I/O drivers -+# -+CONFIG_GAMEPORT=m -+CONFIG_GAMEPORT_NS558=m -+CONFIG_GAMEPORT_L4=m -+CONFIG_GAMEPORT_EMU10K1=m -+CONFIG_GAMEPORT_FM801=m -+CONFIG_SERIO=y -+CONFIG_SERIO_I8042=y -+CONFIG_SERIO_RAW=m -+CONFIG_SERIO_ALTERA_PS2=m -+# CONFIG_SERIO_PS2MULT is not set -+CONFIG_SERIO_ARC_PS2=m -+# CONFIG_SERIO_APBPS2 is not set -+ -+# CONFIG_SERIO_CT82C710 is not set -+# CONFIG_SERIO_OLPC_APSP is not set -+# CONFIG_SERIO_PARKBD is not set -+# CONFIG_SERIO_PCIPS2 is not set -+# CONFIG_SERIO_LIBPS2 is not set -+ -+# -+# Input Device Drivers -+# -+CONFIG_INPUT_KEYBOARD=y -+# CONFIG_KEYBOARD_SUNKBD is not set -+# CONFIG_KEYBOARD_SH_KEYSC is not set -+# CONFIG_KEYBOARD_XTKBD is not set -+# CONFIG_KEYBOARD_MATRIX is not set -+# CONFIG_KEYBOARD_NEWTON is not set -+# CONFIG_KEYBOARD_STOWAWAY is not set -+# CONFIG_KEYBOARD_LKKBD is not set -+# CONFIG_KEYBOARD_LM8323 is not set -+# CONFIG_KEYBOARD_LM8333 is not set -+# CONFIG_KEYBOARD_MAX7359 is not set -+# CONFIG_KEYBOARD_ADP5589 is not set -+# CONFIG_KEYBOARD_MPR121 is not set -+# CONFIG_KEYBOARD_QT1070 is not set -+# CONFIG_KEYBOARD_MCS is not set -+# CONFIG_KEYBOARD_OPENCORES is not set -+# CONFIG_KEYBOARD_SAMSUNG is not set -+# CONFIG_KEYBOARD_QT2160 is not set -+# CONFIG_KEYBOARD_TCA6416 is not set -+# CONFIG_KEYBOARD_TCA8418 is not set -+# CONFIG_KEYBOARD_OMAP4 is not set -+CONFIG_INPUT_MOUSE=y -+# CONFIG_MOUSE_PS2_TOUCHKIT is not set -+CONFIG_MOUSE_PS2_ELANTECH=y -+CONFIG_MOUSE_PS2_SENTELIC=y -+CONFIG_MOUSE_SERIAL=m -+CONFIG_MOUSE_VSXXXAA=m -+CONFIG_MOUSE_APPLETOUCH=m -+CONFIG_MOUSE_BCM5974=m -+CONFIG_MOUSE_SYNAPTICS_I2C=m -+CONFIG_MOUSE_SYNAPTICS_USB=m -+CONFIG_MOUSE_CYAPA=m -+CONFIG_INPUT_JOYSTICK=y -+CONFIG_JOYSTICK_ANALOG=m -+CONFIG_JOYSTICK_A3D=m -+CONFIG_JOYSTICK_ADI=m -+CONFIG_JOYSTICK_COBRA=m -+CONFIG_JOYSTICK_GF2K=m -+CONFIG_JOYSTICK_GRIP=m -+CONFIG_JOYSTICK_GRIP_MP=m -+CONFIG_JOYSTICK_GUILLEMOT=m -+CONFIG_JOYSTICK_INTERACT=m -+CONFIG_JOYSTICK_SIDEWINDER=m -+CONFIG_JOYSTICK_TMDC=m -+CONFIG_JOYSTICK_IFORCE=m -+CONFIG_JOYSTICK_IFORCE_USB=y -+CONFIG_JOYSTICK_IFORCE_232=y -+CONFIG_JOYSTICK_WARRIOR=m -+CONFIG_JOYSTICK_MAGELLAN=m -+CONFIG_JOYSTICK_SPACEORB=m -+CONFIG_JOYSTICK_SPACEBALL=m -+CONFIG_JOYSTICK_STINGER=m -+CONFIG_JOYSTICK_DB9=m -+CONFIG_JOYSTICK_GAMECON=m -+CONFIG_JOYSTICK_TURBOGRAFX=m -+CONFIG_JOYSTICK_JOYDUMP=m -+CONFIG_JOYSTICK_TWIDJOY=m -+CONFIG_JOYSTICK_WALKERA0701=m -+CONFIG_JOYSTICK_XPAD=m -+CONFIG_JOYSTICK_XPAD_FF=y -+CONFIG_JOYSTICK_XPAD_LEDS=y -+CONFIG_JOYSTICK_ZHENHUA=m -+# CONFIG_JOYSTICK_AS5011 is not set -+ -+CONFIG_INPUT_TOUCHSCREEN=y -+# CONFIG_TOUCHSCREEN_AD7879 is not set -+CONFIG_TOUCHSCREEN_AD7879_I2C=m -+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set -+# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set -+# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set -+CONFIG_TOUCHSCREEN_DYNAPRO=m -+CONFIG_TOUCHSCREEN_EDT_FT5X06=m -+CONFIG_TOUCHSCREEN_EETI=m -+CONFIG_TOUCHSCREEN_EGALAX=m -+CONFIG_TOUCHSCREEN_ELO=m -+CONFIG_TOUCHSCREEN_FUJITSU=m -+CONFIG_TOUCHSCREEN_GUNZE=m -+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set -+CONFIG_TOUCHSCREEN_INEXIO=m -+CONFIG_TOUCHSCREEN_ILI210X=m -+CONFIG_TOUCHSCREEN_MMS114=m -+CONFIG_TOUCHSCREEN_MTOUCH=m -+CONFIG_TOUCHSCREEN_MCS5000=m -+CONFIG_TOUCHSCREEN_MK712=m -+CONFIG_TOUCHSCREEN_PENMOUNT=m -+# CONFIG_TOUCHSCREEN_SUR40 is not set -+# CONFIG_TOUCHSCREEN_TPS6507X is not set -+CONFIG_TOUCHSCREEN_TSC_SERIO=m -+CONFIG_TOUCHSCREEN_TSC2007=m -+CONFIG_TOUCHSCREEN_TOUCHIT213=m -+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m -+CONFIG_TOUCHSCREEN_TOUCHWIN=m -+CONFIG_TOUCHSCREEN_PIXCIR=m -+CONFIG_TOUCHSCREEN_UCB1400=m -+CONFIG_TOUCHSCREEN_WACOM_W8001=m -+CONFIG_TOUCHSCREEN_WACOM_I2C=m -+CONFIG_TOUCHSCREEN_USB_E2I=y -+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m -+# CONFIG_TOUCHSCREEN_WM97XX is not set -+CONFIG_TOUCHSCREEN_W90X900=m -+# CONFIG_TOUCHSCREEN_BU21013 is not set -+CONFIG_TOUCHSCREEN_ST1232=m -+CONFIG_TOUCHSCREEN_ATMEL_MXT=m -+# CONFIG_TOUCHSCREEN_MAX11801 is not set -+CONFIG_TOUCHSCREEN_AUO_PIXCIR=m -+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m -+CONFIG_TOUCHSCREEN_ZFORCE=m -+ -+CONFIG_INPUT_PCSPKR=m -+CONFIG_INPUT_RETU_PWRBUTTON=m -+CONFIG_INPUT_UINPUT=m -+CONFIG_INPUT_WISTRON_BTNS=m -+CONFIG_INPUT_ATLAS_BTNS=m -+ -+CONFIG_INPUT_ATI_REMOTE2=m -+CONFIG_INPUT_KEYSPAN_REMOTE=m -+ -+CONFIG_MAC_EMUMOUSEBTN=y -+ -+CONFIG_INPUT_WM831X_ON=m -+ -+ -+# CONFIG_INPUT_AD714X is not set -+# CONFIG_INPUT_PCF8574 is not set -+CONFIG_INPUT_MMA8450=m -+CONFIG_INPUT_MPU3050=m -+CONFIG_INPUT_KXTJ9=m -+# CONFIG_INPUT_KXTJ9_POLLED_MODE is not set -+ -+# -+# Character devices -+# -+CONFIG_VT=y -+CONFIG_VT_CONSOLE=y -+CONFIG_HW_CONSOLE=y -+CONFIG_SERIAL_NONSTANDARD=y -+CONFIG_ROCKETPORT=m -+CONFIG_SYNCLINK=m -+CONFIG_SYNCLINKMP=m -+CONFIG_SYNCLINK_GT=m -+CONFIG_N_HDLC=m -+CONFIG_N_GSM=m -+# CONFIG_TRACE_SINK is not set -+# CONFIG_STALDRV is not set -+# CONFIG_DUMMY_IRQ is not set -+# CONFIG_IBM_ASM is not set -+CONFIG_TIFM_CORE=m -+CONFIG_TIFM_7XX1=m -+CONFIG_TCG_TPM=m -+CONFIG_TCG_TIS=m -+# CONFIG_TCG_TIS_I2C_INFINEON is not set -+# CONFIG_TCG_TIS_I2C_ATMEL is not set -+# CONFIG_TCG_TIS_I2C_NUVOTON is not set -+CONFIG_TCG_NSC=m -+CONFIG_TCG_ATMEL=m -+# CONFIG_TCG_INFINEON is not set -+# CONFIG_TCG_ST33_I2C is not set -+# CONFIG_TCG_XEN is not set -+CONFIG_TELCLOCK=m -+ -+# -+# Serial drivers -+# -+CONFIG_SERIAL_8250=y -+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set -+CONFIG_SERIAL_8250_CONSOLE=y -+CONFIG_SERIAL_8250_CS=m -+CONFIG_SERIAL_8250_NR_UARTS=32 -+CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -+CONFIG_SERIAL_8250_EXTENDED=y -+CONFIG_SERIAL_8250_MANY_PORTS=y -+CONFIG_SERIAL_8250_SHARE_IRQ=y -+# CONFIG_SERIAL_8250_DETECT_IRQ is not set -+CONFIG_SERIAL_8250_RSA=y -+# CONFIG_SERIAL_8250_DW is not set -+CONFIG_CYCLADES=m -+# CONFIG_CYZ_INTR is not set -+# CONFIG_MOXA_INTELLIO is not set -+# CONFIG_MOXA_SMARTIO is not set -+# CONFIG_ISI is not set -+# CONFIG_RIO is not set -+CONFIG_SERIAL_JSM=m -+# CONFIG_SERIAL_SCCNXP is not set -+# CONFIG_SERIAL_MFD_HSU is not set -+ -+# CONFIG_SERIAL_ALTERA_JTAGUART is not set -+# CONFIG_SERIAL_ALTERA_UART is not set -+ -+# -+# Non-8250 serial port support -+# -+CONFIG_SERIAL_CORE=y -+CONFIG_SERIAL_CORE_CONSOLE=y -+# CONFIG_SERIAL_XILINX_PS_UART is not set -+# CONFIG_SERIAL_TIMBERDALE is not set -+CONFIG_SERIAL_ARC=m -+CONFIG_SERIAL_ARC_NR_PORTS=1 -+# CONFIG_SERIAL_RP2 is not set -+# CONFIG_SERIAL_ST_ASC is not set -+# CONFIG_SERIAL_PCH_UART is not set -+ -+CONFIG_UNIX98_PTYS=y -+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y -+CONFIG_PRINTER=m -+CONFIG_LP_CONSOLE=y -+CONFIG_PPDEV=m -+ -+# -+# I2C support -+# -+CONFIG_I2C=y -+# CONFIG_I2C_MUX is not set -+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set -+# CONFIG_I2C_MUX_PCA954x is not set -+# CONFIG_I2C_MUX_GPIO is not set -+# CONFIG_I2C_MUX_PCA9541 is not set -+# CONFIG_I2C_MUX_PINCTRL is not set -+# -+ -+# -+# I2C Algorithms -+# -+# CONFIG_I2C_DEBUG_ALGO is not set -+CONFIG_I2C_ALGOBIT=m -+ -+# -+# I2C Hardware Bus support -+# -+ -+# CONFIG_I2C_ALI1535 is not set -+# CONFIG_I2C_ALI1563 is not set -+# CONFIG_I2C_ALI15X3 is not set -+# CONFIG_I2C_AMD756 is not set -+# CONFIG_I2C_AMD756_S4882 is not set -+# CONFIG_I2C_AMD8111 is not set -+# CONFIG_I2C_DEBUG_CORE is not set -+# CONFIG_I2C_DEBUG_BUS is not set -+# CONFIG_I2C_I801 is not set -+# CONFIG_I2C_ISCH is not set -+# CONFIG_I2C_NFORCE2_S4985 is not set -+# CONFIG_I2C_INTEL_MID is not set -+# CONFIG_I2C_EG20T is not set -+# CONFIG_I2C_CBUS_GPIO is not set -+CONFIG_I2C_VIPERBOARD=m -+ -+CONFIG_EEPROM_AT24=m -+CONFIG_EEPROM_LEGACY=m -+CONFIG_EEPROM_93CX6=m -+CONFIG_EEPROM_MAX6875=m -+ -+CONFIG_I2C_NFORCE2=m -+# CONFIG_I2C_OCORES is not set -+CONFIG_I2C_PARPORT=m -+CONFIG_I2C_PARPORT_LIGHT=m -+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set -+CONFIG_I2C_PASEMI=m -+CONFIG_I2C_PCA_PLATFORM=m -+# CONFIG_I2C_PIIX4 is not set -+# CONFIG_SCx200_ACB is not set -+# CONFIG_I2C_SIS5595 is not set -+# CONFIG_I2C_SIS630 is not set -+# CONFIG_I2C_SIS96X is not set -+CONFIG_I2C_SIMTEC=m -+CONFIG_I2C_STUB=m -+CONFIG_I2C_TINY_USB=m -+# CONFIG_I2C_TAOS_EVM is not set -+# CONFIG_I2C_VIA is not set -+# CONFIG_I2C_VIAPRO is not set -+# CONFIG_I2C_DESIGNWARE is not set -+# CONFIG_I2C_XILINX is not set -+ -+CONFIG_I2C_DIOLAN_U2C=m -+ -+# -+# I2C Hardware Sensors Chip support -+# -+CONFIG_SENSORS_ATK0110=m -+CONFIG_SENSORS_ABITUGURU=m -+CONFIG_SENSORS_ABITUGURU3=m -+CONFIG_SENSORS_AD7414=m -+CONFIG_SENSORS_AD7418=m -+CONFIG_SENSORS_ADM1021=m -+CONFIG_SENSORS_ADM1025=m -+CONFIG_SENSORS_ADM1026=m -+CONFIG_SENSORS_ADM1029=m -+CONFIG_SENSORS_ADM1031=m -+CONFIG_SENSORS_ADM9240=m -+CONFIG_SENSORS_ADT7310=m -+CONFIG_SENSORS_ADT7410=m -+CONFIG_SENSORS_ADS7828=m -+CONFIG_SENSORS_ADT7462=m -+CONFIG_SENSORS_ADT7470=m -+CONFIG_SENSORS_ADT7475=m -+CONFIG_SENSORS_APPLESMC=m -+CONFIG_SENSORS_ASB100=m -+CONFIG_SENSORS_ATXP1=m -+CONFIG_SENSORS_CORETEMP=m -+CONFIG_SENSORS_DME1737=m -+CONFIG_SENSORS_DS1621=m -+# CONFIG_DS1682 is not set -+CONFIG_SENSORS_F71805F=m -+CONFIG_SENSORS_F71882FG=m -+CONFIG_SENSORS_F75375S=m -+CONFIG_SENSORS_FSCHMD=m -+CONFIG_SENSORS_G760A=m -+CONFIG_SENSORS_G762=m -+CONFIG_SENSORS_GL518SM=m -+CONFIG_SENSORS_GL520SM=m -+CONFIG_SENSORS_HDAPS=m -+# CONFIG_SENSORS_HIH6130 is not set -+# CONFIG_SENSORS_HTU21 is not set -+# CONFIG_SENSORS_I5K_AMB is not set -+# FIXME: IBMAEM x86 only? -+CONFIG_SENSORS_IBMAEM=m -+CONFIG_SENSORS_IBMPEX=m -+# CONFIG_SENSORS_IIO_HWMON is not set -+CONFIG_SENSORS_IT87=m -+CONFIG_SENSORS_K8TEMP=m -+CONFIG_SENSORS_K10TEMP=m -+CONFIG_SENSORS_LIS3LV02D=m -+CONFIG_SENSORS_LIS3_SPI=m -+CONFIG_SENSORS_LIS3_I2C=m -+CONFIG_SENSORS_LM63=m -+CONFIG_SENSORS_LM75=m -+CONFIG_SENSORS_LM77=m -+CONFIG_SENSORS_LM78=m -+CONFIG_SENSORS_LM80=m -+CONFIG_SENSORS_LM83=m -+CONFIG_SENSORS_LM85=m -+CONFIG_SENSORS_LM87=m -+CONFIG_SENSORS_LM90=m -+CONFIG_SENSORS_LM92=m -+CONFIG_SENSORS_LM93=m -+CONFIG_SENSORS_LM95234=m -+CONFIG_SENSORS_LTC4245=m -+CONFIG_SENSORS_MAX1619=m -+CONFIG_SENSORS_MAX6650=m -+CONFIG_SENSORS_MAX6697=m -+CONFIG_SENSORS_MCP3021=m -+CONFIG_SENSORS_NCT6775=m -+CONFIG_SENSORS_NTC_THERMISTOR=m -+CONFIG_SENSORS_PC87360=m -+CONFIG_SENSORS_PC87427=m -+CONFIG_SENSORS_PCF8591=m -+CONFIG_SENSORS_SHT15=m -+CONFIG_SENSORS_SIS5595=m -+CONFIG_CHARGER_SMB347=m -+CONFIG_SENSORS_SMSC47M1=m -+CONFIG_SENSORS_SMSC47M192=m -+CONFIG_SENSORS_SMSC47B397=m -+CONFIG_SENSORS_THMC50=m -+CONFIG_SENSORS_TMP401=m -+CONFIG_APDS9802ALS=m -+CONFIG_ISL29020=m -+CONFIG_ISL29003=m -+CONFIG_SENSORS_BH1770=m -+CONFIG_SENSORS_APDS990X=m -+CONFIG_SENSORS_TSL2550=m -+CONFIG_SENSORS_VIA686A=m -+CONFIG_SENSORS_VIA_CPUTEMP=m -+CONFIG_SENSORS_VT1211=m -+CONFIG_SENSORS_VT8231=m -+CONFIG_SENSORS_W83627HF=m -+CONFIG_SENSORS_W83781D=m -+CONFIG_SENSORS_W83L785TS=m -+CONFIG_SENSORS_W83L786NG=m -+CONFIG_SENSORS_W83627EHF=m -+CONFIG_SENSORS_W83791D=m -+CONFIG_SENSORS_W83792D=m -+CONFIG_SENSORS_W83793=m -+CONFIG_SENSORS_LTC4215=m -+CONFIG_SENSORS_LM95241=m -+CONFIG_SENSORS_LM95245=m -+CONFIG_SENSORS_TMP421=m -+CONFIG_SENSORS_WM8350=m -+CONFIG_SENSORS_WM831X=m -+CONFIG_SENSORS_LM73=m -+CONFIG_SENSORS_AMC6821=m -+CONFIG_SENSORS_INA2XX=m -+CONFIG_SENSORS_INA209=m -+CONFIG_SENSORS_ADT7411=m -+CONFIG_SENSORS_ASC7621=m -+CONFIG_SENSORS_EMC1403=m -+CONFIG_SENSORS_TMP102=m -+CONFIG_SENSORS_LTC4261=m -+# CONFIG_SENSORS_BH1780 is not set -+# CONFIG_SENSORS_JC42 is not set -+# CONFIG_SENSORS_SMM665 is not set -+# CONFIG_SENSORS_EMC2103 is not set -+# CONFIG_SENSORS_GPIO_FAN is not set -+CONFIG_SENSORS_W83795=m -+# CONFIG_SENSORS_W83795_FANCTRL is not set -+CONFIG_SENSORS_DS620=m -+CONFIG_SENSORS_SHT21=m -+CONFIG_SENSORS_LINEAGE=m -+CONFIG_SENSORS_LTC4151=m -+CONFIG_SENSORS_MAX6639=m -+CONFIG_SENSORS_SCH5627=m -+CONFIG_SENSORS_SCH5636=m -+CONFIG_SENSORS_ADS1015=m -+CONFIG_SENSORS_MAX16065=m -+CONFIG_SENSORS_MAX6642=m -+CONFIG_SENSORS_ADM1275=m -+CONFIG_SENSORS_UCD9000=m -+CONFIG_SENSORS_UCD9200=m -+CONFIG_SENSORS_ZL6100=m -+CONFIG_SENSORS_EMC6W201=m -+ -+CONFIG_PMBUS=m -+CONFIG_SENSORS_PMBUS=m -+CONFIG_SENSORS_MAX16064=m -+CONFIG_SENSORS_LM25066=m -+CONFIG_SENSORS_LTC2978=m -+CONFIG_SENSORS_MAX34440=m -+CONFIG_SENSORS_MAX8688=m -+CONFIG_SENSORS_MAX1668=m -+CONFIG_SENSORS_MAX197=m -+ -+# Industrial I/O subsystem configuration -+CONFIG_IIO=m -+CONFIG_IIO_BUFFER=y -+CONFIG_IIO_BUFFER_CB=y -+# CONFIG_IIO_KFIFO_BUF is not set -+CONFIG_IIO_TRIGGERED_BUFFER=m -+CONFIG_IIO_TRIGGER=y -+CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 -+CONFIG_IIO_INTERRUPT_TRIGGER=m -+CONFIG_HID_SENSOR_IIO_COMMON=m -+CONFIG_HID_SENSOR_IIO_TRIGGER=m -+CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS=y -+# CONFIG_IIO_SYSFS_TRIGGER is not set -+# CONFIG_AD5446 is not set -+# CONFIG_AD5380 is not set -+# CONFIG_AD5064 is not set -+# CONFIG_BMA180 is not set -+# CONFIG_MAX1363 is not set -+# CONFIG_MAX517 is not set -+# CONFIG_MCP4725 is not set -+# CONFIG_ITG3200 is not set -+# CONFIG_APDS9300 is not set -+# CONFIG_CM32181 is not set -+# CONFIG_CM36651 is not set -+# CONFIG_GP2AP020A00F is not set -+# CONFIG_TSL2583 is not set -+# CONFIG_TSL2x7x is not set -+# CONFIG_TCS3472 is not set -+# CONFIG_TSL4531 is not set -+# CONFIG_NAU7802 is not set -+# CONFIG_TI_ADC081C is not set -+# CONFIG_EXYNOS_ADC is not set -+# CONFIG_VIPERBOARD_ADC is not set -+# CONFIG_INV_MPU6050_IIO is not set -+CONFIG_IIO_ST_GYRO_3AXIS=m -+CONFIG_IIO_ST_MAGN_3AXIS=m -+CONFIG_IIO_ST_ACCEL_3AXIS=m -+CONFIG_HID_SENSOR_INCLINOMETER_3D=m -+# CONFIG_ADJD_S311 is not set -+# CONFIG_SENSORS_TSL2563 is not set -+# CONFIG_VCNL4000 is not set -+# CONFIG_AK8975 is not set -+# CONFIG_MAG3110 is not set -+# CONFIG_TMP006 is not set -+# CONFIG_IIO_ST_PRESS is not set -+# CONFIG_KXSD9 is not set -+# CONFIG_AD7266 is not set -+# CONFIG_AD7298 is not set -+# CONFIG_AD7476 is not set -+# CONFIG_AD7791 is not set -+# CONFIG_AD7793 is not set -+# CONFIG_AD7887 is not set -+# CONFIG_AD7923 is not set -+# CONFIG_MCP320X is not set -+# CONFIG_MCP3422 is not set -+# CONFIG_AD8366 is not set -+# CONFIG_AD5360 is not set -+# CONFIG_AD5421 is not set -+# CONFIG_AD5449 is not set -+# CONFIG_AD5504 is not set -+# CONFIG_AD5624R_SPI is not set -+# CONFIG_AD5686 is not set -+# CONFIG_AD5755 is not set -+# CONFIG_AD5764 is not set -+# CONFIG_AD5791 is not set -+# CONFIG_AD7303 is not set -+# CONFIG_AD9523 is not set -+# CONFIG_ADF4350 is not set -+# CONFIG_ADIS16080 is not set -+# CONFIG_ADIS16130 is not set -+# CONFIG_ADIS16136 is not set -+# CONFIG_ADIS16260 is not set -+# CONFIG_ADXRS450 is not set -+# CONFIG_ADIS16400 is not set -+# CONFIG_ADIS16480 is not set -+# CONFIG_DHT11 is not set -+# CONFIG_MPL3115 is not set -+ -+# staging IIO drivers -+# CONFIG_AD7291 is not set -+# CONFIG_AD7606 is not set -+# CONFIG_AD799X is not set -+# CONFIG_ADT7316 is not set -+# CONFIG_AD7150 is not set -+# CONFIG_AD7152 is not set -+# CONFIG_AD7746 is not set -+# CONFIG_AD5933 is not set -+# CONFIG_ADE7854 is not set -+# CONFIG_SENSORS_ISL29018 is not set -+# CONFIG_SENSORS_ISL29028 is not set -+# CONFIG_SENSORS_HMC5843 is not set -+# CONFIG_IIO_PERIODIC_RTC_TRIGGER is not set -+# CONFIG_IIO_SIMPLE_DUMMY is not set -+# CONFIG_ADIS16201 is not set -+# CONFIG_ADIS16203 is not set -+# CONFIG_ADIS16204 is not set -+# CONFIG_ADIS16209 is not set -+# CONFIG_ADIS16220 is not set -+# CONFIG_ADIS16240 is not set -+# CONFIG_LIS3L02DQ is not set -+# CONFIG_SCA3000 is not set -+# CONFIG_AD7780 is not set -+# CONFIG_AD7816 is not set -+# CONFIG_AD7192 is not set -+# CONFIG_AD7280 is not set -+# CONFIG_AD5930 is not set -+# CONFIG_AD9832 is not set -+# CONFIG_AD9834 is not set -+# CONFIG_AD9850 is not set -+# CONFIG_AD9852 is not set -+# CONFIG_AD9910 is not set -+# CONFIG_AD9951 is not set -+# CONFIG_ADIS16060 is not set -+# CONFIG_ADE7753 is not set -+# CONFIG_ADE7754 is not set -+# CONFIG_ADE7758 is not set -+# CONFIG_ADE7759 is not set -+# CONFIG_AD2S90 is not set -+# CONFIG_AD2S1200 is not set -+# CONFIG_AD2S1210 is not set -+ -+ -+ -+# CONFIG_HMC6352 is not set -+# CONFIG_BMP085 is not set -+# CONFIG_BMP085_I2C is not set -+# CONFIG_PCH_PHUB is not set -+# CONFIG_USB_SWITCH_FSA9480 is not set -+ -+CONFIG_W1=m -+CONFIG_W1_CON=y -+# CONFIG_W1_MASTER_MATROX is not set -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+# CONFIG_HDQ_MASTER_OMAP is not set -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+# CONFIG_W1_SLAVE_DS2408_READBACK is not set -+CONFIG_W1_SLAVE_DS2413=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2433_CRC=y -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_DS2781=m -+CONFIG_W1_SLAVE_DS28E04=m -+CONFIG_W1_SLAVE_BQ27000=m -+ -+# -+# Mice -+# -+ -+# -+# IPMI -+# -+CONFIG_IPMI_HANDLER=m -+# CONFIG_IPMI_PANIC_EVENT is not set -+CONFIG_IPMI_DEVICE_INTERFACE=m -+CONFIG_IPMI_WATCHDOG=m -+CONFIG_IPMI_SI=m -+CONFIG_IPMI_POWEROFF=m -+ -+# -+# Watchdog Cards -+# -+CONFIG_WATCHDOG_CORE=y -+# CONFIG_WATCHDOG_NOWAYOUT is not set -+CONFIG_SOFT_WATCHDOG=m -+CONFIG_WDTPCI=m -+# CONFIG_ACQUIRE_WDT is not set -+# CONFIG_ADVANTECH_WDT is not set -+# CONFIG_EUROTECH_WDT is not set -+CONFIG_IB700_WDT=m -+# CONFIG_SCx200_WDT is not set -+# CONFIG_60XX_WDT is not set -+CONFIG_W83877F_WDT=m -+CONFIG_W83627HF_WDT=m -+CONFIG_MACHZ_WDT=m -+# CONFIG_SC520_WDT is not set -+CONFIG_ALIM7101_WDT=m -+CONFIG_ALIM1535_WDT=m -+CONFIG_IT87_WDT=m -+CONFIG_ITCO_WDT=m -+CONFIG_ITCO_VENDOR_SUPPORT=y -+# CONFIG_SC1200_WDT is not set -+# CONFIG_PC87413_WDT is not set -+# CONFIG_WAFER_WDT is not set -+# CONFIG_CPU5_WDT is not set -+CONFIG_I6300ESB_WDT=m -+CONFIG_IT8712F_WDT=m -+# CONFIG_SBC8360_WDT is not set -+# CONFIG_SBC7240_WDT is not set -+CONFIG_SMSC_SCH311X_WDT=m -+CONFIG_W83977F_WDT=m -+CONFIG_PCIPCWATCHDOG=m -+CONFIG_USBPCWATCHDOG=m -+# CONFIG_SBC_EPX_C3_WATCHDOG is not set -+CONFIG_WM8350_WATCHDOG=m -+CONFIG_WM831X_WATCHDOG=m -+# CONFIG_MAX63XX_WATCHDOG is not set -+# CONFIG_DW_WATCHDOG is not set -+CONFIG_W83697UG_WDT=m -+# CONFIG_MEN_A21_WDT is not set -+# CONFIG_GPIO_WATCHDOG is not set -+ -+CONFIG_HW_RANDOM=y -+CONFIG_HW_RANDOM_TIMERIOMEM=m -+CONFIG_HW_RANDOM_TPM=m -+# CONFIG_HW_RANDOM_ATMEL is not set -+# CONFIG_HW_RANDOM_EXYNOS is not set -+# CONFIG_NVRAM is not set -+# CONFIG_RTC is not set -+# CONFIG_RTC_DEBUG is not set -+# CONFIG_GEN_RTC is not set -+CONFIG_RTC_HCTOSYS=y -+# CONFIG_RTC_SYSTOHC is not set -+CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -+CONFIG_RTC_INTF_SYSFS=y -+CONFIG_RTC_INTF_PROC=y -+CONFIG_RTC_INTF_DEV=y -+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -+CONFIG_RTC_DRV_CMOS=y -+CONFIG_RTC_DRV_DS1307=m -+CONFIG_RTC_DRV_DS1511=m -+CONFIG_RTC_DRV_DS1553=m -+CONFIG_RTC_DRV_DS1672=m -+CONFIG_RTC_DRV_DS1742=m -+CONFIG_RTC_DRV_DS1374=m -+# CONFIG_RTC_DRV_EP93XX is not set -+CONFIG_RTC_DRV_FM3130=m -+CONFIG_RTC_DRV_ISL1208=m -+CONFIG_RTC_DRV_M41T80=m -+CONFIG_RTC_DRV_M41T80_WDT=y -+CONFIG_RTC_DRV_M48T59=m -+CONFIG_RTC_DRV_MAX6900=m -+# CONFIG_RTC_DRV_M48T86 is not set -+CONFIG_RTC_DRV_PCF2127=m -+CONFIG_RTC_DRV_PCF8563=m -+CONFIG_RTC_DRV_PCF8583=m -+CONFIG_RTC_DRV_RS5C372=m -+# CONFIG_RTC_DRV_SA1100 is not set -+# CONFIG_RTC_DRV_TEST is not set -+CONFIG_RTC_DRV_X1205=m -+CONFIG_RTC_DRV_V3020=m -+CONFIG_RTC_DRV_DS2404=m -+CONFIG_RTC_DRV_STK17TA8=m -+# CONFIG_RTC_DRV_S35390A is not set -+CONFIG_RTC_DRV_RX8581=m -+CONFIG_RTC_DRV_RX8025=m -+CONFIG_RTC_DRV_DS1286=m -+CONFIG_RTC_DRV_M48T35=m -+CONFIG_RTC_DRV_BQ4802=m -+CONFIG_RTC_DRV_WM8350=m -+# CONFIG_RTC_DRV_AB3100 is not set -+CONFIG_RTC_DRV_WM831X=m -+CONFIG_RTC_DRV_BQ32K=m -+CONFIG_RTC_DRV_MSM6242=m -+CONFIG_RTC_DRV_RP5C01=m -+CONFIG_RTC_DRV_EM3027=m -+CONFIG_RTC_DRV_RV3029C2=m -+CONFIG_RTC_DRV_PCF50633=m -+CONFIG_RTC_DRV_DS3232=m -+CONFIG_RTC_DRV_ISL12022=m -+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set -+# CONFIG_RTC_DRV_MOXART is not set -+# CONFIG_RTC_DRV_ISL12057 is not set -+ -+CONFIG_R3964=m -+# CONFIG_APPLICOM is not set -+# CONFIG_SONYPI is not set -+ -+# -+# Ftape, the floppy tape device driver -+# -+CONFIG_AGP=y -+CONFIG_AGP_ALI=y -+CONFIG_AGP_ATI=y -+CONFIG_AGP_AMD=y -+CONFIG_AGP_AMD64=y -+CONFIG_AGP_INTEL=y -+CONFIG_AGP_NVIDIA=y -+CONFIG_AGP_SIS=y -+CONFIG_AGP_SWORKS=y -+CONFIG_AGP_VIA=y -+CONFIG_AGP_EFFICEON=y -+ -+CONFIG_VGA_ARB=y -+CONFIG_VGA_ARB_MAX_GPUS=16 -+ -+# CONFIG_STUB_POULSBO is not set -+ -+# -+# PCMCIA character devices -+# -+# CONFIG_SYNCLINK_CS is not set -+ -+CONFIG_CARDMAN_4000=m -+CONFIG_CARDMAN_4040=m -+ -+CONFIG_MWAVE=m -+CONFIG_RAW_DRIVER=y -+CONFIG_MAX_RAW_DEVS=8192 -+CONFIG_HANGCHECK_TIMER=m -+ -+CONFIG_MEDIA_PCI_SUPPORT=y -+# -+# Multimedia devices -+# -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_VIDEO_DEV=m -+# CONFIG_VIDEO_ADV_DEBUG is not set -+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -+CONFIG_VIDEO_V4L2=y -+CONFIG_VIDEO_V4L2_SUBDEV_API=y -+# CONFIG_VIDEO_VIVI is not set -+# CONFIG_USB_SI4713 is not set -+# CONFIG_PLATFORM_SI4713 is not set -+# CONFIG_I2C_SI4713 is not set -+# CONFIG_USB_RAREMONO is not set -+ -+# -+# Video For Linux -+# -+ -+# -+# Video Adapters -+# -+CONFIG_V4L_USB_DRIVERS=y -+CONFIG_VIDEO_CAPTURE_DRIVERS=y -+CONFIG_V4L_PCI_DRIVERS=y -+CONFIG_VIDEO_AU0828=m -+CONFIG_VIDEO_AU0828_V4L2=y -+CONFIG_VIDEO_BT848=m -+CONFIG_VIDEO_BT848_DVB=y -+CONFIG_VIDEO_BWQCAM=m -+CONFIG_VIDEO_SR030PC30=m -+CONFIG_VIDEO_NOON010PC30=m -+CONFIG_VIDEO_CAFE_CCIC=m -+# CONFIG_VIDEO_CPIA is not set -+CONFIG_VIDEO_CPIA2=m -+CONFIG_VIDEO_CQCAM=m -+CONFIG_VIDEO_CX23885=m -+CONFIG_MEDIA_ALTERA_CI=m -+CONFIG_VIDEO_CX18=m -+CONFIG_VIDEO_CX18_ALSA=m -+CONFIG_VIDEO_CX88=m -+CONFIG_VIDEO_CX88_DVB=m -+CONFIG_VIDEO_CX88_ALSA=m -+CONFIG_VIDEO_CX88_BLACKBIRD=m -+CONFIG_VIDEO_CX88_ENABLE_VP3054=y -+CONFIG_VIDEO_CX88_VP3054=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_V4L2=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_VIDEO_EM28XX_RC=y -+CONFIG_VIDEO_CX231XX=m -+CONFIG_VIDEO_CX231XX_ALSA=m -+CONFIG_VIDEO_CX231XX_DVB=m -+CONFIG_VIDEO_CX231XX_RC=y -+CONFIG_VIDEO_HEXIUM_ORION=m -+CONFIG_VIDEO_HEXIUM_GEMINI=m -+CONFIG_VIDEO_IVTV=m -+# CONFIG_VIDEO_IVTV_ALSA is not set -+CONFIG_VIDEO_MEYE=m -+CONFIG_VIDEO_MXB=m -+CONFIG_VIDEO_PVRUSB2_DVB=y -+# CONFIG_VIDEO_PMS is not set -+CONFIG_VIDEO_HDPVR=m -+CONFIG_VIDEO_SAA6588=m -+CONFIG_VIDEO_SAA7134=m -+CONFIG_VIDEO_SAA7134_ALSA=m -+CONFIG_VIDEO_SAA7134_DVB=m -+CONFIG_VIDEO_SAA7134_RC=y -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160_COMMON=m -+CONFIG_VIDEO_STK1160=m -+CONFIG_VIDEO_STK1160_AC97=y -+CONFIG_VIDEO_W9966=m -+CONFIG_VIDEO_ZORAN=m -+CONFIG_VIDEO_ZORAN_AVS6EYES=m -+CONFIG_VIDEO_ZORAN_BUZ=m -+CONFIG_VIDEO_ZORAN_DC10=m -+CONFIG_VIDEO_ZORAN_DC30=m -+CONFIG_VIDEO_ZORAN_LML33=m -+CONFIG_VIDEO_ZORAN_LML33R10=m -+CONFIG_VIDEO_ZORAN_ZR36060=m -+# CONFIG_V4L_ISA_PARPORT_DRIVERS is not set -+CONFIG_VIDEO_FB_IVTV=m -+CONFIG_VIDEO_SAA7164=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m -+CONFIG_VIDEO_TLG2300=m -+CONFIG_VIDEO_USBTV=m -+ -+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -+ -+# -+# Radio Adapters -+# -+CONFIG_RADIO_MAXIRADIO=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_RADIO_WL1273=m -+ -+CONFIG_MEDIA_ATTACH=y -+ -+# -+# V4L/DVB tuners -+# Selected automatically by not setting CONFIG_MEDIA_TUNER_CUSTOMISE -+# -+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set -+ -+# -+# Digital Video Broadcasting Devices -+# -+CONFIG_DVB_CAPTURE_DRIVERS=y -+CONFIG_DVB_CORE=m -+CONFIG_DVB_NET=y -+CONFIG_DVB_MAX_ADAPTERS=8 -+CONFIG_DVB_DYNAMIC_MINORS=y -+ -+# -+# DVB frontends -+# Selected automatically by not setting CONFIG_DVB_FE_CUSTOMISE -+# -+# CONFIG_DVB_FE_CUSTOMISE is not set -+ -+# -+# Supported DVB bridge Modules -+# -+CONFIG_DVB_BT8XX=m -+CONFIG_DVB_BUDGET_CORE=m -+CONFIG_DVB_PLUTO2=m -+CONFIG_SMS_SIANO_MDTV=m -+CONFIG_SMS_SIANO_RC=y -+# CONFIG_SMS_SIANO_DEBUGFS is not set -+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y -+CONFIG_SMS_USB_DRV=m -+CONFIG_SMS_SDIO_DRV=m -+CONFIG_DVB_TTUSB_DEC=m -+CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_DW2102=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_EC168=m -+CONFIG_DVB_USB_PCTV452E=m -+CONFIG_DVB_USB_IT913X=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_DM1105=m -+CONFIG_DVB_FIREDTV=m -+CONFIG_DVB_NGENE=m -+CONFIG_DVB_DDBRIDGE=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m -+ -+CONFIG_DVB_AV7110=m -+CONFIG_DVB_AV7110_OSD=y -+CONFIG_DVB_BUDGET=m -+CONFIG_DVB_BUDGET_CI=m -+CONFIG_DVB_BUDGET_AV=m -+CONFIG_DVB_BUDGET_PATCH=m -+ -+CONFIG_DVB_TTUSB_BUDGET=m -+ -+CONFIG_DVB_USB_CINERGY_T2=m -+CONFIG_DVB_B2C2_FLEXCOP=m -+# CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG is not set -+ -+CONFIG_DVB_B2C2_FLEXCOP_PCI=m -+# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set -+CONFIG_DVB_B2C2_FLEXCOP_USB=m -+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set -+CONFIG_DVB_USB=m -+# CONFIG_DVB_USB_DEBUG is not set -+CONFIG_DVB_USB_A800=m -+CONFIG_DVB_USB_AF9005=m -+CONFIG_DVB_USB_AF9005_REMOTE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_CXUSB=m -+CONFIG_DVB_USB_DIBUSB_MB=m -+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set -+CONFIG_DVB_USB_DIBUSB_MC=m -+CONFIG_DVB_USB_DIB0700=m -+CONFIG_DVB_USB_DIGITV=m -+CONFIG_DVB_USB_DTT200U=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_GP8PSK=m -+CONFIG_DVB_USB_M920X=m -+CONFIG_DVB_USB_NOVA_T_USB2=m -+CONFIG_DVB_USB_CE6230=m -+CONFIG_DVB_USB_OPERA1=m -+CONFIG_DVB_USB_TTUSB2=m -+CONFIG_DVB_USB_UMT_010=m -+CONFIG_DVB_USB_VP702X=m -+CONFIG_DVB_USB_VP7045=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_AZ6007=m -+CONFIG_DVB_USB_LME2510=m -+CONFIG_DVB_USB_RTL28XXU=m -+CONFIG_DVB_USB_AF9035=m -+ -+CONFIG_DVB_PT1=m -+ -+CONFIG_MANTIS_CORE=m -+CONFIG_DVB_MANTIS=m -+CONFIG_DVB_HOPPER=m -+ -+CONFIG_VIDEO_SAA7146=m -+CONFIG_VIDEO_SAA7146_VV=m -+CONFIG_VIDEO_TVP5150=m -+CONFIG_VIDEO_TUNER=m -+CONFIG_VIDEO_BTCX=m -+CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_PVRUSB2_SYSFS=y -+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set -+ -+CONFIG_RC_CORE=m -+CONFIG_RC_DECODERS=y -+CONFIG_LIRC=m -+CONFIG_RC_LOOPBACK=m -+CONFIG_RC_MAP=m -+CONFIG_RC_DEVICES=y -+CONFIG_RC_ATI_REMOTE=m -+CONFIG_IR_NEC_DECODER=m -+CONFIG_IR_RC5_DECODER=m -+CONFIG_IR_RC6_DECODER=m -+CONFIG_IR_JVC_DECODER=m -+CONFIG_IR_SONY_DECODER=m -+CONFIG_IR_RC5_SZ_DECODER=m -+CONFIG_IR_SANYO_DECODER=m -+CONFIG_IR_MCE_KBD_DECODER=m -+CONFIG_IR_LIRC_CODEC=m -+CONFIG_IR_IMON=m -+CONFIG_IR_MCEUSB=m -+CONFIG_IR_ITE_CIR=m -+CONFIG_IR_NUVOTON=m -+CONFIG_IR_FINTEK=m -+CONFIG_IR_REDRAT3=m -+CONFIG_IR_ENE=m -+CONFIG_IR_STREAMZAP=m -+CONFIG_IR_WINBOND_CIR=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m -+CONFIG_IR_GPIO_CIR=m -+ -+CONFIG_V4L_MEM2MEM_DRIVERS=y -+# CONFIG_VIDEO_MEM2MEM_DEINTERLACE is not set -+# CONFIG_VIDEO_SH_VEU is not set -+# CONFIG_VIDEO_RENESAS_VSP1 is not set -+# CONFIG_V4L_TEST_DRIVERS is not set -+ -+# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set -+ -+# -+# Broadcom Crystal HD video decoder driver -+# -+CONFIG_CRYSTALHD=m -+ -+# -+# Graphics support -+# -+ -+CONFIG_DISPLAY_SUPPORT=m -+CONFIG_VIDEO_OUTPUT_CONTROL=m -+ -+# -+# Console display driver support -+# -+CONFIG_VGA_CONSOLE=y -+CONFIG_VGACON_SOFT_SCROLLBACK=y -+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -+CONFIG_DUMMY_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -+ -+# -+# Logo configuration -+# -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_LOGO_LINUX_CLUT224=y -+ -+# -+# Sound -+# -+ -+# -+# Advanced Linux Sound Architecture -+# -+CONFIG_SOUND_OSS_CORE_PRECLAIM=y -+# CONFIG_SND_DEBUG_VERBOSE is not set -+CONFIG_SND_VERBOSE_PROCFS=y -+CONFIG_SND_SEQUENCER=y -+CONFIG_SND_HRTIMER=y -+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y -+CONFIG_SND_SEQ_DUMMY=m -+CONFIG_SND_SEQUENCER_OSS=y -+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y -+CONFIG_SND_OSSEMUL=y -+CONFIG_SND_MIXER_OSS=y -+CONFIG_SND_PCM_OSS=y -+CONFIG_SND_PCM_OSS_PLUGINS=y -+CONFIG_SND_RTCTIMER=y -+CONFIG_SND_DYNAMIC_MINORS=y -+CONFIG_SND_MAX_CARDS=32 -+# CONFIG_SND_SUPPORT_OLD_API is not set -+ -+# -+# Generic devices -+# -+CONFIG_SND_DUMMY=m -+CONFIG_SND_ALOOP=m -+CONFIG_SND_VIRMIDI=m -+CONFIG_SND_MTPAV=m -+CONFIG_SND_MTS64=m -+CONFIG_SND_SERIAL_U16550=m -+CONFIG_SND_MPU401=m -+CONFIG_SND_PORTMAN2X4=m -+CONFIG_SND_AC97_POWER_SAVE=y -+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 -+ -+CONFIG_SND_DRIVERS=y -+ -+# -+# ISA devices -+# -+CONFIG_SND_AD1889=m -+ -+# -+# PCI devices -+# -+CONFIG_SND_PCI=y -+CONFIG_SND_ALI5451=m -+CONFIG_SND_ALS300=m -+CONFIG_SND_ALS4000=m -+CONFIG_SND_ATIIXP=m -+CONFIG_SND_ATIIXP_MODEM=m -+CONFIG_SND_AU8810=m -+CONFIG_SND_AU8820=m -+CONFIG_SND_AU8830=m -+# CONFIG_SND_AW2 is not set -+CONFIG_SND_AZT3328=m -+CONFIG_SND_BT87X=m -+# CONFIG_SND_BT87X_OVERCLOCK is not set -+CONFIG_SND_CA0106=m -+CONFIG_SND_CMIPCI=m -+CONFIG_SND_CS46XX=m -+CONFIG_SND_CS46XX_NEW_DSP=y -+CONFIG_SND_CS4281=m -+CONFIG_SND_CS5530=m -+CONFIG_SND_CS5535AUDIO=m -+CONFIG_SND_EMU10K1=m -+CONFIG_SND_EMU10K1X=m -+CONFIG_SND_ENS1370=m -+CONFIG_SND_ENS1371=m -+CONFIG_SND_ES1938=m -+CONFIG_SND_ES1968=m -+CONFIG_SND_ES1968_INPUT=y -+CONFIG_SND_ES1968_RADIO=y -+CONFIG_SND_FM801=m -+CONFIG_SND_FM801_TEA575X_BOOL=y -+CONFIG_SND_CTXFI=m -+CONFIG_SND_LX6464ES=m -+CONFIG_SND_HDA_INTEL=y -+CONFIG_SND_HDA_INPUT_BEEP=y -+CONFIG_SND_HDA_INPUT_BEEP_MODE=0 -+CONFIG_SND_HDA_INPUT_JACK=y -+CONFIG_SND_HDA_PATCH_LOADER=y -+CONFIG_SND_HDA_HWDEP=y -+CONFIG_SND_HDA_CODEC_REALTEK=y -+CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS=y -+CONFIG_SND_HDA_CODEC_CA0110=y -+CONFIG_SND_HDA_CODEC_ANALOG=y -+CONFIG_SND_HDA_CODEC_SIGMATEL=y -+CONFIG_SND_HDA_CODEC_VIA=y -+CONFIG_SND_HDA_CODEC_CIRRUS=y -+CONFIG_SND_HDA_CODEC_CONEXANT=y -+CONFIG_SND_HDA_CODEC_CMEDIA=y -+CONFIG_SND_HDA_CODEC_SI3054=y -+CONFIG_SND_HDA_CODEC_HDMI=y -+CONFIG_SND_HDA_I915=y -+CONFIG_SND_HDA_CODEC_CA0132=y -+CONFIG_SND_HDA_CODEC_CA0132_DSP=y -+CONFIG_SND_HDA_GENERIC=y -+CONFIG_SND_HDA_POWER_SAVE=y -+CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 -+CONFIG_SND_HDA_RECONFIG=y -+CONFIG_SND_HDA_PREALLOC_SIZE=4096 -+CONFIG_SND_HDSPM=m -+CONFIG_SND_ICE1712=m -+CONFIG_SND_ICE1724=m -+CONFIG_SND_INTEL8X0=y -+CONFIG_SND_INTEL8X0M=m -+CONFIG_SND_KORG1212=m -+CONFIG_SND_MAESTRO3=m -+CONFIG_SND_MAESTRO3_INPUT=y -+CONFIG_SND_MIXART=m -+CONFIG_SND_NM256=m -+CONFIG_SND_OXYGEN=m -+CONFIG_SND_RME32=m -+CONFIG_SND_PCSP=m -+CONFIG_SND_PCXHR=m -+CONFIG_SND_RIPTIDE=m -+CONFIG_SND_RME96=m -+CONFIG_SND_RME9652=m -+CONFIG_SND_SIS7019=m -+CONFIG_SND_SONICVIBES=m -+CONFIG_SND_HDSP=m -+CONFIG_SND_TRIDENT=m -+CONFIG_SND_VIA82XX=m -+CONFIG_SND_VIA82XX_MODEM=m -+CONFIG_SND_VIRTUOSO=m -+CONFIG_SND_VX222=m -+CONFIG_SND_YMFPCI=m -+CONFIG_SND_ASIHPI=m -+CONFIG_SND_LOLA=m -+ -+# -+# ALSA USB devices -+# -+CONFIG_SND_USB=y -+CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y -+CONFIG_SND_USB_USX2Y=m -+CONFIG_SND_USB_US122L=m -+CONFIG_SND_USB_UA101=m -+CONFIG_SND_USB_6FIRE=m -+CONFIG_SND_USB_HIFACE=m -+ -+# -+# PCMCIA devices -+# -+# CONFIG_SND_PCMCIA is not set -+ -+CONFIG_SND_FIREWIRE=y -+CONFIG_SND_FIREWIRE_SPEAKERS=m -+CONFIG_SND_ISIGHT=m -+CONFIG_SND_SCS1X=m -+CONFIG_SND_DICE=m -+ -+# -+# Open Sound System -+# -+# CONFIG_SOUND_PRIME is not set -+ -+# -+# USB support -+# -+CONFIG_USB_SUPPORT=y -+# CONFIG_USB_DEBUG is not set -+ -+# DEPRECATED: See bug 362221. Fix udev. -+# CONFIG_USB_DEVICE_CLASS is not set -+ -+ -+# -+# Miscellaneous USB options -+# -+ -+# Deprecated. -+# CONFIG_USB_DEVICEFS is not set -+ -+CONFIG_USB_DEFAULT_PERSIST=y -+# CONFIG_USB_DYNAMIC_MINORS is not set -+CONFIG_USB_SUSPEND=y -+ -+# -+# USB Host Controller Drivers -+# -+CONFIG_USB_EHCI_ROOT_HUB_TT=y -+CONFIG_USB_EHCI_TT_NEWSCHED=y -+# CONFIG_USB_EHCI_MV is not set -+# CONFIG_USB_EHCI_HCD_PLATFORM is not set -+# CONFIG_USB_ISP116X_HCD is not set -+# CONFIG_USB_ISP1760_HCD is not set -+CONFIG_USB_ISP1362_HCD=m -+CONFIG_USB_FUSBH200_HCD=m -+# CONFIG_USB_FOTG210_HCD is not set -+# CONFIG_USB_GR_UDC is not set -+CONFIG_USB_OHCI_HCD=y -+CONFIG_USB_OHCI_HCD_PCI=y -+# CONFIG_USB_OHCI_HCD_SSB is not set -+# CONFIG_USB_HCD_TEST_MODE is not set -+# CONFIG_USB_OHCI_HCD_PLATFORM is not set -+CONFIG_USB_UHCI_HCD=y -+CONFIG_USB_SL811_HCD=m -+CONFIG_USB_SL811_HCD_ISO=y -+# CONFIG_USB_SL811_CS is not set -+# CONFIG_USB_R8A66597_HCD is not set -+CONFIG_USB_XHCI_HCD=y -+# CONFIG_USB_XHCI_HCD_DEBUGGING is not set -+ -+# -+# USB Device Class drivers -+# -+ -+# -+# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem -+# -+CONFIG_USB_ACM=m -+CONFIG_USB_PRINTER=m -+CONFIG_USB_WDM=m -+CONFIG_USB_TMC=m -+# CONFIG_BLK_DEV_UB is not set -+# CONFIG_USB_STORAGE_DEBUG is not set -+CONFIG_USB_STORAGE_CYPRESS_ATACB=m -+CONFIG_USB_STORAGE_DATAFAB=m -+CONFIG_USB_STORAGE_FREECOM=m -+CONFIG_USB_STORAGE_ISD200=m -+CONFIG_USB_STORAGE_SDDR09=m -+CONFIG_USB_STORAGE_SDDR55=m -+CONFIG_USB_STORAGE_JUMPSHOT=m -+CONFIG_USB_STORAGE_USBAT=y -+CONFIG_USB_STORAGE_ONETOUCH=m -+CONFIG_USB_STORAGE_ALAUDA=m -+CONFIG_USB_STORAGE_KARMA=m -+CONFIG_USB_STORAGE_REALTEK=m -+CONFIG_REALTEK_AUTOPM=y -+CONFIG_USB_STORAGE_ENE_UB6250=m -+# CONFIG_USB_LIBUSUAL is not set -+# CONFIG_USB_UAS is not set -+ -+ -+# -+# USB Human Interface Devices (HID) -+# -+CONFIG_USB_HID=y -+ -+CONFIG_HID_SUPPORT=y -+ -+CONFIG_HID=y -+CONFIG_I2C_HID=m -+CONFIG_HID_BATTERY_STRENGTH=y -+# debugging default is y upstream now -+CONFIG_HIDRAW=y -+CONFIG_UHID=m -+CONFIG_HID_PID=y -+CONFIG_LOGITECH_FF=y -+CONFIG_HID_LOGITECH_DJ=m -+CONFIG_LOGIWII_FF=y -+CONFIG_LOGIRUMBLEPAD2_FF=y -+CONFIG_PANTHERLORD_FF=y -+CONFIG_THRUSTMASTER_FF=y -+CONFIG_HID_WACOM=m -+CONFIG_HID_WACOM_POWER_SUPPLY=y -+CONFIG_ZEROPLUS_FF=y -+CONFIG_USB_HIDDEV=y -+CONFIG_USB_IDMOUSE=m -+CONFIG_DRAGONRISE_FF=y -+CONFIG_GREENASIA_FF=y -+CONFIG_SMARTJOYPLUS_FF=y -+CONFIG_LOGIG940_FF=y -+CONFIG_LOGIWHEELS_FF=y -+CONFIG_HID_MAGICMOUSE=y -+CONFIG_HID_MULTITOUCH=m -+CONFIG_HID_NTRIG=y -+CONFIG_HID_QUANTA=y -+CONFIG_HID_PRIMAX=m -+CONFIG_HID_PS3REMOTE=m -+CONFIG_HID_PRODIKEYS=m -+CONFIG_HID_DRAGONRISE=m -+CONFIG_HID_GYRATION=m -+CONFIG_HID_ICADE=m -+CONFIG_HID_TWINHAN=m -+CONFIG_HID_ORTEK=m -+CONFIG_HID_PANTHERLORD=m -+CONFIG_HID_PETALYNX=m -+CONFIG_HID_PICOLCD=m -+CONFIG_HID_RMI=m -+CONFIG_HID_ROCCAT=m -+CONFIG_HID_ROCCAT_KONE=m -+CONFIG_HID_SAMSUNG=m -+CONFIG_HID_SONY=m -+CONFIG_SONY_FF=y -+CONFIG_HID_SUNPLUS=m -+CONFIG_HID_STEELSERIES=m -+CONFIG_HID_GREENASIA=m -+CONFIG_HID_SMARTJOYPLUS=m -+CONFIG_HID_TOPSEED=m -+CONFIG_HID_THINGM=m -+CONFIG_HID_THRUSTMASTER=m -+CONFIG_HID_XINMO=m -+CONFIG_HID_ZEROPLUS=m -+CONFIG_HID_ZYDACRON=m -+CONFIG_HID_SENSOR_HUB=m -+CONFIG_HID_SENSOR_GYRO_3D=m -+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m -+CONFIG_HID_SENSOR_ALS=m -+CONFIG_HID_SENSOR_ACCEL_3D=m -+CONFIG_HID_EMS_FF=m -+CONFIG_HID_ELECOM=m -+CONFIG_HID_ELO=m -+CONFIG_HID_UCLOGIC=m -+CONFIG_HID_WALTOP=m -+CONFIG_HID_ROCCAT_PYRA=m -+CONFIG_HID_ROCCAT_KONEPLUS=m -+CONFIG_HID_ACRUX=m -+CONFIG_HID_ACRUX_FF=y -+CONFIG_HID_KEYTOUCH=m -+CONFIG_HID_LCPOWER=m -+CONFIG_HID_LENOVO_TPKBD=m -+CONFIG_HID_ROCCAT_ARVO=m -+CONFIG_HID_ROCCAT_ISKU=m -+CONFIG_HID_ROCCAT_KOVAPLUS=m -+CONFIG_HID_HOLTEK=m -+CONFIG_HOLTEK_FF=y -+CONFIG_HID_HUION=m -+CONFIG_HID_SPEEDLINK=m -+CONFIG_HID_WIIMOTE=m -+CONFIG_HID_WIIMOTE_EXT=y -+CONFIG_HID_KYE=m -+CONFIG_HID_SAITEK=m -+CONFIG_HID_TIVO=m -+CONFIG_HID_GENERIC=y -+CONFIG_HID_AUREAL=m -+CONFIG_HID_APPLEIR=m -+ -+ -+# -+# USB Imaging devices -+# -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+ -+# -+# USB Multimedia devices -+# -+ -+CONFIG_USB_DSBR=m -+# CONFIG_USB_ET61X251 is not set -+CONFIG_USB_M5602=m -+CONFIG_USB_STV06XX=m -+CONFIG_USB_GSPCA=m -+CONFIG_USB_GSPCA_MR97310A=m -+CONFIG_USB_GSPCA_BENQ=m -+CONFIG_USB_GSPCA_CONEX=m -+CONFIG_USB_GSPCA_CPIA1=m -+CONFIG_USB_GSPCA_ETOMS=m -+CONFIG_USB_GSPCA_FINEPIX=m -+CONFIG_USB_GSPCA_MARS=m -+CONFIG_USB_GSPCA_OV519=m -+CONFIG_USB_GSPCA_OV534=m -+CONFIG_USB_GSPCA_OV534_9=m -+CONFIG_USB_GSPCA_PAC207=m -+CONFIG_USB_GSPCA_PAC7311=m -+CONFIG_USB_GSPCA_SN9C2028=m -+CONFIG_USB_GSPCA_SN9C20X=m -+CONFIG_USB_GSPCA_SONIXB=m -+CONFIG_USB_GSPCA_SONIXJ=m -+CONFIG_USB_GSPCA_SPCA500=m -+CONFIG_USB_GSPCA_SPCA501=m -+CONFIG_USB_GSPCA_SPCA505=m -+CONFIG_USB_GSPCA_SPCA506=m -+CONFIG_USB_GSPCA_SPCA508=m -+CONFIG_USB_GSPCA_SPCA561=m -+CONFIG_USB_GSPCA_STK014=m -+CONFIG_USB_GSPCA_STK1135=m -+CONFIG_USB_GSPCA_SUNPLUS=m -+CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m -+CONFIG_USB_GSPCA_TV8532=m -+CONFIG_USB_GSPCA_VC032X=m -+CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_GSPCA_SQ905=m -+CONFIG_USB_GSPCA_SQ905C=m -+CONFIG_USB_GSPCA_PAC7302=m -+CONFIG_USB_GSPCA_STV0680=m -+CONFIG_USB_GL860=m -+CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m -+CONFIG_USB_GSPCA_KONICA=m -+CONFIG_USB_GSPCA_XIRLINK_CIT=m -+CONFIG_USB_GSPCA_SPCA1528=m -+CONFIG_USB_GSPCA_SQ930X=m -+CONFIG_USB_GSPCA_NW80X=m -+CONFIG_USB_GSPCA_VICAM=m -+CONFIG_USB_GSPCA_KINECT=m -+CONFIG_USB_GSPCA_SE401=m -+ -+CONFIG_USB_S2255=m -+# CONFIG_VIDEO_SH_MOBILE_CEU is not set -+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set -+# CONFIG_USB_SN9C102 is not set -+CONFIG_USB_ZR364XX=m -+ -+# -+# USB Network adaptors -+# -+CONFIG_USB_CATC=m -+CONFIG_USB_HSO=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_RTL8152=m -+CONFIG_USB_USBNET=m -+CONFIG_USB_SPEEDTOUCH=m -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_AX88179_178A=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SR9700=m -+CONFIG_USB_NET_SMSC95XX=m -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_RNDIS_HOST=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_HUAWEI_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m -+CONFIG_USB_NET_ZAURUS=m -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_CDC_PHONET=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+ -+# -+# USB Host-to-Host Cables -+# -+CONFIG_USB_AN2720=y -+CONFIG_USB_BELKIN=y -+ -+# -+# Intelligent USB Devices/Gadgets -+# -+CONFIG_USB_ARMLINUX=y -+CONFIG_USB_EPSON2888=y -+CONFIG_USB_KC2190=y -+ -+# CONFIG_USB_MUSB_HDRC is not set -+ -+# -+# USB port drivers -+# -+CONFIG_USB_USS720=m -+ -+# -+# USB Serial Converter support -+# -+CONFIG_USB_SERIAL=y -+CONFIG_USB_SERIAL_GENERIC=y -+CONFIG_USB_SERIAL_SIMPLE=m -+CONFIG_USB_SERIAL_AIRCABLE=m -+CONFIG_USB_SERIAL_ARK3116=m -+CONFIG_USB_SERIAL_BELKIN=m -+CONFIG_USB_SERIAL_CH341=m -+CONFIG_USB_SERIAL_CYPRESS_M8=m -+CONFIG_USB_SERIAL_CYBERJACK=m -+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m -+CONFIG_USB_SERIAL_CP210X=m -+CONFIG_USB_SERIAL_QUALCOMM=m -+CONFIG_USB_SERIAL_SYMBOL=m -+CONFIG_USB_SERIAL_EDGEPORT=m -+CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_EMPEG=m -+# CONFIG_USB_SERIAL_F81232 is not set -+CONFIG_USB_SERIAL_FTDI_SIO=m -+CONFIG_USB_SERIAL_FUNSOFT=m -+CONFIG_USB_SERIAL_GARMIN=m -+CONFIG_USB_SERIAL_HP4X=m -+CONFIG_USB_SERIAL_IPAQ=m -+CONFIG_USB_SERIAL_IPW=m -+CONFIG_USB_SERIAL_IR=m -+CONFIG_USB_SERIAL_IUU=m -+CONFIG_USB_SERIAL_KEYSPAN_PDA=m -+CONFIG_USB_SERIAL_KEYSPAN=m -+CONFIG_USB_SERIAL_KEYSPAN_MPR=y -+CONFIG_USB_SERIAL_KEYSPAN_USA28=y -+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -+CONFIG_USB_SERIAL_KEYSPAN_USA19=y -+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -+CONFIG_USB_SERIAL_KLSI=m -+CONFIG_USB_SERIAL_KOBIL_SCT=m -+CONFIG_USB_SERIAL_MCT_U232=m -+# CONFIG_USB_SERIAL_METRO is not set -+CONFIG_USB_SERIAL_MOS7720=m -+CONFIG_USB_SERIAL_MOS7715_PARPORT=y -+# CONFIG_USB_SERIAL_ZIO is not set -+# CONFIG_USB_SERIAL_WISHBONE is not set -+# CONFIG_USB_SERIAL_ZTE is not set -+CONFIG_USB_SERIAL_MOS7840=m -+CONFIG_USB_SERIAL_MOTOROLA=m -+# CONFIG_USB_SERIAL_MXUPORT is not set -+CONFIG_USB_SERIAL_NAVMAN=m -+CONFIG_USB_SERIAL_OPTION=m -+CONFIG_USB_SERIAL_OTI6858=m -+CONFIG_USB_SERIAL_OPTICON=m -+CONFIG_USB_SERIAL_OMNINET=m -+CONFIG_USB_SERIAL_PL2303=m -+# CONFIG_USB_SERIAL_QUATECH2 is not set -+CONFIG_USB_SERIAL_SAFE=m -+CONFIG_USB_SERIAL_SAFE_PADDED=y -+CONFIG_USB_SERIAL_SIERRAWIRELESS=m -+CONFIG_USB_SERIAL_SIEMENS_MPI=m -+CONFIG_USB_SERIAL_SPCP8X5=m -+CONFIG_USB_SERIAL_TI=m -+CONFIG_USB_SERIAL_VISOR=m -+CONFIG_USB_SERIAL_WHITEHEAT=m -+CONFIG_USB_SERIAL_XIRCOM=m -+CONFIG_USB_SERIAL_QCAUX=m -+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m -+CONFIG_USB_SERIAL_XSENS_MT=m -+CONFIG_USB_SERIAL_DEBUG=m -+CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m -+CONFIG_USB_SERIAL_FLASHLOADER=m -+CONFIG_USB_SERIAL_SUUNTO=m -+CONFIG_USB_SERIAL_CONSOLE=y -+ -+CONFIG_USB_EZUSB=y -+CONFIG_USB_EMI62=m -+CONFIG_USB_LED=m -+# CONFIG_USB_CYPRESS_CY7C63 is not set -+ -+# -+# USB Miscellaneous drivers -+# -+ -+CONFIG_USB_ADUTUX=m -+CONFIG_USB_SEVSEG=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_APPLEDISPLAY=m -+ -+# Physical Layer USB driver -+# CONFIG_USB_OTG_FSM is not set -+ -+# CONFIG_GENERIC_PHY is not set -+# CONFIG_PHY_EXYNOS_MIPI_VIDEO is not set -+# CONFIG_PHY_EXYNOS_DP_VIDEO is not set -+# CONFIG_OMAP_USB2 is not set -+# CONFIG_OMAP_USB3 is not set -+# CONFIG_OMAP_CONTROL_USB is not set -+# CONFIG_AM335X_PHY_USB is not set -+# CONFIG_SAMSUNG_USBPHY is not set -+# CONFIG_SAMSUNG_USB2PHY is not set -+# CONFIG_SAMSUNG_USB3PHY is not set -+# CONFIG_BCM_KONA_USB2_PHY is not set -+CONFIG_USB_RCAR_PHY=m -+CONFIG_USB_ATM=m -+CONFIG_USB_CXACRU=m -+# CONFIG_USB_C67X00_HCD is not set -+# CONFIG_USB_CYTHERM is not set -+CONFIG_USB_EMI26=m -+CONFIG_USB_FTDI_ELAN=m -+CONFIG_USB_FILE_STORAGE=m -+# CONFIG_USB_FILE_STORAGE_TEST is not set -+# CONFIG_USB_DWC3 is not set -+# CONFIG_USB_GADGETFS is not set -+# CONFIG_USB_OXU210HP_HCD is not set -+CONFIG_USB_IOWARRIOR=m -+CONFIG_USB_ISIGHTFW=m -+CONFIG_USB_YUREX=m -+CONFIG_USB_EZUSB_FX2=m -+CONFIG_USB_HSIC_USB3503=m -+CONFIG_USB_LCD=m -+CONFIG_USB_LD=m -+CONFIG_USB_LEGOTOWER=m -+CONFIG_USB_MON=y -+CONFIG_USB_PWC=m -+CONFIG_USB_PWC_INPUT_EVDEV=y -+# CONFIG_USB_PWC_DEBUG is not set -+# CONFIG_USB_RIO500 is not set -+CONFIG_USB_SISUSBVGA=m -+CONFIG_USB_SISUSBVGA_CON=y -+CONFIG_RADIO_SI470X=y -+CONFIG_USB_KEENE=m -+CONFIG_USB_MA901=m -+CONFIG_USB_SI470X=m -+CONFIG_I2C_SI470X=m -+CONFIG_RADIO_SI4713=m -+# CONFIG_RADIO_TEF6862 is not set -+CONFIG_USB_MR800=m -+CONFIG_USB_STKWEBCAM=m -+# CONFIG_USB_TEST is not set -+# CONFIG_USB_EHSET_TEST_FIXTURE is not set -+CONFIG_USB_TRANCEVIBRATOR=m -+CONFIG_USB_U132_HCD=m -+CONFIG_USB_UEAGLEATM=m -+CONFIG_USB_XUSBATM=m -+ -+# CONFIG_USB_DWC2 is not set -+ -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+ -+# CONFIG_USB_ISP1301 is not set -+ -+# CONFIG_USB_OTG is not set -+ -+# -+# Sonics Silicon Backplane -+# -+CONFIG_SSB=m -+CONFIG_SSB_PCIHOST=y -+CONFIG_SSB_SDIOHOST=y -+CONFIG_SSB_PCMCIAHOST=y -+# CONFIG_SSB_SILENT is not set -+# CONFIG_SSB_DEBUG is not set -+CONFIG_SSB_DRIVER_PCICORE=y -+CONFIG_SSB_DRIVER_GPIO=y -+ -+# Multifunction USB devices -+# CONFIG_MFD_PCF50633 is not set -+CONFIG_PCF50633_ADC=m -+CONFIG_PCF50633_GPIO=m -+# CONFIG_AB3100_CORE is not set -+CONFIG_INPUT_PCF50633_PMU=m -+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m -+ -+CONFIG_MFD_SUPPORT=y -+CONFIG_MFD_VX855=m -+CONFIG_MFD_SM501=m -+CONFIG_MFD_SM501_GPIO=y -+CONFIG_MFD_RTSX_PCI=m -+# CONFIG_MFD_TI_AM335X_TSCADC is not set -+CONFIG_MFD_VIPERBOARD=m -+# CONFIG_MFD_RETU is not set -+# CONFIG_MFD_TC6393XB is not set -+# CONFIG_MFD_WM8400 is not set -+# CONFIG_MFD_WM8350_I2C is not set -+# CONFIG_MFD_WM8350 is not set -+# CONFIG_MFD_WM831X is not set -+# CONFIG_AB3100_OTP is not set -+# CONFIG_MFD_TIMBERDALE is not set -+# CONFIG_MFD_WM8994 is not set -+# CONFIG_MFD_88PM860X is not set -+# CONFIG_LPC_SCH is not set -+# CONFIG_LPC_ICH is not set -+# CONFIG_HTC_I2CPLD is not set -+# CONFIG_MFD_MAX8925 is not set -+# CONFIG_MFD_ASIC3 is not set -+# CONFIG_MFD_AS3722 is not set -+# CONFIG_HTC_EGPIO is not set -+# CONFIG_TPS6507X is not set -+# CONFIG_ABX500_CORE is not set -+# CONFIG_MFD_RDC321X is not set -+# CONFIG_MFD_JANZ_CMODIO is not set -+# CONFIG_MFD_KEMPLD is not set -+# CONFIG_MFD_WM831X_I2C is not set -+# CONFIG_MFD_CS5535 is not set -+# CONFIG_MFD_STMPE is not set -+# CONFIG_MFD_MAX8998 is not set -+# CONFIG_MFD_TPS6586X is not set -+# CONFIG_MFD_TC3589X is not set -+# CONFIG_MFD_WL1273_CORE is not set -+# CONFIG_MFD_TPS65217 is not set -+# CONFIG_MFD_LM3533 is not set -+# CONFIG_MFD_ARIZONA is not set -+# CONFIG_MFD_ARIZONA_I2C is not set -+# CONFIG_MFD_CROS_EC is not set -+# CONFIG_MFD_TPS65912 is not set -+# CONFIG_MFD_SYSCON is not set -+# CONFIG_MFD_DA9063 is not set -+# CONFIG_MFD_LP3943 is not set -+ -+# -+# File systems -+# -+CONFIG_MISC_FILESYSTEMS=y -+ -+# ext4 is used for ext2 and ext3 filesystems -+CONFIG_JBD2=y -+CONFIG_FS_MBCACHE=y -+CONFIG_REISERFS_FS=m -+# CONFIG_REISERFS_CHECK is not set -+CONFIG_REISERFS_PROC_INFO=y -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+# CONFIG_JFS_DEBUG is not set -+# CONFIG_JFS_STATISTICS is not set -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_XFS_FS=m -+# CONFIG_XFS_DEBUG is not set -+# CONFIG_XFS_RT is not set -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_MINIX_FS=m -+CONFIG_ROMFS_FS=m -+# CONFIG_QFMT_V1 is not set -+CONFIG_QFMT_V2=y -+CONFIG_QUOTACTL=y -+CONFIG_DNOTIFY=y -+# Autofsv3 is obsolete. -+# systemd is dependant upon AUTOFS, so build it in. -+# CONFIG_EXOFS_FS is not set -+# CONFIG_EXOFS_DEBUG is not set -+CONFIG_NILFS2_FS=m -+# CONFIG_LOGFS is not set -+CONFIG_CEPH_FS=m -+CONFIG_CEPH_FSCACHE=y -+CONFIG_BLK_DEV_RBD=m -+CONFIG_CEPH_LIB=m -+CONFIG_CEPH_FS_POSIX_ACL=y -+# CONFIG_CEPH_LIB_USE_DNS_RESOLVER is not set -+ -+CONFIG_FSCACHE=m -+CONFIG_FSCACHE_STATS=y -+# CONFIG_FSCACHE_HISTOGRAM is not set -+# CONFIG_FSCACHE_DEBUG is not set -+CONFIG_FSCACHE_OBJECT_LIST=y -+ -+CONFIG_CACHEFILES=m -+# CONFIG_CACHEFILES_DEBUG is not set -+# CONFIG_CACHEFILES_HISTOGRAM is not set -+ -+# -+# CD-ROM/DVD Filesystems -+# -+ -+# -+# DOS/FAT/NT Filesystems -+# -+CONFIG_FAT_FS=m -+CONFIG_FAT_DEFAULT_CODEPAGE=437 -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+# CONFIG_NTFS_FS is not set -+ -+# -+# Pseudo filesystems -+# -+CONFIG_PROC_FS=y -+CONFIG_PROC_KCORE=y -+CONFIG_PROC_VMCORE=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_TMPFS_XATTR=y -+CONFIG_HUGETLBFS=y -+CONFIG_HUGETLB_PAGE=y -+# CONFIG_DEBUG_FS is not set -+ -+# -+# Miscellaneous filesystems -+# -+# CONFIG_ADFS_FS is not set -+CONFIG_AFFS_FS=m -+CONFIG_ECRYPT_FS=m -+# CONFIG_ECRYPT_FS_MESSAGING is not set -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m -+# CONFIG_HFSPLUS_FS_POSIX_ACL is not set -+CONFIG_BEFS_FS=m -+# CONFIG_BEFS_DEBUG is not set -+# CONFIG_BFS_FS is not set -+# CONFIG_EFS_FS is not set -+ -+CONFIG_CRAMFS=m -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_SQUASHFS_ZLIB=y -+# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set -+# CONFIG_SQUASHFS_EMBEDDED is not set -+# CONFIG_VXFS_FS is not set -+# CONFIG_HPFS_FS is not set -+# CONFIG_QNX4FS_FS is not set -+# CONFIG_QNX6FS_FS is not set -+CONFIG_SYSV_FS=m -+CONFIG_UFS_FS=m -+# CONFIG_UFS_FS_WRITE is not set -+# CONFIG_UFS_DEBUG is not set -+CONFIG_9P_FS=m -+CONFIG_9P_FSCACHE=y -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_9P_FS_SECURITY=y -+# CONFIG_OMFS_FS is not set -+CONFIG_CUSE=m -+# CONFIG_F2FS_FS is not set -+ -+# -+# Network File Systems -+# -+CONFIG_NETWORK_FILESYSTEMS=y -+# CONFIG_NFS_V2 is not set -+CONFIG_NFS_V3=y -+CONFIG_NFS_SWAP=y -+CONFIG_NFS_V4_1=y -+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" -+# CONFIG_NFS_V4_1_MIGRATION is not set -+CONFIG_NFS_V4_2=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3=y -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_NFSD_V4_SECURITY_LABEL=y -+CONFIG_NFS_FSCACHE=y -+# CONFIG_NFS_USE_LEGACY_DNS is not set -+CONFIG_PNFS_OBJLAYOUT=m -+CONFIG_PNFS_BLOCK=m -+CONFIG_LOCKD=m -+CONFIG_LOCKD_V4=y -+CONFIG_EXPORTFS=y -+CONFIG_SUNRPC=m -+CONFIG_SUNRPC_GSS=m -+CONFIG_SUNRPC_XPRT_RDMA=m -+CONFIG_SUNRPC_DEBUG=y -+CONFIG_RPCSEC_GSS_KRB5=m -+CONFIG_CIFS=m -+CONFIG_CIFS_STATS=y -+# CONFIG_CIFS_STATS2 is not set -+CONFIG_CIFS_SMB2=y -+CONFIG_CIFS_UPCALL=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_CIFS_FSCACHE=y -+CONFIG_CIFS_ACL=y -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_DEBUG=y -+# CONFIG_CIFS_DEBUG2 is not set -+CONFIG_CIFS_DFS_UPCALL=y -+CONFIG_CIFS_NFSD_EXPORT=y -+CONFIG_NCP_FS=m -+CONFIG_NCPFS_PACKET_SIGNING=y -+CONFIG_NCPFS_IOCTL_LOCKING=y -+CONFIG_NCPFS_STRONG=y -+CONFIG_NCPFS_NFS_NS=y -+CONFIG_NCPFS_OS2_NS=y -+CONFIG_NCPFS_SMALLDOS=y -+CONFIG_NCPFS_NLS=y -+CONFIG_NCPFS_EXTRAS=y -+CONFIG_CODA_FS=m -+# CONFIG_AFS_FS is not set -+# CONFIG_AF_RXRPC is not set -+ -+CONFIG_OCFS2_FS=m -+# CONFIG_OCFS2_DEBUG_FS is not set -+# CONFIG_OCFS2_DEBUG_MASKLOG is not set -+CONFIG_OCFS2_FS_O2CB=m -+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m -+# CONFIG_OCFS2_FS_STATS is not set -+ -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+# Maybe see if we want this on for debug kernels? -+# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set -+# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set -+# CONFIG_BTRFS_DEBUG is not set -+# CONFIG_BTRFS_ASSERT is not set -+ -+CONFIG_CONFIGFS_FS=y -+ -+CONFIG_DLM=m -+CONFIG_DLM_DEBUG=y -+CONFIG_GFS2_FS=m -+CONFIG_GFS2_FS_LOCKING_DLM=y -+ -+ -+CONFIG_UBIFS_FS_XATTR=y -+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set -+# CONFIG_UBIFS_FS_DEBUG is not set -+ -+# -+# Partition Types -+# -+CONFIG_PARTITION_ADVANCED=y -+# CONFIG_ACORN_PARTITION is not set -+CONFIG_AIX_PARTITION=y -+CONFIG_AMIGA_PARTITION=y -+# CONFIG_ATARI_PARTITION is not set -+CONFIG_BSD_DISKLABEL=y -+CONFIG_EFI_PARTITION=y -+CONFIG_KARMA_PARTITION=y -+CONFIG_LDM_PARTITION=y -+# CONFIG_LDM_DEBUG is not set -+CONFIG_MAC_PARTITION=y -+CONFIG_MSDOS_PARTITION=y -+CONFIG_MINIX_SUBPARTITION=y -+CONFIG_OSF_PARTITION=y -+CONFIG_SGI_PARTITION=y -+CONFIG_SOLARIS_X86_PARTITION=y -+CONFIG_SUN_PARTITION=y -+# CONFIG_SYSV68_PARTITION is not set -+CONFIG_UNIXWARE_DISKLABEL=y -+# CONFIG_ULTRIX_PARTITION is not set -+# CONFIG_CMDLINE_PARTITION is not set -+ -+CONFIG_NLS=y -+ -+# -+# Native Language Support -+# -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_NLS_MAC_ROMAN=m -+CONFIG_NLS_MAC_CELTIC=m -+CONFIG_NLS_MAC_CENTEURO=m -+CONFIG_NLS_MAC_CROATIAN=m -+CONFIG_NLS_MAC_CYRILLIC=m -+CONFIG_NLS_MAC_GAELIC=m -+CONFIG_NLS_MAC_GREEK=m -+CONFIG_NLS_MAC_ICELAND=m -+CONFIG_NLS_MAC_INUIT=m -+CONFIG_NLS_MAC_ROMANIAN=m -+CONFIG_NLS_MAC_TURKISH=m -+ -+# -+# Profiling support -+# -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_OPROFILE_EVENT_MULTIPLEX=y -+ -+# -+# Kernel hacking -+# -+CONFIG_DEBUG_KERNEL=y -+CONFIG_FRAME_WARN=1024 -+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 -+# CONFIG_DEBUG_INFO is not set -+CONFIG_FRAME_POINTER=y -+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -+# CONFIG_DEBUG_DRIVER is not set -+CONFIG_HEADERS_CHECK=y -+# CONFIG_LKDTM is not set -+# CONFIG_NOTIFIER_ERROR_INJECTION is not set -+# CONFIG_READABLE_ASM is not set -+ -+# CONFIG_RT_MUTEX_TESTER is not set -+# CONFIG_DEBUG_LOCKDEP is not set -+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -+ -+# DEBUG options that don't get enabled/disabled with 'make debug/release' -+ -+# This generates a huge amount of dmesg spew -+# CONFIG_DEBUG_KOBJECT is not set -+# -+# This breaks booting until the module patches are in-tree -+# CONFIG_DEBUG_KOBJECT_RELEASE is not set -+# -+# -+# These debug options are deliberatly left on (even in 'make release' kernels). -+# They aren't that much of a performance impact, and the value -+# from getting useful bug-reports makes it worth leaving them on. -+# CONFIG_DEBUG_HIGHMEM is not set -+# CONFIG_DEBUG_SHIRQ is not set -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_DEBUG_DEVRES=y -+CONFIG_DEBUG_RODATA_TEST=y -+CONFIG_DEBUG_NX_TEST=m -+CONFIG_DEBUG_SET_MODULE_RONX=y -+CONFIG_DEBUG_BOOT_PARAMS=y -+# CONFIG_DEBUG_VM is not set -+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set -+CONFIG_LOCKUP_DETECTOR=y -+# CONFIG_DEBUG_INFO_REDUCED is not set -+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -+# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -+# CONFIG_PANIC_ON_OOPS is not set -+CONFIG_PANIC_TIMEOUT=0 -+CONFIG_ATOMIC64_SELFTEST=y -+CONFIG_MEMORY_FAILURE=y -+CONFIG_HWPOISON_INJECT=m -+CONFIG_CROSS_MEMORY_ATTACH=y -+# CONFIG_DEBUG_SECTION_MISMATCH is not set -+# CONFIG_BACKTRACE_SELF_TEST is not set -+CONFIG_RESOURCE_COUNTERS=y -+# CONFIG_DEBUG_VIRTUAL is not set -+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -+CONFIG_EARLY_PRINTK_DBGP=y -+# CONFIG_PAGE_POISONING is not set -+# CONFIG_CRASH_DUMP is not set -+# CONFIG_CRASH is not set -+# CONFIG_GCOV_KERNEL is not set -+# CONFIG_RAMOOPS is not set -+ -+ -+# -+# Security options -+# -+CONFIG_SECURITY=y -+# CONFIG_SECURITY_DMESG_RESTRICT is not set -+CONFIG_SECURITY_NETWORK=y -+CONFIG_SECURITY_NETWORK_XFRM=y -+# CONFIG_SECURITY_PATH is not set -+CONFIG_SECURITY_SELINUX=y -+CONFIG_SECURITY_SELINUX_BOOTPARAM=y -+CONFIG_SECURITY_SELINUX_DISABLE=y -+CONFIG_SECURITY_SELINUX_DEVELOP=y -+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 -+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 -+CONFIG_SECURITY_SELINUX_AVC_STATS=y -+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set -+# CONFIG_SECURITY_SMACK is not set -+# CONFIG_SECURITY_TOMOYO is not set -+# CONFIG_SECURITY_APPARMOR is not set -+# CONFIG_SECURITY_YAMA is not set -+CONFIG_AUDIT=y -+CONFIG_AUDITSYSCALL=y -+# http://lists.fedoraproject.org/pipermail/kernel/2013-February/004125.html -+CONFIG_AUDIT_LOGINUID_IMMUTABLE=y -+ -+CONFIG_SECCOMP=y -+ -+# CONFIG_SSBI is not set -+ -+# -+# Cryptographic options -+# -+CONFIG_CRYPTO=y -+CONFIG_CRYPTO_FIPS=y -+CONFIG_CRYPTO_USER_API_HASH=y -+CONFIG_CRYPTO_USER_API_SKCIPHER=y -+CONFIG_CRYPTO_MANAGER=y -+# Note, CONFIG_CRYPTO_MANAGER_DISABLE_TESTS needs to be unset, or FIPS will be disabled. -+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set -+CONFIG_CRYPTO_HW=y -+CONFIG_CRYPTO_BLKCIPHER=y -+# CONFIG_CRYPTO_CRYPTD is not set -+CONFIG_CRYPTO_AES=y -+CONFIG_CRYPTO_ARC4=m -+CONFIG_CRYPTO_ANUBIS=m -+CONFIG_CRYPTO_AUTHENC=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_CAST6=m -+CONFIG_CRYPTO_CRC32C=y -+CONFIG_CRYPTO_CRC32=m -+CONFIG_CRYPTO_CTR=y -+CONFIG_CRYPTO_DEFLATE=m -+CONFIG_CRYPTO_FCRYPT=m -+CONFIG_CRYPTO_GF128MUL=m -+CONFIG_CRYPTO_CMAC=m -+CONFIG_CRYPTO_HMAC=y -+CONFIG_CRYPTO_KHAZAD=m -+CONFIG_CRYPTO_LZO=m -+CONFIG_CRYPTO_LZ4=m -+CONFIG_CRYPTO_LZ4HC=m -+CONFIG_CRYPTO_NULL=m -+CONFIG_CRYPTO_PCBC=m -+CONFIG_CRYPTO_SALSA20=m -+CONFIG_CRYPTO_SALSA20_586=m -+CONFIG_CRYPTO_SEED=m -+CONFIG_CRYPTO_SEQIV=m -+CONFIG_CRYPTO_SERPENT=m -+CONFIG_CRYPTO_TEA=m -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_VMAC=m -+CONFIG_CRYPTO_CRC32C_INTEL=m -+CONFIG_CRYPTO_GHASH=m -+CONFIG_CRYPTO_DEV_HIFN_795X=m -+CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y -+CONFIG_CRYPTO_PCRYPT=m -+ -+ -+ -+# Random number generation -+ -+# -+# Library routines -+# -+CONFIG_CRC16=y -+CONFIG_CRC32=m -+# CONFIG_CRC32_SELFTEST is not set -+CONFIG_CRC_ITU_T=m -+CONFIG_CRC8=m -+# CONFIG_RANDOM32_SELFTEST is not set -+CONFIG_CORDIC=m -+# CONFIG_DDR is not set -+ -+CONFIG_CRYPTO_ZLIB=m -+CONFIG_ZLIB_INFLATE=y -+CONFIG_ZLIB_DEFLATE=m -+ -+CONFIG_INITRAMFS_SOURCE="" -+CONFIG_KEYS=y -+CONFIG_PERSISTENT_KEYRINGS=y -+CONFIG_BIG_KEYS=y -+CONFIG_TRUSTED_KEYS=m -+CONFIG_ENCRYPTED_KEYS=m -+CONFIG_KEYS_DEBUG_PROC_KEYS=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_CDROM_PKTCDVD_BUFFERS=8 -+# CONFIG_CDROM_PKTCDVD_WCACHE is not set -+ -+CONFIG_ATA_OVER_ETH=m -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=m -+# CONFIG_BACKLIGHT_GENERIC is not set -+CONFIG_BACKLIGHT_PROGEAR=m -+ -+CONFIG_LCD_CLASS_DEVICE=m -+CONFIG_LCD_PLATFORM=m -+ -+CONFIG_FAIR_GROUP_SCHED=y -+CONFIG_CFS_BANDWIDTH=y -+CONFIG_SCHED_OMIT_FRAME_POINTER=y -+CONFIG_RT_GROUP_SCHED=y -+CONFIG_SCHED_AUTOGROUP=y -+ -+CONFIG_CPUSETS=y -+CONFIG_PROC_PID_CPUSET=y -+ -+# CONFIG_CGROUP_DEBUG is not set -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CGROUP_SCHED=y -+CONFIG_MEMCG=y -+CONFIG_MEMCG_SWAP=y -+CONFIG_MEMCG_SWAP_ENABLED=y -+CONFIG_MEMCG_KMEM=y -+# CONFIG_CGROUP_HUGETLB is not set -+CONFIG_CGROUP_PERF=y -+CONFIG_CGROUP_NET_PRIO=m -+# CONFIG_CGROUP_NET_CLASSID is not set -+CONFIG_BLK_CGROUP=y -+ -+# CONFIG_SYSFS_DEPRECATED is not set -+# CONFIG_SYSFS_DEPRECATED_V2 is not set -+ -+CONFIG_PRINTK_TIME=y -+ -+CONFIG_ENABLE_MUST_CHECK=y -+# CONFIG_ENABLE_WARN_DEPRECATED is not set -+ -+CONFIG_KEXEC=y -+ -+CONFIG_HWMON=y -+# CONFIG_HWMON_DEBUG_CHIP is not set -+CONFIG_THERMAL_HWMON=y -+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set -+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -+CONFIG_THERMAL_GOV_FAIR_SHARE=y -+# CONFIG_THERMAL_GOV_USER_SPACE is not set -+CONFIG_THERMAL_GOV_STEP_WISE=y -+# CONFIG_THERMAL_EMULATION is not set -+ -+CONFIG_INOTIFY=y -+CONFIG_INOTIFY_USER=y -+ -+# -+# Bus devices -+# -+# CONFIG_OMAP_OCP2SCP is not set -+CONFIG_PROC_EVENTS=y -+ -+CONFIG_IBMASR=m -+ -+CONFIG_PM=y -+CONFIG_PM_STD_PARTITION="" -+# CONFIG_DPM_WATCHDOG is not set # revisit this in debug -+CONFIG_PM_TRACE=y -+CONFIG_PM_TRACE_RTC=y -+# CONFIG_PM_OPP is not set -+# CONFIG_PM_AUTOSLEEP is not set -+# CONFIG_PM_WAKELOCKS is not set -+CONFIG_HIBERNATION=y -+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -+CONFIG_SUSPEND=y -+ -+CONFIG_CPU_FREQ_TABLE=y -+CONFIG_CPU_FREQ_STAT=m -+CONFIG_CPU_FREQ_STAT_DETAILS=y -+ -+ -+CONFIG_NET_VENDOR_SMC=y -+# CONFIG_IBMTR is not set -+# CONFIG_SKISA is not set -+# CONFIG_PROTEON is not set -+# CONFIG_SMCTR is not set -+ -+# CONFIG_MOUSE_ATIXL is not set -+ -+# CONFIG_MEDIA_PARPORT_SUPPORT is not set -+ -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_CADET=m -+CONFIG_RADIO_RTRACK=m -+CONFIG_RADIO_RTRACK2=m -+CONFIG_RADIO_AZTECH=m -+CONFIG_RADIO_GEMTEK=m -+CONFIG_RADIO_SF16FMI=m -+CONFIG_RADIO_SF16FMR2=m -+CONFIG_RADIO_TERRATEC=m -+CONFIG_RADIO_TRUST=m -+CONFIG_RADIO_TYPHOON=m -+CONFIG_RADIO_ZOLTRIX=m -+ -+CONFIG_SND_DARLA20=m -+CONFIG_SND_GINA20=m -+CONFIG_SND_LAYLA20=m -+CONFIG_SND_DARLA24=m -+CONFIG_SND_GINA24=m -+CONFIG_SND_LAYLA24=m -+CONFIG_SND_MONA=m -+CONFIG_SND_MIA=m -+CONFIG_SND_ECHO3G=m -+CONFIG_SND_INDIGO=m -+CONFIG_SND_INDIGOIO=m -+CONFIG_SND_INDIGODJ=m -+CONFIG_SND_INDIGOIOX=m -+CONFIG_SND_INDIGODJX=m -+ -+CONFIG_BALLOON_COMPACTION=y -+CONFIG_COMPACTION=y -+CONFIG_MIGRATION=y -+CONFIG_BOUNCE=y -+# CONFIG_LEDS_AMS_DELTA is not set -+# CONFIG_LEDS_LOCOMO is not set -+# CONFIG_LEDS_NET48XX is not set -+# CONFIG_LEDS_NET5501 is not set -+# CONFIG_LEDS_PCA9532 is not set -+# CONFIG_LEDS_PCA955X is not set -+# CONFIG_LEDS_BD2802 is not set -+# CONFIG_LEDS_S3C24XX is not set -+# CONFIG_LEDS_PCA9633 is not set -+CONFIG_LEDS_DELL_NETBOOKS=m -+# CONFIG_LEDS_TCA6507 is not set -+# CONFIG_LEDS_LM355x is not set -+# CONFIG_LEDS_OT200 is not set -+# CONFIG_LEDS_PWM is not set -+# CONFIG_LEDS_LP8501 is not set -+# CONFIG_LEDS_PCA963X is not set -+# CONFIG_LEDS_PCA9685 is not set -+CONFIG_LEDS_TRIGGER_TIMER=m -+CONFIG_LEDS_TRIGGER_ONESHOT=m -+CONFIG_LEDS_TRIGGER_IDE_DISK=y -+CONFIG_LEDS_TRIGGER_HEARTBEAT=m -+CONFIG_LEDS_TRIGGER_BACKLIGHT=m -+# CONFIG_LEDS_TRIGGER_CPU is not set -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -+CONFIG_LEDS_TRIGGER_TRANSIENT=m -+CONFIG_LEDS_TRIGGER_CAMERA=m -+CONFIG_LEDS_ALIX2=m -+CONFIG_LEDS_CLEVO_MAIL=m -+CONFIG_LEDS_INTEL_SS4200=m -+CONFIG_LEDS_LM3530=m -+# CONFIG_LEDS_LM3642 is not set -+CONFIG_LEDS_LM3556=m -+CONFIG_LEDS_BLINKM=m -+CONFIG_LEDS_LP3944=m -+CONFIG_LEDS_LP5521=m -+CONFIG_LEDS_LP5523=m -+CONFIG_LEDS_LP5562=m -+CONFIG_LEDS_LT3593=m -+CONFIG_LEDS_REGULATOR=m -+CONFIG_LEDS_WM8350=m -+CONFIG_LEDS_WM831X_STATUS=m -+ -+CONFIG_DMA_ENGINE=y -+CONFIG_DW_DMAC_CORE=m -+CONFIG_DW_DMAC=m -+CONFIG_DW_DMAC_PCI=m -+# CONFIG_DW_DMAC_BIG_ENDIAN_IO is not set -+# CONFIG_TIMB_DMA is not set -+# CONFIG_DMATEST is not set -+CONFIG_ASYNC_TX_DMA=y -+ -+CONFIG_UNUSED_SYMBOLS=y -+ -+CONFIG_UPROBE_EVENT=y -+ -+CONFIG_DYNAMIC_FTRACE=y -+# CONFIG_IRQSOFF_TRACER is not set -+CONFIG_SCHED_TRACER=y -+CONFIG_CONTEXT_SWITCH_TRACER=y -+CONFIG_TRACER_SNAPSHOT=y -+# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set -+CONFIG_FTRACE_SYSCALLS=y -+CONFIG_FTRACE_MCOUNT_RECORD=y -+# CONFIG_FTRACE_STARTUP_TEST is not set -+# CONFIG_TRACE_BRANCH_PROFILING is not set -+CONFIG_FUNCTION_PROFILER=y -+CONFIG_RING_BUFFER_BENCHMARK=m -+# CONFIG_RING_BUFFER_STARTUP_TEST is not set -+# CONFIG_RBTREE_TEST is not set -+# CONFIG_INTERVAL_TREE_TEST is not set -+CONFIG_FUNCTION_TRACER=y -+CONFIG_STACK_TRACER=y -+# CONFIG_FUNCTION_GRAPH_TRACER is not set -+ -+CONFIG_KPROBES=y -+CONFIG_KPROBE_EVENT=y -+# CONFIG_KPROBES_SANITY_TEST is not set -+# CONFIG_JUMP_LABEL is not set -+CONFIG_OPTPROBES=y -+ -+CONFIG_HZ_1000=y -+ -+CONFIG_TIMER_STATS=y -+CONFIG_PERF_COUNTERS=y -+ -+# Auxillary displays -+CONFIG_KS0108=m -+CONFIG_KS0108_PORT=0x378 -+CONFIG_KS0108_DELAY=2 -+CONFIG_CFAG12864B=y -+CONFIG_CFAG12864B_RATE=20 -+ -+# CONFIG_PHANTOM is not set -+ -+# CONFIG_POWER_SUPPLY_DEBUG is not set -+ -+# CONFIG_TEST_POWER is not set -+CONFIG_APM_POWER=m -+# CONFIG_GENERIC_ADC_BATTERY is not set -+# CONFIG_WM831X_POWER is not set -+ -+# CONFIG_BATTERY_DS2760 is not set -+# CONFIG_BATTERY_DS2781 is not set -+# CONFIG_BATTERY_DS2782 is not set -+# CONFIG_BATTERY_SBS is not set -+# CONFIG_BATTERY_BQ20Z75 is not set -+# CONFIG_BATTERY_DS2780 is not set -+# CONFIG_BATTERY_BQ27x00 is not set -+# CONFIG_BATTERY_MAX17040 is not set -+# CONFIG_BATTERY_MAX17042 is not set -+# CONFIG_BATTERY_GOLDFISH is not set -+ -+# CONFIG_CHARGER_ISP1704 is not set -+# CONFIG_CHARGER_MAX8903 is not set -+# CONFIG_CHARGER_LP8727 is not set -+# CONFIG_CHARGER_GPIO is not set -+# CONFIG_CHARGER_PCF50633 is not set -+# CONFIG_CHARGER_BQ2415X is not set -+# CONFIG_CHARGER_BQ24190 is not set -+# CONFIG_CHARGER_BQ24735 is not set -+CONFIG_POWER_RESET=y -+ -+# CONFIG_PDA_POWER is not set -+ -+CONFIG_AUXDISPLAY=y -+ -+CONFIG_UIO=m -+CONFIG_UIO_CIF=m -+# CONFIG_UIO_PDRV is not set -+# CONFIG_UIO_PDRV_GENIRQ is not set -+# CONFIG_UIO_DMEM_GENIRQ is not set -+CONFIG_UIO_AEC=m -+CONFIG_UIO_SERCOS3=m -+CONFIG_UIO_PCI_GENERIC=m -+# CONFIG_UIO_NETX is not set -+# CONFIG_UIO_MF624 is not set -+ -+CONFIG_VFIO=m -+CONFIG_VFIO_IOMMU_TYPE1=m -+CONFIG_VFIO_PCI=m -+ -+ -+# LIRC -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_BT829=m -+CONFIG_LIRC_IGORPLUGUSB=m -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_ZILOG=m -+CONFIG_LIRC_PARALLEL=m -+CONFIG_LIRC_SERIAL=m -+CONFIG_LIRC_SERIAL_TRANSMITTER=y -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SIR=m -+CONFIG_LIRC_TTUSBIR=m -+ -+# CONFIG_SAMPLES is not set -+ -+ -+CONFIG_NOZOMI=m -+# CONFIG_TPS65010 is not set -+ -+CONFIG_INPUT_APANEL=m -+CONFIG_INPUT_GP2A=m -+# CONFIG_INPUT_GPIO_TILT_POLLED is not set -+# CONFIG_INPUT_GPIO_BEEPER is not set -+ -+# CONFIG_INTEL_MENLOW is not set -+CONFIG_ENCLOSURE_SERVICES=m -+CONFIG_IPWIRELESS=m -+ -+# CONFIG_BLK_DEV_XIP is not set -+CONFIG_MEMSTICK=m -+# CONFIG_MEMSTICK_DEBUG is not set -+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set -+CONFIG_MSPRO_BLOCK=m -+# CONFIG_MS_BLOCK is not set -+CONFIG_MEMSTICK_TIFM_MS=m -+CONFIG_MEMSTICK_JMICRON_38X=m -+CONFIG_MEMSTICK_R592=m -+CONFIG_MEMSTICK_REALTEK_PCI=m -+ -+CONFIG_ACCESSIBILITY=y -+CONFIG_A11Y_BRAILLE_CONSOLE=y -+ -+# CONFIG_HTC_PASIC3 is not set -+ -+# MT9V022_PCA9536_SWITCH is not set -+ -+CONFIG_OPTIMIZE_INLINING=y -+ -+# FIXME: This should be x86/ia64 only -+# CONFIG_HP_ILO is not set -+ -+CONFIG_GPIOLIB=y -+# CONFIG_PINCTRL is not set -+# CONFIG_DEBUG_PINCTRL is not set -+# CONFIG_PINMUX is not set -+# CONFIG_PINCONF is not set -+ -+CONFIG_NET_DSA=m -+CONFIG_NET_DSA_MV88E6060=m -+CONFIG_NET_DSA_MV88E6131=m -+CONFIG_NET_DSA_MV88E6123_61_65=m -+ -+# Used by Maemo, we don't care. -+# CONFIG_PHONET is not set -+ -+# CONFIG_ICS932S401 is not set -+# CONFIG_ATMEL_SSC is not set -+ -+# CONFIG_C2PORT is not set -+ -+# CONFIG_REGULATOR_DEBUG is not set -+ -+CONFIG_WM8350_POWER=m -+ -+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -+ -+CONFIG_USB_WUSB=m -+CONFIG_USB_WUSB_CBAF=m -+# CONFIG_USB_WUSB_CBAF_DEBUG is not set -+CONFIG_USB_WHCI_HCD=m -+CONFIG_USB_HWA_HCD=m -+# CONFIG_USB_HCD_BCMA is not set -+# CONFIG_USB_HCD_SSB is not set -+ -+CONFIG_UWB=m -+CONFIG_UWB_HWA=m -+CONFIG_UWB_WHCI=m -+CONFIG_UWB_I1480U=m -+ -+# CONFIG_ANDROID is not set -+CONFIG_STAGING_MEDIA=y -+# CONFIG_DVB_AS102 is not set -+# CONFIG_ET131X is not set -+# CONFIG_SLICOSS is not set -+# CONFIG_WLAGS49_H2 is not set -+# CONFIG_WLAGS49_H25 is not set -+# CONFIG_VIDEO_DT3155 is not set -+# CONFIG_TI_ST is not set -+# CONFIG_FB_XGI is not set -+# CONFIG_VIDEO_GO7007 is not set -+# CONFIG_I2C_BCM2048 is not set -+# CONFIG_VIDEO_TCM825X is not set -+# CONFIG_VIDEO_OMAP4 is not set -+# CONFIG_USB_MSI3101 is not set -+# CONFIG_DT3155 is not set -+# CONFIG_W35UND is not set -+# CONFIG_PRISM2_USB is not set -+# CONFIG_ECHO is not set -+CONFIG_USB_ATMEL=m -+# CONFIG_COMEDI is not set -+# CONFIG_ASUS_OLED is not set -+# CONFIG_PANEL is not set -+# CONFIG_TRANZPORT is not set -+# CONFIG_POHMELFS is not set -+# CONFIG_IDE_PHISON is not set -+# CONFIG_LINE6_USB is not set -+# CONFIG_VME_BUS is not set -+# CONFIG_RAR_REGISTER is not set -+# CONFIG_VT6656 is not set -+# CONFIG_USB_SERIAL_QUATECH_USB2 is not set -+# Larry Finger maintains these (rhbz 913753) -+CONFIG_RTLLIB=m -+CONFIG_RTLLIB_CRYPTO_CCMP=m -+CONFIG_RTLLIB_CRYPTO_TKIP=m -+CONFIG_RTLLIB_CRYPTO_WEP=m -+CONFIG_RTL8192E=m -+# CONFIG_INPUT_GPIO is not set -+# CONFIG_VIDEO_CX25821 is not set -+# CONFIG_R8187SE is not set -+# CONFIG_R8188EU is not set -+# CONFIG_R8821AE is not set -+# CONFIG_RTL8192U is not set -+# CONFIG_FB_SM7XX is not set -+# CONFIG_SPECTRA is not set -+# CONFIG_EASYCAP is not set -+# CONFIG_SOLO6X10 is not set -+# CONFIG_ACPI_QUICKSTART is not set -+# CONFIG_LTE_GDM724X is not set -+CONFIG_R8712U=m # Larry Finger maintains this (rhbz 699618) -+# CONFIG_R8712_AP is not set -+# CONFIG_ATH6K_LEGACY is not set -+# CONFIG_USB_ENESTORAGE is not set -+# CONFIG_BCM_WIMAX is not set -+# CONFIG_USB_BTMTK is not set -+# CONFIG_FT1000 is not set -+# CONFIG_SPEAKUP is not set -+# CONFIG_DX_SEP is not set -+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set -+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set -+# CONFIG_RTS_PSTOR is not set -+CONFIG_ALTERA_STAPL=m -+# CONFIG_DVB_CXD2099 is not set -+# CONFIG_USBIP_CORE is not set -+# CONFIG_INTEL_MEI is not set -+# CONFIG_ZCACHE is not set -+# CONFIG_RTS5139 is not set -+# CONFIG_NVEC_LEDS is not set -+# CONFIG_VT6655 is not set -+# CONFIG_RAMSTER is not set -+# CONFIG_USB_WPAN_HCD is not set -+# CONFIG_WIMAX_GDM72XX is not set -+# CONFIG_IPACK_BUS is not set -+# CONFIG_CSR_WIFI is not set -+# CONFIG_ZCACHE2 is not set -+# CONFIG_NET_VENDOR_SILICOM is not set -+# CONFIG_SBYPASS is not set -+# CONFIG_BPCTL is not set -+# CONFIG_CED1401 is not set -+# CONFIG_DGRP is not set -+# CONFIG_SB105X is not set -+# CONFIG_LUSTRE_FS is not set -+# CONFIG_XILLYBUS is not set -+# CONFIG_DGAP is not set -+# CONFIG_DGNC is not set -+# CONFIG_RTS5208 is not set -+# END OF STAGING -+ -+# -+# Remoteproc drivers (EXPERIMENTAL) -+# -+# CONFIG_STE_MODEM_RPROC is not set -+ -+CONFIG_LIBFC=m -+CONFIG_LIBFCOE=m -+CONFIG_FCOE=m -+CONFIG_FCOE_FNIC=m -+ -+ -+# CONFIG_IMA is not set -+CONFIG_IMA_MEASURE_PCR_IDX=10 -+CONFIG_IMA_AUDIT=y -+CONFIG_IMA_LSM_RULES=y -+ -+# CONFIG_EVM is not set -+# CONFIG_PWM_PCA9685 is not set -+ -+CONFIG_LSM_MMAP_MIN_ADDR=65536 -+ -+CONFIG_STRIP_ASM_SYMS=y -+ -+# CONFIG_RCU_FANOUT_EXACT is not set -+# FIXME: Revisit FAST_NO_HZ after it's fixed -+# CONFIG_RCU_FAST_NO_HZ is not set -+# CONFIG_RCU_NOCB_CPU is not set -+CONFIG_RCU_CPU_STALL_TIMEOUT=60 -+# CONFIG_RCU_TORTURE_TEST is not set -+# CONFIG_RCU_TRACE is not set -+# CONFIG_RCU_CPU_STALL_INFO is not set -+# CONFIG_RCU_USER_QS is not set -+ -+CONFIG_KSM=y -+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 -+ -+CONFIG_FSNOTIFY=y -+CONFIG_FANOTIFY=y -+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y -+ -+CONFIG_IEEE802154=m -+CONFIG_IEEE802154_6LOWPAN=m -+CONFIG_IEEE802154_DRIVERS=m -+CONFIG_IEEE802154_FAKEHARD=m -+CONFIG_IEEE802154_FAKELB=m -+ -+CONFIG_MAC802154=m -+CONFIG_NET_MPLS_GSO=m -+ -+# CONFIG_HSR is not set -+ -+# CONFIG_EXTCON is not set -+# CONFIG_EXTCON_ADC_JACK is not set -+# CONFIG_MEMORY is not set -+ -+CONFIG_PPS=m -+# CONFIG_PPS_CLIENT_KTIMER is not set -+CONFIG_PPS_CLIENT_LDISC=m -+# CONFIG_PPS_DEBUG is not set -+CONFIG_PPS_CLIENT_PARPORT=m -+CONFIG_PPS_GENERATOR_PARPORT=m -+CONFIG_PPS_CLIENT_GPIO=m -+CONFIG_NTP_PPS=y -+ -+CONFIG_PTP_1588_CLOCK=m -+CONFIG_PTP_1588_CLOCK_PCH=m -+ -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_ZSWAP=y -+CONFIG_ZSMALLOC=y -+# CONFIG_PGTABLE_MAPPING is not set -+ -+# CONFIG_MDIO_GPIO is not set -+# CONFIG_KEYBOARD_GPIO_POLLED is not set -+# CONFIG_MOUSE_GPIO is not set -+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set -+# CONFIG_I2C_DESIGNWARE_PCI is not set -+# CONFIG_I2C_GPIO is not set -+# CONFIG_DEBUG_GPIO is not set -+# CONFIG_GPIO_GENERIC_PLATFORM is not set -+# CONFIG_GPIO_CS5535 is not set -+# CONFIG_GPIO_IT8761E is not set -+# CONFIG SB105x is not set -+# CONFIG_GPIO_TS5500 is not set -+CONFIG_GPIO_VIPERBOARD=m -+# CONFIG_UCB1400_CORE is not set -+# CONFIG_TPS6105X is not set -+# CONFIG_RADIO_MIROPCM20 is not set -+# CONFIG_USB_GPIO_VBUS is not set -+# CONFIG_GPIO_SCH is not set -+# CONFIG_GPIO_LANGWELL is not set -+# CONFIG_GPIO_RDC321X is not set -+# CONFIG_GPIO_VX855 is not set -+# CONFIG_GPIO_PCH is not set -+# CONFIG_GPIO_ML_IOH is not set -+# CONFIG_GPIO_AMD8111 is not set -+# CONFIG_GPIO_BT8XX is not set -+# CONFIG_GPIO_GRGPIO is not set -+# CONFIG_GPIO_PL061 is not set -+# CONFIG_GPIO_BCM_KONA is not set -+# CONFIG_GPIO_SCH311X is not set -+CONFIG_GPIO_MAX730X=m -+CONFIG_GPIO_MAX7300=m -+CONFIG_GPIO_MAX732X=m -+CONFIG_GPIO_PCF857X=m -+CONFIG_GPIO_SX150X=y -+CONFIG_GPIO_ADP5588=m -+CONFIG_GPIO_ADNP=m -+CONFIG_GPIO_MAX7301=m -+CONFIG_GPIO_MCP23S08=m -+CONFIG_GPIO_MC33880=m -+CONFIG_GPIO_74X164=m -+ -+# FIXME: Why? -+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y -+ -+CONFIG_TEST_KSTRTOX=y -+CONFIG_XZ_DEC=y -+CONFIG_XZ_DEC_X86=y -+CONFIG_XZ_DEC_POWERPC=y -+# CONFIG_XZ_DEC_IA64 is not set -+CONFIG_XZ_DEC_ARM=y -+# CONFIG_XZ_DEC_ARMTHUMB is not set -+# CONFIG_XZ_DEC_SPARC is not set -+# CONFIG_XZ_DEC_TEST is not set -+ -+# CONFIG_POWER_AVS is not set -+ -+CONFIG_TARGET_CORE=m -+CONFIG_ISCSI_TARGET=m -+CONFIG_LOOPBACK_TARGET=m -+CONFIG_SBP_TARGET=m -+CONFIG_TCM_IBLOCK=m -+CONFIG_TCM_FILEIO=m -+CONFIG_TCM_PSCSI=m -+CONFIG_TCM_FC=m -+ -+CONFIG_HWSPINLOCK=m -+ -+CONFIG_PSTORE=y -+CONFIG_PSTORE_RAM=m -+# CONFIG_PSTORE_CONSOLE is not set -+# CONFIG_PSTORE_FTRACE is not set -+ -+# CONFIG_TEST_MODULE is not set -+# CONFIG_TEST_USER_COPY is not set -+ -+# CONFIG_AVERAGE is not set -+# CONFIG_VMXNET3 is not set -+ -+# CONFIG_SIGMA is not set -+ -+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 -+ -+CONFIG_BCMA=m -+CONFIG_BCMA_BLOCKIO=y -+CONFIG_BCMA_HOST_PCI_POSSIBLE=y -+CONFIG_BCMA_HOST_PCI=y -+# CONFIG_BCMA_HOST_SOC is not set -+CONFIG_BCMA_DRIVER_GMAC_CMN=y -+CONFIG_BCMA_DRIVER_GPIO=y -+# CONFIG_BCMA_DEBUG is not set -+ -+# CONFIG_GOOGLE_FIRMWARE is not set -+# CONFIG_INTEL_MID_PTI is not set -+ -+# CONFIG_MAILBOX is not set -+ -+CONFIG_FMC=m -+CONFIG_FMC_FAKEDEV=m -+CONFIG_FMC_TRIVIAL=m -+CONFIG_FMC_WRITE_EEPROM=m -+CONFIG_FMC_CHARDEV=m -+ -+# CONFIG_GENWQE is not set -+ -+# CONFIG_POWERCAP is not set -+ -+# CONFIG_HSI is not set -+ -+ -+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set -+ -+# CONFIG_PM_DEVFREQ is not set -+# CONFIG_MODULE_SIG is not set -+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set -+# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set -+# CONFIG_MODULE_VERIFY_ELF is not set -+# CONFIG_CRYPTO_KEY_TYPE is not set -+# CONFIG_PGP_LIBRARY is not set -+# CONFIG_PGP_PRELOAD is not set -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_PROC_DEVICETREE=y -+ -diff -Nur linux-3.14.22.orig/arch/arm/configs/imx_v7_defconfig linux-3.14.22/arch/arm/configs/imx_v7_defconfig ---- linux-3.14.22.orig/arch/arm/configs/imx_v7_defconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/configs/imx_v7_defconfig 2014-10-22 14:55:49.702220001 -0500 -@@ -0,0 +1,343 @@ -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_KERNEL_LZO=y -+CONFIG_SYSVIPC=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_LOG_BUF_SHIFT=18 -+CONFIG_CGROUPS=y -+CONFIG_RELAY=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EXPERT=y -+CONFIG_PERF_EVENTS=y -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+# CONFIG_BLK_DEV_BSG is not set -+CONFIG_GPIO_PCA953X=y -+CONFIG_ARCH_MXC=y -+CONFIG_MXC_DEBUG_BOARD=y -+CONFIG_MACH_IMX51_DT=y -+CONFIG_MACH_EUKREA_CPUIMX51SD=y -+CONFIG_SOC_IMX53=y -+CONFIG_SOC_IMX6Q=y -+CONFIG_SOC_IMX6SL=y -+CONFIG_SOC_VF610=y -+# CONFIG_SWP_EMULATE is not set -+CONFIG_SMP=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT=y -+CONFIG_AEABI=y -+# CONFIG_OABI_COMPAT is not set -+CONFIG_HIGHMEM=y -+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_ARM_IMX6_CPUFREQ=y -+CONFIG_CPU_IDLE=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_PM_RUNTIME=y -+CONFIG_PM_DEBUG=y -+CONFIG_PM_TEST_SUSPEND=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_INET=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+CONFIG_IPV6=y -+CONFIG_NETFILTER=y -+CONFIG_VLAN_8021Q=y -+# CONFIG_WIRELESS is not set -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+# CONFIG_STANDALONE is not set -+CONFIG_CMA=y -+CONFIG_CMA_SIZE_MBYTES=320 -+CONFIG_IMX_WEIM=y -+CONFIG_CONNECTOR=y -+CONFIG_MTD=y -+CONFIG_MTD_CMDLINE_PARTS=y -+CONFIG_MTD_BLOCK=y -+CONFIG_MTD_CFI=y -+CONFIG_MTD_JEDECPROBE=y -+CONFIG_MTD_CFI_INTELEXT=y -+CONFIG_MTD_CFI_AMDSTD=y -+CONFIG_MTD_CFI_STAA=y -+CONFIG_MTD_PHYSMAP_OF=y -+CONFIG_MTD_DATAFLASH=y -+CONFIG_MTD_M25P80=y -+CONFIG_MTD_SST25L=y -+CONFIG_MTD_NAND=y -+CONFIG_MTD_NAND_GPMI_NAND=y -+CONFIG_MTD_NAND_MXC=y -+CONFIG_MTD_UBI=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=65536 -+CONFIG_EEPROM_AT24=y -+CONFIG_EEPROM_AT25=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_MULTI_LUN=y -+CONFIG_SCSI_CONSTANTS=y -+CONFIG_SCSI_LOGGING=y -+CONFIG_SCSI_SCAN_ASYNC=y -+# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_ATA=y -+CONFIG_SATA_AHCI_PLATFORM=y -+CONFIG_AHCI_IMX=y -+CONFIG_PATA_IMX=y -+CONFIG_NETDEVICES=y -+# CONFIG_NET_VENDOR_BROADCOM is not set -+CONFIG_CS89x0=y -+CONFIG_CS89x0_PLATFORM=y -+# CONFIG_NET_VENDOR_FARADAY is not set -+# CONFIG_NET_VENDOR_INTEL is not set -+# CONFIG_NET_VENDOR_MARVELL is not set -+# CONFIG_NET_VENDOR_MICREL is not set -+# CONFIG_NET_VENDOR_MICROCHIP is not set -+# CONFIG_NET_VENDOR_NATSEMI is not set -+# CONFIG_NET_VENDOR_SEEQ is not set -+CONFIG_SMC91X=y -+CONFIG_SMC911X=y -+CONFIG_SMSC911X=y -+# CONFIG_NET_VENDOR_STMICRO is not set -+# CONFIG_WLAN is not set -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_EVDEV=y -+CONFIG_INPUT_EVBUG=m -+CONFIG_KEYBOARD_GPIO=y -+CONFIG_KEYBOARD_IMX=y -+CONFIG_MOUSE_PS2=m -+CONFIG_MOUSE_PS2_ELANTECH=y -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_EGALAX=y -+CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH=y -+CONFIG_TOUCHSCREEN_MAX11801=y -+CONFIG_TOUCHSCREEN_MC13783=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_MMA8450=y -+CONFIG_INPUT_ISL29023=y -+CONFIG_SERIO_SERPORT=m -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_IMX=y -+CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_FSL_LPUART=y -+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -+CONFIG_FSL_OTP=y -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_CHARDEV=y -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_I2C_ALGOPCF=m -+CONFIG_I2C_ALGOPCA=m -+CONFIG_I2C_IMX=y -+CONFIG_SPI=y -+CONFIG_SPI_IMX=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_POWER_SUPPLY=y -+CONFIG_SABRESD_MAX8903=y -+CONFIG_IMX6_USB_CHARGER=y -+CONFIG_SENSORS_MAG3110=y -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_IMX_THERMAL=y -+CONFIG_DEVICE_THERMAL=y -+CONFIG_WATCHDOG=y -+CONFIG_IMX2_WDT=y -+CONFIG_MFD_DA9052_I2C=y -+CONFIG_MFD_MC13XXX_SPI=y -+CONFIG_MFD_MC13XXX_I2C=y -+CONFIG_MFD_SI476X_CORE=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+CONFIG_REGULATOR_DA9052=y -+CONFIG_REGULATOR_ANATOP=y -+CONFIG_REGULATOR_MC13783=y -+CONFIG_REGULATOR_MC13892=y -+CONFIG_REGULATOR_PFUZE100=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_VIDEO_V4L2_INT_DEVICE=y -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_MXC_OUTPUT=y -+CONFIG_VIDEO_MXC_CAPTURE=m -+CONFIG_VIDEO_MXC_CSI_CAMERA=m -+CONFIG_MXC_CAMERA_OV5640=m -+CONFIG_MXC_CAMERA_OV5642=m -+CONFIG_MXC_CAMERA_OV5640_MIPI=m -+CONFIG_MXC_TVIN_ADV7180=m -+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m -+CONFIG_VIDEO_MXC_IPU_OUTPUT=y -+CONFIG_VIDEO_MXC_PXP_V4L2=y -+CONFIG_SOC_CAMERA=y -+CONFIG_VIDEO_MX3=y -+CONFIG_RADIO_SI476X=y -+CONFIG_SOC_CAMERA_OV2640=y -+CONFIG_DRM=y -+CONFIG_DRM_VIVANTE=y -+CONFIG_FB=y -+CONFIG_FB_MXS=y -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_LCD_CLASS_DEVICE=y -+CONFIG_LCD_L4F00242T03=y -+CONFIG_LCD_PLATFORM=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=y -+CONFIG_BACKLIGHT_PWM=y -+CONFIG_FB_MXC_SYNC_PANEL=y -+CONFIG_FB_MXC_LDB=y -+CONFIG_FB_MXC_MIPI_DSI=y -+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y -+CONFIG_FB_MXC_HDMI=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_FONTS=y -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+CONFIG_LOGO=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_SOC=y -+CONFIG_SND_IMX_SOC=y -+CONFIG_SND_SOC_EUKREA_TLV320=y -+CONFIG_SND_SOC_IMX_CS42888=y -+CONFIG_SND_SOC_IMX_WM8962=y -+CONFIG_SND_SOC_IMX_SGTL5000=y -+CONFIG_SND_SOC_IMX_SPDIF=y -+CONFIG_SND_SOC_IMX_MC13783=y -+CONFIG_SND_SOC_IMX_HDMI=y -+CONFIG_SND_SOC_IMX_SI476X=y -+CONFIG_USB=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_STORAGE=y -+CONFIG_USB_CHIPIDEA=y -+CONFIG_USB_CHIPIDEA_UDC=y -+CONFIG_USB_CHIPIDEA_HOST=y -+CONFIG_USB_PHY=y -+CONFIG_NOP_USB_XCEIV=y -+CONFIG_USB_MXS_PHY=y -+CONFIG_USB_GADGET=y -+CONFIG_USB_ZERO=m -+CONFIG_USB_ETH=m -+CONFIG_USB_MASS_STORAGE=m -+CONFIG_USB_G_SERIAL=m -+CONFIG_MMC=y -+CONFIG_MMC_UNSAFE_RESUME=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_ESDHC_IMX=y -+CONFIG_MXC_IPU=y -+CONFIG_MXC_GPU_VIV=y -+CONFIG_MXC_ASRC=y -+CONFIG_MXC_MIPI_CSI2=y -+CONFIG_MXC_MLB150=m -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_LEDS_GPIO=y -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_GPIO=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_INTF_DEV_UIE_EMUL=y -+CONFIG_RTC_DRV_MC13XXX=y -+CONFIG_RTC_DRV_MXC=y -+CONFIG_RTC_DRV_SNVS=y -+CONFIG_DMADEVICES=y -+CONFIG_MXC_PXP_V2=y -+CONFIG_IMX_SDMA=y -+CONFIG_MXS_DMA=y -+CONFIG_STAGING=y -+CONFIG_COMMON_CLK_DEBUG=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_PWM=y -+CONFIG_PWM_IMX=y -+CONFIG_EXT2_FS=y -+CONFIG_EXT2_FS_XATTR=y -+CONFIG_EXT2_FS_POSIX_ACL=y -+CONFIG_EXT2_FS_SECURITY=y -+CONFIG_EXT3_FS=y -+CONFIG_EXT3_FS_POSIX_ACL=y -+CONFIG_EXT3_FS_SECURITY=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_QUOTA=y -+CONFIG_QUOTA_NETLINK_INTERFACE=y -+# CONFIG_PRINT_QUOTA_WARNING is not set -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=m -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_JFFS2_FS=y -+CONFIG_UBIFS_FS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_ROOT_NFS=y -+CONFIG_NLS_DEFAULT="cp437" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_UTF8=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_SCHED_DEBUG is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+# CONFIG_FTRACE is not set -+CONFIG_SECURITYFS=y -+CONFIG_CRYPTO_USER=y -+CONFIG_CRYPTO_TEST=m -+CONFIG_CRYPTO_CCM=y -+CONFIG_CRYPTO_GCM=y -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=y -+CONFIG_CRYPTO_ECB=y -+CONFIG_CRYPTO_LRW=y -+CONFIG_CRYPTO_XTS=y -+CONFIG_CRYPTO_MD4=y -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_MICHAEL_MIC=y -+CONFIG_CRYPTO_RMD128=y -+CONFIG_CRYPTO_RMD160=y -+CONFIG_CRYPTO_RMD256=y -+CONFIG_CRYPTO_RMD320=y -+CONFIG_CRYPTO_SHA1=y -+CONFIG_CRYPTO_SHA256=y -+CONFIG_CRYPTO_SHA512=y -+CONFIG_CRYPTO_TGR192=y -+CONFIG_CRYPTO_WP512=y -+CONFIG_CRYPTO_BLOWFISH=y -+CONFIG_CRYPTO_CAMELLIA=y -+CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_TWOFISH=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y -+CONFIG_CRC_CCITT=m -+CONFIG_CRC_T10DIF=y -+CONFIG_CRC7=m -+CONFIG_LIBCRC32C=m -diff -Nur linux-3.14.22.orig/arch/arm/configs/imx_v7_mfg_defconfig linux-3.14.22/arch/arm/configs/imx_v7_mfg_defconfig ---- linux-3.14.22.orig/arch/arm/configs/imx_v7_mfg_defconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/configs/imx_v7_mfg_defconfig 2014-10-22 14:55:49.702220001 -0500 -@@ -0,0 +1,341 @@ -+CONFIG_KERNEL_LZO=y -+CONFIG_SYSVIPC=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_LOG_BUF_SHIFT=18 -+CONFIG_CGROUPS=y -+CONFIG_RELAY=y -+CONFIG_BLK_DEV_INITRD=y -+CONFIG_EXPERT=y -+CONFIG_PERF_EVENTS=y -+# CONFIG_SLUB_DEBUG is not set -+# CONFIG_COMPAT_BRK is not set -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+# CONFIG_BLK_DEV_BSG is not set -+CONFIG_GPIO_PCA953X=y -+CONFIG_ARCH_MXC=y -+CONFIG_MXC_DEBUG_BOARD=y -+CONFIG_MACH_IMX51_DT=y -+CONFIG_MACH_EUKREA_CPUIMX51SD=y -+CONFIG_SOC_IMX53=y -+CONFIG_SOC_IMX6Q=y -+CONFIG_SOC_IMX6SL=y -+CONFIG_SOC_VF610=y -+# CONFIG_SWP_EMULATE is not set -+CONFIG_SMP=y -+CONFIG_VMSPLIT_2G=y -+CONFIG_PREEMPT_VOLUNTARY=y -+CONFIG_AEABI=y -+# CONFIG_OABI_COMPAT is not set -+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y -+CONFIG_CPU_FREQ_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+CONFIG_ARM_IMX6_CPUFREQ=y -+CONFIG_CPU_IDLE=y -+CONFIG_VFP=y -+CONFIG_NEON=y -+CONFIG_BINFMT_MISC=m -+CONFIG_PM_RUNTIME=y -+CONFIG_PM_DEBUG=y -+CONFIG_PM_TEST_SUSPEND=y -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_INET=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+CONFIG_IPV6=y -+CONFIG_NETFILTER=y -+CONFIG_VLAN_8021Q=y -+CONFIG_CFG80211=y -+CONFIG_CFG80211_WEXT=y -+CONFIG_MAC80211=y -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+# CONFIG_STANDALONE is not set -+CONFIG_CMA=y -+CONFIG_CMA_SIZE_MBYTES=320 -+CONFIG_IMX_WEIM=y -+CONFIG_CONNECTOR=y -+CONFIG_MTD=y -+CONFIG_MTD_CMDLINE_PARTS=y -+CONFIG_MTD_BLOCK=y -+CONFIG_MTD_CFI=y -+CONFIG_MTD_JEDECPROBE=y -+CONFIG_MTD_CFI_INTELEXT=y -+CONFIG_MTD_CFI_AMDSTD=y -+CONFIG_MTD_CFI_STAA=y -+CONFIG_MTD_PHYSMAP_OF=y -+CONFIG_MTD_DATAFLASH=y -+CONFIG_MTD_M25P80=y -+CONFIG_MTD_SST25L=y -+CONFIG_MTD_NAND=y -+CONFIG_MTD_NAND_GPMI_NAND=y -+CONFIG_MTD_NAND_MXC=y -+CONFIG_MTD_UBI=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_RAM=y -+CONFIG_BLK_DEV_RAM_SIZE=65536 -+CONFIG_EEPROM_AT24=y -+CONFIG_EEPROM_AT25=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_SCSI_MULTI_LUN=y -+CONFIG_SCSI_CONSTANTS=y -+CONFIG_SCSI_LOGGING=y -+CONFIG_SCSI_SCAN_ASYNC=y -+# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_ATA=y -+CONFIG_SATA_AHCI_PLATFORM=y -+CONFIG_AHCI_IMX=y -+CONFIG_PATA_IMX=y -+CONFIG_NETDEVICES=y -+# CONFIG_NET_VENDOR_BROADCOM is not set -+CONFIG_CS89x0=y -+CONFIG_CS89x0_PLATFORM=y -+# CONFIG_NET_VENDOR_FARADAY is not set -+# CONFIG_NET_VENDOR_INTEL is not set -+# CONFIG_NET_VENDOR_MARVELL is not set -+# CONFIG_NET_VENDOR_MICREL is not set -+# CONFIG_NET_VENDOR_MICROCHIP is not set -+# CONFIG_NET_VENDOR_NATSEMI is not set -+# CONFIG_NET_VENDOR_SEEQ is not set -+CONFIG_SMC91X=y -+CONFIG_SMC911X=y -+CONFIG_SMSC911X=y -+# CONFIG_NET_VENDOR_STMICRO is not set -+CONFIG_ATH_CARDS=y -+CONFIG_ATH6KL=m -+CONFIG_ATH6KL_SDIO=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_EVDEV=y -+CONFIG_INPUT_EVBUG=m -+CONFIG_KEYBOARD_GPIO=y -+CONFIG_KEYBOARD_IMX=y -+CONFIG_MOUSE_PS2=m -+CONFIG_MOUSE_PS2_ELANTECH=y -+CONFIG_INPUT_TOUCHSCREEN=y -+CONFIG_TOUCHSCREEN_EGALAX=y -+CONFIG_TOUCHSCREEN_ELAN=y -+CONFIG_TOUCHSCREEN_MAX11801=y -+CONFIG_TOUCHSCREEN_MC13783=y -+CONFIG_INPUT_MISC=y -+CONFIG_INPUT_MMA8450=y -+CONFIG_INPUT_ISL29023=y -+CONFIG_SERIO_SERPORT=m -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_IMX=y -+CONFIG_SERIAL_IMX_CONSOLE=y -+CONFIG_SERIAL_FSL_LPUART=y -+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y -+CONFIG_FSL_OTP=y -+# CONFIG_I2C_COMPAT is not set -+CONFIG_I2C_CHARDEV=y -+# CONFIG_I2C_HELPER_AUTO is not set -+CONFIG_I2C_ALGOPCF=m -+CONFIG_I2C_ALGOPCA=m -+CONFIG_I2C_IMX=y -+CONFIG_SPI=y -+CONFIG_SPI_IMX=y -+CONFIG_GPIO_SYSFS=y -+CONFIG_POWER_SUPPLY=y -+CONFIG_SABRESD_MAX8903=y -+CONFIG_SENSORS_MAX17135=y -+CONFIG_SENSORS_MAG3110=y -+CONFIG_THERMAL=y -+CONFIG_CPU_THERMAL=y -+CONFIG_IMX_THERMAL=y -+CONFIG_DEVICE_THERMAL=y -+CONFIG_WATCHDOG=y -+CONFIG_IMX2_WDT=y -+CONFIG_MFD_DA9052_I2C=y -+CONFIG_MFD_MC13XXX_SPI=y -+CONFIG_MFD_MC13XXX_I2C=y -+CONFIG_MFD_MAX17135=y -+CONFIG_MFD_SI476X_CORE=y -+CONFIG_REGULATOR=y -+CONFIG_REGULATOR_FIXED_VOLTAGE=y -+CONFIG_REGULATOR_DA9052=y -+CONFIG_REGULATOR_ANATOP=y -+CONFIG_REGULATOR_MC13783=y -+CONFIG_REGULATOR_MC13892=y -+CONFIG_REGULATOR_MAX17135=y -+CONFIG_REGULATOR_PFUZE100=y -+CONFIG_MEDIA_SUPPORT=y -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_VIDEO_V4L2_INT_DEVICE=y -+CONFIG_MEDIA_USB_SUPPORT=y -+CONFIG_USB_VIDEO_CLASS=m -+CONFIG_V4L_PLATFORM_DRIVERS=y -+CONFIG_VIDEO_MXC_OUTPUT=y -+CONFIG_VIDEO_MXC_CAPTURE=m -+CONFIG_VIDEO_MXC_CSI_CAMERA=m -+CONFIG_MXC_CAMERA_OV5640=m -+CONFIG_MXC_CAMERA_OV5642=m -+CONFIG_MXC_CAMERA_OV5640_MIPI=m -+CONFIG_MXC_TVIN_ADV7180=m -+CONFIG_MXC_IPU_DEVICE_QUEUE_SDC=m -+CONFIG_VIDEO_MXC_IPU_OUTPUT=y -+CONFIG_VIDEO_MXC_PXP_V4L2=y -+CONFIG_SOC_CAMERA=y -+CONFIG_VIDEO_MX3=y -+CONFIG_RADIO_SI476X=y -+CONFIG_SOC_CAMERA_OV2640=y -+CONFIG_DRM=y -+CONFIG_DRM_VIVANTE=y -+CONFIG_FB=y -+CONFIG_FB_MXS=y -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_LCD_CLASS_DEVICE=y -+CONFIG_LCD_L4F00242T03=y -+CONFIG_LCD_PLATFORM=y -+CONFIG_BACKLIGHT_CLASS_DEVICE=y -+CONFIG_BACKLIGHT_PWM=y -+CONFIG_FB_MXC_SYNC_PANEL=y -+CONFIG_FB_MXC_LDB=y -+CONFIG_FB_MXC_MIPI_DSI=y -+CONFIG_FB_MXC_TRULY_WVGA_SYNC_PANEL=y -+CONFIG_FB_MXC_HDMI=y -+CONFIG_FB_MXC_EINK_PANEL=y -+CONFIG_FB_MXS_SII902X=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -+CONFIG_FONTS=y -+CONFIG_FONT_8x8=y -+CONFIG_FONT_8x16=y -+CONFIG_LOGO=y -+CONFIG_SOUND=y -+CONFIG_SND=y -+CONFIG_SND_USB_AUDIO=m -+CONFIG_SND_SOC=y -+CONFIG_SND_IMX_SOC=y -+CONFIG_SND_SOC_EUKREA_TLV320=y -+CONFIG_SND_SOC_IMX_CS42888=y -+CONFIG_SND_SOC_IMX_WM8962=y -+CONFIG_SND_SOC_IMX_SGTL5000=y -+CONFIG_SND_SOC_IMX_SPDIF=y -+CONFIG_SND_SOC_IMX_MC13783=y -+CONFIG_SND_SOC_IMX_HDMI=y -+CONFIG_SND_SOC_IMX_SI476X=y -+CONFIG_USB=y -+CONFIG_USB_EHCI_HCD=y -+CONFIG_USB_STORAGE=y -+CONFIG_USB_CHIPIDEA=y -+CONFIG_USB_CHIPIDEA_UDC=y -+CONFIG_USB_CHIPIDEA_HOST=y -+CONFIG_USB_PHY=y -+CONFIG_USB_MXS_PHY=y -+CONFIG_USB_GADGET=y -+# CONFIG_USB_ZERO is not set -+# CONFIG_USB_AUDIO is not set -+# CONFIG_USB_ETH is not set -+# CONFIG_USB_G_NCM is not set -+# CONFIG_USB_GADGETFS is not set -+# CONFIG_USB_FUNCTIONFS is not set -+CONFIG_USB_MASS_STORAGE=y -+CONFIG_FSL_UTP=y -+# CONFIG_USB_G_SERIAL is not set -+# CONFIG_USB_MIDI_GADGET is not set -+# CONFIG_USB_G_PRINTER is not set -+# CONFIG_USB_CDC_COMPOSITE is not set -+# CONFIG_USB_G_ACM_MS is not set -+# CONFIG_USB_G_MULTI is not set -+# CONFIG_USB_G_HID is not set -+# CONFIG_USB_G_DBGP is not set -+# CONFIG_USB_G_WEBCAM is not set -+CONFIG_MMC=y -+CONFIG_MMC_UNSAFE_RESUME=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_ESDHC_IMX=y -+CONFIG_MXC_IPU=y -+CONFIG_MXC_GPU_VIV=y -+CONFIG_MXC_ASRC=y -+CONFIG_MXC_MIPI_CSI2=y -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=y -+CONFIG_RTC_CLASS=y -+CONFIG_RTC_INTF_DEV_UIE_EMUL=y -+CONFIG_RTC_DRV_MC13XXX=y -+CONFIG_RTC_DRV_MXC=y -+CONFIG_RTC_DRV_SNVS=y -+CONFIG_DMADEVICES=y -+CONFIG_MXC_PXP_V2=y -+CONFIG_IMX_SDMA=y -+CONFIG_MXS_DMA=y -+CONFIG_STAGING=y -+CONFIG_COMMON_CLK_DEBUG=y -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_PWM=y -+CONFIG_PWM_IMX=y -+CONFIG_EXT2_FS=y -+CONFIG_EXT2_FS_XATTR=y -+CONFIG_EXT2_FS_POSIX_ACL=y -+CONFIG_EXT2_FS_SECURITY=y -+CONFIG_EXT3_FS=y -+CONFIG_EXT3_FS_POSIX_ACL=y -+CONFIG_EXT3_FS_SECURITY=y -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_QUOTA=y -+CONFIG_QUOTA_NETLINK_INTERFACE=y -+# CONFIG_PRINT_QUOTA_WARNING is not set -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=m -+CONFIG_VFAT_FS=y -+CONFIG_TMPFS=y -+CONFIG_JFFS2_FS=y -+CONFIG_UBIFS_FS=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_ROOT_NFS=y -+CONFIG_NLS_DEFAULT="cp437" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=y -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_UTF8=y -+CONFIG_MAGIC_SYSRQ=y -+# CONFIG_SCHED_DEBUG is not set -+# CONFIG_DEBUG_BUGVERBOSE is not set -+# CONFIG_FTRACE is not set -+CONFIG_SECURITYFS=y -+CONFIG_CRYPTO_USER=y -+CONFIG_CRYPTO_CCM=y -+CONFIG_CRYPTO_GCM=y -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_CTS=y -+CONFIG_CRYPTO_ECB=y -+CONFIG_CRYPTO_LRW=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+CONFIG_CRYPTO_DEV_FSL_CAAM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=y -+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=y -+CONFIG_CRC_CCITT=m -+CONFIG_CRC_T10DIF=y -+CONFIG_CRC7=m -+CONFIG_LIBCRC32C=m -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/arch_timer.h linux-3.14.22/arch/arm/include/asm/arch_timer.h ---- linux-3.14.22.orig/arch/arm/include/asm/arch_timer.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/arch_timer.h 2014-10-22 14:55:49.702220001 -0500 -@@ -107,7 +107,6 @@ - /* Also disable virtual event stream */ - cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN - | ARCH_TIMER_USR_VT_ACCESS_EN -- | ARCH_TIMER_VIRT_EVT_EN - | ARCH_TIMER_USR_VCT_ACCESS_EN - | ARCH_TIMER_USR_PCT_ACCESS_EN); - arch_timer_set_cntkctl(cntkctl); -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/atomic.h linux-3.14.22/arch/arm/include/asm/atomic.h ---- linux-3.14.22.orig/arch/arm/include/asm/atomic.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/atomic.h 2014-10-22 14:55:49.702220001 -0500 -@@ -60,6 +60,7 @@ - int result; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic_add_return\n" - "1: ldrex %0, [%3]\n" -@@ -99,6 +100,7 @@ - int result; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic_sub_return\n" - "1: ldrex %0, [%3]\n" -@@ -121,6 +123,7 @@ - unsigned long res; - - smp_mb(); -+ prefetchw(&ptr->counter); - - do { - __asm__ __volatile__("@ atomic_cmpxchg\n" -@@ -138,6 +141,33 @@ - return oldval; - } - -+static inline int __atomic_add_unless(atomic_t *v, int a, int u) -+{ -+ int oldval, newval; -+ unsigned long tmp; -+ -+ smp_mb(); -+ prefetchw(&v->counter); -+ -+ __asm__ __volatile__ ("@ atomic_add_unless\n" -+"1: ldrex %0, [%4]\n" -+" teq %0, %5\n" -+" beq 2f\n" -+" add %1, %0, %6\n" -+" strex %2, %1, [%4]\n" -+" teq %2, #0\n" -+" bne 1b\n" -+"2:" -+ : "=&r" (oldval), "=&r" (newval), "=&r" (tmp), "+Qo" (v->counter) -+ : "r" (&v->counter), "r" (u), "r" (a) -+ : "cc"); -+ -+ if (oldval != u) -+ smp_mb(); -+ -+ return oldval; -+} -+ - #else /* ARM_ARCH_6 */ - - #ifdef CONFIG_SMP -@@ -186,10 +216,6 @@ - return ret; - } - --#endif /* __LINUX_ARM_ARCH__ */ -- --#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) -- - static inline int __atomic_add_unless(atomic_t *v, int a, int u) - { - int c, old; -@@ -200,6 +226,10 @@ - return c; - } - -+#endif /* __LINUX_ARM_ARCH__ */ -+ -+#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) -+ - #define atomic_inc(v) atomic_add(1, v) - #define atomic_dec(v) atomic_sub(1, v) - -@@ -299,6 +329,7 @@ - unsigned long tmp; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic64_add_return\n" - "1: ldrexd %0, %H0, [%3]\n" -@@ -340,6 +371,7 @@ - unsigned long tmp; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic64_sub_return\n" - "1: ldrexd %0, %H0, [%3]\n" -@@ -364,6 +396,7 @@ - unsigned long res; - - smp_mb(); -+ prefetchw(&ptr->counter); - - do { - __asm__ __volatile__("@ atomic64_cmpxchg\n" -@@ -388,6 +421,7 @@ - unsigned long tmp; - - smp_mb(); -+ prefetchw(&ptr->counter); - - __asm__ __volatile__("@ atomic64_xchg\n" - "1: ldrexd %0, %H0, [%3]\n" -@@ -409,6 +443,7 @@ - unsigned long tmp; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic64_dec_if_positive\n" - "1: ldrexd %0, %H0, [%3]\n" -@@ -436,6 +471,7 @@ - int ret = 1; - - smp_mb(); -+ prefetchw(&v->counter); - - __asm__ __volatile__("@ atomic64_add_unless\n" - "1: ldrexd %0, %H0, [%4]\n" -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/cmpxchg.h linux-3.14.22/arch/arm/include/asm/cmpxchg.h ---- linux-3.14.22.orig/arch/arm/include/asm/cmpxchg.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/cmpxchg.h 2014-10-22 14:55:49.702220001 -0500 -@@ -2,6 +2,7 @@ - #define __ASM_ARM_CMPXCHG_H - - #include -+#include - #include - - #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) -@@ -35,6 +36,7 @@ - #endif - - smp_mb(); -+ prefetchw((const void *)ptr); - - switch (size) { - #if __LINUX_ARM_ARCH__ >= 6 -@@ -138,6 +140,8 @@ - { - unsigned long oldval, res; - -+ prefetchw((const void *)ptr); -+ - switch (size) { - #ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ - case 1: -@@ -230,6 +234,8 @@ - unsigned long long oldval; - unsigned long res; - -+ prefetchw(ptr); -+ - __asm__ __volatile__( - "1: ldrexd %1, %H1, [%3]\n" - " teq %1, %4\n" -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/ftrace.h linux-3.14.22/arch/arm/include/asm/ftrace.h ---- linux-3.14.22.orig/arch/arm/include/asm/ftrace.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/ftrace.h 2014-10-22 14:55:49.890220001 -0500 -@@ -52,15 +52,7 @@ - - #endif - --#define HAVE_ARCH_CALLER_ADDR -- --#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) --#define CALLER_ADDR1 ((unsigned long)return_address(1)) --#define CALLER_ADDR2 ((unsigned long)return_address(2)) --#define CALLER_ADDR3 ((unsigned long)return_address(3)) --#define CALLER_ADDR4 ((unsigned long)return_address(4)) --#define CALLER_ADDR5 ((unsigned long)return_address(5)) --#define CALLER_ADDR6 ((unsigned long)return_address(6)) -+#define ftrace_return_address(n) return_address(n) - - #endif /* ifndef __ASSEMBLY__ */ - -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/futex.h linux-3.14.22/arch/arm/include/asm/futex.h ---- linux-3.14.22.orig/arch/arm/include/asm/futex.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/futex.h 2014-10-22 14:55:49.890220001 -0500 -@@ -23,6 +23,7 @@ - - #define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \ - smp_mb(); \ -+ prefetchw(uaddr); \ - __asm__ __volatile__( \ - "1: ldrex %1, [%3]\n" \ - " " insn "\n" \ -@@ -46,6 +47,8 @@ - return -EFAULT; - - smp_mb(); -+ /* Prefetching cannot fault */ -+ prefetchw(uaddr); - __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" - "1: ldrex %1, [%4]\n" - " teq %1, %2\n" -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/glue-cache.h linux-3.14.22/arch/arm/include/asm/glue-cache.h ---- linux-3.14.22.orig/arch/arm/include/asm/glue-cache.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/glue-cache.h 2014-10-22 14:55:49.890220001 -0500 -@@ -102,19 +102,19 @@ - #endif - - #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) --# ifdef _CACHE -+//# ifdef _CACHE - # define MULTI_CACHE 1 --# else --# define _CACHE v6 --# endif -+//# else -+//# define _CACHE v6 -+//# endif - #endif - - #if defined(CONFIG_CPU_V7) --# ifdef _CACHE -+//# ifdef _CACHE - # define MULTI_CACHE 1 --# else --# define _CACHE v7 --# endif -+//# else -+//# define _CACHE v7 -+//# endif - #endif - - #if defined(CONFIG_CPU_V7M) -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/hardware/cache-l2x0.h linux-3.14.22/arch/arm/include/asm/hardware/cache-l2x0.h ---- linux-3.14.22.orig/arch/arm/include/asm/hardware/cache-l2x0.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/hardware/cache-l2x0.h 2014-10-22 14:55:49.890220001 -0500 -@@ -26,8 +26,8 @@ - #define L2X0_CACHE_TYPE 0x004 - #define L2X0_CTRL 0x100 - #define L2X0_AUX_CTRL 0x104 --#define L2X0_TAG_LATENCY_CTRL 0x108 --#define L2X0_DATA_LATENCY_CTRL 0x10C -+#define L310_TAG_LATENCY_CTRL 0x108 -+#define L310_DATA_LATENCY_CTRL 0x10C - #define L2X0_EVENT_CNT_CTRL 0x200 - #define L2X0_EVENT_CNT1_CFG 0x204 - #define L2X0_EVENT_CNT0_CFG 0x208 -@@ -54,53 +54,93 @@ - #define L2X0_LOCKDOWN_WAY_D_BASE 0x900 - #define L2X0_LOCKDOWN_WAY_I_BASE 0x904 - #define L2X0_LOCKDOWN_STRIDE 0x08 --#define L2X0_ADDR_FILTER_START 0xC00 --#define L2X0_ADDR_FILTER_END 0xC04 -+#define L310_ADDR_FILTER_START 0xC00 -+#define L310_ADDR_FILTER_END 0xC04 - #define L2X0_TEST_OPERATION 0xF00 - #define L2X0_LINE_DATA 0xF10 - #define L2X0_LINE_TAG 0xF30 - #define L2X0_DEBUG_CTRL 0xF40 --#define L2X0_PREFETCH_CTRL 0xF60 --#define L2X0_POWER_CTRL 0xF80 --#define L2X0_DYNAMIC_CLK_GATING_EN (1 << 1) --#define L2X0_STNDBY_MODE_EN (1 << 0) -+#define L310_PREFETCH_CTRL 0xF60 -+#define L310_POWER_CTRL 0xF80 -+#define L310_DYNAMIC_CLK_GATING_EN (1 << 1) -+#define L310_STNDBY_MODE_EN (1 << 0) - - /* Registers shifts and masks */ - #define L2X0_CACHE_ID_PART_MASK (0xf << 6) - #define L2X0_CACHE_ID_PART_L210 (1 << 6) -+#define L2X0_CACHE_ID_PART_L220 (2 << 6) - #define L2X0_CACHE_ID_PART_L310 (3 << 6) - #define L2X0_CACHE_ID_RTL_MASK 0x3f --#define L2X0_CACHE_ID_RTL_R0P0 0x0 --#define L2X0_CACHE_ID_RTL_R1P0 0x2 --#define L2X0_CACHE_ID_RTL_R2P0 0x4 --#define L2X0_CACHE_ID_RTL_R3P0 0x5 --#define L2X0_CACHE_ID_RTL_R3P1 0x6 --#define L2X0_CACHE_ID_RTL_R3P2 0x8 -- --#define L2X0_AUX_CTRL_MASK 0xc0000fff -+#define L210_CACHE_ID_RTL_R0P2_02 0x00 -+#define L210_CACHE_ID_RTL_R0P1 0x01 -+#define L210_CACHE_ID_RTL_R0P2_01 0x02 -+#define L210_CACHE_ID_RTL_R0P3 0x03 -+#define L210_CACHE_ID_RTL_R0P4 0x0b -+#define L210_CACHE_ID_RTL_R0P5 0x0f -+#define L220_CACHE_ID_RTL_R1P7_01REL0 0x06 -+#define L310_CACHE_ID_RTL_R0P0 0x00 -+#define L310_CACHE_ID_RTL_R1P0 0x02 -+#define L310_CACHE_ID_RTL_R2P0 0x04 -+#define L310_CACHE_ID_RTL_R3P0 0x05 -+#define L310_CACHE_ID_RTL_R3P1 0x06 -+#define L310_CACHE_ID_RTL_R3P1_50REL0 0x07 -+#define L310_CACHE_ID_RTL_R3P2 0x08 -+#define L310_CACHE_ID_RTL_R3P3 0x09 -+ -+/* L2C auxiliary control register - bits common to L2C-210/220/310 */ -+#define L2C_AUX_CTRL_WAY_SIZE_SHIFT 17 -+#define L2C_AUX_CTRL_WAY_SIZE_MASK (7 << 17) -+#define L2C_AUX_CTRL_WAY_SIZE(n) ((n) << 17) -+#define L2C_AUX_CTRL_EVTMON_ENABLE BIT(20) -+#define L2C_AUX_CTRL_PARITY_ENABLE BIT(21) -+#define L2C_AUX_CTRL_SHARED_OVERRIDE BIT(22) -+/* L2C-210/220 common bits */ - #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT 0 --#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK 0x7 -+#define L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK (7 << 0) - #define L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT 3 --#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (0x7 << 3) -+#define L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK (7 << 3) - #define L2X0_AUX_CTRL_TAG_LATENCY_SHIFT 6 --#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (0x7 << 6) -+#define L2X0_AUX_CTRL_TAG_LATENCY_MASK (7 << 6) - #define L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT 9 --#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (0x7 << 9) --#define L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT 16 --#define L2X0_AUX_CTRL_WAY_SIZE_SHIFT 17 --#define L2X0_AUX_CTRL_WAY_SIZE_MASK (0x7 << 17) --#define L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT 22 --#define L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT 26 --#define L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT 27 --#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28 --#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29 --#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30 -- --#define L2X0_LATENCY_CTRL_SETUP_SHIFT 0 --#define L2X0_LATENCY_CTRL_RD_SHIFT 4 --#define L2X0_LATENCY_CTRL_WR_SHIFT 8 -- --#define L2X0_ADDR_FILTER_EN 1 -+#define L2X0_AUX_CTRL_DIRTY_LATENCY_MASK (7 << 9) -+#define L2X0_AUX_CTRL_ASSOC_SHIFT 13 -+#define L2X0_AUX_CTRL_ASSOC_MASK (15 << 13) -+/* L2C-210 specific bits */ -+#define L210_AUX_CTRL_WRAP_DISABLE BIT(12) -+#define L210_AUX_CTRL_WA_OVERRIDE BIT(23) -+#define L210_AUX_CTRL_EXCLUSIVE_ABORT BIT(24) -+/* L2C-220 specific bits */ -+#define L220_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) -+#define L220_AUX_CTRL_FWA_SHIFT 23 -+#define L220_AUX_CTRL_FWA_MASK (3 << 23) -+#define L220_AUX_CTRL_NS_LOCKDOWN BIT(26) -+#define L220_AUX_CTRL_NS_INT_CTRL BIT(27) -+/* L2C-310 specific bits */ -+#define L310_AUX_CTRL_FULL_LINE_ZERO BIT(0) /* R2P0+ */ -+#define L310_AUX_CTRL_HIGHPRIO_SO_DEV BIT(10) /* R2P0+ */ -+#define L310_AUX_CTRL_STORE_LIMITATION BIT(11) /* R2P0+ */ -+#define L310_AUX_CTRL_EXCLUSIVE_CACHE BIT(12) -+#define L310_AUX_CTRL_ASSOCIATIVITY_16 BIT(16) -+#define L310_AUX_CTRL_CACHE_REPLACE_RR BIT(25) /* R2P0+ */ -+#define L310_AUX_CTRL_NS_LOCKDOWN BIT(26) -+#define L310_AUX_CTRL_NS_INT_CTRL BIT(27) -+#define L310_AUX_CTRL_DATA_PREFETCH BIT(28) -+#define L310_AUX_CTRL_INSTR_PREFETCH BIT(29) -+#define L310_AUX_CTRL_EARLY_BRESP BIT(30) /* R2P0+ */ -+ -+#define L310_LATENCY_CTRL_SETUP(n) ((n) << 0) -+#define L310_LATENCY_CTRL_RD(n) ((n) << 4) -+#define L310_LATENCY_CTRL_WR(n) ((n) << 8) -+ -+#define L310_ADDR_FILTER_EN 1 -+ -+#define L310_PREFETCH_CTRL_OFFSET_MASK 0x1f -+#define L310_PREFETCH_CTRL_DBL_LINEFILL_INCR BIT(23) -+#define L310_PREFETCH_CTRL_PREFETCH_DROP BIT(24) -+#define L310_PREFETCH_CTRL_DBL_LINEFILL_WRAP BIT(27) -+#define L310_PREFETCH_CTRL_DATA_PREFETCH BIT(28) -+#define L310_PREFETCH_CTRL_INSTR_PREFETCH BIT(29) -+#define L310_PREFETCH_CTRL_DBL_LINEFILL BIT(30) - - #define L2X0_CTRL_EN 1 - -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/outercache.h linux-3.14.22/arch/arm/include/asm/outercache.h ---- linux-3.14.22.orig/arch/arm/include/asm/outercache.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/outercache.h 2014-10-22 14:55:49.890220001 -0500 -@@ -21,6 +21,7 @@ - #ifndef __ASM_OUTERCACHE_H - #define __ASM_OUTERCACHE_H - -+#include - #include - - struct outer_cache_fns { -@@ -28,53 +29,84 @@ - void (*clean_range)(unsigned long, unsigned long); - void (*flush_range)(unsigned long, unsigned long); - void (*flush_all)(void); -- void (*inv_all)(void); - void (*disable)(void); - #ifdef CONFIG_OUTER_CACHE_SYNC - void (*sync)(void); - #endif -- void (*set_debug)(unsigned long); - void (*resume)(void); -+ -+ /* This is an ARM L2C thing */ -+ void (*write_sec)(unsigned long, unsigned); - }; - - extern struct outer_cache_fns outer_cache; - - #ifdef CONFIG_OUTER_CACHE -- -+/** -+ * outer_inv_range - invalidate range of outer cache lines -+ * @start: starting physical address, inclusive -+ * @end: end physical address, exclusive -+ */ - static inline void outer_inv_range(phys_addr_t start, phys_addr_t end) - { - if (outer_cache.inv_range) - outer_cache.inv_range(start, end); - } -+ -+/** -+ * outer_clean_range - clean dirty outer cache lines -+ * @start: starting physical address, inclusive -+ * @end: end physical address, exclusive -+ */ - static inline void outer_clean_range(phys_addr_t start, phys_addr_t end) - { - if (outer_cache.clean_range) - outer_cache.clean_range(start, end); - } -+ -+/** -+ * outer_flush_range - clean and invalidate outer cache lines -+ * @start: starting physical address, inclusive -+ * @end: end physical address, exclusive -+ */ - static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) - { - if (outer_cache.flush_range) - outer_cache.flush_range(start, end); - } - -+/** -+ * outer_flush_all - clean and invalidate all cache lines in the outer cache -+ * -+ * Note: depending on implementation, this may not be atomic - it must -+ * only be called with interrupts disabled and no other active outer -+ * cache masters. -+ * -+ * It is intended that this function is only used by implementations -+ * needing to override the outer_cache.disable() method due to security. -+ * (Some implementations perform this as a clean followed by an invalidate.) -+ */ - static inline void outer_flush_all(void) - { - if (outer_cache.flush_all) - outer_cache.flush_all(); - } - --static inline void outer_inv_all(void) --{ -- if (outer_cache.inv_all) -- outer_cache.inv_all(); --} -- --static inline void outer_disable(void) --{ -- if (outer_cache.disable) -- outer_cache.disable(); --} -- -+/** -+ * outer_disable - clean, invalidate and disable the outer cache -+ * -+ * Disable the outer cache, ensuring that any data contained in the outer -+ * cache is pushed out to lower levels of system memory. The note and -+ * conditions above concerning outer_flush_all() applies here. -+ */ -+extern void outer_disable(void); -+ -+/** -+ * outer_resume - restore the cache configuration and re-enable outer cache -+ * -+ * Restore any configuration that the cache had when previously enabled, -+ * and re-enable the outer cache. -+ */ - static inline void outer_resume(void) - { - if (outer_cache.resume) -@@ -90,13 +122,18 @@ - static inline void outer_flush_range(phys_addr_t start, phys_addr_t end) - { } - static inline void outer_flush_all(void) { } --static inline void outer_inv_all(void) { } - static inline void outer_disable(void) { } - static inline void outer_resume(void) { } - - #endif - - #ifdef CONFIG_OUTER_CACHE_SYNC -+/** -+ * outer_sync - perform a sync point for outer cache -+ * -+ * Ensure that all outer cache operations are complete and any store -+ * buffers are drained. -+ */ - static inline void outer_sync(void) - { - if (outer_cache.sync) -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/pmu.h linux-3.14.22/arch/arm/include/asm/pmu.h ---- linux-3.14.22.orig/arch/arm/include/asm/pmu.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/pmu.h 2014-10-22 14:55:49.890220001 -0500 -@@ -62,9 +62,19 @@ - raw_spinlock_t pmu_lock; - }; - -+struct cpupmu_regs { -+ u32 pmc; -+ u32 pmcntenset; -+ u32 pmuseren; -+ u32 pmintenset; -+ u32 pmxevttype[8]; -+ u32 pmxevtcnt[8]; -+}; -+ - struct arm_pmu { - struct pmu pmu; - cpumask_t active_irqs; -+ cpumask_t valid_cpus; - char *name; - irqreturn_t (*handle_irq)(int irq_num, void *dev); - void (*enable)(struct perf_event *event); -@@ -81,6 +91,8 @@ - int (*request_irq)(struct arm_pmu *, irq_handler_t handler); - void (*free_irq)(struct arm_pmu *); - int (*map_event)(struct perf_event *event); -+ void (*save_regs)(struct arm_pmu *, struct cpupmu_regs *); -+ void (*restore_regs)(struct arm_pmu *, struct cpupmu_regs *); - int num_events; - atomic_t active_events; - struct mutex reserve_mutex; -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/psci.h linux-3.14.22/arch/arm/include/asm/psci.h ---- linux-3.14.22.orig/arch/arm/include/asm/psci.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/psci.h 2014-10-22 14:55:49.890220001 -0500 -@@ -16,6 +16,10 @@ - - #define PSCI_POWER_STATE_TYPE_STANDBY 0 - #define PSCI_POWER_STATE_TYPE_POWER_DOWN 1 -+#define PSCI_POWER_STATE_AFFINITY_LEVEL0 0 -+#define PSCI_POWER_STATE_AFFINITY_LEVEL1 1 -+#define PSCI_POWER_STATE_AFFINITY_LEVEL2 2 -+#define PSCI_POWER_STATE_AFFINITY_LEVEL3 3 - - struct psci_power_state { - u16 id; -@@ -42,4 +46,12 @@ - static inline bool psci_smp_available(void) { return false; } - #endif - -+#ifdef CONFIG_ARM_PSCI -+extern int psci_probe(void); -+#else -+static inline int psci_probe(void) -+{ -+ return -ENODEV; -+} -+#endif - #endif /* __ASM_ARM_PSCI_H */ -diff -Nur linux-3.14.22.orig/arch/arm/include/asm/topology.h linux-3.14.22/arch/arm/include/asm/topology.h ---- linux-3.14.22.orig/arch/arm/include/asm/topology.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/include/asm/topology.h 2014-10-22 14:55:49.890220001 -0500 -@@ -26,11 +26,14 @@ - void init_cpu_topology(void); - void store_cpu_topology(unsigned int cpuid); - const struct cpumask *cpu_coregroup_mask(int cpu); -+int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask); - - #else - - static inline void init_cpu_topology(void) { } - static inline void store_cpu_topology(unsigned int cpuid) { } -+static inline int cluster_to_logical_mask(unsigned int socket_id, -+ cpumask_t *cluster_mask) { return -EINVAL; } - - #endif - -diff -Nur linux-3.14.22.orig/arch/arm/Kconfig linux-3.14.22/arch/arm/Kconfig ---- linux-3.14.22.orig/arch/arm/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/Kconfig 2014-10-22 14:55:49.894220001 -0500 -@@ -1216,19 +1216,6 @@ - register of the Cortex-A9 which reduces the linefill issuing - capabilities of the processor. - --config PL310_ERRATA_588369 -- bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" -- depends on CACHE_L2X0 -- help -- The PL310 L2 cache controller implements three types of Clean & -- Invalidate maintenance operations: by Physical Address -- (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). -- They are architecturally defined to behave as the execution of a -- clean operation followed immediately by an invalidate operation, -- both performing to the same memory location. This functionality -- is not correctly implemented in PL310 as clean lines are not -- invalidated as a result of these operations. -- - config ARM_ERRATA_643719 - bool "ARM errata: LoUIS bit field in CLIDR register is incorrect" - depends on CPU_V7 && SMP -@@ -1251,17 +1238,6 @@ - tables. The workaround changes the TLB flushing routines to invalidate - entries regardless of the ASID. - --config PL310_ERRATA_727915 -- bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" -- depends on CACHE_L2X0 -- help -- PL310 implements the Clean & Invalidate by Way L2 cache maintenance -- operation (offset 0x7FC). This operation runs in background so that -- PL310 can handle normal accesses while it is in progress. Under very -- rare circumstances, due to this erratum, write data can be lost when -- PL310 treats a cacheable write transaction during a Clean & -- Invalidate by Way operation. -- - config ARM_ERRATA_743622 - bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption" - depends on CPU_V7 -@@ -1287,21 +1263,6 @@ - operation is received by a CPU before the ICIALLUIS has completed, - potentially leading to corrupted entries in the cache or TLB. - --config PL310_ERRATA_753970 -- bool "PL310 errata: cache sync operation may be faulty" -- depends on CACHE_PL310 -- help -- This option enables the workaround for the 753970 PL310 (r3p0) erratum. -- -- Under some condition the effect of cache sync operation on -- the store buffer still remains when the operation completes. -- This means that the store buffer is always asked to drain and -- this prevents it from merging any further writes. The workaround -- is to replace the normal offset of cache sync operation (0x730) -- by another offset targeting an unmapped PL310 register 0x740. -- This has the same effect as the cache sync operation: store buffer -- drain and waiting for all buffers empty. -- - config ARM_ERRATA_754322 - bool "ARM errata: possible faulty MMU translations following an ASID switch" - depends on CPU_V7 -@@ -1350,18 +1311,6 @@ - relevant cache maintenance functions and sets a specific bit - in the diagnostic control register of the SCU. - --config PL310_ERRATA_769419 -- bool "PL310 errata: no automatic Store Buffer drain" -- depends on CACHE_L2X0 -- help -- On revisions of the PL310 prior to r3p2, the Store Buffer does -- not automatically drain. This can cause normal, non-cacheable -- writes to be retained when the memory system is idle, leading -- to suboptimal I/O performance for drivers using coherent DMA. -- This option adds a write barrier to the cpu_idle loop so that, -- on systems with an outer cache, the store buffer is drained -- explicitly. -- - config ARM_ERRATA_775420 - bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" - depends on CPU_V7 -@@ -1391,6 +1340,29 @@ - loop buffer may deliver incorrect instructions. This - workaround disables the loop buffer to avoid the erratum. - -+config ARM_ERRATA_794072 -+ bool "ARM errata: A short loop including a DMB instruction might cause a denial of service" -+ depends on CPU_V7 && SMP -+ help -+ This option enables the workaround for the 794072 Cortex-A9 -+ (all revisions). A processor which continuously executes a short -+ loop containing a DMB instruction might prevent a CP15 operation -+ broadcast by another processor making further progress, causing -+ a denial of service. This erratum can be worked around by setting -+ bit[4] of the undocumented Diagnostic Control Register to 1. -+ -+config ARM_ERRATA_761320 -+ bool "Full cache line writes to the same memory region from at least two processors might deadlock processor" -+ depends on CPU_V7 && SMP -+ help -+ This option enables the workaround for the 761320 Cortex-A9 (r0..r3). -+ Under very rare circumstances, full cache line writes -+ from (at least) 2 processors on cache lines in hazard with -+ other requests may cause arbitration issues in the SCU, -+ leading to processor deadlock. This erratum can be -+ worked around by setting bit[21] of the undocumented -+ Diagnostic Control Register to 1. -+ - endmenu - - source "arch/arm/common/Kconfig" -@@ -1835,6 +1807,7 @@ - range 11 64 if ARCH_SHMOBILE_LEGACY - default "12" if SOC_AM33XX - default "9" if SA1111 || ARCH_EFM32 -+ default "14" if ARCH_MXC - default "11" - help - The kernel memory allocator divides physically contiguous memory -diff -Nur linux-3.14.22.orig/arch/arm/kernel/perf_event.c linux-3.14.22/arch/arm/kernel/perf_event.c ---- linux-3.14.22.orig/arch/arm/kernel/perf_event.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/perf_event.c 2014-10-22 14:55:49.894220001 -0500 -@@ -12,6 +12,7 @@ - */ - #define pr_fmt(fmt) "hw perfevents: " fmt - -+#include - #include - #include - #include -@@ -86,6 +87,9 @@ - return armpmu_map_cache_event(cache_map, config); - case PERF_TYPE_RAW: - return armpmu_map_raw_event(raw_event_mask, config); -+ default: -+ if (event->attr.type >= PERF_TYPE_MAX) -+ return armpmu_map_raw_event(raw_event_mask, config); - } - - return -ENOENT; -@@ -159,6 +163,8 @@ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - -+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus)) -+ return; - /* - * ARM pmu always has to update the counter, so ignore - * PERF_EF_UPDATE, see comments in armpmu_start(). -@@ -175,6 +181,8 @@ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - -+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus)) -+ return; - /* - * ARM pmu always has to reprogram the period, so ignore - * PERF_EF_RELOAD, see the comment below. -@@ -202,6 +210,9 @@ - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - -+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus)) -+ return; -+ - armpmu_stop(event, PERF_EF_UPDATE); - hw_events->events[idx] = NULL; - clear_bit(idx, hw_events->used_mask); -@@ -218,6 +229,10 @@ - int idx; - int err = 0; - -+ /* An event following a process won't be stopped earlier */ -+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->valid_cpus)) -+ return 0; -+ - perf_pmu_disable(event->pmu); - - /* If we don't have a space for the counter then finish early. */ -@@ -419,6 +434,10 @@ - int err = 0; - atomic_t *active_events = &armpmu->active_events; - -+ if (event->cpu != -1 && -+ !cpumask_test_cpu(event->cpu, &armpmu->valid_cpus)) -+ return -ENOENT; -+ - /* does not support taken branch sampling */ - if (has_branch_stack(event)) - return -EOPNOTSUPP; -diff -Nur linux-3.14.22.orig/arch/arm/kernel/perf_event_cpu.c linux-3.14.22/arch/arm/kernel/perf_event_cpu.c ---- linux-3.14.22.orig/arch/arm/kernel/perf_event_cpu.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/perf_event_cpu.c 2014-10-22 14:55:49.898220001 -0500 -@@ -19,6 +19,7 @@ - #define pr_fmt(fmt) "CPU PMU: " fmt - - #include -+#include - #include - #include - #include -@@ -31,33 +32,36 @@ - #include - - /* Set at runtime when we know what CPU type we are. */ --static struct arm_pmu *cpu_pmu; -+static DEFINE_PER_CPU(struct arm_pmu *, cpu_pmu); - - static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); - static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); - static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); - -+static DEFINE_PER_CPU(struct cpupmu_regs, cpu_pmu_regs); -+ - /* - * Despite the names, these two functions are CPU-specific and are used - * by the OProfile/perf code. - */ - const char *perf_pmu_name(void) - { -- if (!cpu_pmu) -+ struct arm_pmu *pmu = per_cpu(cpu_pmu, 0); -+ if (!pmu) - return NULL; - -- return cpu_pmu->name; -+ return pmu->name; - } - EXPORT_SYMBOL_GPL(perf_pmu_name); - - int perf_num_counters(void) - { -- int max_events = 0; -+ struct arm_pmu *pmu = per_cpu(cpu_pmu, 0); - -- if (cpu_pmu != NULL) -- max_events = cpu_pmu->num_events; -+ if (!pmu) -+ return 0; - -- return max_events; -+ return pmu->num_events; - } - EXPORT_SYMBOL_GPL(perf_num_counters); - -@@ -75,11 +79,13 @@ - { - int i, irq, irqs; - struct platform_device *pmu_device = cpu_pmu->plat_device; -+ int cpu = -1; - - irqs = min(pmu_device->num_resources, num_possible_cpus()); - - for (i = 0; i < irqs; ++i) { -- if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs)) -+ cpu = cpumask_next(cpu, &cpu_pmu->valid_cpus); -+ if (!cpumask_test_and_clear_cpu(cpu, &cpu_pmu->active_irqs)) - continue; - irq = platform_get_irq(pmu_device, i); - if (irq >= 0) -@@ -91,6 +97,7 @@ - { - int i, err, irq, irqs; - struct platform_device *pmu_device = cpu_pmu->plat_device; -+ int cpu = -1; - - if (!pmu_device) - return -ENODEV; -@@ -103,6 +110,7 @@ - - for (i = 0; i < irqs; ++i) { - err = 0; -+ cpu = cpumask_next(cpu, &cpu_pmu->valid_cpus); - irq = platform_get_irq(pmu_device, i); - if (irq < 0) - continue; -@@ -112,7 +120,7 @@ - * assume that we're running on a uniprocessor machine and - * continue. Otherwise, continue without this interrupt. - */ -- if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { -+ if (irq_set_affinity(irq, cpumask_of(cpu)) && irqs > 1) { - pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", - irq, i); - continue; -@@ -127,7 +135,7 @@ - return err; - } - -- cpumask_set_cpu(i, &cpu_pmu->active_irqs); -+ cpumask_set_cpu(cpu, &cpu_pmu->active_irqs); - } - - return 0; -@@ -136,7 +144,7 @@ - static void cpu_pmu_init(struct arm_pmu *cpu_pmu) - { - int cpu; -- for_each_possible_cpu(cpu) { -+ for_each_cpu_mask(cpu, cpu_pmu->valid_cpus) { - struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); - events->events = per_cpu(hw_events, cpu); - events->used_mask = per_cpu(used_mask, cpu); -@@ -149,7 +157,7 @@ - - /* Ensure the PMU has sane values out of reset. */ - if (cpu_pmu->reset) -- on_each_cpu(cpu_pmu->reset, cpu_pmu, 1); -+ on_each_cpu_mask(&cpu_pmu->valid_cpus, cpu_pmu->reset, cpu_pmu, 1); - } - - /* -@@ -161,21 +169,46 @@ - static int cpu_pmu_notify(struct notifier_block *b, unsigned long action, - void *hcpu) - { -+ struct arm_pmu *pmu = per_cpu(cpu_pmu, (long)hcpu); -+ - if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) - return NOTIFY_DONE; - -- if (cpu_pmu && cpu_pmu->reset) -- cpu_pmu->reset(cpu_pmu); -+ if (pmu && pmu->reset) -+ pmu->reset(pmu); - else - return NOTIFY_DONE; - - return NOTIFY_OK; - } - -+static int cpu_pmu_pm_notify(struct notifier_block *b, -+ unsigned long action, void *hcpu) -+{ -+ int cpu = smp_processor_id(); -+ struct arm_pmu *pmu = per_cpu(cpu_pmu, cpu); -+ struct cpupmu_regs *pmuregs = &per_cpu(cpu_pmu_regs, cpu); -+ -+ if (!pmu) -+ return NOTIFY_DONE; -+ -+ if (action == CPU_PM_ENTER && pmu->save_regs) { -+ pmu->save_regs(pmu, pmuregs); -+ } else if (action == CPU_PM_EXIT && pmu->restore_regs) { -+ pmu->restore_regs(pmu, pmuregs); -+ } -+ -+ return NOTIFY_OK; -+} -+ - static struct notifier_block cpu_pmu_hotplug_notifier = { - .notifier_call = cpu_pmu_notify, - }; - -+static struct notifier_block cpu_pmu_pm_notifier = { -+ .notifier_call = cpu_pmu_pm_notify, -+}; -+ - /* - * PMU platform driver and devicetree bindings. - */ -@@ -247,6 +280,9 @@ - } - } - -+ /* assume PMU support all the CPUs in this case */ -+ cpumask_setall(&pmu->valid_cpus); -+ - put_cpu(); - return ret; - } -@@ -254,15 +290,10 @@ - static int cpu_pmu_device_probe(struct platform_device *pdev) - { - const struct of_device_id *of_id; -- const int (*init_fn)(struct arm_pmu *); - struct device_node *node = pdev->dev.of_node; - struct arm_pmu *pmu; -- int ret = -ENODEV; -- -- if (cpu_pmu) { -- pr_info("attempt to register multiple PMU devices!"); -- return -ENOSPC; -- } -+ int ret = 0; -+ int cpu; - - pmu = kzalloc(sizeof(struct arm_pmu), GFP_KERNEL); - if (!pmu) { -@@ -271,8 +302,28 @@ - } - - if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) { -- init_fn = of_id->data; -- ret = init_fn(pmu); -+ smp_call_func_t init_fn = (smp_call_func_t)of_id->data; -+ struct device_node *ncluster; -+ int cluster = -1; -+ cpumask_t sibling_mask; -+ -+ ncluster = of_parse_phandle(node, "cluster", 0); -+ if (ncluster) { -+ int len; -+ const u32 *hwid; -+ hwid = of_get_property(ncluster, "reg", &len); -+ if (hwid && len == 4) -+ cluster = be32_to_cpup(hwid); -+ } -+ /* set sibling mask to all cpu mask if socket is not specified */ -+ if (cluster == -1 || -+ cluster_to_logical_mask(cluster, &sibling_mask)) -+ cpumask_setall(&sibling_mask); -+ -+ smp_call_function_any(&sibling_mask, init_fn, pmu, 1); -+ -+ /* now set the valid_cpus after init */ -+ cpumask_copy(&pmu->valid_cpus, &sibling_mask); - } else { - ret = probe_current_pmu(pmu); - } -@@ -282,10 +333,12 @@ - goto out_free; - } - -- cpu_pmu = pmu; -- cpu_pmu->plat_device = pdev; -- cpu_pmu_init(cpu_pmu); -- ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW); -+ for_each_cpu_mask(cpu, pmu->valid_cpus) -+ per_cpu(cpu_pmu, cpu) = pmu; -+ -+ pmu->plat_device = pdev; -+ cpu_pmu_init(pmu); -+ ret = armpmu_register(pmu, -1); - - if (!ret) - return 0; -@@ -314,9 +367,17 @@ - if (err) - return err; - -+ err = cpu_pm_register_notifier(&cpu_pmu_pm_notifier); -+ if (err) { -+ unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); -+ return err; -+ } -+ - err = platform_driver_register(&cpu_pmu_driver); -- if (err) -+ if (err) { -+ cpu_pm_unregister_notifier(&cpu_pmu_pm_notifier); - unregister_cpu_notifier(&cpu_pmu_hotplug_notifier); -+ } - - return err; - } -diff -Nur linux-3.14.22.orig/arch/arm/kernel/perf_event_v7.c linux-3.14.22/arch/arm/kernel/perf_event_v7.c ---- linux-3.14.22.orig/arch/arm/kernel/perf_event_v7.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/perf_event_v7.c 2014-10-22 14:55:49.898220001 -0500 -@@ -950,6 +950,51 @@ - } - #endif - -+static void armv7pmu_save_regs(struct arm_pmu *cpu_pmu, -+ struct cpupmu_regs *regs) -+{ -+ unsigned int cnt; -+ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (regs->pmc)); -+ if (!(regs->pmc & ARMV7_PMNC_E)) -+ return; -+ -+ asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (regs->pmcntenset)); -+ asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (regs->pmuseren)); -+ asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (regs->pmintenset)); -+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (regs->pmxevtcnt[0])); -+ for (cnt = ARMV7_IDX_COUNTER0; -+ cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) { -+ armv7_pmnc_select_counter(cnt); -+ asm volatile("mrc p15, 0, %0, c9, c13, 1" -+ : "=r"(regs->pmxevttype[cnt])); -+ asm volatile("mrc p15, 0, %0, c9, c13, 2" -+ : "=r"(regs->pmxevtcnt[cnt])); -+ } -+ return; -+} -+ -+static void armv7pmu_restore_regs(struct arm_pmu *cpu_pmu, -+ struct cpupmu_regs *regs) -+{ -+ unsigned int cnt; -+ if (!(regs->pmc & ARMV7_PMNC_E)) -+ return; -+ -+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (regs->pmcntenset)); -+ asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (regs->pmuseren)); -+ asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (regs->pmintenset)); -+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (regs->pmxevtcnt[0])); -+ for (cnt = ARMV7_IDX_COUNTER0; -+ cnt <= ARMV7_IDX_COUNTER_LAST(cpu_pmu); cnt++) { -+ armv7_pmnc_select_counter(cnt); -+ asm volatile("mcr p15, 0, %0, c9, c13, 1" -+ : : "r"(regs->pmxevttype[cnt])); -+ asm volatile("mcr p15, 0, %0, c9, c13, 2" -+ : : "r"(regs->pmxevtcnt[cnt])); -+ } -+ asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (regs->pmc)); -+} -+ - static void armv7pmu_enable_event(struct perf_event *event) - { - unsigned long flags; -@@ -1223,6 +1268,8 @@ - cpu_pmu->start = armv7pmu_start; - cpu_pmu->stop = armv7pmu_stop; - cpu_pmu->reset = armv7pmu_reset; -+ cpu_pmu->save_regs = armv7pmu_save_regs; -+ cpu_pmu->restore_regs = armv7pmu_restore_regs; - cpu_pmu->max_period = (1LLU << 32) - 1; - }; - -@@ -1240,7 +1287,7 @@ - static int armv7_a8_pmu_init(struct arm_pmu *cpu_pmu) - { - armv7pmu_init(cpu_pmu); -- cpu_pmu->name = "ARMv7 Cortex-A8"; -+ cpu_pmu->name = "ARMv7_Cortex_A8"; - cpu_pmu->map_event = armv7_a8_map_event; - cpu_pmu->num_events = armv7_read_num_pmnc_events(); - return 0; -@@ -1249,7 +1296,7 @@ - static int armv7_a9_pmu_init(struct arm_pmu *cpu_pmu) - { - armv7pmu_init(cpu_pmu); -- cpu_pmu->name = "ARMv7 Cortex-A9"; -+ cpu_pmu->name = "ARMv7_Cortex_A9"; - cpu_pmu->map_event = armv7_a9_map_event; - cpu_pmu->num_events = armv7_read_num_pmnc_events(); - return 0; -@@ -1258,7 +1305,7 @@ - static int armv7_a5_pmu_init(struct arm_pmu *cpu_pmu) - { - armv7pmu_init(cpu_pmu); -- cpu_pmu->name = "ARMv7 Cortex-A5"; -+ cpu_pmu->name = "ARMv7_Cortex_A5"; - cpu_pmu->map_event = armv7_a5_map_event; - cpu_pmu->num_events = armv7_read_num_pmnc_events(); - return 0; -@@ -1267,7 +1314,7 @@ - static int armv7_a15_pmu_init(struct arm_pmu *cpu_pmu) - { - armv7pmu_init(cpu_pmu); -- cpu_pmu->name = "ARMv7 Cortex-A15"; -+ cpu_pmu->name = "ARMv7_Cortex_A15"; - cpu_pmu->map_event = armv7_a15_map_event; - cpu_pmu->num_events = armv7_read_num_pmnc_events(); - cpu_pmu->set_event_filter = armv7pmu_set_event_filter; -@@ -1277,7 +1324,7 @@ - static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu) - { - armv7pmu_init(cpu_pmu); -- cpu_pmu->name = "ARMv7 Cortex-A7"; -+ cpu_pmu->name = "ARMv7_Cortex_A7"; - cpu_pmu->map_event = armv7_a7_map_event; - cpu_pmu->num_events = armv7_read_num_pmnc_events(); - cpu_pmu->set_event_filter = armv7pmu_set_event_filter; -diff -Nur linux-3.14.22.orig/arch/arm/kernel/process.c linux-3.14.22/arch/arm/kernel/process.c ---- linux-3.14.22.orig/arch/arm/kernel/process.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/process.c 2014-10-22 14:55:49.898220001 -0500 -@@ -172,8 +172,10 @@ - */ - void arch_cpu_idle(void) - { -+ idle_notifier_call_chain(IDLE_START); - if (cpuidle_idle_call()) - default_idle(); -+ idle_notifier_call_chain(IDLE_END); - } - - /* -diff -Nur linux-3.14.22.orig/arch/arm/kernel/psci.c linux-3.14.22/arch/arm/kernel/psci.c ---- linux-3.14.22.orig/arch/arm/kernel/psci.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/psci.c 2014-10-22 14:55:49.898220001 -0500 -@@ -42,6 +42,7 @@ - #define PSCI_RET_EOPNOTSUPP -1 - #define PSCI_RET_EINVAL -2 - #define PSCI_RET_EPERM -3 -+#define PSCI_RET_EALREADYON -4 - - static int psci_to_linux_errno(int errno) - { -@@ -54,6 +55,8 @@ - return -EINVAL; - case PSCI_RET_EPERM: - return -EPERM; -+ case PSCI_RET_EALREADYON: -+ return -EAGAIN; - }; - - return -EINVAL; -@@ -153,7 +156,7 @@ - return psci_to_linux_errno(err); - } - --static const struct of_device_id psci_of_match[] __initconst = { -+static const struct of_device_id psci_of_match[] = { - { .compatible = "arm,psci", }, - {}, - }; -@@ -208,3 +211,16 @@ - of_node_put(np); - return; - } -+ -+int psci_probe(void) -+{ -+ struct device_node *np; -+ int ret = -ENODEV; -+ -+ np = of_find_matching_node(NULL, psci_of_match); -+ if (np) -+ ret = 0; -+ -+ of_node_put(np); -+ return ret; -+} -diff -Nur linux-3.14.22.orig/arch/arm/kernel/setup.c linux-3.14.22/arch/arm/kernel/setup.c ---- linux-3.14.22.orig/arch/arm/kernel/setup.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/setup.c 2014-10-22 14:55:49.898220001 -0500 -@@ -273,6 +273,19 @@ - int aliasing_icache; - unsigned int id_reg, num_sets, line_size; - -+#ifdef CONFIG_BIG_LITTLE -+ /* -+ * We expect a combination of Cortex-A15 and Cortex-A7 cores. -+ * A7 = VIPT aliasing I-cache -+ * A15 = PIPT (non-aliasing) I-cache -+ * To cater for this discrepancy, let's assume aliasing I-cache -+ * all the time. This means unneeded extra work on the A15 but -+ * only ptrace is affected which is not performance critical. -+ */ -+ if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc0f0) -+ return 1; -+#endif -+ - /* PIPT caches never alias. */ - if (icache_is_pipt()) - return 0; -diff -Nur linux-3.14.22.orig/arch/arm/kernel/topology.c linux-3.14.22/arch/arm/kernel/topology.c ---- linux-3.14.22.orig/arch/arm/kernel/topology.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/kernel/topology.c 2014-10-22 14:55:49.902220001 -0500 -@@ -267,6 +267,33 @@ - } - - /* -+ * cluster_to_logical_mask - return cpu logical mask of CPUs in a cluster -+ * @socket_id: cluster HW identifier -+ * @cluster_mask: the cpumask location to be initialized, modified by the -+ * function only if return value == 0 -+ * -+ * Return: -+ * -+ * 0 on success -+ * -EINVAL if cluster_mask is NULL or there is no record matching socket_id -+ */ -+int cluster_to_logical_mask(unsigned int socket_id, cpumask_t *cluster_mask) -+{ -+ int cpu; -+ -+ if (!cluster_mask) -+ return -EINVAL; -+ -+ for_each_online_cpu(cpu) -+ if (socket_id == topology_physical_package_id(cpu)) { -+ cpumask_copy(cluster_mask, topology_core_cpumask(cpu)); -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+/* - * init_cpu_topology is called at boot when only one cpu is running - * which prevent simultaneous write access to cpu_topology array - */ -diff -Nur linux-3.14.22.orig/arch/arm/lib/bitops.h linux-3.14.22/arch/arm/lib/bitops.h ---- linux-3.14.22.orig/arch/arm/lib/bitops.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/lib/bitops.h 2014-10-22 14:55:49.902220001 -0500 -@@ -37,6 +37,11 @@ - add r1, r1, r0, lsl #2 @ Get word offset - mov r3, r2, lsl r3 @ create mask - smp_dmb -+#if __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) -+ .arch_extension mp -+ ALT_SMP(W(pldw) [r1]) -+ ALT_UP(W(nop)) -+#endif - 1: ldrex r2, [r1] - ands r0, r2, r3 @ save old value of bit - \instr r2, r2, r3 @ toggle bit -diff -Nur linux-3.14.22.orig/arch/arm/mach-berlin/berlin.c linux-3.14.22/arch/arm/mach-berlin/berlin.c ---- linux-3.14.22.orig/arch/arm/mach-berlin/berlin.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-berlin/berlin.c 2014-10-22 14:55:49.902220001 -0500 -@@ -24,7 +24,7 @@ - * with DT probing for L2CCs, berlin_init_machine can be removed. - * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc - */ -- l2x0_of_init(0x70c00000, 0xfeffffff); -+ l2x0_of_init(0x30c00000, 0xfeffffff); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-cns3xxx/core.c linux-3.14.22/arch/arm/mach-cns3xxx/core.c ---- linux-3.14.22.orig/arch/arm/mach-cns3xxx/core.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-cns3xxx/core.c 2014-10-22 14:55:49.902220001 -0500 -@@ -240,9 +240,9 @@ - * - * 1 cycle of latency for setup, read and write accesses - */ -- val = readl(base + L2X0_TAG_LATENCY_CTRL); -+ val = readl(base + L310_TAG_LATENCY_CTRL); - val &= 0xfffff888; -- writel(val, base + L2X0_TAG_LATENCY_CTRL); -+ writel(val, base + L310_TAG_LATENCY_CTRL); - - /* - * Data RAM Control register -@@ -253,12 +253,12 @@ - * - * 1 cycle of latency for setup, read and write accesses - */ -- val = readl(base + L2X0_DATA_LATENCY_CTRL); -+ val = readl(base + L310_DATA_LATENCY_CTRL); - val &= 0xfffff888; -- writel(val, base + L2X0_DATA_LATENCY_CTRL); -+ writel(val, base + L310_DATA_LATENCY_CTRL); - - /* 32 KiB, 8-way, parity disable */ -- l2x0_init(base, 0x00540000, 0xfe000fff); -+ l2x0_init(base, 0x00500000, 0xfe0f0fff); - } - - #endif /* CONFIG_CACHE_L2X0 */ -diff -Nur linux-3.14.22.orig/arch/arm/mach-exynos/common.c linux-3.14.22/arch/arm/mach-exynos/common.c ---- linux-3.14.22.orig/arch/arm/mach-exynos/common.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-exynos/common.c 2014-10-22 14:55:49.902220001 -0500 -@@ -45,9 +45,6 @@ - #include "common.h" - #include "regs-pmu.h" - --#define L2_AUX_VAL 0x7C470001 --#define L2_AUX_MASK 0xC200ffff -- - static const char name_exynos4210[] = "EXYNOS4210"; - static const char name_exynos4212[] = "EXYNOS4212"; - static const char name_exynos4412[] = "EXYNOS4412"; -@@ -400,7 +397,7 @@ - { - int ret; - -- ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); -+ ret = l2x0_of_init(0x3c400001, 0xc20fffff); - if (ret) - return ret; - -diff -Nur linux-3.14.22.orig/arch/arm/mach-highbank/highbank.c linux-3.14.22/arch/arm/mach-highbank/highbank.c ---- linux-3.14.22.orig/arch/arm/mach-highbank/highbank.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-highbank/highbank.c 2014-10-22 14:55:49.902220001 -0500 -@@ -20,7 +20,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -51,11 +51,13 @@ - } - - --static void highbank_l2x0_disable(void) -+static void highbank_l2c310_write_sec(unsigned long val, unsigned reg) - { -- outer_flush_all(); -- /* Disable PL310 L2 Cache controller */ -- highbank_smc1(0x102, 0x0); -+ if (reg == L2X0_CTRL) -+ highbank_smc1(0x102, val); -+ else -+ WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n", -+ reg); - } - - static void __init highbank_init_irq(void) -@@ -66,11 +68,9 @@ - highbank_scu_map_io(); - - /* Enable PL310 L2 Cache controller */ -- if (IS_ENABLED(CONFIG_CACHE_L2X0) && -- of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) { -- highbank_smc1(0x102, 0x1); -- l2x0_of_init(0, ~0UL); -- outer_cache.disable = highbank_l2x0_disable; -+ if (IS_ENABLED(CONFIG_CACHE_L2X0)) { -+ outer_cache.write_sec = highbank_l2c310_write_sec; -+ l2x0_of_init(0, ~0); - } - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/anatop.c linux-3.14.22/arch/arm/mach-imx/anatop.c ---- linux-3.14.22.orig/arch/arm/mach-imx/anatop.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/anatop.c 2014-10-22 14:55:49.906220001 -0500 -@@ -9,6 +9,7 @@ - * http://www.gnu.org/copyleft/gpl.html - */ - -+#include - #include - #include - #include -@@ -35,6 +36,10 @@ - #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000 - #define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000 - -+#define ANADIG_REG_TARG_MASK 0x1f -+#define ANADIG_REG1_TARG_SHIFT 9 /* VDDPU */ -+#define ANADIG_REG2_TARG_SHIFT 18 /* VDDSOC */ -+ - static struct regmap *anatop; - - static void imx_anatop_enable_weak2p5(bool enable) -@@ -78,6 +83,28 @@ - BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B); - } - -+void imx_anatop_pu_enable(bool enable) -+{ -+ u32 val; -+ -+ regmap_read(anatop, ANADIG_REG_CORE, &val); -+ val &= ANADIG_REG_TARG_MASK << ANADIG_REG2_TARG_SHIFT; -+ /* -+ * set pu regulator only in LDO_BYPASS mode(know by VDDSOC reg 0x1f), -+ * else handled by anatop regulator driver. -+ */ -+ if (((val >> (ANADIG_REG2_TARG_SHIFT)) & ANADIG_REG_TARG_MASK) -+ == ANADIG_REG_TARG_MASK) { -+ if (enable) { -+ regmap_write(anatop, ANADIG_REG_CORE + REG_SET, -+ ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT); -+ udelay(70); /* bypass need 70us to be stable */ -+ } else { -+ regmap_write(anatop, ANADIG_REG_CORE + REG_CLR, -+ ANADIG_REG_TARG_MASK << ANADIG_REG1_TARG_SHIFT); -+ } -+ } -+} - void __init imx_init_revision_from_anatop(void) - { - struct device_node *np; -@@ -104,6 +131,15 @@ - case 2: - revision = IMX_CHIP_REVISION_1_2; - break; -+ case 3: -+ revision = IMX_CHIP_REVISION_1_3; -+ break; -+ case 4: -+ revision = IMX_CHIP_REVISION_1_4; -+ break; -+ case 5: -+ revision = IMX_CHIP_REVISION_1_5; -+ break; - default: - revision = IMX_CHIP_REVISION_UNKNOWN; - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/busfreq_ddr3.c linux-3.14.22/arch/arm/mach-imx/busfreq_ddr3.c ---- linux-3.14.22.orig/arch/arm/mach-imx/busfreq_ddr3.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/busfreq_ddr3.c 2014-10-22 14:55:49.906220001 -0500 -@@ -0,0 +1,471 @@ -+/* -+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file busfreq_ddr3.c -+ * -+ * @brief iMX6 DDR3 frequency change specific file. -+ * -+ * @ingroup PM -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "hardware.h" -+ -+/* DDR settings */ -+static unsigned long (*iram_ddr_settings)[2]; -+static unsigned long (*normal_mmdc_settings)[2]; -+static unsigned long (*iram_iomux_settings)[2]; -+static void __iomem *mmdc_base; -+static void __iomem *iomux_base; -+static void __iomem *ccm_base; -+static void __iomem *l2_base; -+static void __iomem *gic_dist_base; -+static u32 *irqs_used; -+ -+static void *ddr_freq_change_iram_base; -+static int ddr_settings_size; -+static int iomux_settings_size; -+static volatile unsigned int cpus_in_wfe; -+static volatile bool wait_for_ddr_freq_update; -+static int curr_ddr_rate; -+ -+void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings, -+ bool dll_mode, void *iomux_offsets) = NULL; -+ -+extern unsigned int ddr_med_rate; -+extern unsigned int ddr_normal_rate; -+extern int low_bus_freq_mode; -+extern int audio_bus_freq_mode; -+extern void mx6_ddr3_freq_change(u32 freq, void *ddr_settings, -+ bool dll_mode, void *iomux_offsets); -+ -+#define MIN_DLL_ON_FREQ 333000000 -+#define MAX_DLL_OFF_FREQ 125000000 -+#define DDR_FREQ_CHANGE_SIZE 0x2000 -+ -+unsigned long ddr3_dll_mx6q[][2] = { -+ {0x0c, 0x0}, -+ {0x10, 0x0}, -+ {0x1C, 0x04088032}, -+ {0x1C, 0x0408803a}, -+ {0x1C, 0x08408030}, -+ {0x1C, 0x08408038}, -+ {0x818, 0x0}, -+}; -+ -+unsigned long ddr3_calibration[][2] = { -+ {0x83c, 0x0}, -+ {0x840, 0x0}, -+ {0x483c, 0x0}, -+ {0x4840, 0x0}, -+ {0x848, 0x0}, -+ {0x4848, 0x0}, -+ {0x850, 0x0}, -+ {0x4850, 0x0}, -+}; -+ -+unsigned long ddr3_dll_mx6dl[][2] = { -+ {0x0c, 0x0}, -+ {0x10, 0x0}, -+ {0x1C, 0x04008032}, -+ {0x1C, 0x0400803a}, -+ {0x1C, 0x07208030}, -+ {0x1C, 0x07208038}, -+ {0x818, 0x0}, -+}; -+ -+unsigned long iomux_offsets_mx6q[][2] = { -+ {0x5A8, 0x0}, -+ {0x5B0, 0x0}, -+ {0x524, 0x0}, -+ {0x51C, 0x0}, -+ {0x518, 0x0}, -+ {0x50C, 0x0}, -+ {0x5B8, 0x0}, -+ {0x5C0, 0x0}, -+}; -+ -+unsigned long iomux_offsets_mx6dl[][2] = { -+ {0x4BC, 0x0}, -+ {0x4C0, 0x0}, -+ {0x4C4, 0x0}, -+ {0x4C8, 0x0}, -+ {0x4CC, 0x0}, -+ {0x4D0, 0x0}, -+ {0x4D4, 0x0}, -+ {0x4D8, 0x0}, -+}; -+ -+unsigned long ddr3_400[][2] = { -+ {0x83c, 0x42490249}, -+ {0x840, 0x02470247}, -+ {0x483c, 0x42570257}, -+ {0x4840, 0x02400240}, -+ {0x848, 0x4039363C}, -+ {0x4848, 0x3A39333F}, -+ {0x850, 0x38414441}, -+ {0x4850, 0x472D4833} -+}; -+ -+int can_change_ddr_freq(void) -+{ -+ return 1; -+} -+ -+/* -+ * each active core apart from the one changing -+ * the DDR frequency will execute this function. -+ * the rest of the cores have to remain in WFE -+ * state until the frequency is changed. -+ */ -+irqreturn_t wait_in_wfe_irq(int irq, void *dev_id) -+{ -+ u32 me = smp_processor_id(); -+ -+ *((char *)(&cpus_in_wfe) + (u8)me) = 0xff; -+ -+ while (wait_for_ddr_freq_update) -+ wfe(); -+ -+ *((char *)(&cpus_in_wfe) + (u8)me) = 0; -+ -+ return IRQ_HANDLED; -+} -+ -+/* change the DDR frequency. */ -+int update_ddr_freq(int ddr_rate) -+{ -+ int i, j; -+ unsigned int reg; -+ bool dll_off = false; -+ unsigned int online_cpus = 0; -+ int cpu = 0; -+ int me; -+ -+ if (!can_change_ddr_freq()) -+ return -1; -+ -+ if (ddr_rate == curr_ddr_rate) -+ return 0; -+ -+ pr_debug("Bus freq set to %d start...\n", ddr_rate); -+ -+ if (low_bus_freq_mode || audio_bus_freq_mode) -+ dll_off = true; -+ -+ iram_ddr_settings[0][0] = ddr_settings_size; -+ iram_iomux_settings[0][0] = iomux_settings_size; -+ if (ddr_rate == ddr_med_rate && cpu_is_imx6q()) { -+ for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) { -+ iram_ddr_settings[i + 1][0] = -+ normal_mmdc_settings[i][0]; -+ iram_ddr_settings[i + 1][1] = -+ normal_mmdc_settings[i][1]; -+ } -+ for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q); -+ i < iram_ddr_settings[0][0]; j++, i++) { -+ iram_ddr_settings[i + 1][0] = -+ ddr3_400[j][0]; -+ iram_ddr_settings[i + 1][1] = -+ ddr3_400[j][1]; -+ } -+ } else if (ddr_rate == ddr_normal_rate) { -+ for (i = 0; i < iram_ddr_settings[0][0]; i++) { -+ iram_ddr_settings[i + 1][0] = -+ normal_mmdc_settings[i][0]; -+ iram_ddr_settings[i + 1][1] = -+ normal_mmdc_settings[i][1]; -+ } -+ } -+ -+ /* ensure that all Cores are in WFE. */ -+ local_irq_disable(); -+ -+ me = smp_processor_id(); -+ -+ *((char *)(&cpus_in_wfe) + (u8)me) = 0xff; -+ wait_for_ddr_freq_update = true; -+ for_each_online_cpu(cpu) { -+ *((char *)(&online_cpus) + (u8)cpu) = 0xff; -+ if (cpu != me) { -+ /* set the interrupt to be pending in the GIC. */ -+ reg = 1 << (irqs_used[cpu] % 32); -+ writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET -+ + (irqs_used[cpu] / 32) * 4); -+ } -+ } -+ while (cpus_in_wfe != online_cpus) -+ udelay(5); -+ -+ /* -+ * Flush the TLB, to ensure no TLB maintenance occurs -+ * when DDR is in self-refresh. -+ */ -+ local_flush_tlb_all(); -+ /* Now we can change the DDR frequency. */ -+ mx6_change_ddr_freq(ddr_rate, iram_ddr_settings, -+ dll_off, iram_iomux_settings); -+ -+ curr_ddr_rate = ddr_rate; -+ -+ /* DDR frequency change is done . */ -+ wait_for_ddr_freq_update = false; -+ -+ /* wake up all the cores. */ -+ sev(); -+ -+ *((char *)(&cpus_in_wfe) + (u8)me) = 0; -+ -+ local_irq_enable(); -+ -+ pr_debug("Bus freq set to %d done!\n", ddr_rate); -+ -+ return 0; -+} -+ -+int init_mmdc_ddr3_settings(struct platform_device *busfreq_pdev) -+{ -+ struct device *dev = &busfreq_pdev->dev; -+ struct platform_device *ocram_dev; -+ unsigned int iram_paddr; -+ int i, err; -+ u32 cpu; -+ struct device_node *node; -+ struct gen_pool *iram_pool; -+ -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine"); -+ if (!node) { -+ pr_err("failed to find imx6q-mmdc device tree data!\n"); -+ return -EINVAL; -+ } -+ mmdc_base = of_iomap(node, 0); -+ WARN(!mmdc_base, "unable to map mmdc registers\n"); -+ -+ node = NULL; -+ if (cpu_is_imx6q()) -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc"); -+ if (cpu_is_imx6dl()) -+ node = of_find_compatible_node(NULL, NULL, -+ "fsl,imx6dl-iomuxc"); -+ if (!node) { -+ pr_err("failed to find imx6q-iomux device tree data!\n"); -+ return -EINVAL; -+ } -+ iomux_base = of_iomap(node, 0); -+ WARN(!iomux_base, "unable to map iomux registers\n"); -+ -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm"); -+ if (!node) { -+ pr_err("failed to find imx6q-ccm device tree data!\n"); -+ return -EINVAL; -+ } -+ ccm_base = of_iomap(node, 0); -+ WARN(!ccm_base, "unable to map mmdc registers\n"); -+ -+ node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); -+ if (!node) { -+ pr_err("failed to find imx6q-pl310-cache device tree data!\n"); -+ return -EINVAL; -+ } -+ l2_base = of_iomap(node, 0); -+ WARN(!ccm_base, "unable to map mmdc registers\n"); -+ -+ node = NULL; -+ node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic"); -+ if (!node) { -+ pr_err("failed to find imx6q-a9-gic device tree data!\n"); -+ return -EINVAL; -+ } -+ gic_dist_base = of_iomap(node, 0); -+ WARN(!gic_dist_base, "unable to map gic dist registers\n"); -+ -+ if (cpu_is_imx6q()) -+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) + -+ ARRAY_SIZE(ddr3_calibration); -+ if (cpu_is_imx6dl()) -+ ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) + -+ ARRAY_SIZE(ddr3_calibration); -+ -+ normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL); -+ if (cpu_is_imx6q()) { -+ memcpy(normal_mmdc_settings, ddr3_dll_mx6q, -+ sizeof(ddr3_dll_mx6q)); -+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)), -+ ddr3_calibration, sizeof(ddr3_calibration)); -+ } -+ if (cpu_is_imx6dl()) { -+ memcpy(normal_mmdc_settings, ddr3_dll_mx6dl, -+ sizeof(ddr3_dll_mx6dl)); -+ memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)), -+ ddr3_calibration, sizeof(ddr3_calibration)); -+ } -+ /* store the original DDR settings at boot. */ -+ for (i = 0; i < ddr_settings_size; i++) { -+ /* -+ * writes via command mode register cannot be read back. -+ * hence hardcode them in the initial static array. -+ * this may require modification on a per customer basis. -+ */ -+ if (normal_mmdc_settings[i][0] != 0x1C) -+ normal_mmdc_settings[i][1] = -+ readl_relaxed(mmdc_base -+ + normal_mmdc_settings[i][0]); -+ } -+ -+ irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(), -+ GFP_KERNEL); -+ -+ for_each_online_cpu(cpu) { -+ int irq; -+ -+ /* -+ * set up a reserved interrupt to get all -+ * the active cores into a WFE state -+ * before changing the DDR frequency. -+ */ -+ irq = platform_get_irq(busfreq_pdev, cpu); -+ err = request_irq(irq, wait_in_wfe_irq, -+ IRQF_PERCPU, "mmdc_1", NULL); -+ if (err) { -+ dev_err(dev, -+ "Busfreq:request_irq failed %d, err = %d\n", -+ irq, err); -+ return err; -+ } -+ err = irq_set_affinity(irq, cpumask_of(cpu)); -+ if (err) { -+ dev_err(dev, -+ "Busfreq: Cannot set irq affinity irq=%d,\n", -+ irq); -+ return err; -+ } -+ irqs_used[cpu] = irq; -+ } -+ -+ node = NULL; -+ node = of_find_compatible_node(NULL, NULL, "mmio-sram"); -+ if (!node) { -+ dev_err(dev, "%s: failed to find ocram node\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ ocram_dev = of_find_device_by_node(node); -+ if (!ocram_dev) { -+ dev_err(dev, "failed to find ocram device!\n"); -+ return -EINVAL; -+ } -+ -+ iram_pool = dev_get_gen_pool(&ocram_dev->dev); -+ if (!iram_pool) { -+ dev_err(dev, "iram pool unavailable!\n"); -+ return -EINVAL; -+ } -+ -+ iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q); -+ iram_iomux_settings = gen_pool_alloc(iram_pool, -+ (iomux_settings_size * 8) + 8); -+ if (!iram_iomux_settings) { -+ dev_err(dev, "unable to alloc iram for IOMUX settings!\n"); -+ return -ENOMEM; -+ } -+ -+ /* -+ * Allocate extra space to store the number of entries in the -+ * ddr_settings plus 4 extra regsiter information that needs -+ * to be passed to the frequency change code. -+ * sizeof(iram_ddr_settings) = sizeof(ddr_settings) + -+ * entries in ddr_settings + 16. -+ * The last 4 enties store the addresses of the registers: -+ * CCM_BASE_ADDR -+ * MMDC_BASE_ADDR -+ * IOMUX_BASE_ADDR -+ * L2X0_BASE_ADDR -+ */ -+ iram_ddr_settings = gen_pool_alloc(iram_pool, -+ (ddr_settings_size * 8) + 8 + 32); -+ if (!iram_ddr_settings) { -+ dev_err(dev, "unable to alloc iram for ddr settings!\n"); -+ return -ENOMEM; -+ } -+ i = ddr_settings_size + 1; -+ iram_ddr_settings[i][0] = (unsigned long)mmdc_base; -+ iram_ddr_settings[i+1][0] = (unsigned long)ccm_base; -+ iram_ddr_settings[i+2][0] = (unsigned long)iomux_base; -+ iram_ddr_settings[i+3][0] = (unsigned long)l2_base; -+ -+ if (cpu_is_imx6q()) { -+ /* store the IOMUX settings at boot. */ -+ for (i = 0; i < iomux_settings_size; i++) { -+ iomux_offsets_mx6q[i][1] = -+ readl_relaxed(iomux_base + -+ iomux_offsets_mx6q[i][0]); -+ iram_iomux_settings[i+1][0] = iomux_offsets_mx6q[i][0]; -+ iram_iomux_settings[i+1][1] = iomux_offsets_mx6q[i][1]; -+ } -+ } -+ -+ if (cpu_is_imx6dl()) { -+ for (i = 0; i < iomux_settings_size; i++) { -+ iomux_offsets_mx6dl[i][1] = -+ readl_relaxed(iomux_base + -+ iomux_offsets_mx6dl[i][0]); -+ iram_iomux_settings[i+1][0] = iomux_offsets_mx6dl[i][0]; -+ iram_iomux_settings[i+1][1] = iomux_offsets_mx6dl[i][1]; -+ } -+ } -+ -+ ddr_freq_change_iram_base = gen_pool_alloc(iram_pool, -+ DDR_FREQ_CHANGE_SIZE); -+ if (!ddr_freq_change_iram_base) { -+ dev_err(dev, "Cannot alloc iram for ddr freq change code!\n"); -+ return -ENOMEM; -+ } -+ -+ iram_paddr = gen_pool_virt_to_phys(iram_pool, -+ (unsigned long)ddr_freq_change_iram_base); -+ /* -+ * Need to remap the area here since we want -+ * the memory region to be executable. -+ */ -+ ddr_freq_change_iram_base = __arm_ioremap(iram_paddr, -+ DDR_FREQ_CHANGE_SIZE, -+ MT_MEMORY_RWX_NONCACHED); -+ mx6_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base, -+ &mx6_ddr3_freq_change, DDR_FREQ_CHANGE_SIZE); -+ -+ curr_ddr_rate = ddr_normal_rate; -+ -+ return 0; -+} -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/busfreq-imx6.c linux-3.14.22/arch/arm/mach-imx/busfreq-imx6.c ---- linux-3.14.22.orig/arch/arm/mach-imx/busfreq-imx6.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/busfreq-imx6.c 2014-10-22 14:55:49.906220001 -0500 -@@ -0,0 +1,952 @@ -+/* -+ * 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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+/*! -+ * @file busfreq-imx6.c -+ * -+ * @brief A common API for the Freescale Semiconductor iMX6 Busfreq API -+ * -+ * The APIs are for setting bus frequency to different values based on the -+ * highest freqeuncy requested. -+ * -+ * @ingroup PM -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "hardware.h" -+ -+#define LPAPM_CLK 24000000 -+#define DDR3_AUDIO_CLK 50000000 -+#define LPDDR2_AUDIO_CLK 100000000 -+ -+int high_bus_freq_mode; -+int med_bus_freq_mode; -+int audio_bus_freq_mode; -+int low_bus_freq_mode; -+int ultra_low_bus_freq_mode; -+unsigned int ddr_med_rate; -+unsigned int ddr_normal_rate; -+ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+static int bus_freq_scaling_initialized; -+static struct device *busfreq_dev; -+static int busfreq_suspended; -+static u32 org_arm_rate; -+static int bus_freq_scaling_is_active; -+static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count; -+static unsigned int ddr_low_rate; -+ -+extern int init_mmdc_lpddr2_settings(struct platform_device *dev); -+extern int init_mmdc_ddr3_settings(struct platform_device *dev); -+extern int update_ddr_freq(int ddr_rate); -+extern int update_lpddr2_freq(int ddr_rate); -+ -+DEFINE_MUTEX(bus_freq_mutex); -+static DEFINE_SPINLOCK(freq_lock); -+ -+static struct clk *pll2_400; -+static struct clk *periph_clk; -+static struct clk *periph_pre_clk; -+static struct clk *periph_clk2_sel; -+static struct clk *periph_clk2; -+static struct clk *osc_clk; -+static struct clk *cpu_clk; -+static struct clk *pll3; -+static struct clk *pll2; -+static struct clk *pll2_200; -+static struct clk *pll1_sys; -+static struct clk *periph2_clk; -+static struct clk *ocram_clk; -+static struct clk *ahb_clk; -+static struct clk *pll1_sw_clk; -+static struct clk *periph2_pre_clk; -+static struct clk *periph2_clk2_sel; -+static struct clk *periph2_clk2; -+static struct clk *step_clk; -+static struct clk *axi_sel_clk; -+static struct clk *pll3_pfd1_540m; -+ -+static u32 pll2_org_rate; -+static struct delayed_work low_bus_freq_handler; -+static struct delayed_work bus_freq_daemon; -+ -+static void enter_lpm_imx6sl(void) -+{ -+ unsigned long flags; -+ -+ if (high_bus_freq_mode) { -+ pll2_org_rate = clk_get_rate(pll2); -+ /* Set periph_clk to be sourced from OSC_CLK */ -+ clk_set_parent(periph_clk2_sel, osc_clk); -+ clk_set_parent(periph_clk, periph_clk2); -+ /* Ensure AHB/AXI clks are at 24MHz. */ -+ clk_set_rate(ahb_clk, LPAPM_CLK); -+ clk_set_rate(ocram_clk, LPAPM_CLK); -+ } -+ if (audio_bus_count) { -+ /* Set AHB to 8MHz to lower pwer.*/ -+ clk_set_rate(ahb_clk, LPAPM_CLK / 3); -+ -+ /* Set up DDR to 100MHz. */ -+ spin_lock_irqsave(&freq_lock, flags); -+ update_lpddr2_freq(LPDDR2_AUDIO_CLK); -+ spin_unlock_irqrestore(&freq_lock, flags); -+ -+ /* Fix the clock tree in kernel */ -+ clk_set_rate(pll2, pll2_org_rate); -+ clk_set_parent(periph2_pre_clk, pll2_200); -+ clk_set_parent(periph2_clk, periph2_pre_clk); -+ -+ if (low_bus_freq_mode || ultra_low_bus_freq_mode) { -+ /* -+ * Swtich ARM to run off PLL2_PFD2_400MHz -+ * since DDR is anyway at 100MHz. -+ */ -+ clk_set_parent(step_clk, pll2_400); -+ clk_set_parent(pll1_sw_clk, step_clk); -+ /* -+ * Ensure that the clock will be -+ * at original speed. -+ */ -+ clk_set_rate(cpu_clk, org_arm_rate); -+ } -+ low_bus_freq_mode = 0; -+ ultra_low_bus_freq_mode = 0; -+ audio_bus_freq_mode = 1; -+ } else { -+ u32 arm_div, pll1_rate; -+ org_arm_rate = clk_get_rate(cpu_clk); -+ if (low_bus_freq_mode && low_bus_count == 0) { -+ /* -+ * We are already in DDR @ 24MHz state, but -+ * no one but ARM needs the DDR. In this case, -+ * we can lower the DDR freq to 1MHz when ARM -+ * enters WFI in this state. Keep track of this state. -+ */ -+ ultra_low_bus_freq_mode = 1; -+ low_bus_freq_mode = 0; -+ audio_bus_freq_mode = 0; -+ } else { -+ if (!ultra_low_bus_freq_mode && !low_bus_freq_mode) { -+ /* -+ * Set DDR to 24MHz. -+ * Since we are going to bypass PLL2, -+ * we need to move ARM clk off PLL2_PFD2 -+ * to PLL1. Make sure the PLL1 is running -+ * at the lowest possible freq. -+ */ -+ clk_set_rate(pll1_sys, -+ clk_round_rate(pll1_sys, org_arm_rate)); -+ pll1_rate = clk_get_rate(pll1_sys); -+ arm_div = pll1_rate / org_arm_rate + 1; -+ /* -+ * Ensure ARM CLK is lower before -+ * changing the parent. -+ */ -+ clk_set_rate(cpu_clk, org_arm_rate / arm_div); -+ /* Now set the ARM clk parent to PLL1_SYS. */ -+ clk_set_parent(pll1_sw_clk, pll1_sys); -+ -+ /* -+ * Set STEP_CLK back to OSC to save power and -+ * also to maintain the parent.The WFI iram code -+ * will switch step_clk to osc, but the clock API -+ * is not aware of the change and when a new request -+ * to change the step_clk parent to pll2_pfd2_400M -+ * is requested sometime later, the change is ignored. -+ */ -+ clk_set_parent(step_clk, osc_clk); -+ /* Now set DDR to 24MHz. */ -+ spin_lock_irqsave(&freq_lock, flags); -+ update_lpddr2_freq(LPAPM_CLK); -+ spin_unlock_irqrestore(&freq_lock, flags); -+ -+ /* -+ * Fix the clock tree in kernel. -+ * Make sure PLL2 rate is updated as it gets -+ * bypassed in the DDR freq change code. -+ */ -+ clk_set_rate(pll2, LPAPM_CLK); -+ clk_set_parent(periph2_clk2_sel, pll2); -+ clk_set_parent(periph2_clk, periph2_clk2_sel); -+ -+ } -+ if (low_bus_count == 0) { -+ ultra_low_bus_freq_mode = 1; -+ low_bus_freq_mode = 0; -+ } else { -+ ultra_low_bus_freq_mode = 0; -+ low_bus_freq_mode = 1; -+ } -+ audio_bus_freq_mode = 0; -+ } -+ } -+} -+ -+static void exit_lpm_imx6sl(void) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&freq_lock, flags); -+ /* Change DDR freq in IRAM. */ -+ update_lpddr2_freq(ddr_normal_rate); -+ spin_unlock_irqrestore(&freq_lock, flags); -+ -+ /* -+ * Fix the clock tree in kernel. -+ * Make sure PLL2 rate is updated as it gets -+ * un-bypassed in the DDR freq change code. -+ */ -+ clk_set_rate(pll2, pll2_org_rate); -+ clk_set_parent(periph2_pre_clk, pll2_400); -+ clk_set_parent(periph2_clk, periph2_pre_clk); -+ -+ /* Ensure that periph_clk is sourced from PLL2_400. */ -+ clk_set_parent(periph_pre_clk, pll2_400); -+ /* -+ * Before switching the perhiph_clk, ensure that the -+ * AHB/AXI will not be too fast. -+ */ -+ clk_set_rate(ahb_clk, LPAPM_CLK / 3); -+ clk_set_rate(ocram_clk, LPAPM_CLK / 2); -+ clk_set_parent(periph_clk, periph_pre_clk); -+ -+ if (low_bus_freq_mode || ultra_low_bus_freq_mode) { -+ /* Move ARM from PLL1_SW_CLK to PLL2_400. */ -+ clk_set_parent(step_clk, pll2_400); -+ clk_set_parent(pll1_sw_clk, step_clk); -+ clk_set_rate(cpu_clk, org_arm_rate); -+ ultra_low_bus_freq_mode = 0; -+ } -+} -+ -+int reduce_bus_freq(void) -+{ -+ int ret = 0; -+ clk_prepare_enable(pll3); -+ if (cpu_is_imx6sl()) -+ enter_lpm_imx6sl(); -+ else { -+ if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk) -+ != periph_clk)) -+ /* Set axi to periph_clk */ -+ clk_set_parent(axi_sel_clk, periph_clk); -+ -+ if (audio_bus_count) { -+ /* Need to ensure that PLL2_PFD_400M is kept ON. */ -+ clk_prepare_enable(pll2_400); -+ update_ddr_freq(DDR3_AUDIO_CLK); -+ /* Make sure periph clk's parent also got updated */ -+ ret = clk_set_parent(periph_clk2_sel, pll3); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_pre_clk, pll2_200); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_clk, periph_pre_clk); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ audio_bus_freq_mode = 1; -+ low_bus_freq_mode = 0; -+ } else { -+ update_ddr_freq(LPAPM_CLK); -+ /* Make sure periph clk's parent also got updated */ -+ ret = clk_set_parent(periph_clk2_sel, osc_clk); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ /* Set periph_clk parent to OSC via periph_clk2_sel */ -+ ret = clk_set_parent(periph_clk, periph_clk2); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ if (audio_bus_freq_mode) -+ clk_disable_unprepare(pll2_400); -+ low_bus_freq_mode = 1; -+ audio_bus_freq_mode = 0; -+ } -+ } -+ clk_disable_unprepare(pll3); -+ -+ med_bus_freq_mode = 0; -+ high_bus_freq_mode = 0; -+ -+ if (audio_bus_freq_mode) -+ dev_dbg(busfreq_dev, "Bus freq set to audio mode. Count:\ -+ high %d, med %d, audio %d\n", -+ high_bus_count, med_bus_count, audio_bus_count); -+ if (low_bus_freq_mode) -+ dev_dbg(busfreq_dev, "Bus freq set to low mode. Count:\ -+ high %d, med %d, audio %d\n", -+ high_bus_count, med_bus_count, audio_bus_count); -+ -+ return ret; -+} -+ -+static void reduce_bus_freq_handler(struct work_struct *work) -+{ -+ mutex_lock(&bus_freq_mutex); -+ -+ reduce_bus_freq(); -+ -+ mutex_unlock(&bus_freq_mutex); -+} -+ -+/* -+ * Set the DDR, AHB to 24MHz. -+ * This mode will be activated only when none of the modules that -+ * need a higher DDR or AHB frequency are active. -+ */ -+int set_low_bus_freq(void) -+{ -+ if (busfreq_suspended) -+ return 0; -+ -+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) -+ return 0; -+ -+ /* -+ * Check to see if we need to got from -+ * low bus freq mode to audio bus freq mode. -+ * If so, the change needs to be done immediately. -+ */ -+ if (audio_bus_count && (low_bus_freq_mode || ultra_low_bus_freq_mode)) -+ reduce_bus_freq(); -+ else -+ /* -+ * Don't lower the frequency immediately. Instead -+ * scheduled a delayed work and drop the freq if -+ * the conditions still remain the same. -+ */ -+ schedule_delayed_work(&low_bus_freq_handler, -+ usecs_to_jiffies(3000000)); -+ return 0; -+} -+ -+/* -+ * Set the DDR to either 528MHz or 400MHz for iMX6qd -+ * or 400MHz for iMX6dl. -+ */ -+int set_high_bus_freq(int high_bus_freq) -+{ -+ int ret = 0; -+ struct clk *periph_clk_parent; -+ -+ if (bus_freq_scaling_initialized && bus_freq_scaling_is_active) -+ cancel_delayed_work_sync(&low_bus_freq_handler); -+ -+ if (busfreq_suspended) -+ return 0; -+ -+ if (cpu_is_imx6q()) -+ periph_clk_parent = pll2; -+ else -+ periph_clk_parent = pll2_400; -+ -+ if (!bus_freq_scaling_initialized || !bus_freq_scaling_is_active) -+ return 0; -+ -+ if (high_bus_freq_mode) -+ return 0; -+ -+ /* medium bus freq is only supported for MX6DQ */ -+ if (med_bus_freq_mode && !high_bus_freq) -+ return 0; -+ -+ clk_prepare_enable(pll3); -+ if (cpu_is_imx6sl()) -+ exit_lpm_imx6sl(); -+ else { -+ if (high_bus_freq) { -+ update_ddr_freq(ddr_normal_rate); -+ /* Make sure periph clk's parent also got updated */ -+ ret = clk_set_parent(periph_clk2_sel, pll3); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_pre_clk, periph_clk_parent); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_clk, periph_pre_clk); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ if (cpu_is_imx6dl() && (clk_get_parent(axi_sel_clk) -+ != pll3_pfd1_540m)) -+ /* Set axi to pll3_pfd1_540m */ -+ clk_set_parent(axi_sel_clk, pll3_pfd1_540m); -+ } else { -+ update_ddr_freq(ddr_med_rate); -+ /* Make sure periph clk's parent also got updated */ -+ ret = clk_set_parent(periph_clk2_sel, pll3); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_pre_clk, pll2_400); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ ret = clk_set_parent(periph_clk, periph_pre_clk); -+ if (ret) -+ dev_WARN(busfreq_dev, -+ "%s: %d: clk set parent fail!\n", -+ __func__, __LINE__); -+ } -+ if (audio_bus_freq_mode) -+ clk_disable_unprepare(pll2_400); -+ } -+ -+ high_bus_freq_mode = 1; -+ med_bus_freq_mode = 0; -+ low_bus_freq_mode = 0; -+ audio_bus_freq_mode = 0; -+ -+ clk_disable_unprepare(pll3); -+ -+ if (high_bus_freq_mode) -+ dev_dbg(busfreq_dev, "Bus freq set to high mode. Count:\ -+ high %d, med %d, audio %d\n", -+ high_bus_count, med_bus_count, audio_bus_count); -+ if (med_bus_freq_mode) -+ dev_dbg(busfreq_dev, "Bus freq set to med mode. Count:\ -+ high %d, med %d, audio %d\n", -+ high_bus_count, med_bus_count, audio_bus_count); -+ -+ return 0; -+} -+#endif -+ -+void request_bus_freq(enum bus_freq_mode mode) -+{ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ mutex_lock(&bus_freq_mutex); -+ -+ if (mode == BUS_FREQ_HIGH) -+ high_bus_count++; -+ else if (mode == BUS_FREQ_MED) -+ med_bus_count++; -+ else if (mode == BUS_FREQ_AUDIO) -+ audio_bus_count++; -+ else if (mode == BUS_FREQ_LOW) -+ low_bus_count++; -+ -+ if (busfreq_suspended || !bus_freq_scaling_initialized || -+ !bus_freq_scaling_is_active) { -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ cancel_delayed_work_sync(&low_bus_freq_handler); -+ -+ if (cpu_is_imx6dl()) { -+ /* No support for medium setpoint on MX6DL. */ -+ if (mode == BUS_FREQ_MED) { -+ high_bus_count++; -+ mode = BUS_FREQ_HIGH; -+ } -+ } -+ -+ if ((mode == BUS_FREQ_HIGH) && (!high_bus_freq_mode)) { -+ set_high_bus_freq(1); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ -+ if ((mode == BUS_FREQ_MED) && (!high_bus_freq_mode) && -+ (!med_bus_freq_mode)) { -+ set_high_bus_freq(0); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ if ((mode == BUS_FREQ_AUDIO) && (!high_bus_freq_mode) && -+ (!med_bus_freq_mode) && (!audio_bus_freq_mode)) { -+ set_low_bus_freq(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ mutex_unlock(&bus_freq_mutex); -+#endif -+ return; -+} -+EXPORT_SYMBOL(request_bus_freq); -+ -+void release_bus_freq(enum bus_freq_mode mode) -+{ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ mutex_lock(&bus_freq_mutex); -+ -+ if (mode == BUS_FREQ_HIGH) { -+ if (high_bus_count == 0) { -+ dev_err(busfreq_dev, "high bus count mismatch!\n"); -+ dump_stack(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ high_bus_count--; -+ } else if (mode == BUS_FREQ_MED) { -+ if (med_bus_count == 0) { -+ dev_err(busfreq_dev, "med bus count mismatch!\n"); -+ dump_stack(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ med_bus_count--; -+ } else if (mode == BUS_FREQ_AUDIO) { -+ if (audio_bus_count == 0) { -+ dev_err(busfreq_dev, "audio bus count mismatch!\n"); -+ dump_stack(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ audio_bus_count--; -+ } else if (mode == BUS_FREQ_LOW) { -+ if (low_bus_count == 0) { -+ dev_err(busfreq_dev, "low bus count mismatch!\n"); -+ dump_stack(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ low_bus_count--; -+ } -+ -+ if (busfreq_suspended || !bus_freq_scaling_initialized || -+ !bus_freq_scaling_is_active) { -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ -+ if (cpu_is_imx6dl()) { -+ /* No support for medium setpoint on MX6DL. */ -+ if (mode == BUS_FREQ_MED) { -+ high_bus_count--; -+ mode = BUS_FREQ_HIGH; -+ } -+ } -+ -+ if ((!audio_bus_freq_mode) && (high_bus_count == 0) && -+ (med_bus_count == 0) && (audio_bus_count != 0)) { -+ set_low_bus_freq(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ if ((!low_bus_freq_mode) && (high_bus_count == 0) && -+ (med_bus_count == 0) && (audio_bus_count == 0) && -+ (low_bus_count != 0)) { -+ set_low_bus_freq(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ if ((!ultra_low_bus_freq_mode) && (high_bus_count == 0) && -+ (med_bus_count == 0) && (audio_bus_count == 0) && -+ (low_bus_count == 0)) { -+ set_low_bus_freq(); -+ mutex_unlock(&bus_freq_mutex); -+ return; -+ } -+ -+ mutex_unlock(&bus_freq_mutex); -+#endif -+ return; -+} -+EXPORT_SYMBOL(release_bus_freq); -+ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+static void bus_freq_daemon_handler(struct work_struct *work) -+{ -+ mutex_lock(&bus_freq_mutex); -+ if ((!low_bus_freq_mode) && (high_bus_count == 0) && -+ (med_bus_count == 0) && (audio_bus_count == 0)) -+ set_low_bus_freq(); -+ mutex_unlock(&bus_freq_mutex); -+} -+ -+static ssize_t bus_freq_scaling_enable_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ if (bus_freq_scaling_is_active) -+ return sprintf(buf, "Bus frequency scaling is enabled\n"); -+ else -+ return sprintf(buf, "Bus frequency scaling is disabled\n"); -+} -+ -+static ssize_t bus_freq_scaling_enable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t size) -+{ -+ if (strncmp(buf, "1", 1) == 0) { -+ bus_freq_scaling_is_active = 1; -+ set_high_bus_freq(1); -+ /* -+ * We set bus freq to highest at the beginning, -+ * so we use this daemon thread to make sure system -+ * can enter low bus mode if -+ * there is no high bus request pending -+ */ -+ schedule_delayed_work(&bus_freq_daemon, -+ usecs_to_jiffies(5000000)); -+ } else if (strncmp(buf, "0", 1) == 0) { -+ if (bus_freq_scaling_is_active) -+ set_high_bus_freq(1); -+ bus_freq_scaling_is_active = 0; -+ } -+ return size; -+} -+ -+static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event, -+ void *dummy) -+{ -+ mutex_lock(&bus_freq_mutex); -+ -+ if (event == PM_SUSPEND_PREPARE) { -+ high_bus_count++; -+ set_high_bus_freq(1); -+ busfreq_suspended = 1; -+ } else if (event == PM_POST_SUSPEND) { -+ busfreq_suspended = 0; -+ high_bus_count--; -+ schedule_delayed_work(&bus_freq_daemon, -+ usecs_to_jiffies(5000000)); -+ } -+ -+ mutex_unlock(&bus_freq_mutex); -+ -+ return NOTIFY_OK; -+} -+ -+static int busfreq_reboot_notifier_event(struct notifier_block *this, -+ unsigned long event, void *ptr) -+{ -+ /* System is rebooting. Set the system into high_bus_freq_mode. */ -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ return 0; -+} -+ -+static struct notifier_block imx_bus_freq_pm_notifier = { -+ .notifier_call = bus_freq_pm_notify, -+}; -+ -+static struct notifier_block imx_busfreq_reboot_notifier = { -+ .notifier_call = busfreq_reboot_notifier_event, -+}; -+ -+ -+static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show, -+ bus_freq_scaling_enable_store); -+#endif -+ -+/*! -+ * This is the probe routine for the bus frequency driver. -+ * -+ * @param pdev The platform device structure -+ * -+ * @return The function returns 0 on success -+ * -+ */ -+ -+static int busfreq_probe(struct platform_device *pdev) -+{ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ u32 err; -+ -+ busfreq_dev = &pdev->dev; -+ -+ pll2_400 = devm_clk_get(&pdev->dev, "pll2_pfd2_396m"); -+ if (IS_ERR(pll2_400)) { -+ dev_err(busfreq_dev, "%s: failed to get pll2_pfd2_396m\n", -+ __func__); -+ return PTR_ERR(pll2_400); -+ } -+ -+ pll2_200 = devm_clk_get(&pdev->dev, "pll2_198m"); -+ if (IS_ERR(pll2_200)) { -+ dev_err(busfreq_dev, "%s: failed to get pll2_198m\n", -+ __func__); -+ return PTR_ERR(pll2_200); -+ } -+ -+ pll2 = devm_clk_get(&pdev->dev, "pll2_bus"); -+ if (IS_ERR(pll2)) { -+ dev_err(busfreq_dev, "%s: failed to get pll2_bus\n", -+ __func__); -+ return PTR_ERR(pll2); -+ } -+ -+ cpu_clk = devm_clk_get(&pdev->dev, "arm"); -+ if (IS_ERR(cpu_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get cpu_clk\n", -+ __func__); -+ return PTR_ERR(cpu_clk); -+ } -+ -+ pll3 = devm_clk_get(&pdev->dev, "pll3_usb_otg"); -+ if (IS_ERR(pll3)) { -+ dev_err(busfreq_dev, "%s: failed to get pll3_usb_otg\n", -+ __func__); -+ return PTR_ERR(pll3); -+ } -+ -+ periph_clk = devm_clk_get(&pdev->dev, "periph"); -+ if (IS_ERR(periph_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get periph\n", -+ __func__); -+ return PTR_ERR(periph_clk); -+ } -+ -+ periph_pre_clk = devm_clk_get(&pdev->dev, "periph_pre"); -+ if (IS_ERR(periph_pre_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get periph_pre\n", -+ __func__); -+ return PTR_ERR(periph_pre_clk); -+ } -+ -+ periph_clk2 = devm_clk_get(&pdev->dev, "periph_clk2"); -+ if (IS_ERR(periph_clk2)) { -+ dev_err(busfreq_dev, "%s: failed to get periph_clk2\n", -+ __func__); -+ return PTR_ERR(periph_clk2); -+ } -+ -+ periph_clk2_sel = devm_clk_get(&pdev->dev, "periph_clk2_sel"); -+ if (IS_ERR(periph_clk2_sel)) { -+ dev_err(busfreq_dev, "%s: failed to get periph_clk2_sel\n", -+ __func__); -+ return PTR_ERR(periph_clk2_sel); -+ } -+ -+ osc_clk = devm_clk_get(&pdev->dev, "osc"); -+ if (IS_ERR(osc_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get osc_clk\n", -+ __func__); -+ return PTR_ERR(osc_clk); -+ } -+ -+ if (cpu_is_imx6dl()) { -+ axi_sel_clk = devm_clk_get(&pdev->dev, "axi_sel"); -+ if (IS_ERR(axi_sel_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get axi_sel_clk\n", -+ __func__); -+ return PTR_ERR(axi_sel_clk); -+ } -+ -+ pll3_pfd1_540m = devm_clk_get(&pdev->dev, "pll3_pfd1_540m"); -+ if (IS_ERR(pll3_pfd1_540m)) { -+ dev_err(busfreq_dev, -+ "%s: failed to get pll3_pfd1_540m\n", __func__); -+ return PTR_ERR(pll3_pfd1_540m); -+ } -+ } -+ -+ if (cpu_is_imx6sl()) { -+ pll1_sys = devm_clk_get(&pdev->dev, "pll1_sys"); -+ if (IS_ERR(pll1_sys)) { -+ dev_err(busfreq_dev, "%s: failed to get pll1_sys\n", -+ __func__); -+ return PTR_ERR(pll1_sys); -+ } -+ -+ ahb_clk = devm_clk_get(&pdev->dev, "ahb"); -+ if (IS_ERR(ahb_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get ahb_clk\n", -+ __func__); -+ return PTR_ERR(ahb_clk); -+ } -+ -+ ocram_clk = devm_clk_get(&pdev->dev, "ocram"); -+ if (IS_ERR(ocram_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get ocram_clk\n", -+ __func__); -+ return PTR_ERR(ocram_clk); -+ } -+ -+ pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw"); -+ if (IS_ERR(pll1_sw_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get pll1_sw_clk\n", -+ __func__); -+ return PTR_ERR(pll1_sw_clk); -+ } -+ -+ periph2_clk = devm_clk_get(&pdev->dev, "periph2"); -+ if (IS_ERR(periph2_clk)) { -+ dev_err(busfreq_dev, "%s: failed to get periph2\n", -+ __func__); -+ return PTR_ERR(periph2_clk); -+ } -+ -+ periph2_pre_clk = devm_clk_get(&pdev->dev, "periph2_pre"); -+ if (IS_ERR(periph2_pre_clk)) { -+ dev_err(busfreq_dev, -+ "%s: failed to get periph2_pre_clk\n", -+ __func__); -+ return PTR_ERR(periph2_pre_clk); -+ } -+ -+ periph2_clk2 = devm_clk_get(&pdev->dev, "periph2_clk2"); -+ if (IS_ERR(periph2_clk2)) { -+ dev_err(busfreq_dev, -+ "%s: failed to get periph2_clk2\n", -+ __func__); -+ return PTR_ERR(periph2_clk2); -+ } -+ -+ periph2_clk2_sel = devm_clk_get(&pdev->dev, "periph2_clk2_sel"); -+ if (IS_ERR(periph2_clk2_sel)) { -+ dev_err(busfreq_dev, -+ "%s: failed to get periph2_clk2_sel\n", -+ __func__); -+ return PTR_ERR(periph2_clk2_sel); -+ } -+ -+ step_clk = devm_clk_get(&pdev->dev, "step"); -+ if (IS_ERR(step_clk)) { -+ dev_err(busfreq_dev, -+ "%s: failed to get step_clk\n", -+ __func__); -+ return PTR_ERR(periph2_clk2_sel); -+ } -+ -+ } -+ -+ err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr); -+ if (err) { -+ dev_err(busfreq_dev, -+ "Unable to register sysdev entry for BUSFREQ"); -+ return err; -+ } -+ -+ if (of_property_read_u32(pdev->dev.of_node, "fsl,max_ddr_freq", -+ &ddr_normal_rate)) { -+ dev_err(busfreq_dev, "max_ddr_freq entry missing\n"); -+ return -EINVAL; -+ } -+#endif -+ -+ high_bus_freq_mode = 1; -+ med_bus_freq_mode = 0; -+ low_bus_freq_mode = 0; -+ audio_bus_freq_mode = 0; -+ ultra_low_bus_freq_mode = 0; -+ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ bus_freq_scaling_is_active = 1; -+ bus_freq_scaling_initialized = 1; -+ -+ ddr_low_rate = LPAPM_CLK; -+ if (cpu_is_imx6q()) { -+ if (of_property_read_u32(pdev->dev.of_node, "fsl,med_ddr_freq", -+ &ddr_med_rate)) { -+ dev_info(busfreq_dev, -+ "DDR medium rate not supported.\n"); -+ ddr_med_rate = ddr_normal_rate; -+ } -+ } -+ -+ INIT_DELAYED_WORK(&low_bus_freq_handler, reduce_bus_freq_handler); -+ INIT_DELAYED_WORK(&bus_freq_daemon, bus_freq_daemon_handler); -+ register_pm_notifier(&imx_bus_freq_pm_notifier); -+ register_reboot_notifier(&imx_busfreq_reboot_notifier); -+ -+ if (cpu_is_imx6sl()) -+ err = init_mmdc_lpddr2_settings(pdev); -+ else -+ err = init_mmdc_ddr3_settings(pdev); -+ if (err) { -+ dev_err(busfreq_dev, "Busfreq init of MMDC failed\n"); -+ return err; -+ } -+#endif -+ return 0; -+} -+ -+static const struct of_device_id imx6_busfreq_ids[] = { -+ { .compatible = "fsl,imx6_busfreq", }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver busfreq_driver = { -+ .driver = { -+ .name = "imx6_busfreq", -+ .owner = THIS_MODULE, -+ .of_match_table = imx6_busfreq_ids, -+ }, -+ .probe = busfreq_probe, -+}; -+ -+/*! -+ * Initialise the busfreq_driver. -+ * -+ * @return The function always returns 0. -+ */ -+ -+static int __init busfreq_init(void) -+{ -+ if (platform_driver_register(&busfreq_driver) != 0) -+ return -ENODEV; -+ -+ printk(KERN_INFO "Bus freq driver module loaded\n"); -+ -+ return 0; -+} -+ -+static void __exit busfreq_cleanup(void) -+{ -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr); -+ -+ bus_freq_scaling_initialized = 0; -+#endif -+ /* Unregister the device structure */ -+ platform_driver_unregister(&busfreq_driver); -+} -+ -+module_init(busfreq_init); -+module_exit(busfreq_cleanup); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("BusFreq driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/busfreq_lpddr2.c linux-3.14.22/arch/arm/mach-imx/busfreq_lpddr2.c ---- linux-3.14.22.orig/arch/arm/mach-imx/busfreq_lpddr2.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/busfreq_lpddr2.c 2014-10-22 14:55:49.906220001 -0500 -@@ -0,0 +1,183 @@ -+/* -+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file busfreq_lpddr2.c -+ * -+ * @brief iMX6 LPDDR2 frequency change specific file. -+ * -+ * @ingroup PM -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "hardware.h" -+ -+/* DDR settings */ -+static void __iomem *mmdc_base; -+static void __iomem *anatop_base; -+static void __iomem *ccm_base; -+static void __iomem *l2_base; -+static struct device *busfreq_dev; -+static void *ddr_freq_change_iram_base; -+static int curr_ddr_rate; -+ -+unsigned long reg_addrs[4]; -+ -+void (*mx6_change_lpddr2_freq)(u32 ddr_freq, int bus_freq_mode, -+ void *iram_addr) = NULL; -+ -+extern unsigned int ddr_normal_rate; -+extern int low_bus_freq_mode; -+extern int ultra_low_bus_freq_mode; -+extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode, -+ void *iram_addr); -+ -+ -+#define LPDDR2_FREQ_CHANGE_SIZE 0x1000 -+ -+ -+/* change the DDR frequency. */ -+int update_lpddr2_freq(int ddr_rate) -+{ -+ if (ddr_rate == curr_ddr_rate) -+ return 0; -+ -+ dev_dbg(busfreq_dev, "\nBus freq set to %d start...\n", ddr_rate); -+ -+ /* -+ * Flush the TLB, to ensure no TLB maintenance occurs -+ * when DDR is in self-refresh. -+ */ -+ local_flush_tlb_all(); -+ /* Now change DDR frequency. */ -+ mx6_change_lpddr2_freq(ddr_rate, -+ (low_bus_freq_mode | ultra_low_bus_freq_mode), -+ reg_addrs); -+ -+ curr_ddr_rate = ddr_rate; -+ -+ dev_dbg(busfreq_dev, "\nBus freq set to %d done...\n", ddr_rate); -+ -+ return 0; -+} -+ -+int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev) -+{ -+ struct platform_device *ocram_dev; -+ unsigned int iram_paddr; -+ struct device_node *node; -+ struct gen_pool *iram_pool; -+ -+ busfreq_dev = &busfreq_pdev->dev; -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-mmdc"); -+ if (!node) { -+ printk(KERN_ERR "failed to find imx6sl-mmdc device tree data!\n"); -+ return -EINVAL; -+ } -+ mmdc_base = of_iomap(node, 0); -+ WARN(!mmdc_base, "unable to map mmdc registers\n"); -+ -+ node = NULL; -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-ccm"); -+ if (!node) { -+ printk(KERN_ERR "failed to find imx6sl-ccm device tree data!\n"); -+ return -EINVAL; -+ } -+ ccm_base = of_iomap(node, 0); -+ WARN(!ccm_base, "unable to map ccm registers\n"); -+ -+ node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache"); -+ if (!node) { -+ printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n"); -+ return -EINVAL; -+ } -+ l2_base = of_iomap(node, 0); -+ WARN(!l2_base, "unable to map PL310 registers\n"); -+ -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-anatop"); -+ if (!node) { -+ printk(KERN_ERR "failed to find imx6sl-pl310-cache device tree data!\n"); -+ return -EINVAL; -+ } -+ anatop_base = of_iomap(node, 0); -+ WARN(!anatop_base, "unable to map anatop registers\n"); -+ -+ node = NULL; -+ node = of_find_compatible_node(NULL, NULL, "mmio-sram"); -+ if (!node) { -+ dev_err(busfreq_dev, "%s: failed to find ocram node\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ ocram_dev = of_find_device_by_node(node); -+ if (!ocram_dev) { -+ dev_err(busfreq_dev, "failed to find ocram device!\n"); -+ return -EINVAL; -+ } -+ -+ iram_pool = dev_get_gen_pool(&ocram_dev->dev); -+ if (!iram_pool) { -+ dev_err(busfreq_dev, "iram pool unavailable!\n"); -+ return -EINVAL; -+ } -+ -+ reg_addrs[0] = (unsigned long)anatop_base; -+ reg_addrs[1] = (unsigned long)ccm_base; -+ reg_addrs[2] = (unsigned long)mmdc_base; -+ reg_addrs[3] = (unsigned long)l2_base; -+ -+ ddr_freq_change_iram_base = (void *)gen_pool_alloc(iram_pool, -+ LPDDR2_FREQ_CHANGE_SIZE); -+ if (!ddr_freq_change_iram_base) { -+ dev_err(busfreq_dev, -+ "Cannot alloc iram for ddr freq change code!\n"); -+ return -ENOMEM; -+ } -+ -+ iram_paddr = gen_pool_virt_to_phys(iram_pool, -+ (unsigned long)ddr_freq_change_iram_base); -+ /* -+ * Need to remap the area here since we want -+ * the memory region to be executable. -+ */ -+ ddr_freq_change_iram_base = __arm_ioremap(iram_paddr, -+ LPDDR2_FREQ_CHANGE_SIZE, -+ MT_MEMORY_RWX_NONCACHED); -+ mx6_change_lpddr2_freq = (void *)fncpy(ddr_freq_change_iram_base, -+ &mx6_lpddr2_freq_change, LPDDR2_FREQ_CHANGE_SIZE); -+ -+ curr_ddr_rate = ddr_normal_rate; -+ -+ return 0; -+} -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/clk.h linux-3.14.22/arch/arm/mach-imx/clk.h ---- linux-3.14.22.orig/arch/arm/mach-imx/clk.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/clk.h 2014-10-22 14:55:49.906220001 -0500 -@@ -23,7 +23,8 @@ - }; - - struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, -- const char *parent_name, void __iomem *base, u32 div_mask); -+ const char *parent_name, void __iomem *base, -+ u32 div_mask, bool always_on); - - struct clk *clk_register_gate2(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/clk-imx6q.c linux-3.14.22/arch/arm/mach-imx/clk-imx6q.c ---- linux-3.14.22.orig/arch/arm/mach-imx/clk-imx6q.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/clk-imx6q.c 2014-10-22 14:55:49.906220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2011-2013 Freescale Semiconductor, Inc. -+ * Copyright 2011-2014 Freescale Semiconductor, Inc. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public -@@ -24,6 +24,8 @@ - #include "common.h" - #include "hardware.h" - -+#define CCM_CCGR_OFFSET(index) (index * 2) -+ - static const char *step_sels[] = { "osc", "pll2_pfd2_396m", }; - static const char *pll1_sw_sels[] = { "pll1_sys", "step", }; - static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", }; -@@ -39,6 +41,8 @@ - static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll3_pfd0_720m", }; - static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; - static const char *ldb_di_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; -+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", }; -+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", }; - static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; - static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; - static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; -@@ -72,6 +76,10 @@ - "pll4_audio", "pll5_video", "pll8_mlb", "enet_ref", - "pcie_ref", "sata_ref", - }; -+static const char *pll_av_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", }; -+static void __iomem *anatop_base; -+static void __iomem *ccm_base; -+ - - enum mx6q_clks { - dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, -@@ -88,11 +96,11 @@ - periph_clk2, periph2_clk2, ipg, ipg_per, esai_pred, esai_podf, - asrc_pred, asrc_podf, spdif_pred, spdif_podf, can_root, ecspi_root, - gpu2d_core_podf, gpu3d_core_podf, gpu3d_shader, ipu1_podf, ipu2_podf, -- ldb_di0_podf, ldb_di1_podf, ipu1_di0_pre, ipu1_di1_pre, ipu2_di0_pre, -- ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, ssi2_pred, ssi2_podf, -- ssi3_pred, ssi3_podf, uart_serial_podf, usdhc1_podf, usdhc2_podf, -- usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, emi_podf, -- emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf, -+ ldb_di0_podf_unused, ldb_di1_podf_unused, ipu1_di0_pre, ipu1_di1_pre, -+ ipu2_di0_pre, ipu2_di1_pre, hsi_tx_podf, ssi1_pred, ssi1_podf, -+ ssi2_pred, ssi2_podf, ssi3_pred, ssi3_podf, uart_serial_podf, -+ usdhc1_podf, usdhc2_podf, usdhc3_podf, usdhc4_podf, enfc_pred, enfc_podf, -+ emi_podf, emi_slow_podf, vpu_axi_podf, cko1_podf, axi, mmdc_ch0_axi_podf, - mmdc_ch1_axi_podf, arm, ahb, apbh_dma, asrc, can1_ipg, can1_serial, - can2_ipg, can2_serial, ecspi1, ecspi2, ecspi3, ecspi4, ecspi5, enet, - esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb, -@@ -107,7 +115,10 @@ - sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, - usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow, - spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div, -- lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max -+ lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, gpt_3m, video_27m, -+ ldb_di0_div_7, ldb_di1_div_7, ldb_di0_div_sel, ldb_di1_div_sel, -+ caam_mem, caam_aclk, caam_ipg, epit1, epit2, tzasc2, lvds1_in, lvds1_out, -+ pll4_sel, lvds2_in, lvds2_out, anaclk1, anaclk2, clk_max - }; - - static struct clk *clk[clk_max]; -@@ -140,20 +151,131 @@ - { /* sentinel */ } - }; - -+static void init_ldb_clks(enum mx6q_clks new_parent) -+{ -+ u32 reg; -+ -+ /* -+ * Need to follow a strict procedure when changing the LDB -+ * clock, else we can introduce a glitch. Things to keep in -+ * mind: -+ * 1. The current and new parent clocks must be disabled. -+ * 2. The default clock for ldb_dio_clk is mmdc_ch1 which has -+ * no CG bit. -+ * 3. In the RTL implementation of the LDB_DI_CLK_SEL mux -+ * the top four options are in one mux and the PLL3 option along -+ * with another option is in the second mux. There is third mux -+ * used to decide between the first and second mux. -+ * The code below switches the parent to the bottom mux first -+ * and then manipulates the top mux. This ensures that no glitch -+ * will enter the divider. -+ * -+ * Need to disable MMDC_CH1 clock manually as there is no CG bit -+ * for this clock. The only way to disable this clock is to move -+ * it topll3_sw_clk and then to disable pll3_sw_clk -+ * Make sure periph2_clk2_sel is set to pll3_sw_clk -+ */ -+ reg = readl_relaxed(ccm_base + 0x18); -+ reg &= ~(1 << 20); -+ writel_relaxed(reg, ccm_base + 0x18); -+ -+ /* -+ * Set MMDC_CH1 mask bit. -+ */ -+ reg = readl_relaxed(ccm_base + 0x4); -+ reg |= 1 << 16; -+ writel_relaxed(reg, ccm_base + 0x4); -+ -+ /* -+ * Set the periph2_clk_sel to the top mux so that -+ * mmdc_ch1 is from pll3_sw_clk. -+ */ -+ reg = readl_relaxed(ccm_base + 0x14); -+ reg |= 1 << 26; -+ writel_relaxed(reg, ccm_base + 0x14); -+ -+ /* -+ * Wait for the clock switch. -+ */ -+ while (readl_relaxed(ccm_base + 0x48)) -+ ; -+ -+ /* -+ * Disable pll3_sw_clk by selecting the bypass clock source. -+ */ -+ reg = readl_relaxed(ccm_base + 0xc); -+ reg |= 1 << 0; -+ writel_relaxed(reg, ccm_base + 0xc); -+ -+ /* -+ * Set the ldb_di0_clk and ldb_di1_clk to 111b. -+ */ -+ reg = readl_relaxed(ccm_base + 0x2c); -+ reg |= ((7 << 9) | (7 << 12)); -+ writel_relaxed(reg, ccm_base + 0x2c); -+ -+ /* -+ * Set the ldb_di0_clk and ldb_di1_clk to 100b. -+ */ -+ reg = readl_relaxed(ccm_base + 0x2c); -+ reg &= ~((7 << 9) | (7 << 12)); -+ reg |= ((4 << 9) | (4 << 12)); -+ writel_relaxed(reg, ccm_base + 0x2c); -+ -+ /* -+ * Perform the LDB parent clock switch. -+ */ -+ clk_set_parent(clk[ldb_di0_sel], clk[new_parent]); -+ clk_set_parent(clk[ldb_di1_sel], clk[new_parent]); -+ -+ /* -+ * Unbypass pll3_sw_clk. -+ */ -+ reg = readl_relaxed(ccm_base + 0xc); -+ reg &= ~(1 << 0); -+ writel_relaxed(reg, ccm_base + 0xc); -+ -+ /* -+ * Set the periph2_clk_sel back to the bottom mux so that -+ * mmdc_ch1 is from its original parent. -+ */ -+ reg = readl_relaxed(ccm_base + 0x14); -+ reg &= ~(1 << 26); -+ writel_relaxed(reg, ccm_base + 0x14); -+ -+ /* -+ * Wait for the clock switch. -+ */ -+ while (readl_relaxed(ccm_base + 0x48)) -+ ; -+ -+ /* -+ * Clear MMDC_CH1 mask bit. -+ */ -+ reg = readl_relaxed(ccm_base + 0x4); -+ reg &= ~(1 << 16); -+ writel_relaxed(reg, ccm_base + 0x4); -+ -+} -+ - static void __init imx6q_clocks_init(struct device_node *ccm_node) - { - struct device_node *np; - void __iomem *base; - int i, irq; - int ret; -+ u32 reg; - - clk[dummy] = imx_clk_fixed("dummy", 0); - clk[ckil] = imx_obtain_fixed_clock("ckil", 0); - clk[ckih] = imx_obtain_fixed_clock("ckih1", 0); - clk[osc] = imx_obtain_fixed_clock("osc", 0); -+ /* Clock source from external clock via ANACLK1/2 PADs */ -+ clk[anaclk1] = imx_obtain_fixed_clock("anaclk1", 0); -+ clk[anaclk2] = imx_obtain_fixed_clock("anaclk2", 0); - - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); -- base = of_iomap(np, 0); -+ anatop_base = base = of_iomap(np, 0); - WARN_ON(!base); - - /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */ -@@ -165,13 +287,18 @@ - }; - - /* type name parent_name base div_mask */ -- clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); -- clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); -- clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3); -- clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f); -- clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); -- clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); -- clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host","osc", base + 0x20, 0x3); -+ clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f, false); -+ clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1, false); -+ clk[pll3_usb_otg] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3, false); -+ clk[pll4_audio] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "pll4_sel", base + 0x70, 0x7f, false); -+ clk[pll5_video] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f, false); -+ clk[pll6_enet] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3, false); -+ clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3, false); -+ -+ /* name reg shift width parent_names num_parents */ -+ clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); -+ clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); -+ clk[pll4_sel] = imx_clk_mux("pll4_sel", base + 0x70, 14, 2, pll_av_sels, ARRAY_SIZE(pll_av_sels)); - - /* - * Bit 20 is the reserved and read-only bit, we do this only for: -@@ -191,6 +318,11 @@ - - clk[sata_ref] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5); - clk[pcie_ref] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4); -+ /* NOTICE: The gate of the lvds1/2 in/out is used to select the clk direction */ -+ clk[lvds1_in] = imx_clk_gate("lvds1_in", "anaclk1", base + 0x160, 12); -+ clk[lvds2_in] = imx_clk_gate("lvds2_in", "anaclk2", base + 0x160, 13); -+ clk[lvds1_out] = imx_clk_gate("lvds1_out", "lvds1_sel", base + 0x160, 10); -+ clk[lvds2_out] = imx_clk_gate("lvds2_out", "lvds2_sel", base + 0x160, 11); - - clk[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20); - clk[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19); -@@ -199,18 +331,6 @@ - base + 0xe0, 0, 2, 0, clk_enet_ref_table, - &imx_ccm_lock); - -- clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); -- clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); -- -- /* -- * lvds1_gate and lvds2_gate are pseudo-gates. Both can be -- * independently configured as clock inputs or outputs. We treat -- * the "output_enable" bit as a gate, even though it's really just -- * enabling clock output. -- */ -- clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10); -- clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11); -- - /* name parent_name reg idx */ - clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); - clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); -@@ -226,6 +346,8 @@ - clk[pll3_80m] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); - clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); - clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2); -+ clk[gpt_3m] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8); -+ clk[video_27m] = imx_clk_fixed_factor("video_27m", "pll3_pfd1_540m", 1, 20); - - clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock); - clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock); -@@ -233,7 +355,7 @@ - clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock); - - np = ccm_node; -- base = of_iomap(np, 0); -+ ccm_base = base = of_iomap(np, 0); - WARN_ON(!base); - - imx6q_pm_set_ccm_base(base); -@@ -258,14 +380,16 @@ - clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); - clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); - clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT); -- clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); -- clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); -- clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); -- clk[ipu2_di1_pre_sel] = imx_clk_mux("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); -- clk[ipu1_di0_sel] = imx_clk_mux("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels)); -- clk[ipu1_di1_sel] = imx_clk_mux("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels)); -- clk[ipu2_di0_sel] = imx_clk_mux("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels)); -- clk[ipu2_di1_sel] = imx_clk_mux("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels)); -+ clk[ldb_di0_div_sel] = imx_clk_mux_flags("ldb_di0_div_sel", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels), CLK_SET_RATE_PARENT); -+ clk[ldb_di1_div_sel] = imx_clk_mux_flags("ldb_di1_div_sel", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels), CLK_SET_RATE_PARENT); -+ clk[ipu1_di0_pre_sel] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); -+ clk[ipu1_di1_pre_sel] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); -+ clk[ipu2_di0_pre_sel] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); -+ clk[ipu2_di1_pre_sel] = imx_clk_mux_flags("ipu2_di1_pre_sel", base + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT); -+ clk[ipu1_di0_sel] = imx_clk_mux_flags("ipu1_di0_sel", base + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels), CLK_SET_RATE_PARENT); -+ clk[ipu1_di1_sel] = imx_clk_mux_flags("ipu1_di1_sel", base + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels), CLK_SET_RATE_PARENT); -+ clk[ipu2_di0_sel] = imx_clk_mux_flags("ipu2_di0_sel", base + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels), CLK_SET_RATE_PARENT); -+ clk[ipu2_di1_sel] = imx_clk_mux_flags("ipu2_di1_sel", base + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels), CLK_SET_RATE_PARENT); - clk[hsi_tx_sel] = imx_clk_mux("hsi_tx_sel", base + 0x30, 28, 1, hsi_tx_sels, ARRAY_SIZE(hsi_tx_sels)); - clk[pcie_axi_sel] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); - clk[ssi1_sel] = imx_clk_fixup_mux("ssi1_sel", base + 0x1c, 10, 2, ssi_sels, ARRAY_SIZE(ssi_sels), imx_cscmr1_fixup); -@@ -307,9 +431,9 @@ - clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); - clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); - clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); -- clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0); -+ clk[ldb_di0_div_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7); - clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); -- clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0); -+ clk[ldb_di1_div_7] = imx_clk_fixed_factor("ldb_di1_div_7", "ldb_di1_sel", 1, 7); - clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); - clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); - clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); -@@ -344,6 +468,9 @@ - /* name parent_name reg shift */ - clk[apbh_dma] = imx_clk_gate2("apbh_dma", "usdhc3", base + 0x68, 4); - clk[asrc] = imx_clk_gate2("asrc", "asrc_podf", base + 0x68, 6); -+ clk[caam_mem] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8); -+ clk[caam_aclk] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10); -+ clk[caam_ipg] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12); - clk[can1_ipg] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14); - clk[can1_serial] = imx_clk_gate2("can1_serial", "can_root", base + 0x68, 16); - clk[can2_ipg] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18); -@@ -354,6 +481,8 @@ - clk[ecspi4] = imx_clk_gate2("ecspi4", "ecspi_root", base + 0x6c, 6); - clk[ecspi5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8); - clk[enet] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10); -+ clk[epit1] = imx_clk_gate2("epit1", "ipg", base + 0x6c, 12); -+ clk[epit2] = imx_clk_gate2("epit2", "ipg", base + 0x6c, 14); - clk[esai] = imx_clk_gate2("esai", "esai_podf", base + 0x6c, 16); - clk[gpt_ipg] = imx_clk_gate2("gpt_ipg", "ipg", base + 0x6c, 20); - clk[gpt_ipg_per] = imx_clk_gate2("gpt_ipg_per", "ipg_per", base + 0x6c, 22); -@@ -373,15 +502,16 @@ - clk[i2c3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10); - clk[iim] = imx_clk_gate2("iim", "ipg", base + 0x70, 12); - clk[enfc] = imx_clk_gate2("enfc", "enfc_podf", base + 0x70, 14); -+ clk[tzasc2] = imx_clk_gate2("tzasc2", "mmdc_ch0_axi_podf", base + 0x70, 24); - clk[vdoa] = imx_clk_gate2("vdoa", "vdo_axi", base + 0x70, 26); - clk[ipu1] = imx_clk_gate2("ipu1", "ipu1_podf", base + 0x74, 0); - clk[ipu1_di0] = imx_clk_gate2("ipu1_di0", "ipu1_di0_sel", base + 0x74, 2); - clk[ipu1_di1] = imx_clk_gate2("ipu1_di1", "ipu1_di1_sel", base + 0x74, 4); - clk[ipu2] = imx_clk_gate2("ipu2", "ipu2_podf", base + 0x74, 6); - clk[ipu2_di0] = imx_clk_gate2("ipu2_di0", "ipu2_di0_sel", base + 0x74, 8); -- clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_podf", base + 0x74, 12); -- clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_podf", base + 0x74, 14); - clk[ipu2_di1] = imx_clk_gate2("ipu2_di1", "ipu2_di1_sel", base + 0x74, 10); -+ clk[ldb_di0] = imx_clk_gate2("ldb_di0", "ldb_di0_div_sel", base + 0x74, 12); -+ clk[ldb_di1] = imx_clk_gate2("ldb_di1", "ldb_di1_div_sel", base + 0x74, 14); - clk[hsi_tx] = imx_clk_gate2("hsi_tx", "hsi_tx_podf", base + 0x74, 16); - if (cpu_is_imx6dl()) - /* -@@ -413,6 +543,9 @@ - clk[ssi1_ipg] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18); - clk[ssi2_ipg] = imx_clk_gate2("ssi2_ipg", "ipg", base + 0x7c, 20); - clk[ssi3_ipg] = imx_clk_gate2("ssi3_ipg", "ipg", base + 0x7c, 22); -+ clk[ssi1] = imx_clk_gate2("ssi1", "ssi1_podf", base + 0x7c, 18); -+ clk[ssi2] = imx_clk_gate2("ssi2", "ssi2_podf", base + 0x7c, 20); -+ clk[ssi3] = imx_clk_gate2("ssi3", "ssi3_podf", base + 0x7c, 22); - clk[uart_ipg] = imx_clk_gate2("uart_ipg", "ipg", base + 0x7c, 24); - clk[uart_serial] = imx_clk_gate2("uart_serial", "uart_serial_podf", base + 0x7c, 26); - clk[usboh3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0); -@@ -431,25 +564,79 @@ - pr_err("i.MX6q clk %d: register failed with %ld\n", - i, PTR_ERR(clk[i])); - -+ /* Initialize clock gate status */ -+ writel_relaxed(1 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(1) | -+ 3 << CCM_CCGR_OFFSET(0), base + 0x68); -+ if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) -+ writel_relaxed(3 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(10), base + 0x6c); -+ else -+ writel_relaxed(3 << CCM_CCGR_OFFSET(10), base + 0x6c); -+ writel_relaxed(1 << CCM_CCGR_OFFSET(12) | -+ 3 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(10) | -+ 3 << CCM_CCGR_OFFSET(9) | -+ 3 << CCM_CCGR_OFFSET(8), base + 0x70); -+ writel_relaxed(3 << CCM_CCGR_OFFSET(14) | -+ 1 << CCM_CCGR_OFFSET(13) | -+ 3 << CCM_CCGR_OFFSET(12) | -+ 1 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(10), base + 0x74); -+ writel_relaxed(3 << CCM_CCGR_OFFSET(7) | -+ 3 << CCM_CCGR_OFFSET(6) | -+ 3 << CCM_CCGR_OFFSET(4), base + 0x78); -+ writel_relaxed(1 << CCM_CCGR_OFFSET(0), base + 0x7c); -+ writel_relaxed(0, base + 0x80); -+ -+ /* Make sure PFDs are disabled at boot. */ -+ reg = readl_relaxed(anatop_base + 0x100); -+ /* Cannot disable pll2_pfd2_396M, as it is the MMDC clock in iMX6DL */ -+ if (cpu_is_imx6dl()) -+ reg |= 0x80008080; -+ else -+ reg |= 0x80808080; -+ writel_relaxed(reg, anatop_base + 0x100); -+ -+ /* Disable PLL3 PFDs. */ -+ reg = readl_relaxed(anatop_base + 0xF0); -+ reg |= 0x80808080; -+ writel_relaxed(reg, anatop_base + 0xF0); -+ -+ /* Make sure PLLs is disabled */ -+ reg = readl_relaxed(anatop_base + 0xA0); -+ reg &= ~(1 << 13); -+ writel_relaxed(reg, anatop_base + 0xA0); -+ - clk_data.clks = clk; - clk_data.clk_num = ARRAY_SIZE(clk); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - - clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0"); - clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0"); -+ clk_register_clkdev(clk[gpt_3m], "gpt_3m", "imx-gpt.0"); - clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL); - clk_register_clkdev(clk[ahb], "ahb", NULL); - clk_register_clkdev(clk[cko1], "cko1", NULL); - clk_register_clkdev(clk[arm], NULL, "cpu0"); -- clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL); -- clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL); -+ clk_register_clkdev(clk[pll4_audio_div], "pll4_audio_div", NULL); -+ clk_register_clkdev(clk[pll4_sel], "pll4_sel", NULL); -+ clk_register_clkdev(clk[lvds2_in], "lvds2_in", NULL); -+ clk_register_clkdev(clk[esai], "esai", NULL); - -- if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) || -- cpu_is_imx6dl()) { -- clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]); -- clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]); -+ if (cpu_is_imx6dl()) { -+ clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]); - } - -+ clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]); -+ clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]); -+ clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]); -+ clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]); -+ - /* - * The gpmi needs 100MHz frequency in the EDO/Sync mode, - * We can not get the 100MHz from the pll2_pfd0_352m. -@@ -457,6 +644,19 @@ - */ - clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]); - -+ /* Set the parent clks of PCIe lvds1 and pcie_axi to be sata ref, axi */ -+ if (clk_set_parent(clk[lvds1_sel], clk[sata_ref])) -+ pr_err("Failed to set PCIe bus parent clk.\n"); -+ if (clk_set_parent(clk[pcie_axi_sel], clk[axi])) -+ pr_err("Failed to set PCIe parent clk.\n"); -+ -+ /* gpu clock initilazation */ -+ clk_set_parent(clk[gpu3d_shader_sel], clk[pll2_pfd1_594m]); -+ clk_set_rate(clk[gpu3d_shader], 594000000); -+ clk_set_parent(clk[gpu3d_core_sel], clk[mmdc_ch0_axi]); -+ clk_set_rate(clk[gpu3d_core], 528000000); -+ clk_set_parent(clk[gpu2d_core_sel], clk[pll3_usb_otg]); -+ - for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) - clk_prepare_enable(clk[clks_init_on[i]]); - -@@ -465,6 +665,25 @@ - clk_prepare_enable(clk[usbphy2_gate]); - } - -+ /* ipu clock initialization */ -+ init_ldb_clks(pll2_pfd0_352m); -+ clk_set_parent(clk[ipu1_di0_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu1_di1_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu2_di0_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu2_di1_pre_sel], clk[pll5_video_div]); -+ clk_set_parent(clk[ipu1_di0_sel], clk[ipu1_di0_pre]); -+ clk_set_parent(clk[ipu1_di1_sel], clk[ipu1_di1_pre]); -+ clk_set_parent(clk[ipu2_di0_sel], clk[ipu2_di0_pre]); -+ clk_set_parent(clk[ipu2_di1_sel], clk[ipu2_di1_pre]); -+ if (cpu_is_imx6dl()) { -+ clk_set_rate(clk[pll3_pfd1_540m], 540000000); -+ clk_set_parent(clk[ipu1_sel], clk[pll3_pfd1_540m]); -+ clk_set_parent(clk[axi_sel], clk[pll3_pfd1_540m]); -+ } else if (cpu_is_imx6q()) { -+ clk_set_parent(clk[ipu1_sel], clk[mmdc_ch0_axi]); -+ clk_set_parent(clk[ipu2_sel], clk[mmdc_ch0_axi]); -+ } -+ - /* - * Let's initially set up CLKO with OSC24M, since this configuration - * is widely used by imx6q board designs to clock audio codec. -@@ -482,6 +701,18 @@ - if (IS_ENABLED(CONFIG_PCI_IMX6)) - clk_set_parent(clk[lvds1_sel], clk[sata_ref]); - -+ /* Audio clocks */ -+ clk_set_parent(clk[ssi1_sel], clk[pll4_audio_div]); -+ clk_set_parent(clk[ssi2_sel], clk[pll4_audio_div]); -+ clk_set_parent(clk[ssi3_sel], clk[pll4_audio_div]); -+ clk_set_parent(clk[esai_sel], clk[pll4_audio_div]); -+ clk_set_parent(clk[spdif_sel], clk[pll3_pfd3_454m]); -+ clk_set_parent(clk[asrc_sel], clk[pll3_usb_otg]); -+ clk_set_rate(clk[asrc_sel], 7500000); -+ -+ /* Set pll4_audio to a value that can derive 5K-88.2KHz and 8K-96KHz */ -+ clk_set_rate(clk[pll4_audio_div], 541900800); -+ - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); - -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/clk-imx6sl.c linux-3.14.22/arch/arm/mach-imx/clk-imx6sl.c ---- linux-3.14.22.orig/arch/arm/mach-imx/clk-imx6sl.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/clk-imx6sl.c 2014-10-22 14:55:49.906220001 -0500 -@@ -7,9 +7,29 @@ - * - */ - -+#define CCM_CCDR_OFFSET 0x4 -+#define ANATOP_PLL_USB1 0x10 -+#define ANATOP_PLL_USB2 0x20 -+#define ANATOP_PLL_ENET 0xE0 -+#define ANATOP_PLL_BYPASS_OFFSET (1 << 16) -+#define ANATOP_PLL_ENABLE_OFFSET (1 << 13) -+#define ANATOP_PLL_POWER_OFFSET (1 << 12) -+#define ANATOP_PFD_480n_OFFSET 0xf0 -+#define ANATOP_PFD_528n_OFFSET 0x100 -+#define PFD0_CLKGATE (1 << 7) -+#define PFD1_CLK_GATE (1 << 15) -+#define PFD2_CLK_GATE (1 << 23) -+#define PFD3_CLK_GATE (1 << 31) -+#define CCDR_CH0_HS_BYP 17 -+#define OSC_RATE 24000000 -+ -+#define CCM_CCGR_OFFSET(index) (index * 2) -+ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -18,6 +38,7 @@ - #include "clk.h" - #include "common.h" - -+static bool uart_from_osc; - static const char const *step_sels[] = { "osc", "pll2_pfd2", }; - static const char const *pll1_sw_sels[] = { "pll1_sys", "step", }; - static const char const *ocram_alt_sels[] = { "pll2_pfd2", "pll3_pfd1", }; -@@ -25,8 +46,8 @@ - static const char const *pre_periph_sels[] = { "pll2_bus", "pll2_pfd2", "pll2_pfd0", "pll2_198m", }; - static const char const *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", "dummy", }; - static const char const *periph2_clk2_sels[] = { "pll3_usb_otg", "pll2_bus", }; --static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2_podf", }; --static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2_podf", }; -+static const char const *periph_sels[] = { "pre_periph_sel", "periph_clk2", }; -+static const char const *periph2_sels[] = { "pre_periph2_sel", "periph2_clk2", }; - static const char const *csi_lcdif_sels[] = { "mmdc", "pll2_pfd2", "pll3_120m", "pll3_pfd1", }; - static const char const *usdhc_sels[] = { "pll2_pfd2", "pll2_pfd0", }; - static const char const *ssi_sels[] = { "pll3_pfd2", "pll3_pfd3", "pll4_audio_div", "dummy", }; -@@ -38,7 +59,7 @@ - static const char const *epdc_pix_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0", "pll2_pfd1", "pll3_pfd1", }; - static const char const *audio_sels[] = { "pll4_audio_div", "pll3_pfd2", "pll3_pfd3", "pll3_usb_otg", }; - static const char const *ecspi_sels[] = { "pll3_60m", "osc", }; --static const char const *uart_sels[] = { "pll3_80m", "osc", }; -+static const char const *uart_sels[] = { "pll3_80m", "uart_osc_4M", }; - - static struct clk_div_table clk_enet_ref_table[] = { - { .val = 0, .div = 20, }, -@@ -65,6 +86,80 @@ - - static struct clk *clks[IMX6SL_CLK_END]; - static struct clk_onecell_data clk_data; -+static u32 cur_arm_podf; -+static u32 pll1_org_rate; -+ -+extern int low_bus_freq_mode; -+extern int audio_bus_freq_mode; -+ -+/* -+ * On MX6SL, need to ensure that the ARM:IPG clock ratio is maintained -+ * within 12:5 when the clocks to ARM are gated when the SOC enters -+ * WAIT mode. This is necessary to avoid WAIT mode issue (an early -+ * interrupt waking up the ARM). -+ * This function will set the ARM clk to max value within the 12:5 limit. -+ */ -+void imx6sl_set_wait_clk(bool enter) -+{ -+ u32 parent_rate; -+ -+ if (enter) { -+ u32 wait_podf; -+ u32 new_parent_rate = OSC_RATE; -+ u32 ipg_rate = clk_get_rate(clks[IMX6SL_CLK_IPG]); -+ u32 max_arm_wait_clk = (12 * ipg_rate) / 5; -+ parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]); -+ cur_arm_podf = parent_rate / clk_get_rate(clks[IMX6SL_CLK_ARM]); -+ if (low_bus_freq_mode) { -+ /* -+ * IPG clk is at 12MHz at this point, we can only run -+ * ARM at a max of 28.8MHz. So we need to set ARM -+ * to run from the 24MHz OSC, as there is no way to -+ * get 28.8MHz when ARM is sourced from PLL1. -+ */ -+ clk_set_parent(clks[IMX6SL_CLK_STEP], -+ clks[IMX6SL_CLK_OSC]); -+ clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], -+ clks[IMX6SL_CLK_STEP]); -+ } else if (audio_bus_freq_mode) { -+ /* -+ * In this mode ARM is from PLL2_PFD2 (396MHz), -+ * but IPG is at 12MHz. Need to switch ARM to run -+ * from the bypassed PLL1 clocks so that we can run -+ * ARM at 24MHz. -+ */ -+ pll1_org_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SYS]); -+ /* Ensure PLL1 is at 24MHz. */ -+ clk_set_rate(clks[IMX6SL_CLK_PLL1_SYS], OSC_RATE); -+ clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], clks[IMX6SL_CLK_PLL1_SYS]); -+ } else -+ new_parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]); -+ wait_podf = (new_parent_rate + max_arm_wait_clk - 1) / -+ max_arm_wait_clk; -+ -+ clk_set_rate(clks[IMX6SL_CLK_ARM], new_parent_rate / wait_podf); -+ } else { -+ if (low_bus_freq_mode) -+ /* Move ARM back to PLL1. */ -+ clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], -+ clks[IMX6SL_CLK_PLL1_SYS]); -+ else if (audio_bus_freq_mode) { -+ /* Move ARM back to PLL2_PFD2 via STEP_CLK. */ -+ clk_set_parent(clks[IMX6SL_CLK_PLL1_SW], clks[IMX6SL_CLK_STEP]); -+ clk_set_rate(clks[IMX6SL_CLK_PLL1_SYS], pll1_org_rate); -+ } -+ parent_rate = clk_get_rate(clks[IMX6SL_CLK_PLL1_SW]); -+ clk_set_rate(clks[IMX6SL_CLK_ARM], parent_rate / cur_arm_podf); -+ } -+} -+ -+static int __init setup_uart_clk(char *uart_rate) -+{ -+ uart_from_osc = true; -+ return 1; -+} -+ -+__setup("uart_at_4M", setup_uart_clk); - - static void __init imx6sl_clocks_init(struct device_node *ccm_node) - { -@@ -72,6 +167,8 @@ - void __iomem *base; - int irq; - int i; -+ int ret; -+ u32 reg; - - clks[IMX6SL_CLK_DUMMY] = imx_clk_fixed("dummy", 0); - clks[IMX6SL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0); -@@ -82,13 +179,18 @@ - WARN_ON(!base); - - /* type name parent base div_mask */ -- clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); -- clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); -- clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3); -- clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f); -- clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f); -- clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3); -- clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3); -+ clks[IMX6SL_CLK_PLL1_SYS] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f, true); -+ clks[IMX6SL_CLK_PLL2_BUS] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1, true); -+ clks[IMX6SL_CLK_PLL3_USB_OTG] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", base + 0x10, 0x3, false); -+ clks[IMX6SL_CLK_PLL4_AUDIO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4_audio", "osc", base + 0x70, 0x7f, false); -+ clks[IMX6SL_CLK_PLL5_VIDEO] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5_video", "osc", base + 0xa0, 0x7f, false); -+ clks[IMX6SL_CLK_PLL6_ENET] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6_enet", "osc", base + 0xe0, 0x3, false); -+ clks[IMX6SL_CLK_PLL7_USB_HOST] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7_usb_host", "osc", base + 0x20, 0x3, false); -+ -+ /* Ensure the AHB clk is at 132MHz. */ -+ ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000); -+ if (ret) -+ pr_warn("%s: failed to set AHB clock rate %d\n", __func__, ret); - - /* - * usbphy1 and usbphy2 are implemented as dummy gates using reserve -@@ -118,11 +220,36 @@ - clks[IMX6SL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2", "pll3_usb_otg", base + 0xf0, 2); - clks[IMX6SL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3", "pll3_usb_otg", base + 0xf0, 3); - -- /* name parent_name mult div */ -- clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2); -- clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); -- clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); -- clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); -+ /* name parent_name mult div */ -+ clks[IMX6SL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2", 1, 2); -+ clks[IMX6SL_CLK_PLL3_120M] = imx_clk_fixed_factor("pll3_120m", "pll3_usb_otg", 1, 4); -+ clks[IMX6SL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); -+ clks[IMX6SL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); -+ clks[IMX6SL_CLK_UART_OSC_4M] = imx_clk_fixed_factor("uart_osc_4M", "osc", 1, 6); -+ -+ /* Ensure all PFDs but PLL2_PFD2 are disabled. */ -+ reg = readl_relaxed(base + ANATOP_PFD_480n_OFFSET); -+ reg |= (PFD0_CLKGATE | PFD1_CLK_GATE | PFD2_CLK_GATE | PFD3_CLK_GATE); -+ writel_relaxed(reg, base + ANATOP_PFD_480n_OFFSET); -+ reg = readl_relaxed(base + ANATOP_PFD_528n_OFFSET); -+ reg |= (PFD0_CLKGATE | PFD1_CLK_GATE); -+ writel_relaxed(reg, base + ANATOP_PFD_528n_OFFSET); -+ -+ /* Ensure Unused PLLs are disabled. */ -+ reg = readl_relaxed(base + ANATOP_PLL_USB1); -+ reg |= ANATOP_PLL_BYPASS_OFFSET; -+ reg &= ~(ANATOP_PLL_ENABLE_OFFSET | ANATOP_PLL_POWER_OFFSET); -+ writel_relaxed(reg, base + ANATOP_PLL_USB1); -+ -+ reg = readl_relaxed(base + ANATOP_PLL_USB2); -+ reg |= ANATOP_PLL_BYPASS_OFFSET; -+ reg &= ~(ANATOP_PLL_ENABLE_OFFSET | ANATOP_PLL_POWER_OFFSET); -+ writel_relaxed(reg, base + ANATOP_PLL_USB2); -+ -+ reg = readl_relaxed(base + ANATOP_PLL_ENET); -+ reg |= (ANATOP_PLL_BYPASS_OFFSET | ANATOP_PLL_POWER_OFFSET); -+ reg &= ~ANATOP_PLL_ENABLE_OFFSET; -+ writel_relaxed(reg, base + ANATOP_PLL_ENET); - - np = ccm_node; - base = of_iomap(np, 0); -@@ -158,7 +285,7 @@ - clks[IMX6SL_CLK_EPDC_PIX_SEL] = imx_clk_mux("epdc_pix_sel", base + 0x38, 15, 3, epdc_pix_sels, ARRAY_SIZE(epdc_pix_sels)); - clks[IMX6SL_CLK_SPDIF0_SEL] = imx_clk_mux("spdif0_sel", base + 0x30, 20, 2, audio_sels, ARRAY_SIZE(audio_sels)); - clks[IMX6SL_CLK_SPDIF1_SEL] = imx_clk_mux("spdif1_sel", base + 0x30, 7, 2, audio_sels, ARRAY_SIZE(audio_sels)); -- clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels)); -+ clks[IMX6SL_CLK_EXTERN_AUDIO_SEL] = imx_clk_mux_flags("extern_audio_sel", base + 0x20, 19, 2, audio_sels, ARRAY_SIZE(audio_sels), CLK_SET_RATE_PARENT); - clks[IMX6SL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels)); - clks[IMX6SL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels)); - -@@ -168,8 +295,8 @@ - - /* name parent_name reg shift width */ - clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3); -- clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3); -- clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3); -+ clks[IMX6SL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3); -+ clks[IMX6SL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3); - clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2); - clks[IMX6SL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3); - clks[IMX6SL_CLK_LCDIF_AXI_PODF] = imx_clk_divider("lcdif_axi_podf", "lcdif_axi_sel", base + 0x3c, 16, 3); -@@ -251,6 +378,25 @@ - pr_err("i.MX6SL clk %d: register failed with %ld\n", - i, PTR_ERR(clks[i])); - -+ /* Initialize clock gate status */ -+ writel_relaxed(1 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(1) | -+ 3 << CCM_CCGR_OFFSET(0), base + 0x68); -+ writel_relaxed(3 << CCM_CCGR_OFFSET(10), base + 0x6c); -+ writel_relaxed(1 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(10) | -+ 3 << CCM_CCGR_OFFSET(9) | -+ 3 << CCM_CCGR_OFFSET(8), base + 0x70); -+ writel_relaxed(3 << CCM_CCGR_OFFSET(14) | -+ 3 << CCM_CCGR_OFFSET(13) | -+ 3 << CCM_CCGR_OFFSET(12) | -+ 3 << CCM_CCGR_OFFSET(11) | -+ 3 << CCM_CCGR_OFFSET(10), base + 0x74); -+ writel_relaxed(3 << CCM_CCGR_OFFSET(7) | -+ 3 << CCM_CCGR_OFFSET(4), base + 0x78); -+ writel_relaxed(1 << CCM_CCGR_OFFSET(0), base + 0x7c); -+ writel_relaxed(0, base + 0x80); -+ - clk_data.clks = clks; - clk_data.clk_num = ARRAY_SIZE(clks); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -@@ -258,17 +404,58 @@ - clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0"); - clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0"); - -+ /* -+ * Make sure the ARM clk is enabled to maintain the correct usecount -+ * and enabling/disabling of parent PLLs. -+ */ -+ ret = clk_prepare_enable(clks[IMX6SL_CLK_ARM]); -+ if (ret) -+ pr_warn("%s: failed to enable ARM core clock %d\n", -+ __func__, ret); -+ -+ /* -+ * Make sure the MMDC clk is enabled to maintain the correct usecount -+ * and enabling/disabling of parent PLLs. -+ */ -+ ret = clk_prepare_enable(clks[IMX6SL_CLK_MMDC_ROOT]); -+ if (ret) -+ pr_warn("%s: failed to enable MMDC clock %d\n", -+ __func__, ret); -+ - if (IS_ENABLED(CONFIG_USB_MXS_PHY)) { - clk_prepare_enable(clks[IMX6SL_CLK_USBPHY1_GATE]); - clk_prepare_enable(clks[IMX6SL_CLK_USBPHY2_GATE]); - } - -+ clk_set_parent(clks[IMX6SL_CLK_GPU2D_OVG_SEL], -+ clks[IMX6SL_CLK_PLL2_BUS]); -+ clk_set_parent(clks[IMX6SL_CLK_GPU2D_SEL], clks[IMX6SL_CLK_PLL2_BUS]); -+ - /* Audio-related clocks configuration */ - clk_set_parent(clks[IMX6SL_CLK_SPDIF0_SEL], clks[IMX6SL_CLK_PLL3_PFD3]); - -+ /* set extern_audio to be sourced from PLL4/audio PLL */ -+ clk_set_parent(clks[IMX6SL_CLK_EXTERN_AUDIO_SEL], clks[IMX6SL_CLK_PLL4_AUDIO_DIV]); -+ /* set extern_audio to 24MHz */ -+ clk_set_rate(clks[IMX6SL_CLK_PLL4_AUDIO], 24000000); -+ clk_set_rate(clks[IMX6SL_CLK_EXTERN_AUDIO], 24000000); -+ -+ /* set SSI2 parent to PLL4 */ -+ clk_set_parent(clks[IMX6SL_CLK_SSI2_SEL], clks[IMX6SL_CLK_PLL4_AUDIO_DIV]); -+ clk_set_rate(clks[IMX6SL_CLK_SSI2], 24000000); -+ - /* Set initial power mode */ - imx6q_set_lpm(WAIT_CLOCKED); - -+ /* Ensure that CH0 handshake is bypassed. */ -+ reg = readl_relaxed(base + CCM_CCDR_OFFSET); -+ reg |= 1 << CCDR_CH0_HS_BYP; -+ writel_relaxed(reg, base + CCM_CCDR_OFFSET); -+ -+ /* Set the UART parent if needed. */ -+ if (uart_from_osc) -+ ret = clk_set_parent(clks[IMX6SL_CLK_UART_SEL], clks[IMX6SL_CLK_UART_OSC_4M]); -+ - np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpt"); - base = of_iomap(np, 0); - WARN_ON(!base); -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/clk-pfd.c linux-3.14.22/arch/arm/mach-imx/clk-pfd.c ---- linux-3.14.22.orig/arch/arm/mach-imx/clk-pfd.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/clk-pfd.c 2014-10-22 14:55:49.906220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2012 Freescale Semiconductor, Inc. -+ * Copyright 2012-2013 Freescale Semiconductor, Inc. - * Copyright 2012 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public -@@ -17,6 +17,8 @@ - #include - #include "clk.h" - -+#define BYPASS_RATE 24000000 -+ - /** - * struct clk_pfd - IMX PFD clock - * @clk_hw: clock source -@@ -62,9 +64,14 @@ - u64 tmp = parent_rate; - u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f; - -- tmp *= 18; -- do_div(tmp, frac); -- -+ /* -+ * If the parent PLL is in bypass state, the PFDs -+ * are also in bypass state. -+ */ -+ if (tmp != BYPASS_RATE) { -+ tmp *= 18; -+ do_div(tmp, frac); -+ } - return tmp; - } - -@@ -74,17 +81,22 @@ - u64 tmp = *prate; - u8 frac; - -- tmp = tmp * 18 + rate / 2; -- do_div(tmp, rate); -- frac = tmp; -- if (frac < 12) -- frac = 12; -- else if (frac > 35) -- frac = 35; -- tmp = *prate; -- tmp *= 18; -- do_div(tmp, frac); -- -+ /* -+ * If the parent PLL is in bypass state, the PFDs -+ * are also in bypass state. -+ */ -+ if (tmp != BYPASS_RATE) { -+ tmp = tmp * 18 + rate / 2; -+ do_div(tmp, rate); -+ frac = tmp; -+ if (frac < 12) -+ frac = 12; -+ else if (frac > 35) -+ frac = 35; -+ tmp = *prate; -+ tmp *= 18; -+ do_div(tmp, frac); -+ } - return tmp; - } - -@@ -95,6 +107,9 @@ - u64 tmp = parent_rate; - u8 frac; - -+ if (tmp == BYPASS_RATE) -+ return 0; -+ - tmp = tmp * 18 + rate / 2; - do_div(tmp, rate); - frac = tmp; -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/clk-pllv3.c linux-3.14.22/arch/arm/mach-imx/clk-pllv3.c ---- linux-3.14.22.orig/arch/arm/mach-imx/clk-pllv3.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/clk-pllv3.c 2014-10-22 14:55:49.906220001 -0500 -@@ -26,12 +26,15 @@ - #define BM_PLL_ENABLE (0x1 << 13) - #define BM_PLL_BYPASS (0x1 << 16) - #define BM_PLL_LOCK (0x1 << 31) -+#define BYPASS_RATE 24000000 -+#define BYPASS_MASK 0x10000 - - /** - * struct clk_pllv3 - IMX PLL clock version 3 - * @clk_hw: clock source - * @base: base address of PLL registers - * @powerup_set: set POWER bit to power up the PLL -+ * @always_on : Leave the PLL powered up all the time. - * @div_mask: mask of divider bits - * - * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 -@@ -41,7 +44,9 @@ - struct clk_hw hw; - void __iomem *base; - bool powerup_set; -+ bool always_on; - u32 div_mask; -+ u32 rate_req; - }; - - #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) -@@ -61,54 +66,53 @@ - break; - if (time_after(jiffies, timeout)) - break; -- usleep_range(50, 500); -+ udelay(100); - } while (1); - - return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT; - } - --static int clk_pllv3_prepare(struct clk_hw *hw) -+static int clk_pllv3_power_up_down(struct clk_hw *hw, bool enable) - { - struct clk_pllv3 *pll = to_clk_pllv3(hw); -- u32 val; -- int ret; -- -- val = readl_relaxed(pll->base); -- if (pll->powerup_set) -- val |= BM_PLL_POWER; -- else -- val &= ~BM_PLL_POWER; -- writel_relaxed(val, pll->base); -- -- ret = clk_pllv3_wait_lock(pll); -- if (ret) -- return ret; -+ u32 val, ret = 0; - -- val = readl_relaxed(pll->base); -- val &= ~BM_PLL_BYPASS; -- writel_relaxed(val, pll->base); -- -- return 0; --} -+ if (enable) { -+ val = readl_relaxed(pll->base); -+ val &= ~BM_PLL_BYPASS; -+ if (pll->powerup_set) -+ val |= BM_PLL_POWER; -+ else -+ val &= ~BM_PLL_POWER; -+ writel_relaxed(val, pll->base); -+ -+ ret = clk_pllv3_wait_lock(pll); -+ } else { -+ val = readl_relaxed(pll->base); -+ val |= BM_PLL_BYPASS; -+ if (pll->powerup_set) -+ val &= ~BM_PLL_POWER; -+ else -+ val |= BM_PLL_POWER; -+ writel_relaxed(val, pll->base); -+ } - --static void clk_pllv3_unprepare(struct clk_hw *hw) --{ -- struct clk_pllv3 *pll = to_clk_pllv3(hw); -- u32 val; -+ if (!ret) { -+ val = readl_relaxed(pll->base); -+ val &= ~BM_PLL_BYPASS; -+ writel_relaxed(val, pll->base); -+ } - -- val = readl_relaxed(pll->base); -- val |= BM_PLL_BYPASS; -- if (pll->powerup_set) -- val &= ~BM_PLL_POWER; -- else -- val |= BM_PLL_POWER; -- writel_relaxed(val, pll->base); -+ return ret; - } - - static int clk_pllv3_enable(struct clk_hw *hw) - { - struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 val; -+ -+ if (pll->rate_req != BYPASS_RATE) -+ clk_pllv3_power_up_down(hw, true); - - val = readl_relaxed(pll->base); - val |= BM_PLL_ENABLE; -@@ -123,8 +127,12 @@ - u32 val; - - val = readl_relaxed(pll->base); -- val &= ~BM_PLL_ENABLE; -+ if (!pll->always_on) -+ val &= ~BM_PLL_ENABLE; - writel_relaxed(val, pll->base); -+ -+ if (pll->rate_req != BYPASS_RATE) -+ clk_pllv3_power_up_down(hw, false); - } - - static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, -@@ -132,8 +140,15 @@ - { - struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 div = readl_relaxed(pll->base) & pll->div_mask; -+ u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK; -+ u32 rate; -+ -+ if (pll->rate_req == BYPASS_RATE && bypass) -+ rate = BYPASS_RATE; -+ else -+ rate = (div == 1) ? parent_rate * 22 : parent_rate * 20; - -- return (div == 1) ? parent_rate * 22 : parent_rate * 20; -+ return rate; - } - - static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate, -@@ -141,6 +156,10 @@ - { - unsigned long parent_rate = *prate; - -+ /* If the PLL is bypassed, its rate is 24MHz. */ -+ if (rate == BYPASS_RATE) -+ return BYPASS_RATE; -+ - return (rate >= parent_rate * 22) ? parent_rate * 22 : - parent_rate * 20; - } -@@ -151,6 +170,22 @@ - struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 val, div; - -+ pll->rate_req = rate; -+ val = readl_relaxed(pll->base); -+ -+ /* If the PLL is bypassed, its rate is 24MHz. */ -+ if (rate == BYPASS_RATE) { -+ /* Set the bypass bit. */ -+ val |= BM_PLL_BYPASS; -+ /* Power down the PLL. */ -+ if (pll->powerup_set) -+ val &= ~BM_PLL_POWER; -+ else -+ val |= BM_PLL_POWER; -+ writel_relaxed(val, pll->base); -+ -+ return 0; -+ } - if (rate == parent_rate * 22) - div = 1; - else if (rate == parent_rate * 20) -@@ -167,8 +202,6 @@ - } - - static const struct clk_ops clk_pllv3_ops = { -- .prepare = clk_pllv3_prepare, -- .unprepare = clk_pllv3_unprepare, - .enable = clk_pllv3_enable, - .disable = clk_pllv3_disable, - .recalc_rate = clk_pllv3_recalc_rate, -@@ -181,6 +214,10 @@ - { - struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 div = readl_relaxed(pll->base) & pll->div_mask; -+ u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK; -+ -+ if (pll->rate_req == BYPASS_RATE && bypass) -+ return BYPASS_RATE; - - return parent_rate * div / 2; - } -@@ -193,6 +230,9 @@ - unsigned long max_rate = parent_rate * 108 / 2; - u32 div; - -+ if (rate == BYPASS_RATE) -+ return BYPASS_RATE; -+ - if (rate > max_rate) - rate = max_rate; - else if (rate < min_rate) -@@ -210,9 +250,26 @@ - unsigned long max_rate = parent_rate * 108 / 2; - u32 val, div; - -- if (rate < min_rate || rate > max_rate) -+ if (rate != BYPASS_RATE && (rate < min_rate || rate > max_rate)) - return -EINVAL; - -+ pll->rate_req = rate; -+ val = readl_relaxed(pll->base); -+ -+ if (rate == BYPASS_RATE) { -+ /* -+ * Set the PLL in bypass mode if rate requested is -+ * BYPASS_RATE. -+ */ -+ val |= BM_PLL_BYPASS; -+ /* Power down the PLL. */ -+ if (pll->powerup_set) -+ val &= ~BM_PLL_POWER; -+ else -+ val |= BM_PLL_POWER; -+ writel_relaxed(val, pll->base); -+ return 0; -+ } - div = rate * 2 / parent_rate; - val = readl_relaxed(pll->base); - val &= ~pll->div_mask; -@@ -223,8 +280,6 @@ - } - - static const struct clk_ops clk_pllv3_sys_ops = { -- .prepare = clk_pllv3_prepare, -- .unprepare = clk_pllv3_unprepare, - .enable = clk_pllv3_enable, - .disable = clk_pllv3_disable, - .recalc_rate = clk_pllv3_sys_recalc_rate, -@@ -239,6 +294,10 @@ - u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET); - u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET); - u32 div = readl_relaxed(pll->base) & pll->div_mask; -+ u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK; -+ -+ if (pll->rate_req == BYPASS_RATE && bypass) -+ return BYPASS_RATE; - - return (parent_rate * div) + ((parent_rate / mfd) * mfn); - } -@@ -253,6 +312,9 @@ - u32 mfn, mfd = 1000000; - s64 temp64; - -+ if (rate == BYPASS_RATE) -+ return BYPASS_RATE; -+ - if (rate > max_rate) - rate = max_rate; - else if (rate < min_rate) -@@ -273,13 +335,36 @@ - struct clk_pllv3 *pll = to_clk_pllv3(hw); - unsigned long min_rate = parent_rate * 27; - unsigned long max_rate = parent_rate * 54; -- u32 val, div; -+ u32 val, newval, div; - u32 mfn, mfd = 1000000; - s64 temp64; -+ int ret; - -- if (rate < min_rate || rate > max_rate) -+ if (rate != BYPASS_RATE && (rate < min_rate || rate > max_rate)) - return -EINVAL; - -+ pll->rate_req = rate; -+ val = readl_relaxed(pll->base); -+ -+ if (rate == BYPASS_RATE) { -+ /* -+ * Set the PLL in bypass mode if rate requested is -+ * BYPASS_RATE. -+ */ -+ /* Bypass the PLL */ -+ val |= BM_PLL_BYPASS; -+ /* Power down the PLL. */ -+ if (pll->powerup_set) -+ val &= ~BM_PLL_POWER; -+ else -+ val |= BM_PLL_POWER; -+ writel_relaxed(val, pll->base); -+ return 0; -+ } -+ /* Else clear the bypass bit. */ -+ val &= ~BM_PLL_BYPASS; -+ writel_relaxed(val, pll->base); -+ - div = rate / parent_rate; - temp64 = (u64) (rate - div * parent_rate); - temp64 *= mfd; -@@ -287,18 +372,30 @@ - mfn = temp64; - - val = readl_relaxed(pll->base); -- val &= ~pll->div_mask; -- val |= div; -- writel_relaxed(val, pll->base); -+ -+ /* set the PLL into bypass mode */ -+ newval = val | BM_PLL_BYPASS; -+ writel_relaxed(newval, pll->base); -+ -+ /* configure the new frequency */ -+ newval &= ~pll->div_mask; -+ newval |= div; -+ writel_relaxed(newval, pll->base); - writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); -- writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); -+ writel(mfd, pll->base + PLL_DENOM_OFFSET); - -- return clk_pllv3_wait_lock(pll); -+ ret = clk_pllv3_wait_lock(pll); -+ if (ret == 0 && val & BM_PLL_POWER) { -+ /* only if it locked can we switch back to the PLL */ -+ newval &= ~BM_PLL_BYPASS; -+ newval |= val & BM_PLL_BYPASS; -+ writel(newval, pll->base); -+ } -+ -+ return ret; - } - - static const struct clk_ops clk_pllv3_av_ops = { -- .prepare = clk_pllv3_prepare, -- .unprepare = clk_pllv3_unprepare, - .enable = clk_pllv3_enable, - .disable = clk_pllv3_disable, - .recalc_rate = clk_pllv3_av_recalc_rate, -@@ -313,8 +410,6 @@ - } - - static const struct clk_ops clk_pllv3_enet_ops = { -- .prepare = clk_pllv3_prepare, -- .unprepare = clk_pllv3_unprepare, - .enable = clk_pllv3_enable, - .disable = clk_pllv3_disable, - .recalc_rate = clk_pllv3_enet_recalc_rate, -@@ -322,7 +417,7 @@ - - struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, - const char *parent_name, void __iomem *base, -- u32 div_mask) -+ u32 div_mask, bool always_on) - { - struct clk_pllv3 *pll; - const struct clk_ops *ops; -@@ -352,6 +447,7 @@ - } - pll->base = base; - pll->div_mask = div_mask; -+ pll->always_on = always_on; - - init.name = name; - init.ops = ops; -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/common.h linux-3.14.22/arch/arm/mach-imx/common.h ---- linux-3.14.22.orig/arch/arm/mach-imx/common.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/common.h 2014-10-22 14:55:49.906220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. - */ - - /* -@@ -116,7 +116,6 @@ - void imx_set_cpu_jump(int cpu, void *jump_addr); - u32 imx_get_cpu_arg(int cpu); - void imx_set_cpu_arg(int cpu, u32 arg); --void v7_cpu_resume(void); - #ifdef CONFIG_SMP - void v7_secondary_startup(void); - void imx_scu_map_io(void); -@@ -129,7 +128,7 @@ - #endif - void imx_src_init(void); - void imx_gpc_init(void); --void imx_gpc_pre_suspend(void); -+void imx_gpc_pre_suspend(bool arm_power_off); - void imx_gpc_post_resume(void); - void imx_gpc_mask_all(void); - void imx_gpc_restore_all(void); -@@ -138,14 +137,28 @@ - void imx_anatop_init(void); - void imx_anatop_pre_suspend(void); - void imx_anatop_post_resume(void); -+void imx_anatop_pu_enable(bool enable); - int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); --void imx6q_set_chicken_bit(void); -+void imx6q_set_cache_lpm_in_wait(bool enable); -+void imx6sl_set_wait_clk(bool enter); -+void imx6_enet_mac_init(const char *compatible); - - void imx_cpu_die(unsigned int cpu); - int imx_cpu_kill(unsigned int cpu); - -+#ifdef CONFIG_SUSPEND -+void v7_cpu_resume(void); -+void imx6_suspend(void __iomem *ocram_vbase); -+#else -+static inline void v7_cpu_resume(void) {} -+static inline void imx6_suspend(void __iomem *ocram_vbase) {} -+#endif -+ - void imx6q_pm_init(void); -+void imx6dl_pm_init(void); -+void imx6sl_pm_init(void); - void imx6q_pm_set_ccm_base(void __iomem *base); -+ - #ifdef CONFIG_PM - void imx5_pm_init(void); - #else -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/cpuidle.h linux-3.14.22/arch/arm/mach-imx/cpuidle.h ---- linux-3.14.22.orig/arch/arm/mach-imx/cpuidle.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/cpuidle.h 2014-10-22 14:55:49.906220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2012 Freescale Semiconductor, Inc. -+ * Copyright 2012-2013 Freescale Semiconductor, Inc. - * Copyright 2012 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public -@@ -13,6 +13,7 @@ - #ifdef CONFIG_CPU_IDLE - extern int imx5_cpuidle_init(void); - extern int imx6q_cpuidle_init(void); -+extern int imx6sl_cpuidle_init(void); - #else - static inline int imx5_cpuidle_init(void) - { -@@ -22,4 +23,8 @@ - { - return 0; - } -+static inline int imx6sl_cpuidle_init(void) -+{ -+ return 0; -+} - #endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/cpuidle-imx6q.c linux-3.14.22/arch/arm/mach-imx/cpuidle-imx6q.c ---- linux-3.14.22.orig/arch/arm/mach-imx/cpuidle-imx6q.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/cpuidle-imx6q.c 2014-10-22 14:55:49.906220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2012 Freescale Semiconductor, Inc. -+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -68,8 +68,8 @@ - /* Need to enable SCU standby for entering WAIT modes */ - imx_scu_standby_enable(); - -- /* Set chicken bit to get a reliable WAIT mode support */ -- imx6q_set_chicken_bit(); -+ /* Set cache lpm bit for reliable WAIT mode support */ -+ imx6q_set_cache_lpm_in_wait(true); - - return cpuidle_register(&imx6q_cpuidle_driver, NULL); - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/cpuidle-imx6sl.c linux-3.14.22/arch/arm/mach-imx/cpuidle-imx6sl.c ---- linux-3.14.22.orig/arch/arm/mach-imx/cpuidle-imx6sl.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/cpuidle-imx6sl.c 2014-10-22 14:55:49.906220001 -0500 -@@ -0,0 +1,149 @@ -+/* -+ * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "common.h" -+#include "cpuidle.h" -+ -+extern u32 audio_bus_freq_mode; -+extern u32 ultra_low_bus_freq_mode; -+extern unsigned long reg_addrs[]; -+extern void imx6sl_low_power_wfi(void); -+ -+static void __iomem *iomux_base; -+static void *wfi_iram_base; -+ -+void (*imx6sl_wfi_in_iram_fn)(void *wfi_iram_base, -+ void *iomux_addr, void *regs_addr, u32 audio_mode) = NULL; -+ -+#define WFI_IN_IRAM_SIZE 0x1000 -+ -+static int imx6sl_enter_wait(struct cpuidle_device *dev, -+ struct cpuidle_driver *drv, int index) -+{ -+ imx6q_set_lpm(WAIT_UNCLOCKED); -+#ifdef CONFIG_ARM_IMX6_CPUFREQ -+ if (ultra_low_bus_freq_mode || audio_bus_freq_mode) { -+ /* -+ * Flush the TLB, to ensure no TLB maintenance occurs -+ * when DDR is in self-refresh. -+ */ -+ local_flush_tlb_all(); -+ /* -+ * Run WFI code from IRAM. -+ * Drop the DDR freq to 1MHz and AHB to 3MHz -+ * Also float DDR IO pads. -+ */ -+ imx6sl_wfi_in_iram_fn(wfi_iram_base, iomux_base, reg_addrs, audio_bus_freq_mode); -+ } -+ else -+#endif -+ { -+ imx6sl_set_wait_clk(true); -+ cpu_do_idle(); -+ imx6sl_set_wait_clk(false); -+ } -+ imx6q_set_lpm(WAIT_CLOCKED); -+ -+ return index; -+} -+ -+static struct cpuidle_driver imx6sl_cpuidle_driver = { -+ .name = "imx6sl_cpuidle", -+ .owner = THIS_MODULE, -+ .states = { -+ /* WFI */ -+ ARM_CPUIDLE_WFI_STATE, -+ /* WAIT */ -+ { -+ .exit_latency = 50, -+ .target_residency = 75, -+ .flags = CPUIDLE_FLAG_TIME_VALID | -+ CPUIDLE_FLAG_TIMER_STOP, -+ .enter = imx6sl_enter_wait, -+ .name = "WAIT", -+ .desc = "Clock off", -+ }, -+ }, -+ .state_count = 2, -+ .safe_state_index = 0, -+}; -+ -+int __init imx6sl_cpuidle_init(void) -+{ -+ struct platform_device *ocram_dev; -+ unsigned int iram_paddr; -+ struct device_node *node; -+ struct gen_pool *iram_pool; -+ -+ node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-iomuxc"); -+ if (!node) { -+ pr_err("failed to find imx6sl-iomuxc device tree data!\n"); -+ return -EINVAL; -+ } -+ iomux_base = of_iomap(node, 0); -+ WARN(!iomux_base, "unable to map iomux registers\n"); -+ -+ node = NULL; -+ node = of_find_compatible_node(NULL, NULL, "mmio-sram"); -+ if (!node) { -+ pr_err("%s: failed to find ocram node\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ ocram_dev = of_find_device_by_node(node); -+ if (!ocram_dev) { -+ pr_err("failed to find ocram device!\n"); -+ return -EINVAL; -+ } -+ -+ iram_pool = dev_get_gen_pool(&ocram_dev->dev); -+ if (!iram_pool) { -+ pr_err("iram pool unavailable!\n"); -+ return -EINVAL; -+ } -+ /* -+ * Allocate IRAM memory when ARM executes WFI in -+ * ultra_low_power_mode. -+ */ -+ wfi_iram_base = (void *)gen_pool_alloc(iram_pool, -+ WFI_IN_IRAM_SIZE); -+ if (!wfi_iram_base) { -+ pr_err("Cannot alloc iram for wfi code!\n"); -+ return -ENOMEM; -+ } -+ -+ iram_paddr = gen_pool_virt_to_phys(iram_pool, -+ (unsigned long)wfi_iram_base); -+ /* -+ * Need to remap the area here since we want -+ * the memory region to be executable. -+ */ -+ wfi_iram_base = __arm_ioremap(iram_paddr, -+ WFI_IN_IRAM_SIZE, -+ MT_MEMORY_RWX_NONCACHED); -+ if (!wfi_iram_base) -+ pr_err("wfi_ram_base NOT remapped\n"); -+ -+ imx6sl_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base, -+ &imx6sl_low_power_wfi, WFI_IN_IRAM_SIZE); -+ -+ return cpuidle_register(&imx6sl_cpuidle_driver, NULL); -+} -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/ddr3_freq_imx6.S linux-3.14.22/arch/arm/mach-imx/ddr3_freq_imx6.S ---- linux-3.14.22.orig/arch/arm/mach-imx/ddr3_freq_imx6.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/ddr3_freq_imx6.S 2014-10-22 14:55:49.906220001 -0500 -@@ -0,0 +1,893 @@ -+/* -+ * 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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+ -+#define MMDC0_MDPDC 0x4 -+#define MMDC0_MDCF0 0x0c -+#define MMDC0_MDCF1 0x10 -+#define MMDC0_MDMISC 0x18 -+#define MMDC0_MDSCR 0x1c -+#define MMDC0_MAPSR 0x404 -+#define MMDC0_MADPCR0 0x410 -+#define MMDC0_MPZQHWCTRL 0x800 -+#define MMDC1_MPZQHWCTRL 0x4800 -+#define MMDC0_MPODTCTRL 0x818 -+#define MMDC1_MPODTCTRL 0x4818 -+#define MMDC0_MPDGCTRL0 0x83c -+#define MMDC1_MPDGCTRL0 0x483c -+#define MMDC0_MPMUR0 0x8b8 -+#define MMDC1_MPMUR0 0x48b8 -+ -+#define CCM_CBCDR 0x14 -+#define CCM_CBCMR 0x18 -+#define CCM_CSCMR1 0x1c -+#define CCM_CDHIPR 0x48 -+ -+#define L2_CACHE_SYNC 0x730 -+ -+ .align 3 -+ -+ .macro switch_to_528MHz -+ -+ /* check if periph_clk_sel is already set */ -+ ldr r0, [r6, #CCM_CBCDR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ beq set_ahb_podf_before_switch -+ -+ /* change periph_clk to be sourced from pll3_clk. */ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(3 << 12) -+ str r0, [r6, #CCM_CBCMR] -+ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(0x38 << 20) -+ str r0, [r6, #CCM_CBCDR] -+ -+ /* -+ * set the AHB dividers before the switch, -+ * don't change AXI clock divider, -+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4, -+ */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #0xd00 -+ orr r0, r0, #(1 << 16) -+ str r0, [r6, #CCM_CBCDR] -+ -+wait_div_update528: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update528 -+ -+ /* now switch periph_clk to pll3_main_clk. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ orr r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch3: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch3 -+ -+ b switch_pre_periph_clk_528 -+ -+set_ahb_podf_before_switch: -+ /* -+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4, -+ */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #0xd00 -+ orr r0, r0, #(1 << 16) -+ str r0, [r6, #CCM_CBCDR] -+ -+wait_div_update528_1: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update528_1 -+ -+switch_pre_periph_clk_528: -+ -+ /* now switch pre_periph_clk to PLL2_528MHz. */ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(0xc << 16) -+ str r0, [r6, #CCM_CBCMR] -+ -+ /* now switch periph_clk back. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch4: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch4 -+ -+ .endm -+ -+ .macro switch_to_400MHz -+ -+ /* check if periph_clk_sel is already set. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ beq set_ahb_podf_before_switch1 -+ -+ /* change periph_clk to be sourced from pll3_clk. */ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(3 << 12) -+ str r0, [r6, #CCM_CBCMR] -+ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(0x38 << 24) -+ str r0, [r6, #CCM_CBCDR] -+ -+ /* now switch periph_clk to pll3_main_clk. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ orr r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch5: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch5 -+ -+ b switch_pre_periph_clk_400 -+ -+set_ahb_podf_before_switch1: -+ /* -+ * set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4, -+ */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #(0x9 << 8) -+ orr r0, r0, #(1 << 16) -+ str r0, [r6, #CCM_CBCDR] -+ -+wait_div_update400_1: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update400_1 -+ -+switch_pre_periph_clk_400: -+ -+ /* now switch pre_periph_clk to PFD_400MHz. */ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(0xc << 16) -+ orr r0, r0, #(0x4 << 16) -+ str r0, [r6, #CCM_CBCMR] -+ -+ /* now switch periph_clk back. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch6: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch6 -+ -+ /* -+ * change AHB divider so that we are at 400/3=133MHz. -+ * don't change AXI clock divider. -+ * set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3, -+ */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #(0x9 << 8) -+ orr r0, r0, #(1 << 16) -+ str r0, [r6, #CCM_CBCDR] -+ -+wait_div_update400_2: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update400_2 -+ -+ .endm -+ -+ .macro switch_to_50MHz -+ -+ /* check if periph_clk_sel is already set. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ beq switch_pre_periph_clk_50 -+ -+ /* -+ * set the periph_clk to be sourced from PLL2_PFD_200M -+ * change periph_clk to be sourced from pll3_clk. -+ * ensure PLL3 is the source and set the divider to 1. -+ */ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(0x3 << 12) -+ str r0, [r6, #CCM_CBCMR] -+ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(0x38 << 24) -+ str r0, [r6, #CCM_CBCDR] -+ -+ /* now switch periph_clk to pll3_main_clk. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ orr r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch_50: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch_50 -+ -+switch_pre_periph_clk_50: -+ -+ /* now switch pre_periph_clk to PFD_200MHz. */ -+ ldr r0, [r6, #CCM_CBCMR] -+ orr r0, r0, #(0xc << 16) -+ str r0, [r6, #CCM_CBCMR] -+ -+ /* -+ * set the MMDC_DIV=4, AXI_DIV = 4, AHB_DIV=8, -+ */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #(0x18 << 16) -+ orr r0, r0, #(0x3 << 16) -+ -+ /* -+ * if changing AHB divider remember to change -+ * the IPGPER divider too below. -+ */ -+ orr r0, r0, #0x1d00 -+ str r0, [r6, #CCM_CBCDR] -+ -+wait_div_update_50: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update_50 -+ -+ /* now switch periph_clk back. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch2: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch2 -+ -+ .endm -+ -+ .macro switch_to_24MHz -+ /* -+ * change the freq now try setting DDR to 24MHz. -+ * source it from the periph_clk2 ensure the -+ * periph_clk2 is sourced from 24MHz and the -+ * divider is 1. -+ */ -+ -+ ldr r0, [r6, #CCM_CBCMR] -+ bic r0, r0, #(0x3 << 12) -+ orr r0, r0, #(1 << 12) -+ str r0, [r6, #CCM_CBCMR] -+ -+ ldr r0, [r6, #CCM_CBCDR] -+ bic r0, r0, #(0x38 << 24) -+ str r0, [r6, #CCM_CBCDR] -+ -+ /* now switch periph_clk to 24MHz. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ orr r0, r0, #(1 << 25) -+ str r0, [r6, #CCM_CBCDR] -+ -+periph_clk_switch1: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne periph_clk_switch1 -+ -+ /* change all the dividers to 1. */ -+ ldr r0, [r6, #CCM_CBCDR] -+ ldr r2, =0x3f1f00 -+ bic r0, r0, r2 -+ orr r0, r0, #(1 << 8) -+ str r0, [r6, #CCM_CBCDR] -+ -+ /* Wait for the divider to change. */ -+wait_div_update: -+ ldr r0, [r6, #CCM_CDHIPR] -+ cmp r0, #0 -+ bne wait_div_update -+ -+ .endm -+ -+/* -+ * mx6_ddr3_freq_change -+ * -+ * idle the processor (eg, wait for interrupt). -+ * make sure DDR is in self-refresh. -+ * IRQs are already disabled. -+ */ -+ENTRY(mx6_ddr3_freq_change) -+ -+ stmfd sp!, {r4-r12} -+ -+ /* -+ * r5 -> mmdc_base -+ * r6 -> ccm_base -+ * r7 -> iomux_base -+ * r12 -> l2_base -+ */ -+ mov r4, r0 -+ mov r8, r1 -+ mov r9, r2 -+ mov r11, r3 -+ -+ /* -+ * Get the addresses of the registers. -+ * They are last few entries in the -+ * ddr_settings parameter. -+ * The first entry contains the count, -+ * and each entry is 2 words. -+ */ -+ ldr r0, [r1] -+ add r0, r0, #1 -+ lsl r0, r0, #3 -+ add r1, r0, r1 -+ /* mmdc_base. */ -+ ldr r5, [r1] -+ add r1, #8 -+ /* ccm_base */ -+ ldr r6, [r1] -+ add r1, #8 -+ /*iomux_base */ -+ ldr r7, [r1] -+ add r1, #8 -+ /*l2_base */ -+ ldr r12, [r1] -+ -+ddr_freq_change: -+ /* -+ * make sure no TLB miss will occur when -+ * the DDR is in self refresh. invalidate -+ * TLB single entry to ensure that the -+ * address is not already in the TLB. -+ */ -+ -+ adr r10, ddr_freq_change -+ -+ ldr r2, [r6] -+ ldr r2, [r5] -+ ldr r2, [r7] -+ ldr r2, [r8] -+ ldr r2, [r10] -+ ldr r2, [r11] -+ ldr r2, [r12] -+ -+#ifdef CONFIG_CACHE_L2X0 -+ /* -+ * Make sure the L2 buffers are drained. -+ * Sync operation on L2 drains the buffers. -+ */ -+ mov r1, #0x0 -+ str r1, [r12, #L2_CACHE_SYNC] -+#endif -+ -+ /* disable automatic power saving. */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ orr r0, r0, #0x01 -+ str r0, [r5, #MMDC0_MAPSR] -+ -+ /* disable MMDC power down timer. */ -+ ldr r0, [r5, #MMDC0_MDPDC] -+ bic r0, r0, #(0xff << 8) -+ str r0, [r5, #MMDC0_MDPDC] -+ -+ /* delay for a while */ -+ ldr r1, =4 -+delay1: -+ ldr r2, =0 -+cont1: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont1 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay1 -+ -+ /* set CON_REG */ -+ ldr r0, =0x8000 -+ str r0, [r5, #MMDC0_MDSCR] -+poll_conreq_set_1: -+ ldr r0, [r5, #MMDC0_MDSCR] -+ and r0, r0, #(0x4 << 12) -+ cmp r0, #(0x4 << 12) -+ bne poll_conreq_set_1 -+ -+ ldr r0, =0x00008010 -+ str r0, [r5, #MMDC0_MDSCR] -+ ldr r0, =0x00008018 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* -+ * if requested frequency is greater than -+ * 300MHz go to DLL on mode. -+ */ -+ ldr r1, =300000000 -+ cmp r4, r1 -+ bge dll_on_mode -+ -+dll_off_mode: -+ -+ /* if DLL is currently on, turn it off. */ -+ cmp r9, #1 -+ beq continue_dll_off_1 -+ -+ ldr r0, =0x00018031 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x00018039 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r1, =10 -+delay1a: -+ ldr r2, =0 -+cont1a: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont1a -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay1a -+ -+continue_dll_off_1: -+ /* set DVFS - enter self refresh mode */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ orr r0, r0, #(1 << 21) -+ str r0, [r5, #MMDC0_MAPSR] -+ -+ /* de-assert con_req */ -+ mov r0, #0x0 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+poll_dvfs_set_1: -+ ldr r0, [r5, #MMDC0_MAPSR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ bne poll_dvfs_set_1 -+ -+ ldr r1, =24000000 -+ cmp r4, r1 -+ beq switch_freq_24 -+ -+ switch_to_50MHz -+ b continue_dll_off_2 -+ -+switch_freq_24: -+ switch_to_24MHz -+ -+continue_dll_off_2: -+ -+ /* set SBS - block ddr accesses */ -+ ldr r0, [r5, #MMDC0_MADPCR0] -+ orr r0, r0, #(1 << 8) -+ str r0, [r5, #MMDC0_MADPCR0] -+ -+ /* clear DVFS - exit from self refresh mode */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ bic r0, r0, #(1 << 21) -+ str r0, [r5, #MMDC0_MAPSR] -+ -+poll_dvfs_clear_1: -+ ldr r0, [r5, #MMDC0_MAPSR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ beq poll_dvfs_clear_1 -+ -+ /* if DLL was previously on, continue DLL off routine. */ -+ cmp r9, #1 -+ beq continue_dll_off_3 -+ -+ ldr r0, =0x00018031 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x00018039 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x08208030 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x08208038 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x00088032 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x0008803A -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* delay for a while. */ -+ ldr r1, =4 -+delay_1: -+ ldr r2, =0 -+cont_1: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont_1 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay_1 -+ -+ ldr r0, [r5, #MMDC0_MDCF0] -+ bic r0, r0, #0xf -+ orr r0, r0, #0x3 -+ str r0, [r5, #MMDC0_MDCF0] -+ -+ ldr r0, [r5, #MMDC0_MDCF1] -+ bic r0, r0, #0x7 -+ orr r0, r0, #0x4 -+ str r0, [r5, #MMDC0_MDCF1] -+ -+ ldr r0, =0x00091680 -+ str r0, [r5, #MMDC0_MDMISC] -+ -+ /* enable dqs pull down in the IOMUX. */ -+ ldr r1, [r11] -+ add r11, r11, #8 -+ ldr r2, =0x3028 -+update_iomux: -+ ldr r0, [r11, #0x0] -+ ldr r3, [r7, r0] -+ bic r3, r3, r2 -+ orr r3, r3, #(0x3 << 12) -+ orr r3, r3, #0x28 -+ str r3, [r7, r0] -+ add r11, r11, #8 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt update_iomux -+ -+ /* ODT disabled. */ -+ ldr r0, =0x0 -+ ldr r2, =MMDC0_MPODTCTRL -+ str r0, [r5, r2] -+ ldr r2, =MMDC1_MPODTCTRL -+ str r0, [r5, r2] -+ -+ /* DQS gating disabled. */ -+ ldr r2, =MMDC0_MPDGCTRL0 -+ ldr r0, [r5, r2] -+ orr r0, r0, #(1 << 29) -+ str r0, [r5, r2] -+ -+ ldr r2, =MMDC1_MPDGCTRL0 -+ ldr r0, [r5, r2] -+ orr r0, r0, #(0x1 << 29) -+ str r0, [r5, r2] -+ -+ /* MMDC0_MAPSR adopt power down enable. */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ bic r0, r0, #0x01 -+ str r0, [r5, #MMDC0_MAPSR] -+ -+ /* frc_msr + mu bypass */ -+ ldr r0, =0x00000060 -+ str r0, [r5, #MMDC0_MPMUR0] -+ ldr r2, =MMDC1_MPMUR0 -+ str r0, [r5, r2] -+ ldr r0, =0x00000460 -+ str r0, [r5, #MMDC0_MPMUR0] -+ ldr r2, =MMDC1_MPMUR0 -+ str r0, [r5, r2] -+ ldr r0, =0x00000c60 -+ str r0, [r5, #MMDC0_MPMUR0] -+ ldr r2, =MMDC1_MPMUR0 -+ str r0, [r5, r2] -+ -+continue_dll_off_3: -+ /* clear SBS - unblock accesses to DDR. */ -+ ldr r0, [r5, #MMDC0_MADPCR0] -+ bic r0, r0, #(0x1 << 8) -+ str r0, [r5, #MMDC0_MADPCR0] -+ -+ mov r0, #0x0 -+ str r0, [r5, #MMDC0_MDSCR] -+poll_conreq_clear_1: -+ ldr r0, [r5, #MMDC0_MDSCR] -+ and r0, r0, #(0x4 << 12) -+ cmp r0, #(0x4 << 12) -+ beq poll_conreq_clear_1 -+ -+ b done -+ -+dll_on_mode: -+ /* assert DVFS - enter self refresh mode. */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ orr r0, r0, #(1 << 21) -+ str r0, [r5, #MMDC0_MAPSR] -+ -+ /* de-assert CON_REQ. */ -+ mov r0, #0x0 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* poll DVFS ack. */ -+poll_dvfs_set_2: -+ ldr r0, [r5, #MMDC0_MAPSR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ bne poll_dvfs_set_2 -+ -+ ldr r1, =528000000 -+ cmp r4, r1 -+ beq switch_freq_528 -+ -+ switch_to_400MHz -+ -+ b continue_dll_on -+ -+switch_freq_528: -+ switch_to_528MHz -+ -+continue_dll_on: -+ -+ /* set SBS step-by-step mode. */ -+ ldr r0, [r5, #MMDC0_MADPCR0] -+ orr r0, r0, #( 1 << 8) -+ str r0, [r5, #MMDC0_MADPCR0] -+ -+ /* clear DVFS - exit self refresh mode. */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ bic r0, r0, #(1 << 21) -+ str r0, [r5, #MMDC0_MAPSR] -+ -+poll_dvfs_clear_2: -+ ldr r0, [r5, #MMDC0_MAPSR] -+ and r0, r0, #(1 << 25) -+ cmp r0, #(1 << 25) -+ beq poll_dvfs_clear_2 -+ -+ /* if DLL is currently off, turn it back on. */ -+ cmp r9, #0 -+ beq update_calibration_only -+ -+ ldr r0, =0xa5390003 -+ str r0, [r5, #MMDC0_MPZQHWCTRL] -+ ldr r2, =MMDC1_MPZQHWCTRL -+ str r0, [r5, r2] -+ -+ /* enable DQS gating. */ -+ ldr r2, =MMDC0_MPDGCTRL0 -+ ldr r0, [r5, r2] -+ bic r0, r0, #(1 << 29) -+ str r0, [r5, r2] -+ -+ ldr r2, =MMDC1_MPDGCTRL0 -+ ldr r0, [r5, r2] -+ bic r0, r0, #(1 << 29) -+ str r0, [r5, r2] -+ -+ /* force measure. */ -+ ldr r0, =0x00000800 -+ str r0, [r5, #MMDC0_MPMUR0] -+ ldr r2, =MMDC1_MPMUR0 -+ str r0, [r5, r2] -+ -+ /* delay for while. */ -+ ldr r1, =4 -+delay5: -+ ldr r2, =0 -+cont5: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont5 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay5 -+ -+ /* disable dqs pull down in the IOMUX. */ -+ ldr r1, [r11] -+ add r11, r11, #8 -+update_iomux1: -+ ldr r0, [r11, #0x0] -+ ldr r3, [r11, #0x4] -+ str r3, [r7, r0] -+ add r11, r11, #8 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt update_iomux1 -+ -+ /* config MMDC timings to 528MHz. */ -+ ldr r9, [r8] -+ add r8, r8, #8 -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ /* update MISC register: WALAT, RALAT */ -+ ldr r0, =0x00081740 -+ str r0, [r5, #MMDC0_MDMISC] -+ -+ /* configure ddr devices to dll on, odt. */ -+ ldr r0, =0x00028031 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x00028039 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* delay for while. */ -+ ldr r1, =4 -+delay7: -+ ldr r2, =0 -+cont7: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont7 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay7 -+ -+ /* reset dll. */ -+ ldr r0, =0x09208030 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x09208038 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* delay for while. */ -+ ldr r1, =100 -+delay8: -+ ldr r2, =0 -+cont8: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont8 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay8 -+ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ ldr r0, =0x00428031 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x00428039 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ /* issue a zq command. */ -+ ldr r0, =0x04008040 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ ldr r0, =0x04008048 -+ str r0, [r5, #MMDC0_MDSCR] -+ -+ /* MMDC ODT enable. */ -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ -+ ldr r2, =0x4818 -+ str r0, [r5, r2] -+ -+ /* delay for while. */ -+ ldr r1, =40 -+delay15: -+ ldr r2, =0 -+cont15: -+ ldr r0, [r5, r2] -+ add r2, r2, #4 -+ cmp r2, #16 -+ bne cont15 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt delay15 -+ -+ /* MMDC0_MAPSR adopt power down enable. */ -+ ldr r0, [r5, #MMDC0_MAPSR] -+ bic r0, r0, #0x01 -+ str r0, [r5, #MMDC0_MAPSR] -+ -+ /* enable MMDC power down timer. */ -+ ldr r0, [r5, #MMDC0_MDPDC] -+ orr r0, r0, #(0x55 << 8) -+ str r0, [r5, #MMDC0_MDPDC] -+ -+ b update_calibration -+ -+update_calibration_only: -+ ldr r1, [r8] -+ sub r1, r1, #7 -+ add r8, r8, #64 -+ b update_calib -+ -+update_calibration: -+ /* write the new calibration values. */ -+ mov r1, r9 -+ sub r1, r1, #7 -+ -+update_calib: -+ ldr r0, [r8, #0x0] -+ ldr r3, [r8, #0x4] -+ str r3, [r5, r0] -+ add r8, r8, #8 -+ sub r1, r1, #1 -+ cmp r1, #0 -+ bgt update_calib -+ -+ /* perform a force measurement. */ -+ ldr r0, =0x800 -+ str r0, [r5, #MMDC0_MPMUR0] -+ ldr r2, =MMDC1_MPMUR0 -+ str r0, [r5, r2] -+ -+ /* clear SBS - unblock DDR accesses. */ -+ ldr r0, [r5, #MMDC0_MADPCR0] -+ bic r0, r0, #(1 << 8) -+ str r0, [r5, #MMDC0_MADPCR0] -+ -+ mov r0, #0x0 -+ str r0, [r5, #MMDC0_MDSCR] -+poll_conreq_clear_2: -+ ldr r0, [r5, #MMDC0_MDSCR] -+ and r0, r0, #(0x4 << 12) -+ cmp r0, #(0x4 << 12) -+ beq poll_conreq_clear_2 -+ -+done: -+ /* restore registers */ -+ -+ ldmfd sp!, {r4-r12} -+ mov pc, lr -+ -+ .type mx6_do_ddr3_freq_change, #object -+ENTRY(mx6_do_ddr_freq_change) -+ .word mx6_ddr3_freq_change -+ .size mx6_ddr3_freq_change, . - mx6_ddr3_freq_change -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/gpc.c linux-3.14.22/arch/arm/mach-imx/gpc.c ---- linux-3.14.22.orig/arch/arm/mach-imx/gpc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/gpc.c 2014-10-22 14:55:49.906220001 -0500 -@@ -10,30 +10,69 @@ - * http://www.gnu.org/copyleft/gpl.html - */ - -+#include -+#include - #include - #include -+#include - #include - #include - #include -+#include - #include -+#include -+#include -+#include - #include "common.h" -+#include "hardware.h" - - #define GPC_IMR1 0x008 - #define GPC_PGC_CPU_PDN 0x2a0 -+#define GPC_PGC_GPU_PDN 0x260 -+#define GPC_PGC_GPU_PUPSCR 0x264 -+#define GPC_PGC_GPU_PDNSCR 0x268 -+#define GPC_PGC_GPU_SW_SHIFT 0 -+#define GPC_PGC_GPU_SW_MASK 0x3f -+#define GPC_PGC_GPU_SW2ISO_SHIFT 8 -+#define GPC_PGC_GPU_SW2ISO_MASK 0x3f -+#define GPC_PGC_CPU_PUPSCR 0x2a4 -+#define GPC_PGC_CPU_PDNSCR 0x2a8 -+#define GPC_PGC_CPU_SW_SHIFT 0 -+#define GPC_PGC_CPU_SW_MASK 0x3f -+#define GPC_PGC_CPU_SW2ISO_SHIFT 8 -+#define GPC_PGC_CPU_SW2ISO_MASK 0x3f -+#define GPC_CNTR 0x0 -+#define GPC_CNTR_PU_UP_REQ_SHIFT 0x1 -+#define GPC_CNTR_PU_DOWN_REQ_SHIFT 0x0 - - #define IMR_NUM 4 - - static void __iomem *gpc_base; - static u32 gpc_wake_irqs[IMR_NUM]; - static u32 gpc_saved_imrs[IMR_NUM]; -+static struct clk *gpu3d_clk, *gpu3d_shader_clk, *gpu2d_clk, *gpu2d_axi_clk; -+static struct clk *openvg_axi_clk, *vpu_clk, *ipg_clk; -+static struct device *gpc_dev; -+struct regulator *pu_reg; -+struct notifier_block nb; -+static struct regulator_dev *pu_dummy_regulator_rdev; -+static struct regulator_init_data pu_dummy_initdata = { -+ .constraints = { -+ .max_uV = 1450000, /* allign with real max of anatop */ -+ .valid_ops_mask = REGULATOR_CHANGE_STATUS | -+ REGULATOR_CHANGE_VOLTAGE, -+ }, -+}; -+static int pu_dummy_enable; - --void imx_gpc_pre_suspend(void) -+void imx_gpc_pre_suspend(bool arm_power_off) - { - void __iomem *reg_imr1 = gpc_base + GPC_IMR1; - int i; - -- /* Tell GPC to power off ARM core when suspend */ -- writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); -+ if (arm_power_off) -+ /* Tell GPC to power off ARM core when suspend */ -+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); - - for (i = 0; i < IMR_NUM; i++) { - gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); -@@ -120,10 +159,119 @@ - writel_relaxed(val, reg); - } - -+static void imx_pu_clk(bool enable) -+{ -+ if (enable) { -+ if (cpu_is_imx6sl()) { -+ clk_prepare_enable(gpu2d_clk); -+ clk_prepare_enable(openvg_axi_clk); -+ } else { -+ clk_prepare_enable(vpu_clk); -+ clk_prepare_enable(gpu3d_clk); -+ clk_prepare_enable(gpu3d_shader_clk); -+ clk_prepare_enable(gpu2d_clk); -+ clk_prepare_enable(gpu2d_axi_clk); -+ clk_prepare_enable(openvg_axi_clk); -+ } -+ } else { -+ if (cpu_is_imx6sl()) { -+ clk_disable_unprepare(gpu2d_clk); -+ clk_disable_unprepare(openvg_axi_clk); -+ } else { -+ clk_disable_unprepare(openvg_axi_clk); -+ clk_disable_unprepare(gpu2d_axi_clk); -+ clk_disable_unprepare(gpu2d_clk); -+ clk_disable_unprepare(gpu3d_shader_clk); -+ clk_disable_unprepare(gpu3d_clk); -+ clk_disable_unprepare(vpu_clk); -+ } -+ } -+} -+ -+static void imx_gpc_pu_enable(bool enable) -+{ -+ u32 rate, delay_us; -+ u32 gpu_pupscr_sw2iso, gpu_pdnscr_iso2sw; -+ u32 gpu_pupscr_sw, gpu_pdnscr_iso; -+ -+ /* get ipg clk rate for PGC delay */ -+ rate = clk_get_rate(ipg_clk); -+ -+ if (enable) { -+ imx_anatop_pu_enable(true); -+ /* -+ * need to add necessary delay between powering up PU LDO and -+ * disabling PU isolation in PGC, the counter of PU isolation -+ * is based on ipg clk. -+ */ -+ gpu_pupscr_sw2iso = (readl_relaxed(gpc_base + -+ GPC_PGC_GPU_PUPSCR) >> GPC_PGC_GPU_SW2ISO_SHIFT) -+ & GPC_PGC_GPU_SW2ISO_MASK; -+ gpu_pupscr_sw = (readl_relaxed(gpc_base + -+ GPC_PGC_GPU_PUPSCR) >> GPC_PGC_GPU_SW_SHIFT) -+ & GPC_PGC_GPU_SW_MASK; -+ delay_us = (gpu_pupscr_sw2iso + gpu_pupscr_sw) * 1000000 -+ / rate + 1; -+ udelay(delay_us); -+ -+ imx_pu_clk(true); -+ writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN); -+ writel_relaxed(1 << GPC_CNTR_PU_UP_REQ_SHIFT, -+ gpc_base + GPC_CNTR); -+ while (readl_relaxed(gpc_base + GPC_CNTR) & -+ (1 << GPC_CNTR_PU_UP_REQ_SHIFT)) -+ ; -+ imx_pu_clk(false); -+ } else { -+ writel_relaxed(1, gpc_base + GPC_PGC_GPU_PDN); -+ writel_relaxed(1 << GPC_CNTR_PU_DOWN_REQ_SHIFT, -+ gpc_base + GPC_CNTR); -+ while (readl_relaxed(gpc_base + GPC_CNTR) & -+ (1 << GPC_CNTR_PU_DOWN_REQ_SHIFT)) -+ ; -+ /* -+ * need to add necessary delay between enabling PU isolation -+ * in PGC and powering down PU LDO , the counter of PU isolation -+ * is based on ipg clk. -+ */ -+ gpu_pdnscr_iso2sw = (readl_relaxed(gpc_base + -+ GPC_PGC_GPU_PDNSCR) >> GPC_PGC_GPU_SW2ISO_SHIFT) -+ & GPC_PGC_GPU_SW2ISO_MASK; -+ gpu_pdnscr_iso = (readl_relaxed(gpc_base + -+ GPC_PGC_GPU_PDNSCR) >> GPC_PGC_GPU_SW_SHIFT) -+ & GPC_PGC_GPU_SW_MASK; -+ delay_us = (gpu_pdnscr_iso2sw + gpu_pdnscr_iso) * 1000000 -+ / rate + 1; -+ udelay(delay_us); -+ imx_anatop_pu_enable(false); -+ } -+} -+ -+static int imx_gpc_regulator_notify(struct notifier_block *nb, -+ unsigned long event, -+ void *ignored) -+{ -+ switch (event) { -+ case REGULATOR_EVENT_PRE_DISABLE: -+ imx_gpc_pu_enable(false); -+ break; -+ case REGULATOR_EVENT_ENABLE: -+ imx_gpc_pu_enable(true); -+ break; -+ default: -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ - void __init imx_gpc_init(void) - { - struct device_node *np; - int i; -+ u32 val; -+ u32 cpu_pupscr_sw2iso, cpu_pupscr_sw; -+ u32 cpu_pdnscr_iso2sw, cpu_pdnscr_iso; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); - gpc_base = of_iomap(np, 0); -@@ -137,4 +285,190 @@ - gic_arch_extn.irq_mask = imx_gpc_irq_mask; - gic_arch_extn.irq_unmask = imx_gpc_irq_unmask; - gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake; -+ -+ /* -+ * If there are CPU isolation timing settings in dts, -+ * update them according to dts, otherwise, keep them -+ * with default value in registers. -+ */ -+ cpu_pupscr_sw2iso = cpu_pupscr_sw = -+ cpu_pdnscr_iso2sw = cpu_pdnscr_iso = 0; -+ -+ /* Read CPU isolation setting for GPC */ -+ of_property_read_u32(np, "fsl,cpu_pupscr_sw2iso", &cpu_pupscr_sw2iso); -+ of_property_read_u32(np, "fsl,cpu_pupscr_sw", &cpu_pupscr_sw); -+ of_property_read_u32(np, "fsl,cpu_pdnscr_iso2sw", &cpu_pdnscr_iso2sw); -+ of_property_read_u32(np, "fsl,cpu_pdnscr_iso", &cpu_pdnscr_iso); -+ -+ /* Update CPU PUPSCR timing if it is defined in dts */ -+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_PUPSCR); -+ if (cpu_pupscr_sw2iso) -+ val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT); -+ if (cpu_pupscr_sw) -+ val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT); -+ val |= cpu_pupscr_sw2iso << GPC_PGC_CPU_SW2ISO_SHIFT; -+ val |= cpu_pupscr_sw << GPC_PGC_CPU_SW_SHIFT; -+ writel_relaxed(val, gpc_base + GPC_PGC_CPU_PUPSCR); -+ -+ /* Update CPU PDNSCR timing if it is defined in dts */ -+ val = readl_relaxed(gpc_base + GPC_PGC_CPU_PDNSCR); -+ if (cpu_pdnscr_iso2sw) -+ val &= ~(GPC_PGC_CPU_SW2ISO_MASK << GPC_PGC_CPU_SW2ISO_SHIFT); -+ if (cpu_pdnscr_iso) -+ val &= ~(GPC_PGC_CPU_SW_MASK << GPC_PGC_CPU_SW_SHIFT); -+ val |= cpu_pdnscr_iso2sw << GPC_PGC_CPU_SW2ISO_SHIFT; -+ val |= cpu_pdnscr_iso << GPC_PGC_CPU_SW_SHIFT; -+ writel_relaxed(val, gpc_base + GPC_PGC_CPU_PDNSCR); -+} -+ -+static int imx_pureg_set_voltage(struct regulator_dev *reg, int min_uV, -+ int max_uV, unsigned *selector) -+{ -+ return 0; -+} -+ -+static int imx_pureg_enable(struct regulator_dev *rdev) -+{ -+ pu_dummy_enable = 1; -+ -+ return 0; -+} -+ -+static int imx_pureg_disable(struct regulator_dev *rdev) -+{ -+ pu_dummy_enable = 0; -+ -+ return 0; - } -+ -+static int imx_pureg_is_enable(struct regulator_dev *rdev) -+{ -+ return pu_dummy_enable; -+} -+ -+static int imx_pureg_list_voltage(struct regulator_dev *rdev, -+ unsigned int selector) -+{ -+ return 0; -+} -+ -+static struct regulator_ops pu_dummy_ops = { -+ .set_voltage = imx_pureg_set_voltage, -+ .enable = imx_pureg_enable, -+ .disable = imx_pureg_disable, -+ .is_enabled = imx_pureg_is_enable, -+ .list_voltage = imx_pureg_list_voltage, -+}; -+ -+static struct regulator_desc pu_dummy_desc = { -+ .name = "pureg-dummy", -+ .id = -1, -+ .type = REGULATOR_VOLTAGE, -+ .owner = THIS_MODULE, -+ .ops = &pu_dummy_ops, -+}; -+ -+static int pu_dummy_probe(struct platform_device *pdev) -+{ -+ struct regulator_config config = { }; -+ int ret; -+ -+ config.dev = &pdev->dev; -+ config.init_data = &pu_dummy_initdata; -+ config.of_node = pdev->dev.of_node; -+ -+ pu_dummy_regulator_rdev = regulator_register(&pu_dummy_desc, &config); -+ if (IS_ERR(pu_dummy_regulator_rdev)) { -+ ret = PTR_ERR(pu_dummy_regulator_rdev); -+ dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id imx_pudummy_ids[] = { -+ { .compatible = "fsl,imx6-dummy-pureg" }, -+}; -+MODULE_DEVICE_TABLE(of, imx_pudummy_ids); -+ -+static struct platform_driver pu_dummy_driver = { -+ .probe = pu_dummy_probe, -+ .driver = { -+ .name = "pu-dummy", -+ .owner = THIS_MODULE, -+ .of_match_table = imx_pudummy_ids, -+ }, -+}; -+ -+static int imx_gpc_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ gpc_dev = &pdev->dev; -+ -+ pu_reg = devm_regulator_get(gpc_dev, "pu"); -+ if (IS_ERR(pu_reg)) { -+ ret = PTR_ERR(pu_reg); -+ dev_info(gpc_dev, "pu regulator not ready.\n"); -+ return ret; -+ } -+ nb.notifier_call = &imx_gpc_regulator_notify; -+ -+ /* Get gpu&vpu clk for power up PU by GPC */ -+ if (cpu_is_imx6sl()) { -+ gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_podf"); -+ openvg_axi_clk = devm_clk_get(gpc_dev, "gpu2d_ovg"); -+ ipg_clk = devm_clk_get(gpc_dev, "ipg"); -+ if (IS_ERR(gpu2d_clk) || IS_ERR(openvg_axi_clk) -+ || IS_ERR(ipg_clk)) { -+ dev_err(gpc_dev, "failed to get clk!\n"); -+ return -ENOENT; -+ } -+ } else { -+ gpu3d_clk = devm_clk_get(gpc_dev, "gpu3d_core"); -+ gpu3d_shader_clk = devm_clk_get(gpc_dev, "gpu3d_shader"); -+ gpu2d_clk = devm_clk_get(gpc_dev, "gpu2d_core"); -+ gpu2d_axi_clk = devm_clk_get(gpc_dev, "gpu2d_axi"); -+ openvg_axi_clk = devm_clk_get(gpc_dev, "openvg_axi"); -+ vpu_clk = devm_clk_get(gpc_dev, "vpu_axi"); -+ ipg_clk = devm_clk_get(gpc_dev, "ipg"); -+ if (IS_ERR(gpu3d_clk) || IS_ERR(gpu3d_shader_clk) -+ || IS_ERR(gpu2d_clk) || IS_ERR(gpu2d_axi_clk) -+ || IS_ERR(openvg_axi_clk) || IS_ERR(vpu_clk) -+ || IS_ERR(ipg_clk)) { -+ dev_err(gpc_dev, "failed to get clk!\n"); -+ return -ENOENT; -+ } -+ } -+ -+ ret = regulator_register_notifier(pu_reg, &nb); -+ if (ret) { -+ dev_err(gpc_dev, -+ "regulator notifier request failed\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id imx_gpc_ids[] = { -+ { .compatible = "fsl,imx6q-gpc" }, -+}; -+MODULE_DEVICE_TABLE(of, imx_gpc_ids); -+ -+static struct platform_driver imx_gpc_platdrv = { -+ .driver = { -+ .name = "imx-gpc", -+ .owner = THIS_MODULE, -+ .of_match_table = imx_gpc_ids, -+ }, -+ .probe = imx_gpc_probe, -+}; -+module_platform_driver(imx_gpc_platdrv); -+ -+module_platform_driver(pu_dummy_driver); -+ -+MODULE_AUTHOR("Anson Huang "); -+MODULE_DESCRIPTION("Freescale i.MX GPC driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/hardware.h linux-3.14.22/arch/arm/mach-imx/hardware.h ---- linux-3.14.22.orig/arch/arm/mach-imx/hardware.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/hardware.h 2014-10-22 14:55:49.910220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. -+ * Copyright 2004-2007, 2014 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Juergen Beisert, kernel@pengutronix.de - * - * This program is free software; you can redistribute it and/or -@@ -20,7 +20,9 @@ - #ifndef __ASM_ARCH_MXC_HARDWARE_H__ - #define __ASM_ARCH_MXC_HARDWARE_H__ - -+#ifndef __ASSEMBLY__ - #include -+#endif - #include - - #define addr_in_module(addr, mod) \ -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/headsmp.S linux-3.14.22/arch/arm/mach-imx/headsmp.S ---- linux-3.14.22.orig/arch/arm/mach-imx/headsmp.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/headsmp.S 2014-10-22 14:55:49.910220001 -0500 -@@ -12,8 +12,6 @@ - - #include - #include --#include --#include - - .section ".text.head", "ax" - -@@ -35,37 +33,3 @@ - b secondary_startup - ENDPROC(v7_secondary_startup) - #endif -- --#ifdef CONFIG_ARM_CPU_SUSPEND --/* -- * The following code must assume it is running from physical address -- * where absolute virtual addresses to the data section have to be -- * turned into relative ones. -- */ -- --#ifdef CONFIG_CACHE_L2X0 -- .macro pl310_resume -- adr r0, l2x0_saved_regs_offset -- ldr r2, [r0] -- add r2, r2, r0 -- ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0 -- ldr r1, [r2, #L2X0_R_AUX_CTRL] @ get aux_ctrl value -- str r1, [r0, #L2X0_AUX_CTRL] @ restore aux_ctrl -- mov r1, #0x1 -- str r1, [r0, #L2X0_CTRL] @ re-enable L2 -- .endm -- --l2x0_saved_regs_offset: -- .word l2x0_saved_regs - . -- --#else -- .macro pl310_resume -- .endm --#endif -- --ENTRY(v7_cpu_resume) -- bl v7_invalidate_l1 -- pl310_resume -- b cpu_resume --ENDPROC(v7_cpu_resume) --#endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/imx6sl_wfi.S linux-3.14.22/arch/arm/mach-imx/imx6sl_wfi.S ---- linux-3.14.22.orig/arch/arm/mach-imx/imx6sl_wfi.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/imx6sl_wfi.S 2014-10-22 14:55:49.910220001 -0500 -@@ -0,0 +1,639 @@ -+/* -+ * Copyright (C) 2012-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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+#define IRAM_WAIT_SIZE (1 << 11) -+ -+ .macro sl_ddr_io_save -+ -+ ldr r4, [r1, #0x30c] /* DRAM_DQM0 */ -+ ldr r5, [r1, #0x310] /* DRAM_DQM1 */ -+ ldr r6, [r1, #0x314] /* DRAM_DQM2 */ -+ ldr r7, [r1, #0x318] /* DRAM_DQM3 */ -+ stmfd r9!, {r4-r7} -+ -+ ldr r4, [r1, #0x5c4] /* GPR_B0DS */ -+ ldr r5, [r1, #0x5cc] /* GPR_B1DS */ -+ ldr r6, [r1, #0x5d4] /* GPR_B2DS */ -+ ldr r7, [r1, #0x5d8] /* GPR_B3DS */ -+ stmfd r9!, {r4-r7} -+ -+ ldr r4, [r1, #0x300] /* DRAM_CAS */ -+ ldr r5, [r1, #0x31c] /* DRAM_RAS */ -+ ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */ -+ ldr r7, [r1, #0x5ac] /* GPR_ADDS*/ -+ stmfd r9!, {r4-r7} -+ -+ ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */ -+ ldr r5, [r1, #0x5c0] /* DDRMODE */ -+ ldr r6, [r1, #0x33c] /* DRAM_SODT0*/ -+ ldr r7, [r1, #0x340] /* DRAM_SODT1*/ -+ stmfd r9!, {r4-r7} -+ -+ ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */ -+ ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */ -+ ldr r6, [r1, #0x320] /* DRAM_RESET */ -+ stmfd r9!, {r4-r6} -+ -+ .endm -+ -+ .macro sl_ddr_io_restore -+ -+ /* -+ * r9 points to IRAM stack. -+ * r1 points to IOMUX base address. -+ * r8 points to MMDC base address. -+ */ -+ ldmea r9!, {r4-r7} -+ str r4, [r1, #0x30c] /* DRAM_DQM0 */ -+ str r5, [r1, #0x310] /* DRAM_DQM1 */ -+ str r6, [r1, #0x314] /* DRAM_DQM2 */ -+ str r7, [r1, #0x318] /* DRAM_DQM3 */ -+ -+ ldmea r9!, {r4-r7} -+ str r4, [r1, #0x5c4] /* GPR_B0DS */ -+ str r5, [r1, #0x5cc] /* GPR_B1DS */ -+ str r6, [r1, #0x5d4] /* GPR_B2DS */ -+ str r7, [r1, #0x5d8] /* GPR_B3DS */ -+ -+ ldmea r9!, {r4-r7} -+ str r4, [r1, #0x300] /* DRAM_CAS */ -+ str r5, [r1, #0x31c] /* DRAM_RAS */ -+ str r6, [r1, #0x338] /* DRAM_SDCLK_0 */ -+ str r7, [r1, #0x5ac] /* GPR_ADDS*/ -+ -+ ldmea r9!, {r4-r7} -+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */ -+ str r5, [r1, #0x5c0] /* DDRMODE */ -+ str r6, [r1, #0x33c] /* DRAM_SODT0*/ -+ str r7, [r1, #0x340] /* DRAM_SODT1*/ -+ -+ ldmea r9!, {r4-r6} -+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */ -+ str r5, [r1, #0x334] /* DRAM_SDCKE1 */ -+ str r6, [r1, #0x320] /* DRAM_RESET */ -+ -+ /* -+ * Need to reset the FIFO to avoid MMDC lockup -+ * caused because of floating/changing the -+ * configuration of many DDR IO pads. -+ */ -+ ldr r7, =0x83c -+ ldr r6, [r8, r7] -+ orr r6, r6, #0x80000000 -+ str r6, [r8, r7] -+fifo_reset1_wait: -+ ldr r6, [r8, r7] -+ and r6, r6, #0x80000000 -+ cmp r6, #0 -+ bne fifo_reset1_wait -+ -+ /* reset FIFO a second time */ -+ ldr r6, [r8, r7] -+ orr r6, r6, #0x80000000 -+ str r6, [r8, r7] -+fifo_reset2_wait: -+ ldr r6, [r8, r7] -+ and r6, r6, #0x80000000 -+ cmp r6, #0 -+ bne fifo_reset2_wait -+ -+ .endm -+ -+ .macro sl_ddr_io_set_lpm -+ -+ mov r4, #0 -+ str r4, [r1, #0x30c] /* DRAM_DQM0 */ -+ str r4, [r1, #0x310] /* DRAM_DQM1 */ -+ str r4, [r1, #0x314] /* DRAM_DQM2 */ -+ str r4, [r1, #0x318] /* DRAM_DQM3 */ -+ -+ str r4, [r1, #0x5c4] /* GPR_B0DS */ -+ str r4, [r1, #0x5cc] /* GPR_B1DS */ -+ str r4, [r1, #0x5d4] /* GPR_B2DS */ -+ str r4, [r1, #0x5d8] /* GPR_B3DS */ -+ -+ str r4, [r1, #0x300] /* DRAM_CAS */ -+ str r4, [r1, #0x31c] /* DRAM_RAS */ -+ str r4, [r1, #0x338] /* DRAM_SDCLK_0 */ -+ str r4, [r1, #0x5ac] /* GPR_ADDS*/ -+ -+ str r4, [r1, #0x5b0] /* DDRMODE_CTL */ -+ str r4, [r1, #0x5c0] /* DDRMODE */ -+ str r4, [r1, #0x33c] /* DRAM_SODT0*/ -+ str r4, [r1, #0x340] /* DRAM_SODT1*/ -+ -+ mov r4, #0x80000 -+ str r4, [r1, #0x320] /* DRAM_RESET */ -+ mov r4, #0x1000 -+ str r4, [r1, #0x330] /* DRAM_SDCKE0 */ -+ str r4, [r1, #0x334] /* DRAM_SDCKE1 */ -+ -+ .endm -+ -+/* -+ * imx6sl_low_power_wfi -+ * -+ * Idle the processor (eg, wait for interrupt). -+ * Make sure DDR is in self-refresh. -+ * IRQs are already disabled. -+ * r0: WFI IRAMcode base address. -+ * r1: IOMUX base address -+ * r2: Base address of CCM, ANATOP and MMDC -+ * r3: 1 if in audio_bus_freq_mode -+ */ -+ .align 3 -+ENTRY(imx6sl_low_power_wfi) -+ -+ push {r4-r11} -+ -+mx6sl_lpm_wfi: -+ /* Store audio_bus_freq_mode */ -+ mov r11, r3 -+ -+ mov r4,r2 -+ /* Get the IRAM data storage address. */ -+ mov r10, r0 -+ mov r9, r0 /* get suspend_iram_base */ -+ add r9, r9, #IRAM_WAIT_SIZE -+ -+ /* Anatop Base address in r3. */ -+ ldr r3, [r4] -+ /* CCM Base Address in r2 */ -+ ldr r2, [r4, #0x4] -+ /* MMDC Base Address in r8 */ -+ ldr r8, [r4, #0x8] -+ /* L2 Base Address in r7 */ -+ ldr r7, [r4, #0xC] -+ -+ ldr r6, [r8] -+ ldr r6, [r3] -+ ldr r6, [r2] -+ ldr r6, [r1] -+ -+ /* Store the original ARM PODF. */ -+ ldr r0, [r2, #0x10] -+ -+ /* Drain all the L1 buffers. */ -+ dsb -+ -+#ifdef CONFIG_CACHE_L2X0 -+ /* -+ * Need to make sure the buffers in L2 are drained. -+ * Performing a sync operation does this. -+ */ -+ mov r6, #0x0 -+ str r6, [r7, #0x730] -+#endif -+ -+ /* -+ * The second dsb might be needed to keep cache sync (device write) -+ * ordering with the memory accesses before it. -+ */ -+ dsb -+ isb -+ -+ /* Save the DDR IO state. */ -+ sl_ddr_io_save -+ -+ /* Disable Automatic power savings. */ -+ ldr r6, [r8, #0x404] -+ orr r6, r6, #0x01 -+ str r6, [r8, #0x404] -+ -+ /* Make the DDR explicitly enter self-refresh. */ -+ ldr r6, [r8, #0x404] -+ orr r6, r6, #0x200000 -+ str r6, [r8, #0x404] -+ -+poll_dvfs_set_1: -+ ldr r6, [r8, #0x404] -+ and r6, r6, #0x2000000 -+ cmp r6, #0x2000000 -+ bne poll_dvfs_set_1 -+ -+ /* set SBS step-by-step mode */ -+ ldr r6, [r8, #0x410] -+ orr r6, r6, #0x100 -+ str r6, [r8, #0x410] -+ -+ cmp r11, #1 -+ beq audio_mode -+ /* -+ * Now set DDR rate to 1MHz. -+ * DDR is from bypassed PLL2 on periph2_clk2 path. -+ * Set the periph2_clk2_podf to divide by 8. -+ */ -+ ldr r6, [r2, #0x14] -+ orr r6, r6, #0x07 -+ str r6, [r2, #0x14] -+ -+ /* Now set MMDC PODF to divide by 3. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x38 -+ orr r6, r6, #0x10 -+ str r6, [r2, #0x14] -+ b mmdc_podf -+ -+audio_mode: -+ /* MMDC is from PLL2_200M. -+ * Set the mmdc_podf to div by 8. -+ */ -+ ldr r6, [r2, #0x14] -+ orr r6, r6, #0x38 -+ str r6, [r2, #0x14] -+ -+ /* Loop till podf is accepted. */ -+mmdc_podf: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne mmdc_podf -+ -+ /* Set the DDR IO in LPM state. */ -+ sl_ddr_io_set_lpm -+ -+ cmp r11, #1 -+ beq do_audio_arm_clk -+ -+ /* -+ * Check if none of the PLLs are -+ * locked, except PLL1 which will get -+ * bypassed below. -+ * We should not be here if PLL2 is not -+ * bypassed. -+ */ -+ ldr r7, =1 -+ /* USB1 PLL3 */ -+ ldr r6, [r3, #0x10] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ beq no_analog_saving -+ -+ /* USB2 PLL7 */ -+ ldr r6, [r3, #0x20] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ beq no_analog_saving -+ -+ /* Audio PLL4 */ -+ ldr r6, [r3, #0x70] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ beq no_analog_saving -+ -+ /* Video PLL5 */ -+ ldr r6, [r3, #0xA0] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ beq no_analog_saving -+ -+ /* ENET PLL8 */ -+ ldr r6, [r3, #0xE0] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ beq no_analog_saving -+ -+ b cont -+ -+no_analog_saving: -+ ldr r7, =0 -+ -+cont: -+ /* Set the AHB to 3MHz. AXI to 3MHz. */ -+ ldr r9, [r2, #0x14] -+ mov r6, r9 -+ orr r6, r6, #0x1c00 -+ orr r6, r6, #0x70000 -+ str r6, [r2, #0x14] -+ -+ /* Loop till podf is accepted. */ -+ahb_podf: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne podf_loop -+ -+ /* -+ * Now set ARM to 24MHz. -+ * Move ARM to be sourced from STEP_CLK -+ * after setting STEP_CLK to 24MHz. -+ */ -+ ldr r6, [r2, #0xc] -+ bic r6, r6, #0x100 -+ str r6, [r2, #0x0c] -+ /* Now PLL1_SW_CLK to step_clk. */ -+ ldr r6, [r2, #0x0c] -+ orr r6, r6, #0x4 -+ str r6, [r2, #0x0c] -+ -+ /* Bypass PLL1 and power it down. */ -+ ldr r6, =(1 << 16) -+ orr r6, r6, #0x1000 -+ str r6, [r3, #0x04] -+ -+ /* -+ * Set the ARM PODF to divide by 8. -+ * IPG is at 1.5MHz here, we need ARM to -+ * run at the 12:5 ratio (WAIT mode issue). -+ */ -+ ldr r6, =0x7 -+ str r6, [r2, #0x10] -+ -+ /* Loop till podf is accepted. */ -+podf_loop: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne podf_loop -+ -+ /* -+ * Check if we can save some -+ * power in the Analog section. -+ */ -+ cmp r7, #0x1 -+ bne do_wfi -+ -+ /* Disable 1p1 brown out. */ -+ ldr r6, [r3, #0x110] -+ bic r6, r6, #0x2 -+ str r6, [r3, #0x110] -+ -+ /* Enable the weak 2P5 */ -+ ldr r6, [r3, #0x130] -+ orr r6, r6, #0x40000 -+ str r6, [r3, #0x130] -+ -+ /* Disable main 2p5. */ -+ ldr r6, [r3, #0x130] -+ bic r6, r6, #0x1 -+ str r6, [r3, #0x130] -+ -+ /* -+ * Set the OSC bias current to -37.5% -+ * to drop the power on VDDHIGH. -+ */ -+ ldr r6, [r3, #0x150] -+ orr r6, r6, #0xC000 -+ str r6, [r3, #0x150] -+ -+ /* Enable low power bandgap */ -+ ldr r6, [r3, #0x260] -+ orr r6, r6, #0x20 -+ str r6, [r3, #0x260] -+ -+ /* -+ * Turn off the bias current -+ * from the regular bandgap. -+ */ -+ ldr r6, [r3, #0x260] -+ orr r6, r6, #0x80 -+ str r6, [r3, #0x260] -+ -+ /* -+ * Clear the REFTOP_SELFBIASOFF, -+ * self-bias circuit of the band gap. -+ * Per RM, should be cleared when -+ * band gap is powered down. -+ */ -+ ldr r6, [r3, #0x150] -+ bic r6, r6, #0x8 -+ str r6, [r3, #0x150] -+ -+ /* Power down the regular bandgap. */ -+ ldr r6, [r3, #0x150] -+ orr r6, r6, #0x1 -+ str r6, [r3, #0x150] -+ -+ b do_wfi -+ -+do_audio_arm_clk: -+ /* -+ * ARM is from PLL2_PFD2_400M here. -+ * Switch ARM to bypassed PLL1. -+ */ -+ ldr r6, [r2, #0xC] -+ bic r6, r6, #0x4 -+ str r6, [r2, #0xC] -+ -+ /* -+ * Set the ARM_PODF to divide by 2 -+ * as IPG is at 4MHz, we cannot run -+ * ARM_CLK above 9.6MHz when -+ * system enters WAIT mode. -+ */ -+ ldr r6, =0x2 -+ str r6, [r2, #0x10] -+ -+ /* Loop till podf is accepted. */ -+podf_loop_audio: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne podf_loop_audio -+ -+do_wfi: -+ /* Now do WFI. */ -+ wfi -+ -+ /* Set original ARM PODF back. */ -+ str r0, [r2, #0x10] -+ -+ /* Loop till podf is accepted. */ -+podf_loop1: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne podf_loop1 -+ -+ cmp r11, #1 -+ beq audio_arm_clk_restore -+ -+ /* -+ * Check if powered down -+ * analog components. -+ */ -+ cmp r7, #0x1 -+ bne skip_analog_restore -+ -+ /* Power up the regular bandgap. */ -+ ldr r6, [r3, #0x150] -+ bic r6, r6, #0x1 -+ str r6, [r3, #0x150] -+ -+ /* -+ * Turn on the bias current -+ * from the regular bandgap. -+ */ -+ ldr r6, [r3, #0x260] -+ bic r6, r6, #0x80 -+ str r6, [r3, #0x260] -+ -+ /* Disable the low power bandgap */ -+ ldr r6, [r3, #0x260] -+ bic r6, r6, #0x20 -+ str r6, [r3, #0x260] -+ -+ /* -+ * Set the OSC bias current to max -+ * value for normal operation. -+ */ -+ ldr r6, [r3, #0x150] -+ bic r6, r6, #0xC000 -+ str r6, [r3, #0x150] -+ -+ /* Enable main 2p5. */ -+ ldr r6, [r3, #0x130] -+ orr r6, r6, #0x1 -+ str r6, [r3, #0x130] -+ -+ /* Ensure the 2P5 is up. */ -+loop_2p5: -+ ldr r6, [r3, #0x130] -+ and r6, r6, #0x20000 -+ cmp r6, #0x20000 -+ bne loop_2p5 -+ -+ /* Disable the weak 2P5 */ -+ ldr r6, [r3, #0x130] -+ bic r6, r6, #0x40000 -+ str r6, [r3, #0x130] -+ -+ /* Enable 1p1 brown out. */ -+ ldr r6, [r3, #0x110] -+ orr r6, r6, #0x2 -+ str r6, [r3, #0x110] -+ -+skip_analog_restore: -+ -+ /* Power up PLL1 and un-bypass it. */ -+ ldr r6, =(1 << 12) -+ str r6, [r3, #0x08] -+ -+ /* Wait for PLL1 to relock. */ -+wait_for_pll_lock: -+ ldr r6, [r3, #0x0] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ bne wait_for_pll_lock -+ -+ ldr r6, =(1 << 16) -+ str r6, [r3, #0x08] -+ -+ /* Set PLL1_sw_clk back to PLL1. */ -+ ldr r6, [r2, #0x0c] -+ bic r6, r6, #0x4 -+ str r6, [r2, #0xc] -+ -+ /* Restore AHB/AXI back. */ -+ str r9, [r2, #0x14] -+ -+ /* Loop till podf is accepted. */ -+ahb_podf1: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne podf_loop1 -+ -+ b wfi_restore -+ -+ audio_arm_clk_restore: -+ /* Move ARM back to PLL2_PFD2_400M */ -+ ldr r6, [r2, #0xC] -+ orr r6, r6, #0x4 -+ str r6, [r2, #0xC] -+ -+wfi_restore: -+ /* get suspend_iram_base */ -+ mov r9, r10 -+ add r9, r9, #IRAM_WAIT_SIZE -+ -+ /* Restore the DDR IO before exiting self-refresh. */ -+ sl_ddr_io_restore -+ -+ /* -+ * Set MMDC back to 24MHz. -+ * Set periph2_clk2_podf to divide by 1 -+ * Now set MMDC PODF to divide by 1. -+ */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x3f -+ str r6, [r2, #0x14] -+ -+mmdc_podf1: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0x0 -+ bne mmdc_podf1 -+ -+ /* clear DVFS - exit from self refresh mode */ -+ ldr r6, [r8, #0x404] -+ bic r6, r6, #0x200000 -+ str r6, [r8, #0x404] -+ -+poll_dvfs_clear_1: -+ ldr r6, [r8, #0x404] -+ and r6, r6, #0x2000000 -+ cmp r6, #0x2000000 -+ beq poll_dvfs_clear_1 -+ -+ /* -+ * Add these nops so that the -+ * prefetcher will not try to get -+ * any instructions from DDR. -+ * The prefetch depth is about 23 -+ * on A9, so adding 25 nops. -+ */ -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+ nop -+ nop -+ nop -+ nop -+ nop -+ -+ /* Enable Automatic power savings. */ -+ ldr r6, [r8, #0x404] -+ bic r6, r6, #0x01 -+ str r6, [r8, #0x404] -+ -+ /* clear SBS - unblock DDR accesses */ -+ ldr r6, [r8, #0x410] -+ bic r6, r6, #0x100 -+ str r6, [r8, #0x410] -+ -+ -+ pop {r4-r11} -+ -+ /* Restore registers */ -+ mov pc, lr -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/Kconfig linux-3.14.22/arch/arm/mach-imx/Kconfig ---- linux-3.14.22.orig/arch/arm/mach-imx/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/Kconfig 2014-10-22 14:55:49.910220001 -0500 -@@ -1,5 +1,6 @@ - config ARCH_MXC - bool "Freescale i.MX family" if ARCH_MULTI_V4_V5 || ARCH_MULTI_V6_V7 -+ select ARCH_HAS_RESET_CONTROLLER - select ARCH_REQUIRE_GPIOLIB - select ARM_CPU_SUSPEND if PM - select ARM_PATCH_PHYS_VIRT -@@ -13,6 +14,7 @@ - select PINCTRL - select SOC_BUS - select SPARSE_IRQ -+ select SRAM - select USE_OF - help - Support for Freescale MXC/iMX-based family of processors -@@ -63,7 +65,6 @@ - - config HAVE_IMX_SRC - def_bool y if SMP -- select ARCH_HAS_RESET_CONTROLLER - - config IMX_HAVE_IOMUX_V1 - bool -@@ -791,6 +792,8 @@ - select ARM_ERRATA_754322 - select ARM_ERRATA_764369 if SMP - select ARM_ERRATA_775420 -+ select ARM_ERRATA_794072 if SMP -+ select ARM_ERRATA_761320 if SMP - select ARM_GIC - select CPU_V7 - select HAVE_ARM_SCU if SMP -@@ -803,11 +806,13 @@ - select MFD_SYSCON - select MIGHT_HAVE_PCI - select PCI_DOMAINS if PCI -+ select ARCH_SUPPORTS_MSI - select PINCTRL_IMX6Q - select PL310_ERRATA_588369 if CACHE_PL310 - select PL310_ERRATA_727915 if CACHE_PL310 - select PL310_ERRATA_769419 if CACHE_PL310 - select PM_OPP if PM -+ select ZONE_DMA - - help - This enables support for Freescale i.MX6 Quad processor. -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/lpddr2_freq_imx6.S linux-3.14.22/arch/arm/mach-imx/lpddr2_freq_imx6.S ---- linux-3.14.22.orig/arch/arm/mach-imx/lpddr2_freq_imx6.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/lpddr2_freq_imx6.S 2014-10-22 14:55:49.910220001 -0500 -@@ -0,0 +1,484 @@ -+/* -+ * Copyright (C) 2012-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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+ -+ .macro mx6sl_switch_to_24MHz -+ -+ /* -+ * Set MMDC clock to be sourced from PLL3. -+ * Ensure first periph2_clk2 is sourced from PLL3. -+ * Set the PERIPH2_CLK2_PODF to divide by 2. -+ */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x7 -+ orr r6, r6, #0x1 -+ str r6, [r2, #0x14] -+ -+ /* Select PLL3 to source MMDC. */ -+ ldr r6, [r2, #0x18] -+ bic r6, r6, #0x100000 -+ str r6, [r2, #0x18] -+ -+ /* Swtich periph2_clk_sel to run from PLL3. */ -+ ldr r6, [r2, #0x14] -+ orr r6, r6, #0x4000000 -+ str r6, [r2, #0x14] -+ -+periph2_clk_switch1: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne periph2_clk_switch1 -+ -+ /* -+ * Need to clock gate the 528 PFDs before -+ * powering down PLL2. -+ * Only the PLL2_PFD2_400M should be ON -+ * at this time, so only clock gate that one. -+ */ -+ ldr r6, [r3, #0x100] -+ orr r6, r6, #0x800000 -+ str r6, [r3, #0x100] -+ -+ /* -+ * Set PLL2 to bypass state. We should be here -+ * only if MMDC is not sourced from PLL2. -+ */ -+ ldr r6, [r3, #0x30] -+ orr r6, r6, #0x10000 -+ str r6, [r3, #0x30] -+ -+ ldr r6, [r3, #0x30] -+ orr r6, r6, #0x1000 -+ str r6, [r3, #0x30] -+ -+ /* Ensure pre_periph2_clk_mux is set to pll2 */ -+ ldr r6, [r2, #0x18] -+ bic r6, r6, #0x600000 -+ str r6, [r2, #0x18] -+ -+ /* Set MMDC clock to be sourced from the bypassed PLL2. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x4000000 -+ str r6, [r2, #0x14] -+ -+periph2_clk_switch2: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne periph2_clk_switch2 -+ -+ /* -+ * Now move MMDC back to periph2_clk2 source. -+ * after selecting PLL2 as the option. -+ * Select PLL2 as the source. -+ */ -+ ldr r6, [r2, #0x18] -+ orr r6, r6, #0x100000 -+ str r6, [r2, #0x18] -+ -+ /* set periph2_clk2_podf to divide by 1. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x7 -+ str r6, [r2, #0x14] -+ -+ /* Now move periph2_clk to periph2_clk2 source */ -+ ldr r6, [r2, #0x14] -+ orr r6, r6, #0x4000000 -+ str r6, [r2, #0x14] -+ -+periph2_clk_switch3: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne periph2_clk_switch3 -+ -+ /* Now set the MMDC PODF back to 1.*/ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x38 -+ str r6, [r2, #0x14] -+ -+mmdc_podf0: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne mmdc_podf0 -+ -+ .endm -+ -+ .macro ddr_switch_400MHz -+ -+ /* Set MMDC divider first, in case PLL3 is at 480MHz. */ -+ ldr r6, [r3, #0x10] -+ and r6, r6, #0x10000 -+ cmp r6, #0x10000 -+ beq pll3_in_bypass -+ -+ /* Set MMDC divder to divide by 2. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x38 -+ orr r6, r6, #0x8 -+ str r6, [r2, #0x14] -+ -+mmdc_podf: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne mmdc_podf -+ -+pll3_in_bypass: -+ /* -+ * Check if we are switching between -+ * 400Mhz <-> 100MHz.If so, we should -+ * try to source MMDC from PLL2_200M. -+ */ -+ cmp r1, #0 -+ beq not_low_bus_freq -+ -+ /* Ensure that MMDC is sourced from PLL2 mux first. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x4000000 -+ str r6, [r2, #0x14] -+ -+periph2_clk_switch4: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne periph2_clk_switch4 -+ -+not_low_bus_freq: -+ /* Now ensure periph2_clk2_sel mux is set to PLL3 */ -+ ldr r6, [r2, #0x18] -+ bic r6, r6, #0x100000 -+ str r6, [r2, #0x18] -+ -+ /* Now switch MMDC to PLL3. */ -+ ldr r6, [r2, #0x14] -+ orr r6, r6, #0x4000000 -+ str r6, [r2, #0x14] -+ -+periph2_clk_switch5: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne periph2_clk_switch5 -+ -+ /* -+ * Check if PLL2 is already unlocked. -+ * If so do nothing with PLL2. -+ */ -+ cmp r1, #0 -+ beq pll2_already_on -+ -+ /* Now power up PLL2 and unbypass it. */ -+ ldr r6, [r3, #0x30] -+ bic r6, r6, #0x1000 -+ str r6, [r3, #0x30] -+ -+ /* Make sure PLL2 has locked.*/ -+wait_for_pll_lock: -+ ldr r6, [r3, #0x30] -+ and r6, r6, #0x80000000 -+ cmp r6, #0x80000000 -+ bne wait_for_pll_lock -+ -+ ldr r6, [r3, #0x30] -+ bic r6, r6, #0x10000 -+ str r6, [r3, #0x30] -+ -+ /* -+ * Need to enable the 528 PFDs after -+ * powering up PLL2. -+ * Only the PLL2_PFD2_400M should be ON -+ * as it feeds the MMDC. Rest should have -+ * been managed by clock code. -+ */ -+ ldr r6, [r3, #0x100] -+ bic r6, r6, #0x800000 -+ str r6, [r3, #0x100] -+ -+pll2_already_on: -+ /* -+ * Now switch MMDC clk back to pll2_mux option. -+ * Ensure pre_periph2_clk2 is set to pll2_pfd_400M. -+ * If switching to audio DDR freq, set the -+ * pre_periph2_clk2 to PLL2_PFD_200M -+ */ -+ ldr r6, =400000000 -+ cmp r6, r0 -+ bne use_pll2_pfd_200M -+ -+ ldr r6, [r2, #0x18] -+ bic r6, r6, #0x600000 -+ orr r6, r6, #0x200000 -+ str r6, [r2, #0x18] -+ ldr r6, =400000000 -+ b cont2 -+ -+use_pll2_pfd_200M: -+ ldr r6, [r2, #0x18] -+ orr r6, r6, #0x600000 -+ str r6, [r2, #0x18] -+ ldr r6, =200000000 -+ -+cont2: -+ ldr r4, [r2, #0x14] -+ bic r4, r4, #0x4000000 -+ str r4, [r2, #0x14] -+ -+periph2_clk_switch6: -+ ldr r4, [r2, #0x48] -+ cmp r4, #0 -+ bne periph2_clk_switch6 -+ -+change_divider_only: -+ /* -+ * Calculate the MMDC divider -+ * based on the requested freq. -+ */ -+ ldr r4, =0 -+Loop2: -+ sub r6, r6, r0 -+ cmp r6, r0 -+ blt Div_Found -+ add r4, r4, #1 -+ bgt Loop2 -+ -+ /* Shift divider into correct offset. */ -+ lsl r4, r4, #3 -+Div_Found: -+ /* Set the MMDC PODF. */ -+ ldr r6, [r2, #0x14] -+ bic r6, r6, #0x38 -+ orr r6, r6, r4 -+ str r6, [r2, #0x14] -+ -+mmdc_podf1: -+ ldr r6, [r2, #0x48] -+ cmp r6, #0 -+ bne mmdc_podf1 -+ -+ .endm -+ -+ .macro mmdc_clk_lower_100MHz -+ -+ /* -+ * Prior to reducing the DDR frequency (at 528/400 MHz), -+ * read the Measure unit count bits (MU_UNIT_DEL_NUM) -+ */ -+ ldr r5, =0x8B8 -+ ldr r6, [r8, r5] -+ /* Original MU unit count */ -+ mov r6, r6, LSR #16 -+ ldr r4, =0x3FF -+ and r6, r6, r4 -+ /* Original MU unit count * 2 */ -+ mov r7, r6, LSL #1 -+ /* -+ * Bypass the automatic measure unit when below 100 MHz -+ * by setting the Measure unit bypass enable bit (MU_BYP_EN) -+ */ -+ ldr r6, [r8, r5] -+ orr r6, r6, #0x400 -+ str r6, [r8, r5] -+ /* -+ * Double the measure count value read in step 1 and program it in the -+ * measurement bypass bits (MU_BYP_VAL) of the MMDC PHY Measure Unit -+ * Register for the reduced frequency operation below 100 MHz -+ */ -+ ldr r6, [r8, r5] -+ ldr r4, =0x3FF -+ bic r6, r6, r4 -+ orr r6, r6, r7 -+ str r6, [r8, r5] -+ /* Now perform a Force Measurement. */ -+ ldr r6, [r8, r5] -+ orr r6, r6, #0x800 -+ str r6, [r8, r5] -+ /* Wait for FRC_MSR to clear. */ -+force_measure: -+ ldr r6, [r8, r5] -+ and r6, r6, #0x800 -+ cmp r6, #0x0 -+ bne force_measure -+ -+ .endm -+ -+ .macro mmdc_clk_above_100MHz -+ -+ /* Make sure that the PHY measurement unit is NOT in bypass mode */ -+ ldr r5, =0x8B8 -+ ldr r6, [r8, r5] -+ bic r6, r6, #0x400 -+ str r6, [r8, r5] -+ /* Now perform a Force Measurement. */ -+ ldr r6, [r8, r5] -+ orr r6, r6, #0x800 -+ str r6, [r8, r5] -+ /* Wait for FRC_MSR to clear. */ -+force_measure1: -+ ldr r6, [r8, r5] -+ and r6, r6, #0x800 -+ cmp r6, #0x0 -+ bne force_measure1 -+ .endm -+ -+/* -+ * mx6_lpddr2_freq_change -+ * -+ * Make sure DDR is in self-refresh. -+ * IRQs are already disabled. -+ * r0 : DDR freq. -+ * r1: low_bus_freq_mode flag -+ * r2: Pointer to array containing addresses of registers. -+ */ -+ .align 3 -+ENTRY(mx6_lpddr2_freq_change) -+ -+ push {r4-r10} -+ -+ mov r4, r2 -+ ldr r3, [r4] @ANATOP_BASE_ADDR -+ ldr r2, [r4, #0x4] @CCM_BASE_ADDR -+ ldr r8, [r4, #0x8] @MMDC_P0_BASE_ADDR -+ ldr r7, [r4, #0xC] @L2_BASE_ADDR -+ -+lpddr2_freq_change: -+ adr r9, lpddr2_freq_change -+ -+ /* Prime all TLB entries. */ -+ ldr r6, [r9] -+ ldr r6, [r8] -+ ldr r6, [r3] -+ ldr r6, [r2] -+ -+ /* Drain all the L1 buffers. */ -+ dsb -+ -+#ifdef CONFIG_CACHE_L2X0 -+ /* -+ * Need to make sure the buffers in L2 are drained. -+ * Performing a sync operation does this. -+ */ -+ mov r6, #0x0 -+ str r6, [r7, #0x730] -+#endif -+ -+ /* -+ * The second dsb might be needed to keep cache sync (device write) -+ * ordering with the memory accesses before it. -+ */ -+ dsb -+ isb -+ -+ /* Disable Automatic power savings. */ -+ ldr r6, [r8, #0x404] -+ orr r6, r6, #0x01 -+ str r6, [r8, #0x404] -+ -+ /* MMDC0_MDPDC disable power down timer */ -+ ldr r6, [r8, #0x4] -+ bic r6, r6, #0xff00 -+ str r6, [r8, #0x4] -+ -+ /* Delay for a while */ -+ ldr r10, =10 -+delay1: -+ ldr r7, =0 -+cont1: -+ ldr r6, [r8, r7] -+ add r7, r7, #4 -+ cmp r7, #16 -+ bne cont1 -+ sub r10, r10, #1 -+ cmp r10, #0 -+ bgt delay1 -+ -+ /* Make the DDR explicitly enter self-refresh. */ -+ ldr r6, [r8, #0x404] -+ orr r6, r6, #0x200000 -+ str r6, [r8, #0x404] -+ -+poll_dvfs_set_1: -+ ldr r6, [r8, #0x404] -+ and r6, r6, #0x2000000 -+ cmp r6, #0x2000000 -+ bne poll_dvfs_set_1 -+ -+ /* set SBS step-by-step mode */ -+ ldr r6, [r8, #0x410] -+ orr r6, r6, #0x100 -+ str r6, [r8, #0x410] -+ -+ ldr r10, =100000000 -+ cmp r0, r10 -+ bgt set_ddr_mu_above_100 -+ mmdc_clk_lower_100MHz -+ -+set_ddr_mu_above_100: -+ ldr r10, =24000000 -+ cmp r0, r10 -+ beq set_to_24MHz -+ -+ ddr_switch_400MHz -+ -+ ldr r10,=100000000 -+ cmp r0, r10 -+ blt done -+ mmdc_clk_above_100MHz -+ -+ b done -+ -+set_to_24MHz: -+ mx6sl_switch_to_24MHz -+ -+done: -+ /* clear DVFS - exit from self refresh mode */ -+ ldr r6, [r8, #0x404] -+ bic r6, r6, #0x200000 -+ str r6, [r8, #0x404] -+ -+poll_dvfs_clear_1: -+ ldr r6, [r8, #0x404] -+ and r6, r6, #0x2000000 -+ cmp r6, #0x2000000 -+ beq poll_dvfs_clear_1 -+ -+ /* Enable Automatic power savings. */ -+ ldr r6, [r8, #0x404] -+ bic r6, r6, #0x01 -+ str r6, [r8, #0x404] -+ -+ ldr r10, =24000000 -+ cmp r0, r10 -+ beq skip_power_down -+ -+ /* Enable MMDC power down timer. */ -+ ldr r6, [r8, #0x4] -+ orr r6, r6, #0x5500 -+ str r6, [r8, #0x4] -+ -+skip_power_down: -+ /* clear SBS - unblock DDR accesses */ -+ ldr r6, [r8, #0x410] -+ bic r6, r6, #0x100 -+ str r6, [r8, #0x410] -+ -+ pop {r4-r10} -+ -+ /* Restore registers */ -+ mov pc, lr -+ -+ .type mx6_lpddr2_do_iram, #object -+ENTRY(mx6_lpddr2_do_iram) -+ .word mx6_lpddr2_freq_change -+ .size mx6_lpddr2_freq_change, . - mx6_lpddr2_freq_change -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/mach-imx6q.c linux-3.14.22/arch/arm/mach-imx/mach-imx6q.c ---- linux-3.14.22.orig/arch/arm/mach-imx/mach-imx6q.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/mach-imx6q.c 2014-10-22 14:55:49.910220001 -0500 -@@ -1,5 +1,5 @@ - /* -- * Copyright 2011-2013 Freescale Semiconductor, Inc. -+ * Copyright 2011-2014 Freescale Semiconductor, Inc. - * Copyright 2011 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -22,15 +23,18 @@ - #include - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - #include - #include - #include -+#include - #include - #include - #include -@@ -194,6 +198,101 @@ - - } - -+static void __init imx6q_csi_mux_init(void) -+{ -+ /* -+ * MX6Q SabreSD board: -+ * IPU1 CSI0 connects to parallel interface. -+ * Set GPR1 bit 19 to 0x1. -+ * -+ * MX6DL SabreSD board: -+ * IPU1 CSI0 connects to parallel interface. -+ * Set GPR13 bit 0-2 to 0x4. -+ * IPU1 CSI1 connects to MIPI CSI2 virtual channel 1. -+ * Set GPR13 bit 3-5 to 0x1. -+ */ -+ struct regmap *gpr; -+ -+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); -+ if (!IS_ERR(gpr)) { -+ if (of_machine_is_compatible("fsl,imx6q-sabresd") || -+ of_machine_is_compatible("fsl,imx6q-sabreauto")) -+ regmap_update_bits(gpr, IOMUXC_GPR1, 1 << 19, 1 << 19); -+ else if (of_machine_is_compatible("fsl,imx6dl-sabresd") || -+ of_machine_is_compatible("fsl,imx6dl-sabreauto")) -+ regmap_update_bits(gpr, IOMUXC_GPR13, 0x3F, 0x0C); -+ } else { -+ pr_err("%s(): failed to find fsl,imx6q-iomux-gpr regmap\n", -+ __func__); -+ } -+} -+ -+#define OCOTP_MACn(n) (0x00000620 + (n) * 0x10) -+void __init imx6_enet_mac_init(const char *compatible) -+{ -+ struct device_node *ocotp_np, *enet_np; -+ void __iomem *base; -+ struct property *newmac; -+ u32 macaddr_low, macaddr_high; -+ u8 *macaddr; -+ -+ enet_np = of_find_compatible_node(NULL, NULL, compatible); -+ if (!enet_np) -+ return; -+ -+ if (of_get_mac_address(enet_np)) -+ goto put_enet_node; -+ -+ ocotp_np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp"); -+ if (!ocotp_np) { -+ pr_warn("failed to find ocotp node\n"); -+ goto put_enet_node; -+ } -+ -+ base = of_iomap(ocotp_np, 0); -+ if (!base) { -+ pr_warn("failed to map ocotp\n"); -+ goto put_ocotp_node; -+ } -+ -+ macaddr_high = readl_relaxed(base + OCOTP_MACn(0)); -+ macaddr_low = readl_relaxed(base + OCOTP_MACn(1)); -+ -+ newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); -+ if (!newmac) -+ goto put_ocotp_node; -+ -+ newmac->value = newmac + 1; -+ newmac->length = 6; -+ newmac->name = kstrdup("local-mac-address", GFP_KERNEL); -+ if (!newmac->name) { -+ kfree(newmac); -+ goto put_ocotp_node; -+ } -+ -+ macaddr = newmac->value; -+ macaddr[5] = macaddr_high & 0xff; -+ macaddr[4] = (macaddr_high >> 8) & 0xff; -+ macaddr[3] = (macaddr_high >> 16) & 0xff; -+ macaddr[2] = (macaddr_high >> 24) & 0xff; -+ macaddr[1] = macaddr_low & 0xff; -+ macaddr[0] = (macaddr_low >> 8) & 0xff; -+ -+ of_update_property(enet_np, newmac); -+ -+put_ocotp_node: -+ of_node_put(ocotp_np); -+put_enet_node: -+ of_node_put(enet_np); -+} -+ -+static inline void imx6q_enet_init(void) -+{ -+ imx6_enet_mac_init("fsl,imx6q-fec"); -+ imx6q_enet_phy_init(); -+ imx6q_1588_init(); -+} -+ - static void __init imx6q_init_machine(void) - { - struct device *parent; -@@ -207,20 +306,22 @@ - if (parent == NULL) - pr_warn("failed to initialize soc device\n"); - -- imx6q_enet_phy_init(); -- - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); - -+ imx6q_enet_init(); - imx_anatop_init(); -- imx6q_pm_init(); -- imx6q_1588_init(); -+ cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); -+ imx6q_csi_mux_init(); - } - - #define OCOTP_CFG3 0x440 - #define OCOTP_CFG3_SPEED_SHIFT 16 - #define OCOTP_CFG3_SPEED_1P2GHZ 0x3 -+#define OCOTP_CFG3_SPEED_1GHZ 0x2 -+#define OCOTP_CFG3_SPEED_850MHZ 0x1 -+#define OCOTP_CFG3_SPEED_800MHZ 0x0 - --static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev) -+static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev) - { - struct device_node *np; - void __iomem *base; -@@ -238,11 +339,31 @@ - goto put_node; - } - -+ /* -+ * SPEED_GRADING[1:0] defines the max speed of ARM: -+ * 2b'11: 1200000000Hz; -- i.MX6Q only. -+ * 2b'10: 1000000000Hz; -+ * 2b'01: 850000000Hz; -- i.MX6Q Only, exclusive with 1GHz. -+ * 2b'00: 800000000Hz; -+ * We need to set the max speed of ARM according to fuse map. -+ */ -+ - val = readl_relaxed(base + OCOTP_CFG3); - val >>= OCOTP_CFG3_SPEED_SHIFT; -- if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ) -- if (dev_pm_opp_disable(cpu_dev, 1200000000)) -- pr_warn("failed to disable 1.2 GHz OPP\n"); -+ if (cpu_is_imx6q()) { -+ if ((val & 0x3) < OCOTP_CFG3_SPEED_1P2GHZ) -+ if (dev_pm_opp_disable(cpu_dev, 1200000000)) -+ pr_warn("failed to disable 1.2 GHz OPP\n"); -+ } -+ if ((val & 0x3) < OCOTP_CFG3_SPEED_1GHZ) -+ if (dev_pm_opp_disable(cpu_dev, 996000000)) -+ pr_warn("failed to disable 1 GHz OPP\n"); -+ if (cpu_is_imx6q()) { -+ if ((val & 0x3) < OCOTP_CFG3_SPEED_850MHZ || -+ (val & 0x3) == OCOTP_CFG3_SPEED_1GHZ) -+ if (dev_pm_opp_disable(cpu_dev, 852000000)) -+ pr_warn("failed to disable 850 MHz OPP\n"); -+ } - - put_node: - of_node_put(np); -@@ -268,29 +389,70 @@ - goto put_node; - } - -- imx6q_opp_check_1p2ghz(cpu_dev); -+ imx6q_opp_check_speed_grading(cpu_dev); - - put_node: - of_node_put(np); - } - -+#define ESAI_AUDIO_MCLK 24576000 -+ -+static void __init imx6q_audio_lvds2_init(void) -+{ -+ struct clk *pll4_sel, *lvds2_in, *pll4_audio_div, *esai; -+ -+ pll4_audio_div = clk_get_sys(NULL, "pll4_audio_div"); -+ pll4_sel = clk_get_sys(NULL, "pll4_sel"); -+ lvds2_in = clk_get_sys(NULL, "lvds2_in"); -+ esai = clk_get_sys(NULL, "esai"); -+ if (IS_ERR(pll4_audio_div) || IS_ERR(pll4_sel) || -+ IS_ERR(lvds2_in) || IS_ERR(esai)) -+ return; -+ -+ if (clk_get_rate(lvds2_in) != ESAI_AUDIO_MCLK) -+ return; -+ -+ clk_set_parent(pll4_sel, lvds2_in); -+ clk_set_rate(pll4_audio_div, 786432000); -+ clk_set_rate(esai, ESAI_AUDIO_MCLK); -+} -+ - static struct platform_device imx6q_cpufreq_pdev = { -- .name = "imx6q-cpufreq", -+ .name = "imx6-cpufreq", - }; - - static void __init imx6q_init_late(void) - { -+ struct regmap *gpr; -+ -+ /* -+ * Need to force IOMUXC irq pending to meet CCM low power mode -+ * restriction, this is recommended by hardware team. -+ */ -+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); -+ if (!IS_ERR(gpr)) -+ regmap_update_bits(gpr, IOMUXC_GPR1, -+ IMX6Q_GPR1_GINT_MASK, -+ IMX6Q_GPR1_GINT_ASSERT); -+ - /* - * WAIT mode is broken on TO 1.0 and 1.1, so there is no point - * to run cpuidle on them. - */ -- if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) -+ if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) -+ || (cpu_is_imx6dl() && imx_get_soc_revision() > -+ IMX_CHIP_REVISION_1_0)) - imx6q_cpuidle_init(); - -- if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) { -+ if (IS_ENABLED(CONFIG_ARM_IMX6_CPUFREQ)) { - imx6q_opp_init(); - platform_device_register(&imx6q_cpufreq_pdev); - } -+ -+ if (of_machine_is_compatible("fsl,imx6q-sabreauto") -+ || of_machine_is_compatible("fsl,imx6dl-sabreauto")) { -+ imx6q_audio_lvds2_init(); -+ } - } - - static void __init imx6q_map_io(void) -@@ -315,6 +477,12 @@ - }; - - DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") -+ /* -+ * i.MX6Q/DL maps system memory at 0x10000000 (offset 256MiB), and -+ * GPU has a limit on physical address that it accesses, which must -+ * be below 2GiB. -+ */ -+ .dma_zone_size = (SZ_2G - SZ_256M), - .smp = smp_ops(imx_smp_ops), - .map_io = imx6q_map_io, - .init_irq = imx6q_init_irq, -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/mach-imx6sl.c linux-3.14.22/arch/arm/mach-imx/mach-imx6sl.c ---- linux-3.14.22.orig/arch/arm/mach-imx/mach-imx6sl.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/mach-imx6sl.c 2014-10-22 14:55:49.910220001 -0500 -@@ -17,8 +17,9 @@ - #include - - #include "common.h" -+#include "cpuidle.h" - --static void __init imx6sl_fec_init(void) -+static void __init imx6sl_fec_clk_init(void) - { - struct regmap *gpr; - -@@ -34,8 +35,17 @@ - } - } - -+static inline void imx6sl_fec_init(void) -+{ -+ imx6sl_fec_clk_init(); -+ imx6_enet_mac_init("fsl,imx6sl-fec"); -+} -+ - static void __init imx6sl_init_late(void) - { -+ /* Init CPUIDLE */ -+ imx6sl_cpuidle_init(); -+ - /* imx6sl reuses imx6q cpufreq driver */ - if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) - platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); -@@ -55,8 +65,7 @@ - - imx6sl_fec_init(); - imx_anatop_init(); -- /* Reuse imx6q pm code */ -- imx6q_pm_init(); -+ imx6sl_pm_init(); - } - - static void __init imx6sl_init_irq(void) -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/mach-vf610.c linux-3.14.22/arch/arm/mach-imx/mach-vf610.c ---- linux-3.14.22.orig/arch/arm/mach-imx/mach-vf610.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/mach-vf610.c 2014-10-22 14:55:49.910220001 -0500 -@@ -22,7 +22,7 @@ - - static void __init vf610_init_irq(void) - { -- l2x0_of_init(0, ~0UL); -+ l2x0_of_init(0, ~0); - irqchip_init(); - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/Makefile linux-3.14.22/arch/arm/mach-imx/Makefile ---- linux-3.14.22.orig/arch/arm/mach-imx/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/Makefile 2014-10-22 14:55:49.910220001 -0500 -@@ -30,6 +30,7 @@ - ifeq ($(CONFIG_CPU_IDLE),y) - obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o - obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o -+obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o - endif - - ifdef CONFIG_SND_IMX_SOC -@@ -101,9 +102,18 @@ - obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o - obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o - --obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o --# i.MX6SL reuses i.MX6Q code --obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o -+AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a -+obj-$(CONFIG_PM) += suspend-imx6.o pm-imx6.o headsmp.o -+ -+obj-y += busfreq-imx6.o -+ifeq ($(CONFIG_ARM_IMX6_CPUFREQ),y) -+obj-$(CONFIG_SOC_IMX6Q) += ddr3_freq_imx6.o busfreq_ddr3.o -+obj-$(CONFIG_SOC_IMX6SL) += lpddr2_freq_imx6.o busfreq_lpddr2.o -+endif -+ifeq ($(CONFIG_CPU_IDLE), y) -+obj-$(CONFIG_SOC_IMX6SL) += imx6sl_wfi.o -+endif -+ - - # i.MX5 based machines - obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/mx6.h linux-3.14.22/arch/arm/mach-imx/mx6.h ---- linux-3.14.22.orig/arch/arm/mach-imx/mx6.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/mx6.h 2014-10-22 14:55:49.910220001 -0500 -@@ -0,0 +1,35 @@ -+/* -+ * Copyright 2004-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 version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_ARCH_MXC_IOMAP_H__ -+#define __ASM_ARCH_MXC_IOMAP_H__ -+ -+#define MX6Q_IO_P2V(x) IMX_IO_P2V(x) -+#define MX6Q_IO_ADDRESS(x) IOMEM(MX6Q_IO_P2V(x)) -+ -+#define MX6Q_L2_BASE_ADDR 0x00a02000 -+#define MX6Q_L2_SIZE 0x1000 -+#define MX6Q_IOMUXC_BASE_ADDR 0x020e0000 -+#define MX6Q_IOMUXC_SIZE 0x4000 -+#define MX6Q_SRC_BASE_ADDR 0x020d8000 -+#define MX6Q_SRC_SIZE 0x4000 -+#define MX6Q_CCM_BASE_ADDR 0x020c4000 -+#define MX6Q_CCM_SIZE 0x4000 -+#define MX6Q_ANATOP_BASE_ADDR 0x020c8000 -+#define MX6Q_ANATOP_SIZE 0x1000 -+#define MX6Q_GPC_BASE_ADDR 0x020dc000 -+#define MX6Q_GPC_SIZE 0x4000 -+#define MX6Q_MMDC_P0_BASE_ADDR 0x021b0000 -+#define MX6Q_MMDC_P0_SIZE 0x4000 -+#define MX6Q_MMDC_P1_BASE_ADDR 0x021b4000 -+#define MX6Q_MMDC_P1_SIZE 0x4000 -+ -+#define MX6_SUSPEND_IRAM_SIZE 0x1000 -+#endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/mxc.h linux-3.14.22/arch/arm/mach-imx/mxc.h ---- linux-3.14.22.orig/arch/arm/mach-imx/mxc.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/mxc.h 2014-10-22 14:55:49.910220001 -0500 -@@ -42,6 +42,8 @@ - #define IMX_CHIP_REVISION_1_1 0x11 - #define IMX_CHIP_REVISION_1_2 0x12 - #define IMX_CHIP_REVISION_1_3 0x13 -+#define IMX_CHIP_REVISION_1_4 0x14 -+#define IMX_CHIP_REVISION_1_5 0x15 - #define IMX_CHIP_REVISION_2_0 0x20 - #define IMX_CHIP_REVISION_2_1 0x21 - #define IMX_CHIP_REVISION_2_2 0x22 -@@ -177,6 +179,7 @@ - extern struct cpu_op *(*get_cpu_op)(int *op); - #endif - -+#define cpu_is_imx6() (cpu_is_imx6q() || cpu_is_imx6dl() || cpu_is_imx6sl()) - #define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35()) - #define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27()) - -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/pm-imx6.c linux-3.14.22/arch/arm/mach-imx/pm-imx6.c ---- linux-3.14.22.orig/arch/arm/mach-imx/pm-imx6.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/pm-imx6.c 2014-10-22 14:55:49.910220001 -0500 -@@ -0,0 +1,580 @@ -+/* -+ * Copyright 2011-2014 Freescale Semiconductor, Inc. -+ * Copyright 2011 Linaro Ltd. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "common.h" -+#include "hardware.h" -+ -+#define CCR 0x0 -+#define BM_CCR_WB_COUNT (0x7 << 16) -+#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) -+#define BM_CCR_RBC_EN (0x1 << 27) -+ -+#define CLPCR 0x54 -+#define BP_CLPCR_LPM 0 -+#define BM_CLPCR_LPM (0x3 << 0) -+#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) -+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) -+#define BM_CLPCR_SBYOS (0x1 << 6) -+#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) -+#define BM_CLPCR_VSTBY (0x1 << 8) -+#define BP_CLPCR_STBY_COUNT 9 -+#define BM_CLPCR_STBY_COUNT (0x3 << 9) -+#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) -+#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) -+#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) -+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) -+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) -+#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) -+#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) -+#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) -+#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) -+#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) -+#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) -+ -+#define CGPR 0x64 -+#define BM_CGPR_INT_MEM_CLK_LPM (0x1 << 17) -+ -+#define MX6Q_SUSPEND_OCRAM_SIZE 0x1000 -+#define MX6_MAX_MMDC_IO_NUM 33 -+ -+static void __iomem *ccm_base; -+static void __iomem *suspend_ocram_base; -+static void (*imx6_suspend_in_ocram_fn)(void __iomem *ocram_vbase); -+ -+/* -+ * suspend ocram space layout: -+ * ======================== high address ====================== -+ * . -+ * . -+ * . -+ * ^ -+ * ^ -+ * ^ -+ * imx6_suspend code -+ * PM_INFO structure(imx6_cpu_pm_info) -+ * ======================== low address ======================= -+ */ -+ -+struct imx6_pm_base { -+ phys_addr_t pbase; -+ void __iomem *vbase; -+}; -+ -+struct imx6_pm_socdata { -+ u32 cpu_type; -+ const char *mmdc_compat; -+ const char *src_compat; -+ const char *iomuxc_compat; -+ const char *gpc_compat; -+ const u32 mmdc_io_num; -+ const u32 *mmdc_io_offset; -+}; -+ -+static const u32 imx6q_mmdc_io_offset[] __initconst = { -+ 0x5ac, 0x5b4, 0x528, 0x520, /* DQM0 ~ DQM3 */ -+ 0x514, 0x510, 0x5bc, 0x5c4, /* DQM4 ~ DQM7 */ -+ 0x56c, 0x578, 0x588, 0x594, /* CAS, RAS, SDCLK_0, SDCLK_1 */ -+ 0x5a8, 0x5b0, 0x524, 0x51c, /* SDQS0 ~ SDQS3 */ -+ 0x518, 0x50c, 0x5b8, 0x5c0, /* SDQS4 ~ SDQS7 */ -+ 0x784, 0x788, 0x794, 0x79c, /* GPR_B0DS ~ GPR_B3DS */ -+ 0x7a0, 0x7a4, 0x7a8, 0x748, /* GPR_B4DS ~ GPR_B7DS */ -+ 0x59c, 0x5a0, 0x750, 0x774, /* SODT0, SODT1, MODE_CTL, MODE */ -+ 0x74c, /* GPR_ADDS */ -+}; -+ -+static const struct imx6_pm_socdata imx6q_pm_data __initconst = { -+ .cpu_type = MXC_CPU_IMX6Q, -+ .mmdc_compat = "fsl,imx6q-mmdc", -+ .src_compat = "fsl,imx6q-src", -+ .iomuxc_compat = "fsl,imx6q-iomuxc", -+ .gpc_compat = "fsl,imx6q-gpc", -+ .mmdc_io_num = ARRAY_SIZE(imx6q_mmdc_io_offset), -+ .mmdc_io_offset = imx6q_mmdc_io_offset, -+}; -+ -+/* -+ * This structure is for passing necessary data for low level ocram -+ * suspend code(arch/arm/mach-imx/suspend-imx6.S), if this struct -+ * definition is changed, the offset definition in -+ * arch/arm/mach-imx/suspend-imx6.S must be also changed accordingly, -+ * otherwise, the suspend to ocram function will be broken! -+ */ -+struct imx6_cpu_pm_info { -+ phys_addr_t pbase; /* The physical address of pm_info. */ -+ phys_addr_t resume_addr; /* The physical resume address for asm code */ -+ u32 cpu_type; -+ u32 pm_info_size; /* Size of pm_info. */ -+ struct imx6_pm_base mmdc_base; -+ struct imx6_pm_base src_base; -+ struct imx6_pm_base iomuxc_base; -+ struct imx6_pm_base ccm_base; -+ struct imx6_pm_base gpc_base; -+ struct imx6_pm_base l2_base; -+ u32 mmdc_io_num; /* Number of MMDC IOs which need saved/restored. */ -+ u32 mmdc_io_val[MX6_MAX_MMDC_IO_NUM][2]; /* To save offset and value */ -+} __aligned(8); -+ -+void imx6q_set_cache_lpm_in_wait(bool enable) -+{ -+ if ((cpu_is_imx6q() && imx_get_soc_revision() > -+ IMX_CHIP_REVISION_1_1) || -+ (cpu_is_imx6dl() && imx_get_soc_revision() > -+ IMX_CHIP_REVISION_1_0)) { -+ u32 val; -+ -+ val = readl_relaxed(ccm_base + CGPR); -+ if (enable) -+ val |= BM_CGPR_INT_MEM_CLK_LPM; -+ else -+ val &= ~BM_CGPR_INT_MEM_CLK_LPM; -+ writel_relaxed(val, ccm_base + CGPR); -+ } -+} -+ -+static void imx6q_enable_rbc(bool enable) -+{ -+ u32 val; -+ -+ /* -+ * need to mask all interrupts in GPC before -+ * operating RBC configurations -+ */ -+ imx_gpc_mask_all(); -+ -+ /* configure RBC enable bit */ -+ val = readl_relaxed(ccm_base + CCR); -+ val &= ~BM_CCR_RBC_EN; -+ val |= enable ? BM_CCR_RBC_EN : 0; -+ writel_relaxed(val, ccm_base + CCR); -+ -+ /* configure RBC count */ -+ val = readl_relaxed(ccm_base + CCR); -+ val &= ~BM_CCR_RBC_BYPASS_COUNT; -+ val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; -+ writel(val, ccm_base + CCR); -+ -+ /* -+ * need to delay at least 2 cycles of CKIL(32K) -+ * due to hardware design requirement, which is -+ * ~61us, here we use 65us for safe -+ */ -+ udelay(65); -+ -+ /* restore GPC interrupt mask settings */ -+ imx_gpc_restore_all(); -+} -+ -+static void imx6q_enable_wb(bool enable) -+{ -+ u32 val; -+ -+ /* configure well bias enable bit */ -+ val = readl_relaxed(ccm_base + CLPCR); -+ val &= ~BM_CLPCR_WB_PER_AT_LPM; -+ val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; -+ writel_relaxed(val, ccm_base + CLPCR); -+ -+ /* configure well bias count */ -+ val = readl_relaxed(ccm_base + CCR); -+ val &= ~BM_CCR_WB_COUNT; -+ val |= enable ? BM_CCR_WB_COUNT : 0; -+ writel_relaxed(val, ccm_base + CCR); -+} -+ -+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) -+{ -+ struct irq_desc *iomuxc_irq_desc; -+ u32 val = readl_relaxed(ccm_base + CLPCR); -+ -+ val &= ~BM_CLPCR_LPM; -+ switch (mode) { -+ case WAIT_CLOCKED: -+ break; -+ case WAIT_UNCLOCKED: -+ val |= 0x1 << BP_CLPCR_LPM; -+ val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; -+ val &= ~BM_CLPCR_VSTBY; -+ val &= ~BM_CLPCR_SBYOS; -+ if (cpu_is_imx6sl()) -+ val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; -+ else -+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; -+ break; -+ case STOP_POWER_ON: -+ val |= 0x2 << BP_CLPCR_LPM; -+ val &= ~BM_CLPCR_VSTBY; -+ val &= ~BM_CLPCR_SBYOS; -+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; -+ break; -+ case WAIT_UNCLOCKED_POWER_OFF: -+ val |= 0x1 << BP_CLPCR_LPM; -+ val &= ~BM_CLPCR_VSTBY; -+ val &= ~BM_CLPCR_SBYOS; -+ break; -+ case STOP_POWER_OFF: -+ val |= 0x2 << BP_CLPCR_LPM; -+ val |= 0x3 << BP_CLPCR_STBY_COUNT; -+ val |= BM_CLPCR_VSTBY; -+ val |= BM_CLPCR_SBYOS; -+ if (cpu_is_imx6sl()) { -+ val |= BM_CLPCR_BYPASS_PMIC_READY; -+ val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; -+ } else { -+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * ERR007265: CCM: When improper low-power sequence is used, -+ * the SoC enters low power mode before the ARM core executes WFI. -+ * -+ * Software workaround: -+ * 1) Software should trigger IRQ #32 (IOMUX) to be always pending -+ * by setting IOMUX_GPR1_GINT. -+ * 2) Software should then unmask IRQ #32 in GPC before setting CCM -+ * Low-Power mode. -+ * 3) Software should mask IRQ #32 right after CCM Low-Power mode -+ * is set (set bits 0-1 of CCM_CLPCR). -+ */ -+ iomuxc_irq_desc = irq_to_desc(32); -+ imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data); -+ writel_relaxed(val, ccm_base + CLPCR); -+ imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data); -+ -+ return 0; -+} -+ -+static int imx6q_suspend_finish(unsigned long val) -+{ -+ if (!imx6_suspend_in_ocram_fn) { -+ cpu_do_idle(); -+ } else { -+ /* -+ * call low level suspend function in ocram, -+ * as we need to float DDR IO. -+ */ -+ local_flush_tlb_all(); -+ imx6_suspend_in_ocram_fn(suspend_ocram_base); -+ } -+ -+ return 0; -+} -+ -+static int imx6q_pm_enter(suspend_state_t state) -+{ -+ struct regmap *g; -+ -+ /* -+ * L2 can exit by 'reset' or Inband beacon (from remote EP) -+ * toggling phy_powerdown has same effect as 'inband beacon' -+ * So, toggle bit18 of GPR1, used as a workaround of errata -+ * "PCIe PCIe does not support L2 Power Down" -+ */ -+ if (IS_ENABLED(CONFIG_PCI_IMX6)) { -+ g = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); -+ if (IS_ERR(g)) { -+ pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); -+ return PTR_ERR(g); -+ } -+ regmap_update_bits(g, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, -+ IMX6Q_GPR1_PCIE_TEST_PD); -+ } -+ -+ switch (state) { -+ case PM_SUSPEND_STANDBY: -+ imx6q_set_lpm(STOP_POWER_ON); -+ imx6q_set_cache_lpm_in_wait(true); -+ imx_gpc_pre_suspend(false); -+ if (cpu_is_imx6sl()) -+ imx6sl_set_wait_clk(true); -+ /* Zzz ... */ -+ cpu_do_idle(); -+ if (cpu_is_imx6sl()) -+ imx6sl_set_wait_clk(false); -+ imx_gpc_post_resume(); -+ imx6q_set_lpm(WAIT_CLOCKED); -+ break; -+ case PM_SUSPEND_MEM: -+ imx6q_set_cache_lpm_in_wait(false); -+ imx6q_set_lpm(STOP_POWER_OFF); -+ imx6q_enable_wb(true); -+ /* -+ * For suspend into ocram, asm code already take care of -+ * RBC setting, so we do NOT need to do that here. -+ */ -+ if (!imx6_suspend_in_ocram_fn) -+ imx6q_enable_rbc(true); -+ imx_gpc_pre_suspend(true); -+ imx_anatop_pre_suspend(); -+ imx_set_cpu_jump(0, v7_cpu_resume); -+ /* Zzz ... */ -+ cpu_suspend(0, imx6q_suspend_finish); -+ if (cpu_is_imx6q() || cpu_is_imx6dl()) -+ imx_smp_prepare(); -+ imx_anatop_post_resume(); -+ imx_gpc_post_resume(); -+ imx6q_enable_wb(false); -+ imx6q_set_lpm(WAIT_CLOCKED); -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ /* -+ * L2 can exit by 'reset' or Inband beacon (from remote EP) -+ * toggling phy_powerdown has same effect as 'inband beacon' -+ * So, toggle bit18 of GPR1, used as a workaround of errata -+ * "PCIe PCIe does not support L2 Power Down" -+ */ -+ if (IS_ENABLED(CONFIG_PCI_IMX6)) { -+ regmap_update_bits(g, IOMUXC_GPR1, IMX6Q_GPR1_PCIE_TEST_PD, -+ !IMX6Q_GPR1_PCIE_TEST_PD); -+ } -+ -+ return 0; -+} -+ -+static int imx6q_pm_valid(suspend_state_t state) -+{ -+ return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM); -+} -+ -+static const struct platform_suspend_ops imx6q_pm_ops = { -+ .enter = imx6q_pm_enter, -+ .valid = imx6q_pm_valid, -+}; -+ -+void __init imx6q_pm_set_ccm_base(void __iomem *base) -+{ -+ ccm_base = base; -+} -+ -+static int __init imx6_pm_get_base(struct imx6_pm_base *base, -+ const char *compat) -+{ -+ struct device_node *node; -+ struct resource res; -+ int ret = 0; -+ -+ node = of_find_compatible_node(NULL, NULL, compat); -+ if (!node) { -+ ret = -ENODEV; -+ goto out; -+ } -+ -+ ret = of_address_to_resource(node, 0, &res); -+ if (ret) -+ goto put_node; -+ -+ base->pbase = res.start; -+ base->vbase = ioremap(res.start, resource_size(&res)); -+ if (!base->vbase) -+ ret = -ENOMEM; -+ -+put_node: -+ of_node_put(node); -+out: -+ return ret; -+} -+ -+static int __init imx6q_ocram_suspend_init(const struct imx6_pm_socdata -+ *socdata) -+{ -+ phys_addr_t ocram_pbase; -+ struct device_node *node; -+ struct platform_device *pdev; -+ struct imx6_cpu_pm_info *pm_info; -+ struct gen_pool *ocram_pool; -+ unsigned long ocram_base; -+ int i, ret = 0; -+ const u32 *mmdc_offset_array; -+ -+ if (!socdata) { -+ pr_warn("%s: invalid argument!\n", __func__); -+ return -EINVAL; -+ } -+ -+ node = of_find_compatible_node(NULL, NULL, "mmio-sram"); -+ if (!node) { -+ pr_warn("%s: failed to find ocram node!\n", __func__); -+ return -ENODEV; -+ } -+ -+ pdev = of_find_device_by_node(node); -+ if (!pdev) { -+ pr_warn("%s: failed to find ocram device!\n", __func__); -+ ret = -ENODEV; -+ goto put_node; -+ } -+ -+ ocram_pool = dev_get_gen_pool(&pdev->dev); -+ if (!ocram_pool) { -+ pr_warn("%s: ocram pool unavailable!\n", __func__); -+ ret = -ENODEV; -+ goto put_node; -+ } -+ -+ ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE); -+ if (!ocram_base) { -+ pr_warn("%s: unable to alloc ocram!\n", __func__); -+ ret = -ENOMEM; -+ goto put_node; -+ } -+ -+ ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base); -+ -+ suspend_ocram_base = __arm_ioremap_exec(ocram_pbase, -+ MX6Q_SUSPEND_OCRAM_SIZE, false); -+ -+ pm_info = suspend_ocram_base; -+ pm_info->pbase = ocram_pbase; -+ pm_info->resume_addr = virt_to_phys(v7_cpu_resume); -+ pm_info->pm_info_size = sizeof(*pm_info); -+ -+ /* -+ * ccm physical address is not used by asm code currently, -+ * so get ccm virtual address directly, as we already have -+ * it from ccm driver. -+ */ -+ pm_info->ccm_base.vbase = ccm_base; -+ -+ ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat); -+ if (ret) { -+ pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret); -+ goto put_node; -+ } -+ -+ ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat); -+ if (ret) { -+ pr_warn("%s: failed to get src base %d!\n", __func__, ret); -+ goto src_map_failed; -+ } -+ -+ ret = imx6_pm_get_base(&pm_info->iomuxc_base, socdata->iomuxc_compat); -+ if (ret) { -+ pr_warn("%s: failed to get iomuxc base %d!\n", __func__, ret); -+ goto iomuxc_map_failed; -+ } -+ -+ ret = imx6_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat); -+ if (ret) { -+ pr_warn("%s: failed to get gpc base %d!\n", __func__, ret); -+ goto gpc_map_failed; -+ } -+ -+ ret = imx6_pm_get_base(&pm_info->l2_base, "arm,pl310-cache"); -+ if (ret) { -+ pr_warn("%s: failed to get pl310-cache base %d!\n", -+ __func__, ret); -+ goto pl310_cache_map_failed; -+ } -+ -+ pm_info->cpu_type = socdata->cpu_type; -+ pm_info->mmdc_io_num = socdata->mmdc_io_num; -+ mmdc_offset_array = socdata->mmdc_io_offset; -+ -+ for (i = 0; i < pm_info->mmdc_io_num; i++) { -+ pm_info->mmdc_io_val[i][0] = -+ mmdc_offset_array[i]; -+ pm_info->mmdc_io_val[i][1] = -+ readl_relaxed(pm_info->iomuxc_base.vbase + -+ mmdc_offset_array[i]); -+ } -+ -+ imx6_suspend_in_ocram_fn = fncpy( -+ suspend_ocram_base + sizeof(*pm_info), -+ &imx6_suspend, -+ MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info)); -+ -+ goto put_node; -+ -+pl310_cache_map_failed: -+ iounmap(&pm_info->gpc_base.vbase); -+gpc_map_failed: -+ iounmap(&pm_info->iomuxc_base.vbase); -+iomuxc_map_failed: -+ iounmap(&pm_info->src_base.vbase); -+src_map_failed: -+ iounmap(&pm_info->mmdc_base.vbase); -+put_node: -+ of_node_put(node); -+ -+ return ret; -+} -+ -+static void __init imx6_pm_common_init(const struct imx6_pm_socdata -+ *socdata) -+{ -+ struct regmap *gpr; -+ int ret; -+ -+ WARN_ON(!ccm_base); -+ -+ ret = imx6q_ocram_suspend_init(socdata); -+ if (ret) -+ pr_warn("%s: failed to initialize ocram suspend %d!\n", -+ __func__, ret); -+ -+ /* -+ * This is for SW workaround step #1 of ERR007265, see comments -+ * in imx6q_set_lpm for details of this errata. -+ * Force IOMUXC irq pending, so that the interrupt to GPC can be -+ * used to deassert dsm_request signal when the signal gets -+ * asserted unexpectedly. -+ */ -+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); -+ if (!IS_ERR(gpr)) -+ regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT_MASK, -+ IMX6Q_GPR1_GINT_MASK); -+ -+ -+ suspend_set_ops(&imx6q_pm_ops); -+} -+ -+void __init imx6q_pm_init(void) -+{ -+ imx6_pm_common_init(&imx6q_pm_data); -+} -+ -+void __init imx6dl_pm_init(void) -+{ -+ imx6_pm_common_init(NULL); -+} -+ -+void __init imx6sl_pm_init(void) -+{ -+ imx6_pm_common_init(NULL); -+} -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/pm-imx6q.c linux-3.14.22/arch/arm/mach-imx/pm-imx6q.c ---- linux-3.14.22.orig/arch/arm/mach-imx/pm-imx6q.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/pm-imx6q.c 1969-12-31 18:00:00.000000000 -0600 -@@ -1,241 +0,0 @@ --/* -- * Copyright 2011-2013 Freescale Semiconductor, Inc. -- * Copyright 2011 Linaro Ltd. -- * -- * The code contained herein is licensed under the GNU General Public -- * License. You may obtain a copy of the GNU General Public License -- * Version 2 or later at the following locations: -- * -- * http://www.opensource.org/licenses/gpl-license.html -- * http://www.gnu.org/copyleft/gpl.html -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include "common.h" --#include "hardware.h" -- --#define CCR 0x0 --#define BM_CCR_WB_COUNT (0x7 << 16) --#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21) --#define BM_CCR_RBC_EN (0x1 << 27) -- --#define CLPCR 0x54 --#define BP_CLPCR_LPM 0 --#define BM_CLPCR_LPM (0x3 << 0) --#define BM_CLPCR_BYPASS_PMIC_READY (0x1 << 2) --#define BM_CLPCR_ARM_CLK_DIS_ON_LPM (0x1 << 5) --#define BM_CLPCR_SBYOS (0x1 << 6) --#define BM_CLPCR_DIS_REF_OSC (0x1 << 7) --#define BM_CLPCR_VSTBY (0x1 << 8) --#define BP_CLPCR_STBY_COUNT 9 --#define BM_CLPCR_STBY_COUNT (0x3 << 9) --#define BM_CLPCR_COSC_PWRDOWN (0x1 << 11) --#define BM_CLPCR_WB_PER_AT_LPM (0x1 << 16) --#define BM_CLPCR_WB_CORE_AT_LPM (0x1 << 17) --#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS (0x1 << 19) --#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS (0x1 << 21) --#define BM_CLPCR_MASK_CORE0_WFI (0x1 << 22) --#define BM_CLPCR_MASK_CORE1_WFI (0x1 << 23) --#define BM_CLPCR_MASK_CORE2_WFI (0x1 << 24) --#define BM_CLPCR_MASK_CORE3_WFI (0x1 << 25) --#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) --#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) -- --#define CGPR 0x64 --#define BM_CGPR_CHICKEN_BIT (0x1 << 17) -- --static void __iomem *ccm_base; -- --void imx6q_set_chicken_bit(void) --{ -- u32 val = readl_relaxed(ccm_base + CGPR); -- -- val |= BM_CGPR_CHICKEN_BIT; -- writel_relaxed(val, ccm_base + CGPR); --} -- --static void imx6q_enable_rbc(bool enable) --{ -- u32 val; -- -- /* -- * need to mask all interrupts in GPC before -- * operating RBC configurations -- */ -- imx_gpc_mask_all(); -- -- /* configure RBC enable bit */ -- val = readl_relaxed(ccm_base + CCR); -- val &= ~BM_CCR_RBC_EN; -- val |= enable ? BM_CCR_RBC_EN : 0; -- writel_relaxed(val, ccm_base + CCR); -- -- /* configure RBC count */ -- val = readl_relaxed(ccm_base + CCR); -- val &= ~BM_CCR_RBC_BYPASS_COUNT; -- val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0; -- writel(val, ccm_base + CCR); -- -- /* -- * need to delay at least 2 cycles of CKIL(32K) -- * due to hardware design requirement, which is -- * ~61us, here we use 65us for safe -- */ -- udelay(65); -- -- /* restore GPC interrupt mask settings */ -- imx_gpc_restore_all(); --} -- --static void imx6q_enable_wb(bool enable) --{ -- u32 val; -- -- /* configure well bias enable bit */ -- val = readl_relaxed(ccm_base + CLPCR); -- val &= ~BM_CLPCR_WB_PER_AT_LPM; -- val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0; -- writel_relaxed(val, ccm_base + CLPCR); -- -- /* configure well bias count */ -- val = readl_relaxed(ccm_base + CCR); -- val &= ~BM_CCR_WB_COUNT; -- val |= enable ? BM_CCR_WB_COUNT : 0; -- writel_relaxed(val, ccm_base + CCR); --} -- --int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) --{ -- struct irq_desc *iomuxc_irq_desc; -- u32 val = readl_relaxed(ccm_base + CLPCR); -- -- val &= ~BM_CLPCR_LPM; -- switch (mode) { -- case WAIT_CLOCKED: -- break; -- case WAIT_UNCLOCKED: -- val |= 0x1 << BP_CLPCR_LPM; -- val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM; -- break; -- case STOP_POWER_ON: -- val |= 0x2 << BP_CLPCR_LPM; -- break; -- case WAIT_UNCLOCKED_POWER_OFF: -- val |= 0x1 << BP_CLPCR_LPM; -- val &= ~BM_CLPCR_VSTBY; -- val &= ~BM_CLPCR_SBYOS; -- break; -- case STOP_POWER_OFF: -- val |= 0x2 << BP_CLPCR_LPM; -- val |= 0x3 << BP_CLPCR_STBY_COUNT; -- val |= BM_CLPCR_VSTBY; -- val |= BM_CLPCR_SBYOS; -- if (cpu_is_imx6sl()) { -- val |= BM_CLPCR_BYPASS_PMIC_READY; -- val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS; -- } else { -- val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS; -- } -- break; -- default: -- return -EINVAL; -- } -- -- /* -- * ERR007265: CCM: When improper low-power sequence is used, -- * the SoC enters low power mode before the ARM core executes WFI. -- * -- * Software workaround: -- * 1) Software should trigger IRQ #32 (IOMUX) to be always pending -- * by setting IOMUX_GPR1_GINT. -- * 2) Software should then unmask IRQ #32 in GPC before setting CCM -- * Low-Power mode. -- * 3) Software should mask IRQ #32 right after CCM Low-Power mode -- * is set (set bits 0-1 of CCM_CLPCR). -- */ -- iomuxc_irq_desc = irq_to_desc(32); -- imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data); -- writel_relaxed(val, ccm_base + CLPCR); -- imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data); -- -- return 0; --} -- --static int imx6q_suspend_finish(unsigned long val) --{ -- cpu_do_idle(); -- return 0; --} -- --static int imx6q_pm_enter(suspend_state_t state) --{ -- switch (state) { -- case PM_SUSPEND_MEM: -- imx6q_set_lpm(STOP_POWER_OFF); -- imx6q_enable_wb(true); -- imx6q_enable_rbc(true); -- imx_gpc_pre_suspend(); -- imx_anatop_pre_suspend(); -- imx_set_cpu_jump(0, v7_cpu_resume); -- /* Zzz ... */ -- cpu_suspend(0, imx6q_suspend_finish); -- if (cpu_is_imx6q() || cpu_is_imx6dl()) -- imx_smp_prepare(); -- imx_anatop_post_resume(); -- imx_gpc_post_resume(); -- imx6q_enable_rbc(false); -- imx6q_enable_wb(false); -- imx6q_set_lpm(WAIT_CLOCKED); -- break; -- default: -- return -EINVAL; -- } -- -- return 0; --} -- --static const struct platform_suspend_ops imx6q_pm_ops = { -- .enter = imx6q_pm_enter, -- .valid = suspend_valid_only_mem, --}; -- --void __init imx6q_pm_set_ccm_base(void __iomem *base) --{ -- ccm_base = base; --} -- --void __init imx6q_pm_init(void) --{ -- struct regmap *gpr; -- -- WARN_ON(!ccm_base); -- -- /* -- * This is for SW workaround step #1 of ERR007265, see comments -- * in imx6q_set_lpm for details of this errata. -- * Force IOMUXC irq pending, so that the interrupt to GPC can be -- * used to deassert dsm_request signal when the signal gets -- * asserted unexpectedly. -- */ -- gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); -- if (!IS_ERR(gpr)) -- regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT, -- IMX6Q_GPR1_GINT); -- -- -- suspend_set_ops(&imx6q_pm_ops); --} -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/suspend-imx6.S linux-3.14.22/arch/arm/mach-imx/suspend-imx6.S ---- linux-3.14.22.orig/arch/arm/mach-imx/suspend-imx6.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-imx/suspend-imx6.S 2014-10-22 14:55:49.922220001 -0500 -@@ -0,0 +1,306 @@ -+/* -+ * Copyright 2014 Freescale Semiconductor, Inc. -+ * -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include "hardware.h" -+ -+/* -+ * ==================== low level suspend ==================== -+ * -+ * Better to follow below rules to use ARM registers: -+ * r0: pm_info structure address; -+ * r1 ~ r4: for saving pm_info members; -+ * r5 ~ r10: free registers; -+ * r11: io base address. -+ * -+ * suspend ocram space layout: -+ * ======================== high address ====================== -+ * . -+ * . -+ * . -+ * ^ -+ * ^ -+ * ^ -+ * imx6_suspend code -+ * PM_INFO structure(imx6_cpu_pm_info) -+ * ======================== low address ======================= -+ */ -+ -+/* -+ * Below offsets are based on struct imx6_cpu_pm_info -+ * which defined in arch/arm/mach-imx/pm-imx6q.c, this -+ * structure contains necessary pm info for low level -+ * suspend related code. -+ */ -+#define PM_INFO_PBASE_OFFSET 0x0 -+#define PM_INFO_RESUME_ADDR_OFFSET 0x4 -+#define PM_INFO_CPU_TYPE_OFFSET 0x8 -+#define PM_INFO_PM_INFO_SIZE_OFFSET 0xC -+#define PM_INFO_MX6Q_MMDC_P_OFFSET 0x10 -+#define PM_INFO_MX6Q_MMDC_V_OFFSET 0x14 -+#define PM_INFO_MX6Q_SRC_P_OFFSET 0x18 -+#define PM_INFO_MX6Q_SRC_V_OFFSET 0x1C -+#define PM_INFO_MX6Q_IOMUXC_P_OFFSET 0x20 -+#define PM_INFO_MX6Q_IOMUXC_V_OFFSET 0x24 -+#define PM_INFO_MX6Q_CCM_P_OFFSET 0x28 -+#define PM_INFO_MX6Q_CCM_V_OFFSET 0x2C -+#define PM_INFO_MX6Q_GPC_P_OFFSET 0x30 -+#define PM_INFO_MX6Q_GPC_V_OFFSET 0x34 -+#define PM_INFO_MX6Q_L2_P_OFFSET 0x38 -+#define PM_INFO_MX6Q_L2_V_OFFSET 0x3C -+#define PM_INFO_MMDC_IO_NUM_OFFSET 0x40 -+#define PM_INFO_MMDC_IO_VAL_OFFSET 0x44 -+ -+#define MX6Q_SRC_GPR1 0x20 -+#define MX6Q_SRC_GPR2 0x24 -+#define MX6Q_MMDC_MAPSR 0x404 -+#define MX6Q_GPC_IMR1 0x08 -+#define MX6Q_GPC_IMR2 0x0c -+#define MX6Q_GPC_IMR3 0x10 -+#define MX6Q_GPC_IMR4 0x14 -+#define MX6Q_CCM_CCR 0x0 -+ -+ .align 3 -+ -+ .macro sync_l2_cache -+ -+ /* sync L2 cache to drain L2's buffers to DRAM. */ -+#ifdef CONFIG_CACHE_L2X0 -+ ldr r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET] -+ mov r6, #0x0 -+ str r6, [r11, #L2X0_CACHE_SYNC] -+1: -+ ldr r6, [r11, #L2X0_CACHE_SYNC] -+ ands r6, r6, #0x1 -+ bne 1b -+#endif -+ -+ .endm -+ -+ .macro resume_mmdc -+ -+ /* restore MMDC IO */ -+ cmp r5, #0x0 -+ ldreq r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET] -+ ldrne r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET] -+ -+ ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] -+ ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET -+ add r7, r7, r0 -+1: -+ ldr r8, [r7], #0x4 -+ ldr r9, [r7], #0x4 -+ str r9, [r11, r8] -+ subs r6, r6, #0x1 -+ bne 1b -+ -+ cmp r5, #0x0 -+ ldreq r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET] -+ ldrne r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET] -+ -+ /* let DDR out of self-refresh */ -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ bic r7, r7, #(1 << 21) -+ str r7, [r11, #MX6Q_MMDC_MAPSR] -+2: -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ ands r7, r7, #(1 << 25) -+ bne 2b -+ -+ /* enable DDR auto power saving */ -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ bic r7, r7, #0x1 -+ str r7, [r11, #MX6Q_MMDC_MAPSR] -+ -+ .endm -+ -+ENTRY(imx6_suspend) -+ ldr r1, [r0, #PM_INFO_PBASE_OFFSET] -+ ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET] -+ ldr r3, [r0, #PM_INFO_CPU_TYPE_OFFSET] -+ ldr r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET] -+ -+ /* -+ * counting the resume address in iram -+ * to set it in SRC register. -+ */ -+ ldr r6, =imx6_suspend -+ ldr r7, =resume -+ sub r7, r7, r6 -+ add r8, r1, r4 -+ add r9, r8, r7 -+ -+ /* -+ * make sure TLB contain the addr we want, -+ * as we will access them after MMDC IO floated. -+ */ -+ -+ ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET] -+ ldr r6, [r11, #0x0] -+ ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] -+ ldr r6, [r11, #0x0] -+ ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET] -+ ldr r6, [r11, #0x0] -+ -+ /* use r11 to store the IO address */ -+ ldr r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET] -+ /* store physical resume addr and pm_info address. */ -+ str r9, [r11, #MX6Q_SRC_GPR1] -+ str r1, [r11, #MX6Q_SRC_GPR2] -+ -+ /* need to sync L2 cache before DSM. */ -+ sync_l2_cache -+ -+ ldr r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET] -+ /* -+ * put DDR explicitly into self-refresh and -+ * disable automatic power savings. -+ */ -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ orr r7, r7, #0x1 -+ str r7, [r11, #MX6Q_MMDC_MAPSR] -+ -+ /* make the DDR explicitly enter self-refresh. */ -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ orr r7, r7, #(1 << 21) -+ str r7, [r11, #MX6Q_MMDC_MAPSR] -+ -+poll_dvfs_set: -+ ldr r7, [r11, #MX6Q_MMDC_MAPSR] -+ ands r7, r7, #(1 << 25) -+ beq poll_dvfs_set -+ -+ ldr r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET] -+ ldr r6, =0x0 -+ ldr r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] -+ ldr r8, =PM_INFO_MMDC_IO_VAL_OFFSET -+ add r8, r8, r0 -+set_mmdc_io_lpm: -+ ldr r9, [r8], #0x8 -+ str r6, [r11, r9] -+ subs r7, r7, #0x1 -+ bne set_mmdc_io_lpm -+ -+ /* -+ * mask all GPC interrupts before -+ * enabling the RBC counters to -+ * avoid the counter starting too -+ * early if an interupt is already -+ * pending. -+ */ -+ ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] -+ ldr r6, [r11, #MX6Q_GPC_IMR1] -+ ldr r7, [r11, #MX6Q_GPC_IMR2] -+ ldr r8, [r11, #MX6Q_GPC_IMR3] -+ ldr r9, [r11, #MX6Q_GPC_IMR4] -+ -+ ldr r10, =0xffffffff -+ str r10, [r11, #MX6Q_GPC_IMR1] -+ str r10, [r11, #MX6Q_GPC_IMR2] -+ str r10, [r11, #MX6Q_GPC_IMR3] -+ str r10, [r11, #MX6Q_GPC_IMR4] -+ -+ /* -+ * enable the RBC bypass counter here -+ * to hold off the interrupts. RBC counter -+ * = 32 (1ms), Minimum RBC delay should be -+ * 400us for the analog LDOs to power down. -+ */ -+ ldr r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET] -+ ldr r10, [r11, #MX6Q_CCM_CCR] -+ bic r10, r10, #(0x3f << 21) -+ orr r10, r10, #(0x20 << 21) -+ str r10, [r11, #MX6Q_CCM_CCR] -+ -+ /* enable the counter. */ -+ ldr r10, [r11, #MX6Q_CCM_CCR] -+ orr r10, r10, #(0x1 << 27) -+ str r10, [r11, #MX6Q_CCM_CCR] -+ -+ /* unmask all the GPC interrupts. */ -+ ldr r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET] -+ str r6, [r11, #MX6Q_GPC_IMR1] -+ str r7, [r11, #MX6Q_GPC_IMR2] -+ str r8, [r11, #MX6Q_GPC_IMR3] -+ str r9, [r11, #MX6Q_GPC_IMR4] -+ -+ /* -+ * now delay for a short while (3usec) -+ * ARM is at 1GHz at this point -+ * so a short loop should be enough. -+ * this delay is required to ensure that -+ * the RBC counter can start counting in -+ * case an interrupt is already pending -+ * or in case an interrupt arrives just -+ * as ARM is about to assert DSM_request. -+ */ -+ ldr r6, =2000 -+rbc_loop: -+ subs r6, r6, #0x1 -+ bne rbc_loop -+ -+ /* Zzz, enter stop mode */ -+ wfi -+ nop -+ nop -+ nop -+ nop -+ -+ /* -+ * run to here means there is pending -+ * wakeup source, system should auto -+ * resume, we need to restore MMDC IO first -+ */ -+ mov r5, #0x0 -+ resume_mmdc -+ -+ /* return to suspend finish */ -+ mov pc, lr -+ -+resume: -+ /* invalidate L1 I-cache first */ -+ mov r6, #0x0 -+ mcr p15, 0, r6, c7, c5, 0 -+ mcr p15, 0, r6, c7, c5, 6 -+ /* enable the Icache and branch prediction */ -+ mov r6, #0x1800 -+ mcr p15, 0, r6, c1, c0, 0 -+ isb -+ -+ /* get physical resume address from pm_info. */ -+ ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET] -+ /* clear core0's entry and parameter */ -+ ldr r11, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET] -+ mov r7, #0x0 -+ str r7, [r11, #MX6Q_SRC_GPR1] -+ str r7, [r11, #MX6Q_SRC_GPR2] -+ -+ mov r5, #0x1 -+ resume_mmdc -+ -+ mov pc, lr -+ENDPROC(imx6_suspend) -+ -+/* -+ * The following code must assume it is running from physical address -+ * where absolute virtual addresses to the data section have to be -+ * turned into relative ones. -+ */ -+ -+ENTRY(v7_cpu_resume) -+ bl v7_invalidate_l1 -+#ifdef CONFIG_CACHE_L2X0 -+ bl l2c310_early_resume -+#endif -+ b cpu_resume -+ENDPROC(v7_cpu_resume) -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/system.c linux-3.14.22/arch/arm/mach-imx/system.c ---- linux-3.14.22.orig/arch/arm/mach-imx/system.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/system.c 2014-10-22 14:55:49.922220001 -0500 -@@ -34,6 +34,7 @@ - - static void __iomem *wdog_base; - static struct clk *wdog_clk; -+static u32 wdog_source = 1; /* use WDOG1 default */ - - /* - * Reset the system. It is called by machine_restart(). -@@ -47,6 +48,15 @@ - - if (cpu_is_mx1()) - wcr_enable = (1 << 0); -+ /* -+ * Some i.MX6 boards use WDOG2 to reset external pmic in bypass mode, -+ * so do WDOG2 reset here. Do not set SRS, since we will -+ * trigger external POR later. Use WDOG1 to reset in ldo-enable -+ * mode. You can set it by "fsl,wdog-reset" in dts. -+ */ -+ else if (wdog_source == 2 && (cpu_is_imx6q() || cpu_is_imx6dl() || -+ cpu_is_imx6sl())) -+ wcr_enable = 0x14; - else - wcr_enable = (1 << 2); - -@@ -90,12 +100,29 @@ - - void __init mxc_arch_reset_init_dt(void) - { -- struct device_node *np; -+ struct device_node *np = NULL; -+ -+ if (cpu_is_imx6q() || cpu_is_imx6dl()) -+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); -+ else if (cpu_is_imx6sl()) -+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-gpc"); -+ -+ if (np) -+ of_property_read_u32(np, "fsl,wdog-reset", &wdog_source); -+ pr_info("Use WDOG%d as reset source\n", wdog_source); - - np = of_find_compatible_node(NULL, NULL, "fsl,imx21-wdt"); - wdog_base = of_iomap(np, 0); - WARN_ON(!wdog_base); - -+ /* Some i.MX6 boards use WDOG2 to reset board in ldo-bypass mode */ -+ if (wdog_source == 2 && (cpu_is_imx6q() || cpu_is_imx6dl() || -+ cpu_is_imx6sl())) { -+ np = of_find_compatible_node(np, NULL, "fsl,imx21-wdt"); -+ wdog_base = of_iomap(np, 0); -+ WARN_ON(!wdog_base); -+ } -+ - wdog_clk = of_clk_get(np, 0); - if (IS_ERR(wdog_clk)) { - pr_warn("%s: failed to get wdog clock\n", __func__); -@@ -124,7 +151,7 @@ - } - - /* Configure the L2 PREFETCH and POWER registers */ -- val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); -+ val = readl_relaxed(l2x0_base + L310_PREFETCH_CTRL); - val |= 0x70800000; - /* - * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 -@@ -137,14 +164,12 @@ - */ - if (cpu_is_imx6q()) - val &= ~(1 << 30 | 1 << 23); -- writel_relaxed(val, l2x0_base + L2X0_PREFETCH_CTRL); -- val = L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN; -- writel_relaxed(val, l2x0_base + L2X0_POWER_CTRL); -+ writel_relaxed(val, l2x0_base + L310_PREFETCH_CTRL); - - iounmap(l2x0_base); - of_node_put(np); - - out: -- l2x0_of_init(0, ~0UL); -+ l2x0_of_init(0, ~0); - } - #endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-imx/time.c linux-3.14.22/arch/arm/mach-imx/time.c ---- linux-3.14.22.orig/arch/arm/mach-imx/time.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-imx/time.c 2014-10-22 14:55:49.926220001 -0500 -@@ -60,7 +60,11 @@ - #define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ - #define V2_TCTL_CLK_IPG (1 << 6) - #define V2_TCTL_CLK_PER (2 << 6) -+#define V2_TCTL_CLK_OSC_DIV8 (5 << 6) -+#define V2_TCTL_CLK_OSC (7 << 6) -+#define V2_TCTL_24MEN (1 << 10) - #define V2_TCTL_FRR (1 << 9) -+#define V2_TPRER_PRE24M 12 - #define V2_IR 0x0c - #define V2_TSTAT 0x08 - #define V2_TSTAT_OF1 (1 << 0) -@@ -277,11 +281,20 @@ - - void __init mxc_timer_init(void __iomem *base, int irq) - { -- uint32_t tctl_val; -+ uint32_t tctl_val, tprer_val; - struct clk *timer_clk; - struct clk *timer_ipg_clk; - -- timer_clk = clk_get_sys("imx-gpt.0", "per"); -+ /* -+ * gpt clk source from 24M OSC on imx6q > TO1.0 and -+ * imx6dl, others from per clk. -+ */ -+ if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0) -+ || cpu_is_imx6dl()) -+ timer_clk = clk_get_sys("imx-gpt.0", "gpt_3m"); -+ else -+ timer_clk = clk_get_sys("imx-gpt.0", "per"); -+ - if (IS_ERR(timer_clk)) { - pr_err("i.MX timer: unable to get clk\n"); - return; -@@ -302,10 +315,24 @@ - __raw_writel(0, timer_base + MXC_TCTL); - __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ - -- if (timer_is_v2()) -- tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; -- else -+ if (timer_is_v2()) { -+ if ((cpu_is_imx6q() && imx_get_soc_revision() > -+ IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) { -+ tctl_val = V2_TCTL_CLK_OSC_DIV8 | V2_TCTL_FRR | -+ V2_TCTL_WAITEN | MXC_TCTL_TEN; -+ if (cpu_is_imx6dl()) { -+ /* 24 / 8 = 3 MHz */ -+ tprer_val = 7 << V2_TPRER_PRE24M; -+ __raw_writel(tprer_val, timer_base + MXC_TPRER); -+ tctl_val |= V2_TCTL_24MEN; -+ } -+ } else { -+ tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | -+ V2_TCTL_WAITEN | MXC_TCTL_TEN; -+ } -+ } else { - tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; -+ } - - __raw_writel(tctl_val, timer_base + MXC_TCTL); - -diff -Nur linux-3.14.22.orig/arch/arm/mach-nomadik/cpu-8815.c linux-3.14.22/arch/arm/mach-nomadik/cpu-8815.c ---- linux-3.14.22.orig/arch/arm/mach-nomadik/cpu-8815.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-nomadik/cpu-8815.c 2014-10-22 14:55:49.926220001 -0500 -@@ -147,7 +147,7 @@ - { - #ifdef CONFIG_CACHE_L2X0 - /* At full speed latency must be >=2, so 0x249 in low bits */ -- l2x0_of_init(0x00730249, 0xfe000fff); -+ l2x0_of_init(0x00700249, 0xfe0fefff); - #endif - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-omap2/common.h linux-3.14.22/arch/arm/mach-omap2/common.h ---- linux-3.14.22.orig/arch/arm/mach-omap2/common.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-omap2/common.h 2014-10-22 14:55:49.926220001 -0500 -@@ -91,6 +91,7 @@ - extern void omap3_secure_sync32k_timer_init(void); - extern void omap3_gptimer_timer_init(void); - extern void omap4_local_timer_init(void); -+int omap_l2_cache_init(void); - extern void omap5_realtime_timer_init(void); - - void omap2420_init_early(void); -diff -Nur linux-3.14.22.orig/arch/arm/mach-omap2/io.c linux-3.14.22/arch/arm/mach-omap2/io.c ---- linux-3.14.22.orig/arch/arm/mach-omap2/io.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-omap2/io.c 2014-10-22 14:55:49.926220001 -0500 -@@ -608,6 +608,7 @@ - am43xx_clockdomains_init(); - am43xx_hwmod_init(); - omap_hwmod_init_postsetup(); -+ omap_l2_cache_init(); - omap_clk_soc_init = am43xx_dt_clk_init; - } - -@@ -639,6 +640,7 @@ - omap44xx_clockdomains_init(); - omap44xx_hwmod_init(); - omap_hwmod_init_postsetup(); -+ omap_l2_cache_init(); - omap_clk_soc_init = omap4xxx_dt_clk_init; - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-omap2/Kconfig linux-3.14.22/arch/arm/mach-omap2/Kconfig ---- linux-3.14.22.orig/arch/arm/mach-omap2/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-omap2/Kconfig 2014-10-22 14:55:49.926220001 -0500 -@@ -78,6 +78,7 @@ - select MULTI_IRQ_HANDLER - select ARM_GIC - select MACH_OMAP_GENERIC -+ select MIGHT_HAVE_CACHE_L2X0 - - config SOC_DRA7XX - bool "TI DRA7XX" -diff -Nur linux-3.14.22.orig/arch/arm/mach-omap2/omap4-common.c linux-3.14.22/arch/arm/mach-omap2/omap4-common.c ---- linux-3.14.22.orig/arch/arm/mach-omap2/omap4-common.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-omap2/omap4-common.c 2014-10-22 14:55:49.926220001 -0500 -@@ -166,75 +166,57 @@ - return l2cache_base; - } - --static void omap4_l2x0_disable(void) -+static void omap4_l2c310_write_sec(unsigned long val, unsigned reg) - { -- outer_flush_all(); -- /* Disable PL310 L2 Cache controller */ -- omap_smc1(0x102, 0x0); --} -+ unsigned smc_op; - --static void omap4_l2x0_set_debug(unsigned long val) --{ -- /* Program PL310 L2 Cache controller debug register */ -- omap_smc1(0x100, val); -+ switch (reg) { -+ case L2X0_CTRL: -+ smc_op = OMAP4_MON_L2X0_CTRL_INDEX; -+ break; -+ -+ case L2X0_AUX_CTRL: -+ smc_op = OMAP4_MON_L2X0_AUXCTRL_INDEX; -+ break; -+ -+ case L2X0_DEBUG_CTRL: -+ smc_op = OMAP4_MON_L2X0_DBG_CTRL_INDEX; -+ break; -+ -+ case L310_PREFETCH_CTRL: -+ smc_op = OMAP4_MON_L2X0_PREFETCH_INDEX; -+ break; -+ -+ default: -+ WARN_ONCE(1, "OMAP L2C310: ignoring write to reg 0x%x\n", reg); -+ return; -+ } -+ -+ omap_smc1(smc_op, val); - } - --static int __init omap_l2_cache_init(void) -+int __init omap_l2_cache_init(void) - { -- u32 aux_ctrl = 0; -- -- /* -- * To avoid code running on other OMAPs in -- * multi-omap builds -- */ -- if (!cpu_is_omap44xx()) -- return -ENODEV; -+ u32 aux_ctrl; - - /* Static mapping, never released */ - l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K); - if (WARN_ON(!l2cache_base)) - return -ENOMEM; - -- /* -- * 16-way associativity, parity disabled -- * Way size - 32KB (es1.0) -- * Way size - 64KB (es2.0 +) -- */ -- aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) | -- (0x1 << 25) | -- (0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) | -- (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT)); -- -- if (omap_rev() == OMAP4430_REV_ES1_0) { -- aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT; -- } else { -- aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | -- (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | -- (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | -- (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | -- (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT)); -- } -- if (omap_rev() != OMAP4430_REV_ES1_0) -- omap_smc1(0x109, aux_ctrl); -- -- /* Enable PL310 L2 Cache controller */ -- omap_smc1(0x102, 0x1); -+ /* 16-way associativity, parity disabled, way size - 64KB (es2.0 +) */ -+ aux_ctrl = L2C_AUX_CTRL_SHARED_OVERRIDE | -+ L310_AUX_CTRL_DATA_PREFETCH | -+ L310_AUX_CTRL_INSTR_PREFETCH; - -+ outer_cache.write_sec = omap4_l2c310_write_sec; - if (of_have_populated_dt()) -- l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); -+ l2x0_of_init(aux_ctrl, 0xcf9fffff); - else -- l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); -- -- /* -- * Override default outer_cache.disable with a OMAP4 -- * specific one -- */ -- outer_cache.disable = omap4_l2x0_disable; -- outer_cache.set_debug = omap4_l2x0_set_debug; -+ l2x0_init(l2cache_base, aux_ctrl, 0xcf9fffff); - - return 0; - } --omap_early_initcall(omap_l2_cache_init); - #endif - - void __iomem *omap4_get_sar_ram_base(void) -diff -Nur linux-3.14.22.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c linux-3.14.22/arch/arm/mach-omap2/omap-mpuss-lowpower.c ---- linux-3.14.22.orig/arch/arm/mach-omap2/omap-mpuss-lowpower.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-omap2/omap-mpuss-lowpower.c 2014-10-22 14:55:49.926220001 -0500 -@@ -187,19 +187,15 @@ - * in every restore MPUSS OFF path. - */ - #ifdef CONFIG_CACHE_L2X0 --static void save_l2x0_context(void) -+static void __init save_l2x0_context(void) - { -- u32 val; -- void __iomem *l2x0_base = omap4_get_l2cache_base(); -- if (l2x0_base) { -- val = __raw_readl(l2x0_base + L2X0_AUX_CTRL); -- __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET); -- val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL); -- __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); -- } -+ __raw_writel(l2x0_saved_regs.aux_ctrl, -+ sar_base + L2X0_AUXCTRL_OFFSET); -+ __raw_writel(l2x0_saved_regs.prefetch_ctrl, -+ sar_base + L2X0_PREFETCH_CTRL_OFFSET); - } - #else --static void save_l2x0_context(void) -+static void __init save_l2x0_context(void) - {} - #endif - -diff -Nur linux-3.14.22.orig/arch/arm/mach-prima2/l2x0.c linux-3.14.22/arch/arm/mach-prima2/l2x0.c ---- linux-3.14.22.orig/arch/arm/mach-prima2/l2x0.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-prima2/l2x0.c 2014-10-22 14:55:49.926220001 -0500 -@@ -8,43 +8,10 @@ - - #include - #include --#include - #include - --struct l2x0_aux --{ -- u32 val; -- u32 mask; --}; -- --static struct l2x0_aux prima2_l2x0_aux __initconst = { -- .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT, -- .mask = 0, --}; -- --static struct l2x0_aux marco_l2x0_aux __initconst = { -- .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | -- (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT), -- .mask = L2X0_AUX_CTRL_MASK, --}; -- --static struct of_device_id sirf_l2x0_ids[] __initconst = { -- { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, }, -- { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, }, -- {}, --}; -- - static int __init sirfsoc_l2x0_init(void) - { -- struct device_node *np; -- const struct l2x0_aux *aux; -- -- np = of_find_matching_node(NULL, sirf_l2x0_ids); -- if (np) { -- aux = of_match_node(sirf_l2x0_ids, np)->data; -- return l2x0_of_init(aux->val, aux->mask); -- } -- -- return 0; -+ return l2x0_of_init(0, ~0); - } - early_initcall(sirfsoc_l2x0_init); -diff -Nur linux-3.14.22.orig/arch/arm/mach-prima2/pm.c linux-3.14.22/arch/arm/mach-prima2/pm.c ---- linux-3.14.22.orig/arch/arm/mach-prima2/pm.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-prima2/pm.c 2014-10-22 14:55:49.926220001 -0500 -@@ -71,7 +71,6 @@ - case PM_SUSPEND_MEM: - sirfsoc_pre_suspend_power_off(); - -- outer_flush_all(); - outer_disable(); - /* go zzz */ - cpu_suspend(0, sirfsoc_finish_suspend); -diff -Nur linux-3.14.22.orig/arch/arm/mach-realview/realview_eb.c linux-3.14.22/arch/arm/mach-realview/realview_eb.c ---- linux-3.14.22.orig/arch/arm/mach-realview/realview_eb.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-realview/realview_eb.c 2014-10-22 14:55:49.926220001 -0500 -@@ -442,8 +442,13 @@ - realview_eb11mp_fixup(); - - #ifdef CONFIG_CACHE_L2X0 -- /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled -- * Bits: .... ...0 0111 1001 0000 .... .... .... */ -+ /* -+ * The PL220 needs to be manually configured as the hardware -+ * doesn't report the correct sizes. -+ * 1MB (128KB/way), 8-way associativity, event monitor and -+ * parity enabled, ignore share bit, no force write allocate -+ * Bits: .... ...0 0111 1001 0000 .... .... .... -+ */ - l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); - #endif - platform_device_register(&pmu_device); -diff -Nur linux-3.14.22.orig/arch/arm/mach-realview/realview_pb1176.c linux-3.14.22/arch/arm/mach-realview/realview_pb1176.c ---- linux-3.14.22.orig/arch/arm/mach-realview/realview_pb1176.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-realview/realview_pb1176.c 2014-10-22 14:55:49.926220001 -0500 -@@ -355,7 +355,13 @@ - int i; - - #ifdef CONFIG_CACHE_L2X0 -- /* 128Kb (16Kb/way) 8-way associativity. evmon/parity/share enabled. */ -+ /* -+ * The PL220 needs to be manually configured as the hardware -+ * doesn't report the correct sizes. -+ * 128kB (16kB/way), 8-way associativity, event monitor and -+ * parity enabled, ignore share bit, no force write allocate -+ * Bits: .... ...0 0111 0011 0000 .... .... .... -+ */ - l2x0_init(__io_address(REALVIEW_PB1176_L220_BASE), 0x00730000, 0xfe000fff); - #endif - -diff -Nur linux-3.14.22.orig/arch/arm/mach-realview/realview_pb11mp.c linux-3.14.22/arch/arm/mach-realview/realview_pb11mp.c ---- linux-3.14.22.orig/arch/arm/mach-realview/realview_pb11mp.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-realview/realview_pb11mp.c 2014-10-22 14:55:49.926220001 -0500 -@@ -337,8 +337,13 @@ - int i; - - #ifdef CONFIG_CACHE_L2X0 -- /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled -- * Bits: .... ...0 0111 1001 0000 .... .... .... */ -+ /* -+ * The PL220 needs to be manually configured as the hardware -+ * doesn't report the correct sizes. -+ * 1MB (128KB/way), 8-way associativity, event monitor and -+ * parity enabled, ignore share bit, no force write allocate -+ * Bits: .... ...0 0111 1001 0000 .... .... .... -+ */ - l2x0_init(__io_address(REALVIEW_TC11MP_L220_BASE), 0x00790000, 0xfe000fff); - #endif - -diff -Nur linux-3.14.22.orig/arch/arm/mach-realview/realview_pbx.c linux-3.14.22/arch/arm/mach-realview/realview_pbx.c ---- linux-3.14.22.orig/arch/arm/mach-realview/realview_pbx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-realview/realview_pbx.c 2014-10-22 14:55:49.926220001 -0500 -@@ -370,8 +370,8 @@ - __io_address(REALVIEW_PBX_TILE_L220_BASE); - - /* set RAM latencies to 1 cycle for eASIC */ -- writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); -- writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); -+ writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); -+ writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); - - /* 16KB way size, 8-way associativity, parity disabled - * Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */ -diff -Nur linux-3.14.22.orig/arch/arm/mach-rockchip/rockchip.c linux-3.14.22/arch/arm/mach-rockchip/rockchip.c ---- linux-3.14.22.orig/arch/arm/mach-rockchip/rockchip.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-rockchip/rockchip.c 2014-10-22 14:55:49.926220001 -0500 -@@ -25,7 +25,7 @@ - - static void __init rockchip_dt_init(void) - { -- l2x0_of_init(0, ~0UL); -+ l2x0_of_init(0, ~0); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/board-armadillo800eva.c linux-3.14.22/arch/arm/mach-shmobile/board-armadillo800eva.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/board-armadillo800eva.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/board-armadillo800eva.c 2014-10-22 14:55:49.926220001 -0500 -@@ -1270,8 +1270,8 @@ - - - #ifdef CONFIG_CACHE_L2X0 -- /* Early BRESP enable, Shared attribute override enable, 32K*8way */ -- l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff); -+ /* Shared attribute override enable, 32K*8way */ -+ l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff); - #endif - - i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c linux-3.14.22/arch/arm/mach-shmobile/board-armadillo800eva-reference.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/board-armadillo800eva-reference.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/board-armadillo800eva-reference.c 2014-10-22 14:55:49.926220001 -0500 -@@ -164,8 +164,8 @@ - r8a7740_meram_workaround(); - - #ifdef CONFIG_CACHE_L2X0 -- /* Early BRESP enable, Shared attribute override enable, 32K*8way */ -- l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff); -+ /* Shared attribute override enable, 32K*8way */ -+ l2x0_init(IOMEM(0xf0002000), 0x00400000, 0xc20f0fff); - #endif - - r8a7740_add_standard_devices_dt(); -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/board-kzm9g.c linux-3.14.22/arch/arm/mach-shmobile/board-kzm9g.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/board-kzm9g.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/board-kzm9g.c 2014-10-22 14:55:49.926220001 -0500 -@@ -878,8 +878,8 @@ - gpio_request_one(223, GPIOF_IN, NULL); /* IRQ8 */ - - #ifdef CONFIG_CACHE_L2X0 -- /* Early BRESP enable, Shared attribute override enable, 64K*8way */ -- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff); -+ /* Shared attribute override enable, 64K*8way */ -+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); - #endif - - i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c linux-3.14.22/arch/arm/mach-shmobile/board-kzm9g-reference.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/board-kzm9g-reference.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/board-kzm9g-reference.c 2014-10-22 14:55:49.926220001 -0500 -@@ -36,8 +36,8 @@ - sh73a0_add_standard_devices_dt(); - - #ifdef CONFIG_CACHE_L2X0 -- /* Early BRESP enable, Shared attribute override enable, 64K*8way */ -- l2x0_init(IOMEM(0xf0100000), 0x40460000, 0x82000fff); -+ /* Shared attribute override enable, 64K*8way */ -+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); - #endif - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/setup-r8a7778.c linux-3.14.22/arch/arm/mach-shmobile/setup-r8a7778.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/setup-r8a7778.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/setup-r8a7778.c 2014-10-22 14:55:49.926220001 -0500 -@@ -298,10 +298,10 @@ - void __iomem *base = ioremap_nocache(0xf0100000, 0x1000); - if (base) { - /* -- * Early BRESP enable, Shared attribute override enable, 64K*16way -+ * Shared attribute override enable, 64K*16way - * don't call iounmap(base) - */ -- l2x0_init(base, 0x40470000, 0x82000fff); -+ l2x0_init(base, 0x00400000, 0xc20f0fff); - } - #endif - -diff -Nur linux-3.14.22.orig/arch/arm/mach-shmobile/setup-r8a7779.c linux-3.14.22/arch/arm/mach-shmobile/setup-r8a7779.c ---- linux-3.14.22.orig/arch/arm/mach-shmobile/setup-r8a7779.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-shmobile/setup-r8a7779.c 2014-10-22 14:55:49.926220001 -0500 -@@ -700,8 +700,8 @@ - void __init r8a7779_add_standard_devices(void) - { - #ifdef CONFIG_CACHE_L2X0 -- /* Early BRESP enable, Shared attribute override enable, 64K*16way */ -- l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff); -+ /* Shared attribute override enable, 64K*16way */ -+ l2x0_init(IOMEM(0xf0100000), 0x00400000, 0xc20f0fff); - #endif - r8a7779_pm_init(); - -diff -Nur linux-3.14.22.orig/arch/arm/mach-socfpga/socfpga.c linux-3.14.22/arch/arm/mach-socfpga/socfpga.c ---- linux-3.14.22.orig/arch/arm/mach-socfpga/socfpga.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-socfpga/socfpga.c 2014-10-22 14:55:49.926220001 -0500 -@@ -104,7 +104,7 @@ - - static void __init socfpga_cyclone5_init(void) - { -- l2x0_of_init(0, ~0UL); -+ l2x0_of_init(0, ~0); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - socfpga_init_clocks(); - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-spear/platsmp.c linux-3.14.22/arch/arm/mach-spear/platsmp.c ---- linux-3.14.22.orig/arch/arm/mach-spear/platsmp.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-spear/platsmp.c 2014-10-22 14:55:49.926220001 -0500 -@@ -20,6 +20,18 @@ - #include - #include "generic.h" - -+/* -+ * Write pen_release in a way that is guaranteed to be visible to all -+ * observers, irrespective of whether they're taking part in coherency -+ * or not. This is necessary for the hotplug code to work reliably. -+ */ -+static void write_pen_release(int val) -+{ -+ pen_release = val; -+ smp_wmb(); -+ sync_cache_w(&pen_release); -+} -+ - static DEFINE_SPINLOCK(boot_lock); - - static void __iomem *scu_base = IOMEM(VA_SCU_BASE); -@@ -30,8 +42,7 @@ - * let the primary processor know we're out of the - * pen, then head off into the C entry point - */ -- pen_release = -1; -- smp_wmb(); -+ write_pen_release(-1); - - /* - * Synchronise with the boot thread. -@@ -58,9 +69,7 @@ - * Note that "pen_release" is the hardware CPU ID, whereas - * "cpu" is Linux's internal ID. - */ -- pen_release = cpu; -- flush_cache_all(); -- outer_flush_all(); -+ write_pen_release(cpu); - - timeout = jiffies + (1 * HZ); - while (time_before(jiffies, timeout)) { -diff -Nur linux-3.14.22.orig/arch/arm/mach-spear/spear13xx.c linux-3.14.22/arch/arm/mach-spear/spear13xx.c ---- linux-3.14.22.orig/arch/arm/mach-spear/spear13xx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-spear/spear13xx.c 2014-10-22 14:55:49.926220001 -0500 -@@ -38,15 +38,15 @@ - if (!IS_ENABLED(CONFIG_CACHE_L2X0)) - return; - -- writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL); -+ writel_relaxed(0x06, VA_L2CC_BASE + L310_PREFETCH_CTRL); - - /* - * Program following latencies in order to make - * SPEAr1340 work at 600 MHz - */ -- writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL); -- writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL); -- l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff); -+ writel_relaxed(0x221, VA_L2CC_BASE + L310_TAG_LATENCY_CTRL); -+ writel_relaxed(0x441, VA_L2CC_BASE + L310_DATA_LATENCY_CTRL); -+ l2x0_init(VA_L2CC_BASE, 0x30a00001, 0xfe0fffff); - } - - /* -diff -Nur linux-3.14.22.orig/arch/arm/mach-sti/board-dt.c linux-3.14.22/arch/arm/mach-sti/board-dt.c ---- linux-3.14.22.orig/arch/arm/mach-sti/board-dt.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-sti/board-dt.c 2014-10-22 14:55:49.926220001 -0500 -@@ -16,15 +16,9 @@ - - void __init stih41x_l2x0_init(void) - { -- u32 way_size = 0x4; -- u32 aux_ctrl; -- /* may be this can be encoded in macros like BIT*() */ -- aux_ctrl = (0x1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) | -- (0x1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) | -- (0x1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) | -- (way_size << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); -- -- l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); -+ l2x0_of_init(L2C_AUX_CTRL_SHARED_OVERRIDE | -+ L310_AUX_CTRL_DATA_PREFETCH | -+ L310_AUX_CTRL_INSTR_PREFETCH, 0xc00f0fff); - } - - static void __init stih41x_machine_init(void) -diff -Nur linux-3.14.22.orig/arch/arm/mach-tegra/pm.h linux-3.14.22/arch/arm/mach-tegra/pm.h ---- linux-3.14.22.orig/arch/arm/mach-tegra/pm.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-tegra/pm.h 2014-10-22 14:55:49.926220001 -0500 -@@ -35,8 +35,6 @@ - void tegra30_lp1_iram_hook(void); - void tegra30_sleep_core_init(void); - --extern unsigned long l2x0_saved_regs_addr; -- - void tegra_clear_cpu_in_lp2(void); - bool tegra_set_cpu_in_lp2(void); - -diff -Nur linux-3.14.22.orig/arch/arm/mach-tegra/reset-handler.S linux-3.14.22/arch/arm/mach-tegra/reset-handler.S ---- linux-3.14.22.orig/arch/arm/mach-tegra/reset-handler.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-tegra/reset-handler.S 2014-10-22 14:55:49.926220001 -0500 -@@ -19,7 +19,6 @@ - - #include - #include --#include - - #include "flowctrl.h" - #include "fuse.h" -@@ -78,8 +77,10 @@ - str r1, [r0] - #endif - -+#ifdef CONFIG_CACHE_L2X0 - /* L2 cache resume & re-enable */ -- l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr -+ bl l2c310_early_resume -+#endif - end_ca9_scu_l2_resume: - mov32 r9, 0xc0f - cmp r8, r9 -@@ -89,12 +90,6 @@ - ENDPROC(tegra_resume) - #endif - --#ifdef CONFIG_CACHE_L2X0 -- .globl l2x0_saved_regs_addr --l2x0_saved_regs_addr: -- .long 0 --#endif -- - .align L1_CACHE_SHIFT - ENTRY(__tegra_cpu_reset_handler_start) - -diff -Nur linux-3.14.22.orig/arch/arm/mach-tegra/sleep.h linux-3.14.22/arch/arm/mach-tegra/sleep.h ---- linux-3.14.22.orig/arch/arm/mach-tegra/sleep.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-tegra/sleep.h 2014-10-22 14:55:49.926220001 -0500 -@@ -120,37 +120,6 @@ - mov \tmp1, \tmp1, lsr #8 - .endm - --/* Macro to resume & re-enable L2 cache */ --#ifndef L2X0_CTRL_EN --#define L2X0_CTRL_EN 1 --#endif -- --#ifdef CONFIG_CACHE_L2X0 --.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs -- W(adr) \tmp1, \phys_l2x0_saved_regs -- ldr \tmp1, [\tmp1] -- ldr \tmp2, [\tmp1, #L2X0_R_PHY_BASE] -- ldr \tmp3, [\tmp2, #L2X0_CTRL] -- tst \tmp3, #L2X0_CTRL_EN -- bne exit_l2_resume -- ldr \tmp3, [\tmp1, #L2X0_R_TAG_LATENCY] -- str \tmp3, [\tmp2, #L2X0_TAG_LATENCY_CTRL] -- ldr \tmp3, [\tmp1, #L2X0_R_DATA_LATENCY] -- str \tmp3, [\tmp2, #L2X0_DATA_LATENCY_CTRL] -- ldr \tmp3, [\tmp1, #L2X0_R_PREFETCH_CTRL] -- str \tmp3, [\tmp2, #L2X0_PREFETCH_CTRL] -- ldr \tmp3, [\tmp1, #L2X0_R_PWR_CTRL] -- str \tmp3, [\tmp2, #L2X0_POWER_CTRL] -- ldr \tmp3, [\tmp1, #L2X0_R_AUX_CTRL] -- str \tmp3, [\tmp2, #L2X0_AUX_CTRL] -- mov \tmp3, #L2X0_CTRL_EN -- str \tmp3, [\tmp2, #L2X0_CTRL] --exit_l2_resume: --.endm --#else /* CONFIG_CACHE_L2X0 */ --.macro l2_cache_resume, tmp1, tmp2, tmp3, phys_l2x0_saved_regs --.endm --#endif /* CONFIG_CACHE_L2X0 */ - #else - void tegra_pen_lock(void); - void tegra_pen_unlock(void); -diff -Nur linux-3.14.22.orig/arch/arm/mach-tegra/tegra.c linux-3.14.22/arch/arm/mach-tegra/tegra.c ---- linux-3.14.22.orig/arch/arm/mach-tegra/tegra.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-tegra/tegra.c 2014-10-22 14:55:49.930220001 -0500 -@@ -73,27 +73,7 @@ - static void __init tegra_init_cache(void) - { - #ifdef CONFIG_CACHE_L2X0 -- static const struct of_device_id pl310_ids[] __initconst = { -- { .compatible = "arm,pl310-cache", }, -- {} -- }; -- -- struct device_node *np; -- int ret; -- void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; -- u32 aux_ctrl, cache_type; -- -- np = of_find_matching_node(NULL, pl310_ids); -- if (!np) -- return; -- -- cache_type = readl(p + L2X0_CACHE_TYPE); -- aux_ctrl = (cache_type & 0x700) << (17-8); -- aux_ctrl |= 0x7C400001; -- -- ret = l2x0_of_init(aux_ctrl, 0x8200c3fe); -- if (!ret) -- l2x0_saved_regs_addr = virt_to_phys(&l2x0_saved_regs); -+ l2x0_of_init(0x3c400001, 0xc20fc3fe); - #endif - } - -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/board-mop500-audio.c linux-3.14.22/arch/arm/mach-ux500/board-mop500-audio.c ---- linux-3.14.22.orig/arch/arm/mach-ux500/board-mop500-audio.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/board-mop500-audio.c 2014-10-22 14:55:49.930220001 -0500 -@@ -9,7 +9,6 @@ - #include - #include - --#include "irqs.h" - #include - - #include "ste-dma40-db8500.h" -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/cache-l2x0.c linux-3.14.22/arch/arm/mach-ux500/cache-l2x0.c ---- linux-3.14.22.orig/arch/arm/mach-ux500/cache-l2x0.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/cache-l2x0.c 2014-10-22 14:55:49.930220001 -0500 -@@ -35,10 +35,16 @@ - return 0; - } - --static int __init ux500_l2x0_init(void) -+static void ux500_l2c310_write_sec(unsigned long val, unsigned reg) - { -- u32 aux_val = 0x3e000000; -+ /* -+ * We can't write to secure registers as we are in non-secure -+ * mode, until we have some SMI service available. -+ */ -+} - -+static int __init ux500_l2x0_init(void) -+{ - if (cpu_is_u8500_family() || cpu_is_ux540_family()) - l2x0_base = __io_address(U8500_L2CC_BASE); - else -@@ -48,28 +54,12 @@ - /* Unlock before init */ - ux500_l2x0_unlock(); - -- /* DBx540's L2 has 128KB way size */ -- if (cpu_is_ux540_family()) -- /* 128KB way size */ -- aux_val |= (0x4 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); -- else -- /* 64KB way size */ -- aux_val |= (0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT); -+ outer_cache.write_sec = ux500_l2c310_write_sec; - -- /* 64KB way size, 8 way associativity, force WA */ - if (of_have_populated_dt()) -- l2x0_of_init(aux_val, 0xc0000fff); -+ l2x0_of_init(0, ~0); - else -- l2x0_init(l2x0_base, aux_val, 0xc0000fff); -- -- /* -- * We can't disable l2 as we are in non secure mode, currently -- * this seems be called only during kexec path. So let's -- * override outer.disable with nasty assignment until we have -- * some SMI service available. -- */ -- outer_cache.disable = NULL; -- outer_cache.set_debug = NULL; -+ l2x0_init(l2x0_base, 0, ~0); - - return 0; - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/cpu-db8500.c linux-3.14.22/arch/arm/mach-ux500/cpu-db8500.c ---- linux-3.14.22.orig/arch/arm/mach-ux500/cpu-db8500.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/cpu-db8500.c 2014-10-22 14:55:49.930220001 -0500 -@@ -27,7 +27,6 @@ - #include - - #include "setup.h" --#include "irqs.h" - - #include "board-mop500-regulators.h" - #include "board-mop500.h" -@@ -35,14 +34,11 @@ - #include "id.h" - - struct ab8500_platform_data ab8500_platdata = { -- .irq_base = MOP500_AB8500_IRQ_BASE, - .regulator = &ab8500_regulator_plat_data, - }; - - struct prcmu_pdata db8500_prcmu_pdata = { - .ab_platdata = &ab8500_platdata, -- .ab_irq = IRQ_DB8500_AB8500, -- .irq_base = IRQ_PRCMU_BASE, - .version_offset = DB8500_PRCMU_FW_VERSION_OFFSET, - .legacy_offset = DB8500_PRCMU_LEGACY_OFFSET, - }; -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/irqs-board-mop500.h linux-3.14.22/arch/arm/mach-ux500/irqs-board-mop500.h ---- linux-3.14.22.orig/arch/arm/mach-ux500/irqs-board-mop500.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/irqs-board-mop500.h 1969-12-31 18:00:00.000000000 -0600 -@@ -1,55 +0,0 @@ --/* -- * Copyright (C) ST-Ericsson SA 2010 -- * -- * Author: Rabin Vincent -- * License terms: GNU General Public License (GPL) version 2 -- */ -- --#ifndef __MACH_IRQS_BOARD_MOP500_H --#define __MACH_IRQS_BOARD_MOP500_H -- --/* Number of AB8500 irqs is taken from header file */ --#include -- --#define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START --#define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ -- + AB8500_MAX_NR_IRQS) -- --/* TC35892 */ --#define TC35892_NR_INTERNAL_IRQS 8 --#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) --#define TC35892_NR_GPIOS 24 --#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) -- --#define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS -- --#define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END --#define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \ -- + MOP500_EGPIO_NR_IRQS) --/* STMPE1601 irqs */ --#define STMPE_NR_INTERNAL_IRQS 9 --#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x)) --#define STMPE_NR_GPIOS 24 --#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS) -- --#define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END --#define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x)) -- --#define MOP500_STMPE1601_IRQ_END \ -- MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS) -- --#define MOP500_NR_IRQS MOP500_STMPE1601_IRQ_END -- --#define MOP500_IRQ_END MOP500_NR_IRQS -- --/* -- * We may have several boards, but only one will run at a -- * time, so the one with most IRQs will bump this ahead, -- * but the IRQ_BOARD_START remains the same for either board. -- */ --#if MOP500_IRQ_END > IRQ_BOARD_END --#undef IRQ_BOARD_END --#define IRQ_BOARD_END MOP500_IRQ_END --#endif -- --#endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/irqs-db8500.h linux-3.14.22/arch/arm/mach-ux500/irqs-db8500.h ---- linux-3.14.22.orig/arch/arm/mach-ux500/irqs-db8500.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/irqs-db8500.h 1969-12-31 18:00:00.000000000 -0600 -@@ -1,125 +0,0 @@ --/* -- * Copyright (C) ST-Ericsson SA 2010 -- * -- * Author: Rabin Vincent -- * License terms: GNU General Public License (GPL) version 2 -- */ -- --#ifndef __MACH_IRQS_DB8500_H --#define __MACH_IRQS_DB8500_H -- --#define IRQ_DB8500_MTU0 (IRQ_SHPI_START + 4) --#define IRQ_DB8500_SPI2 (IRQ_SHPI_START + 6) --#define IRQ_DB8500_PMU (IRQ_SHPI_START + 7) --#define IRQ_DB8500_SPI0 (IRQ_SHPI_START + 8) --#define IRQ_DB8500_RTT (IRQ_SHPI_START + 9) --#define IRQ_DB8500_PKA (IRQ_SHPI_START + 10) --#define IRQ_DB8500_UART0 (IRQ_SHPI_START + 11) --#define IRQ_DB8500_I2C3 (IRQ_SHPI_START + 12) --#define IRQ_DB8500_L2CC (IRQ_SHPI_START + 13) --#define IRQ_DB8500_SSP0 (IRQ_SHPI_START + 14) --#define IRQ_DB8500_CRYP1 (IRQ_SHPI_START + 15) --#define IRQ_DB8500_MSP1_RX (IRQ_SHPI_START + 16) --#define IRQ_DB8500_MTU1 (IRQ_SHPI_START + 17) --#define IRQ_DB8500_RTC (IRQ_SHPI_START + 18) --#define IRQ_DB8500_UART1 (IRQ_SHPI_START + 19) --#define IRQ_DB8500_USB_WAKEUP (IRQ_SHPI_START + 20) --#define IRQ_DB8500_I2C0 (IRQ_SHPI_START + 21) --#define IRQ_DB8500_I2C1 (IRQ_SHPI_START + 22) --#define IRQ_DB8500_USBOTG (IRQ_SHPI_START + 23) --#define IRQ_DB8500_DMA_SECURE (IRQ_SHPI_START + 24) --#define IRQ_DB8500_DMA (IRQ_SHPI_START + 25) --#define IRQ_DB8500_UART2 (IRQ_SHPI_START + 26) --#define IRQ_DB8500_ICN_PMU1 (IRQ_SHPI_START + 27) --#define IRQ_DB8500_ICN_PMU2 (IRQ_SHPI_START + 28) --#define IRQ_DB8500_HSIR_EXCEP (IRQ_SHPI_START + 29) --#define IRQ_DB8500_MSP0 (IRQ_SHPI_START + 31) --#define IRQ_DB8500_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32) --#define IRQ_DB8500_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33) --#define IRQ_DB8500_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34) --#define IRQ_DB8500_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35) --#define IRQ_DB8500_HSIR_CH4_OVRRUN (IRQ_SHPI_START + 36) --#define IRQ_DB8500_HSIR_CH5_OVRRUN (IRQ_SHPI_START + 37) --#define IRQ_DB8500_HSIR_CH6_OVRRUN (IRQ_SHPI_START + 38) --#define IRQ_DB8500_HSIR_CH7_OVRRUN (IRQ_SHPI_START + 39) --#define IRQ_DB8500_AB8500 (IRQ_SHPI_START + 40) --#define IRQ_DB8500_SDMMC2 (IRQ_SHPI_START + 41) --#define IRQ_DB8500_SIA (IRQ_SHPI_START + 42) --#define IRQ_DB8500_SIA2 (IRQ_SHPI_START + 43) --#define IRQ_DB8500_SVA (IRQ_SHPI_START + 44) --#define IRQ_DB8500_SVA2 (IRQ_SHPI_START + 45) --#define IRQ_DB8500_PRCMU0 (IRQ_SHPI_START + 46) --#define IRQ_DB8500_PRCMU1 (IRQ_SHPI_START + 47) --#define IRQ_DB8500_DISP (IRQ_SHPI_START + 48) --#define IRQ_DB8500_SPI3 (IRQ_SHPI_START + 49) --#define IRQ_DB8500_SDMMC1 (IRQ_SHPI_START + 50) --#define IRQ_DB8500_I2C4 (IRQ_SHPI_START + 51) --#define IRQ_DB8500_SSP1 (IRQ_SHPI_START + 52) --#define IRQ_DB8500_SKE (IRQ_SHPI_START + 53) --#define IRQ_DB8500_KB (IRQ_SHPI_START + 54) --#define IRQ_DB8500_I2C2 (IRQ_SHPI_START + 55) --#define IRQ_DB8500_B2R2 (IRQ_SHPI_START + 56) --#define IRQ_DB8500_CRYP0 (IRQ_SHPI_START + 57) --#define IRQ_DB8500_SDMMC3 (IRQ_SHPI_START + 59) --#define IRQ_DB8500_SDMMC0 (IRQ_SHPI_START + 60) --#define IRQ_DB8500_HSEM (IRQ_SHPI_START + 61) --#define IRQ_DB8500_MSP1 (IRQ_SHPI_START + 62) --#define IRQ_DB8500_SBAG (IRQ_SHPI_START + 63) --#define IRQ_DB8500_SPI1 (IRQ_SHPI_START + 96) --#define IRQ_DB8500_SRPTIMER (IRQ_SHPI_START + 97) --#define IRQ_DB8500_MSP2 (IRQ_SHPI_START + 98) --#define IRQ_DB8500_SDMMC4 (IRQ_SHPI_START + 99) --#define IRQ_DB8500_SDMMC5 (IRQ_SHPI_START + 100) --#define IRQ_DB8500_HSIRD0 (IRQ_SHPI_START + 104) --#define IRQ_DB8500_HSIRD1 (IRQ_SHPI_START + 105) --#define IRQ_DB8500_HSITD0 (IRQ_SHPI_START + 106) --#define IRQ_DB8500_HSITD1 (IRQ_SHPI_START + 107) --#define IRQ_DB8500_CTI0 (IRQ_SHPI_START + 108) --#define IRQ_DB8500_CTI1 (IRQ_SHPI_START + 109) --#define IRQ_DB8500_ICN_ERR (IRQ_SHPI_START + 110) --#define IRQ_DB8500_MALI_PPMMU (IRQ_SHPI_START + 112) --#define IRQ_DB8500_MALI_PP (IRQ_SHPI_START + 113) --#define IRQ_DB8500_MALI_GPMMU (IRQ_SHPI_START + 114) --#define IRQ_DB8500_MALI_GP (IRQ_SHPI_START + 115) --#define IRQ_DB8500_MALI (IRQ_SHPI_START + 116) --#define IRQ_DB8500_PRCMU_SEM (IRQ_SHPI_START + 118) --#define IRQ_DB8500_GPIO0 (IRQ_SHPI_START + 119) --#define IRQ_DB8500_GPIO1 (IRQ_SHPI_START + 120) --#define IRQ_DB8500_GPIO2 (IRQ_SHPI_START + 121) --#define IRQ_DB8500_GPIO3 (IRQ_SHPI_START + 122) --#define IRQ_DB8500_GPIO4 (IRQ_SHPI_START + 123) --#define IRQ_DB8500_GPIO5 (IRQ_SHPI_START + 124) --#define IRQ_DB8500_GPIO6 (IRQ_SHPI_START + 125) --#define IRQ_DB8500_GPIO7 (IRQ_SHPI_START + 126) --#define IRQ_DB8500_GPIO8 (IRQ_SHPI_START + 127) -- --#define IRQ_CA_WAKE_REQ_ED (IRQ_SHPI_START + 71) --#define IRQ_AC_READ_NOTIFICATION_0_ED (IRQ_SHPI_START + 66) --#define IRQ_AC_READ_NOTIFICATION_1_ED (IRQ_SHPI_START + 64) --#define IRQ_CA_MSG_PEND_NOTIFICATION_0_ED (IRQ_SHPI_START + 67) --#define IRQ_CA_MSG_PEND_NOTIFICATION_1_ED (IRQ_SHPI_START + 65) -- --#define IRQ_CA_WAKE_REQ_V1 (IRQ_SHPI_START + 83) --#define IRQ_AC_READ_NOTIFICATION_0_V1 (IRQ_SHPI_START + 78) --#define IRQ_AC_READ_NOTIFICATION_1_V1 (IRQ_SHPI_START + 76) --#define IRQ_CA_MSG_PEND_NOTIFICATION_0_V1 (IRQ_SHPI_START + 79) --#define IRQ_CA_MSG_PEND_NOTIFICATION_1_V1 (IRQ_SHPI_START + 77) -- --#ifdef CONFIG_UX500_SOC_DB8500 -- --/* Virtual interrupts corresponding to the PRCMU wakeups. */ --#define IRQ_PRCMU_BASE IRQ_SOC_START --#define IRQ_PRCMU_END (IRQ_PRCMU_BASE + 23) -- --/* -- * We may have several SoCs, but only one will run at a -- * time, so the one with most IRQs will bump this ahead, -- * but the IRQ_SOC_START remains the same for either SoC. -- */ --#if IRQ_SOC_END < IRQ_PRCMU_END --#undef IRQ_SOC_END --#define IRQ_SOC_END IRQ_PRCMU_END --#endif -- --#endif /* CONFIG_UX500_SOC_DB8500 */ --#endif -diff -Nur linux-3.14.22.orig/arch/arm/mach-ux500/irqs.h linux-3.14.22/arch/arm/mach-ux500/irqs.h ---- linux-3.14.22.orig/arch/arm/mach-ux500/irqs.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-ux500/irqs.h 1969-12-31 18:00:00.000000000 -0600 -@@ -1,49 +0,0 @@ --/* -- * Copyright (C) 2008 STMicroelectronics -- * Copyright (C) 2009 ST-Ericsson. -- * -- * 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. -- */ --#ifndef ASM_ARCH_IRQS_H --#define ASM_ARCH_IRQS_H -- --#define IRQ_LOCALTIMER 29 --#define IRQ_LOCALWDOG 30 -- --/* Shared Peripheral Interrupt (SHPI) */ --#define IRQ_SHPI_START 32 -- --/* -- * MTU0 preserved for now until plat-nomadik is taught not to use it. Don't -- * add any other IRQs here, use the irqs-dbx500.h files. -- */ --#define IRQ_MTU0 (IRQ_SHPI_START + 4) -- --#define DBX500_NR_INTERNAL_IRQS 166 -- --/* After chip-specific IRQ numbers we have the GPIO ones */ --#define NOMADIK_NR_GPIO 288 --#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + DBX500_NR_INTERNAL_IRQS) --#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS) --#define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) -- --#define IRQ_SOC_START IRQ_GPIO_END --/* This will be overridden by SoC-specific irq headers */ --#define IRQ_SOC_END IRQ_SOC_START -- --#include "irqs-db8500.h" -- --#define IRQ_BOARD_START IRQ_SOC_END --/* This will be overridden by board-specific irq headers */ --#define IRQ_BOARD_END IRQ_BOARD_START -- --#ifdef CONFIG_MACH_MOP500 --#include "irqs-board-mop500.h" --#endif -- --#define UX500_NR_IRQS IRQ_BOARD_END -- --#endif /* ASM_ARCH_IRQS_H */ -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/ct-ca9x4.c linux-3.14.22/arch/arm/mach-vexpress/ct-ca9x4.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/ct-ca9x4.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/ct-ca9x4.c 2014-10-22 14:55:49.930220001 -0500 -@@ -45,6 +45,23 @@ - iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); - } - -+static void __init ca9x4_l2_init(void) -+{ -+#ifdef CONFIG_CACHE_L2X0 -+ void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); -+ -+ if (l2x0_base) { -+ /* set RAM latencies to 1 cycle for this core tile. */ -+ writel(0, l2x0_base + L310_TAG_LATENCY_CTRL); -+ writel(0, l2x0_base + L310_DATA_LATENCY_CTRL); -+ -+ l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); -+ } else { -+ pr_err("L2C: unable to map L2 cache controller\n"); -+ } -+#endif -+} -+ - #ifdef CONFIG_HAVE_ARM_TWD - static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER); - -@@ -63,6 +80,7 @@ - gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K), - ioremap(A9_MPCORE_GIC_CPU, SZ_256)); - ca9x4_twd_init(); -+ ca9x4_l2_init(); - } - - static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) -@@ -141,16 +159,6 @@ - { - int i; - --#ifdef CONFIG_CACHE_L2X0 -- void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K); -- -- /* set RAM latencies to 1 cycle for this core tile. */ -- writel(0, l2x0_base + L2X0_TAG_LATENCY_CTRL); -- writel(0, l2x0_base + L2X0_DATA_LATENCY_CTRL); -- -- l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff); --#endif -- - for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) - amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); - -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/dcscb.c linux-3.14.22/arch/arm/mach-vexpress/dcscb.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/dcscb.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/dcscb.c 2014-10-22 14:55:49.930220001 -0500 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - - #define RST_HOLD0 0x0 -@@ -193,6 +194,12 @@ - unsigned int cfg; - int ret; - -+ ret = psci_probe(); -+ if (!ret) { -+ pr_debug("psci found. Aborting native init\n"); -+ return -ENODEV; -+ } -+ - if (!cci_probed()) - return -ENODEV; - -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/Kconfig linux-3.14.22/arch/arm/mach-vexpress/Kconfig ---- linux-3.14.22.orig/arch/arm/mach-vexpress/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/Kconfig 2014-10-22 14:55:49.930220001 -0500 -@@ -55,6 +55,7 @@ - - config ARCH_VEXPRESS_CA9X4 - bool "Versatile Express Cortex-A9x4 tile" -+ select ARM_ERRATA_643719 - - config ARCH_VEXPRESS_DCSCB - bool "Dual Cluster System Control Block (DCSCB) support" -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/Makefile linux-3.14.22/arch/arm/mach-vexpress/Makefile ---- linux-3.14.22.orig/arch/arm/mach-vexpress/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/Makefile 2014-10-22 14:55:49.930220001 -0500 -@@ -8,8 +8,15 @@ - obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o - obj-$(CONFIG_ARCH_VEXPRESS_DCSCB) += dcscb.o dcscb_setup.o - CFLAGS_dcscb.o += -march=armv7-a -+CFLAGS_REMOVE_dcscb.o = -pg - obj-$(CONFIG_ARCH_VEXPRESS_SPC) += spc.o -+CFLAGS_REMOVE_spc.o = -pg - obj-$(CONFIG_ARCH_VEXPRESS_TC2_PM) += tc2_pm.o - CFLAGS_tc2_pm.o += -march=armv7-a -+CFLAGS_REMOVE_tc2_pm.o = -pg -+ifeq ($(CONFIG_ARCH_VEXPRESS_TC2_PM),y) -+obj-$(CONFIG_ARM_PSCI) += tc2_pm_psci.o -+CFLAGS_REMOVE_tc2_pm_psci.o = -pg -+endif - obj-$(CONFIG_SMP) += platsmp.o - obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/spc.c linux-3.14.22/arch/arm/mach-vexpress/spc.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/spc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/spc.c 2014-10-22 14:55:49.930220001 -0500 -@@ -392,7 +392,7 @@ - * +--------------------------+ - * | 31 20 | 19 0 | - * +--------------------------+ -- * | u_volt | freq(kHz) | -+ * | m_volt | freq(kHz) | - * +--------------------------+ - */ - #define MULT_FACTOR 20 -@@ -414,7 +414,7 @@ - ret = ve_spc_read_sys_cfg(SYSCFG_SCC, off, &data); - if (!ret) { - opps->freq = (data & FREQ_MASK) * MULT_FACTOR; -- opps->u_volt = data >> VOLT_SHIFT; -+ opps->u_volt = (data >> VOLT_SHIFT) * 1000; - } else { - break; - } -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/tc2_pm.c linux-3.14.22/arch/arm/mach-vexpress/tc2_pm.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/tc2_pm.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/tc2_pm.c 2014-10-22 14:55:49.930220001 -0500 -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include - -@@ -329,6 +330,12 @@ - u32 a15_cluster_id, a7_cluster_id, sys_info; - struct device_node *np; - -+ ret = psci_probe(); -+ if (!ret) { -+ pr_debug("psci found. Aborting native init\n"); -+ return -ENODEV; -+ } -+ - /* - * The power management-related features are hidden behind - * SCC registers. We need to extract runtime information like -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/tc2_pm_psci.c linux-3.14.22/arch/arm/mach-vexpress/tc2_pm_psci.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/tc2_pm_psci.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mach-vexpress/tc2_pm_psci.c 2014-10-22 14:55:49.930220001 -0500 -@@ -0,0 +1,173 @@ -+/* -+ * arch/arm/mach-vexpress/tc2_pm_psci.c - TC2 PSCI support -+ * -+ * Created by: Achin Gupta, December 2012 -+ * Copyright: (C) 2012 ARM Limited -+ * -+ * Some portions of this file were originally written by Nicolas Pitre -+ * Copyright: (C) 2012 Linaro Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+/* -+ * Platform specific state id understood by the firmware and used to -+ * program the power controller -+ */ -+#define PSCI_POWER_STATE_ID 0 -+ -+#define TC2_CLUSTERS 2 -+#define TC2_MAX_CPUS_PER_CLUSTER 3 -+ -+static atomic_t tc2_pm_use_count[TC2_MAX_CPUS_PER_CLUSTER][TC2_CLUSTERS]; -+ -+static int tc2_pm_psci_power_up(unsigned int cpu, unsigned int cluster) -+{ -+ unsigned int mpidr = (cluster << 8) | cpu; -+ int ret = 0; -+ -+ BUG_ON(!psci_ops.cpu_on); -+ -+ switch (atomic_inc_return(&tc2_pm_use_count[cpu][cluster])) { -+ case 1: -+ /* -+ * This is a request to power up a cpu that linux thinks has -+ * been powered down. Retries are needed if the firmware has -+ * seen the power down request as yet. -+ */ -+ do -+ ret = psci_ops.cpu_on(mpidr, -+ virt_to_phys(mcpm_entry_point)); -+ while (ret == -EAGAIN); -+ -+ return ret; -+ case 2: -+ /* This power up request has overtaken a power down request */ -+ return ret; -+ default: -+ /* Any other value is a bug */ -+ BUG(); -+ } -+} -+ -+static void tc2_pm_psci_power_down(void) -+{ -+ struct psci_power_state power_state; -+ unsigned int mpidr, cpu, cluster; -+ -+ mpidr = read_cpuid_mpidr(); -+ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); -+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); -+ -+ BUG_ON(!psci_ops.cpu_off); -+ -+ switch (atomic_dec_return(&tc2_pm_use_count[cpu][cluster])) { -+ case 1: -+ /* -+ * Overtaken by a power up. Flush caches, exit coherency, -+ * return & fake a reset -+ */ -+ set_cr(get_cr() & ~CR_C); -+ -+ flush_cache_louis(); -+ -+ asm volatile ("clrex"); -+ set_auxcr(get_auxcr() & ~(1 << 6)); -+ -+ return; -+ case 0: -+ /* A normal request to possibly power down the cluster */ -+ power_state.id = PSCI_POWER_STATE_ID; -+ power_state.type = PSCI_POWER_STATE_TYPE_POWER_DOWN; -+ power_state.affinity_level = PSCI_POWER_STATE_AFFINITY_LEVEL1; -+ -+ psci_ops.cpu_off(power_state); -+ -+ /* On success this function never returns */ -+ default: -+ /* Any other value is a bug */ -+ BUG(); -+ } -+} -+ -+static void tc2_pm_psci_suspend(u64 unused) -+{ -+ struct psci_power_state power_state; -+ -+ BUG_ON(!psci_ops.cpu_suspend); -+ -+ /* On TC2 always attempt to power down the cluster */ -+ power_state.id = PSCI_POWER_STATE_ID; -+ power_state.type = PSCI_POWER_STATE_TYPE_POWER_DOWN; -+ power_state.affinity_level = PSCI_POWER_STATE_AFFINITY_LEVEL1; -+ -+ psci_ops.cpu_suspend(power_state, virt_to_phys(mcpm_entry_point)); -+ -+ /* On success this function never returns */ -+ BUG(); -+} -+ -+static const struct mcpm_platform_ops tc2_pm_power_ops = { -+ .power_up = tc2_pm_psci_power_up, -+ .power_down = tc2_pm_psci_power_down, -+ .suspend = tc2_pm_psci_suspend, -+}; -+ -+static void __init tc2_pm_usage_count_init(void) -+{ -+ unsigned int mpidr, cpu, cluster; -+ -+ mpidr = read_cpuid_mpidr(); -+ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); -+ cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); -+ -+ pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster); -+ BUG_ON(cluster >= TC2_CLUSTERS || cpu >= TC2_MAX_CPUS_PER_CLUSTER); -+ -+ atomic_set(&tc2_pm_use_count[cpu][cluster], 1); -+} -+ -+static int __init tc2_pm_psci_init(void) -+{ -+ int ret; -+ -+ ret = psci_probe(); -+ if (ret) { -+ pr_debug("psci not found. Aborting psci init\n"); -+ return -ENODEV; -+ } -+ -+ if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7")) -+ return -ENODEV; -+ -+ tc2_pm_usage_count_init(); -+ -+ ret = mcpm_platform_register(&tc2_pm_power_ops); -+ if (!ret) -+ ret = mcpm_sync_init(NULL); -+ if (!ret) -+ pr_info("TC2 power management using PSCI initialized\n"); -+ return ret; -+} -+ -+early_initcall(tc2_pm_psci_init); -diff -Nur linux-3.14.22.orig/arch/arm/mach-vexpress/v2m.c linux-3.14.22/arch/arm/mach-vexpress/v2m.c ---- linux-3.14.22.orig/arch/arm/mach-vexpress/v2m.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-vexpress/v2m.c 2014-10-22 14:55:49.930220001 -0500 -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -369,6 +370,31 @@ - .init_machine = v2m_init, - MACHINE_END - -+static void __init v2m_dt_hdlcd_init(void) -+{ -+ struct device_node *node; -+ int len, na, ns; -+ const __be32 *prop; -+ phys_addr_t fb_base, fb_size; -+ -+ node = of_find_compatible_node(NULL, NULL, "arm,hdlcd"); -+ if (!node) -+ return; -+ -+ na = of_n_addr_cells(node); -+ ns = of_n_size_cells(node); -+ -+ prop = of_get_property(node, "framebuffer", &len); -+ if (WARN_ON(!prop || len < (na + ns) * sizeof(*prop))) -+ return; -+ -+ fb_base = of_read_number(prop, na); -+ fb_size = of_read_number(prop + na, ns); -+ -+ if (WARN_ON(memblock_remove(fb_base, fb_size))) -+ return; -+}; -+ - static struct map_desc v2m_rs1_io_desc __initdata = { - .virtual = V2M_PERIPH, - .pfn = __phys_to_pfn(0x1c000000), -@@ -421,6 +447,8 @@ - } - - versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); -+ -+ v2m_dt_hdlcd_init(); - } - - static const struct of_device_id v2m_dt_bus_match[] __initconst = { -diff -Nur linux-3.14.22.orig/arch/arm/mach-zynq/common.c linux-3.14.22/arch/arm/mach-zynq/common.c ---- linux-3.14.22.orig/arch/arm/mach-zynq/common.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mach-zynq/common.c 2014-10-22 14:55:49.930220001 -0500 -@@ -67,7 +67,7 @@ - /* - * 64KB way size, 8-way associativity, parity disabled - */ -- l2x0_of_init(0x02060000, 0xF0F0FFFF); -+ l2x0_of_init(0x02000000, 0xf0ffffff); - - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - -diff -Nur linux-3.14.22.orig/arch/arm/mm/cache-feroceon-l2.c linux-3.14.22/arch/arm/mm/cache-feroceon-l2.c ---- linux-3.14.22.orig/arch/arm/mm/cache-feroceon-l2.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/cache-feroceon-l2.c 2014-10-22 14:55:49.930220001 -0500 -@@ -343,7 +343,6 @@ - outer_cache.inv_range = feroceon_l2_inv_range; - outer_cache.clean_range = feroceon_l2_clean_range; - outer_cache.flush_range = feroceon_l2_flush_range; -- outer_cache.inv_all = l2_inv_all; - - enable_l2(); - -diff -Nur linux-3.14.22.orig/arch/arm/mm/cache-l2x0.c linux-3.14.22/arch/arm/mm/cache-l2x0.c ---- linux-3.14.22.orig/arch/arm/mm/cache-l2x0.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/cache-l2x0.c 2014-10-22 14:55:49.934220001 -0500 -@@ -16,18 +16,33 @@ - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -+#include - #include - #include -+#include - #include - #include - #include - #include - - #include -+#include -+#include - #include - #include "cache-tauros3.h" - #include "cache-aurora-l2.h" - -+struct l2c_init_data { -+ const char *type; -+ unsigned way_size_0; -+ unsigned num_lock; -+ void (*of_parse)(const struct device_node *, u32 *, u32 *); -+ void (*enable)(void __iomem *, u32, unsigned); -+ void (*fixup)(void __iomem *, u32, struct outer_cache_fns *); -+ void (*save)(void __iomem *); -+ struct outer_cache_fns outer_cache; -+}; -+ - #define CACHE_LINE_SIZE 32 - - static void __iomem *l2x0_base; -@@ -36,96 +51,116 @@ - static u32 l2x0_size; - static unsigned long sync_reg_offset = L2X0_CACHE_SYNC; - --/* Aurora don't have the cache ID register available, so we have to -- * pass it though the device tree */ --static u32 cache_id_part_number_from_dt; -- - struct l2x0_regs l2x0_saved_regs; - --struct l2x0_of_data { -- void (*setup)(const struct device_node *, u32 *, u32 *); -- void (*save)(void); -- struct outer_cache_fns outer_cache; --}; -- --static bool of_init = false; -- --static inline void cache_wait_way(void __iomem *reg, unsigned long mask) -+/* -+ * Common code for all cache controllers. -+ */ -+static inline void l2c_wait_mask(void __iomem *reg, unsigned long mask) - { - /* wait for cache operation by line or way to complete */ - while (readl_relaxed(reg) & mask) - cpu_relax(); - } - --#ifdef CONFIG_CACHE_PL310 --static inline void cache_wait(void __iomem *reg, unsigned long mask) -+/* -+ * By default, we write directly to secure registers. Platforms must -+ * override this if they are running non-secure. -+ */ -+static void l2c_write_sec(unsigned long val, void __iomem *base, unsigned reg) - { -- /* cache operations by line are atomic on PL310 */ -+ if (val == readl_relaxed(base + reg)) -+ return; -+ if (outer_cache.write_sec) -+ outer_cache.write_sec(val, reg); -+ else -+ writel_relaxed(val, base + reg); - } --#else --#define cache_wait cache_wait_way --#endif - --static inline void cache_sync(void) -+/* -+ * This should only be called when we have a requirement that the -+ * register be written due to a work-around, as platforms running -+ * in non-secure mode may not be able to access this register. -+ */ -+static inline void l2c_set_debug(void __iomem *base, unsigned long val) - { -- void __iomem *base = l2x0_base; -- -- writel_relaxed(0, base + sync_reg_offset); -- cache_wait(base + L2X0_CACHE_SYNC, 1); -+ l2c_write_sec(val, base, L2X0_DEBUG_CTRL); - } - --static inline void l2x0_clean_line(unsigned long addr) -+static void __l2c_op_way(void __iomem *reg) - { -- void __iomem *base = l2x0_base; -- cache_wait(base + L2X0_CLEAN_LINE_PA, 1); -- writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); -+ writel_relaxed(l2x0_way_mask, reg); -+ l2c_wait_mask(reg, l2x0_way_mask); - } - --static inline void l2x0_inv_line(unsigned long addr) -+static inline void l2c_unlock(void __iomem *base, unsigned num) - { -- void __iomem *base = l2x0_base; -- cache_wait(base + L2X0_INV_LINE_PA, 1); -- writel_relaxed(addr, base + L2X0_INV_LINE_PA); -+ unsigned i; -+ -+ for (i = 0; i < num; i++) { -+ writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_D_BASE + -+ i * L2X0_LOCKDOWN_STRIDE); -+ writel_relaxed(0, base + L2X0_LOCKDOWN_WAY_I_BASE + -+ i * L2X0_LOCKDOWN_STRIDE); -+ } - } - --#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) --static inline void debug_writel(unsigned long val) -+/* -+ * Enable the L2 cache controller. This function must only be -+ * called when the cache controller is known to be disabled. -+ */ -+static void l2c_enable(void __iomem *base, u32 aux, unsigned num_lock) - { -- if (outer_cache.set_debug) -- outer_cache.set_debug(val); -+ unsigned long flags; -+ -+ l2c_write_sec(aux, base, L2X0_AUX_CTRL); -+ -+ l2c_unlock(base, num_lock); -+ -+ local_irq_save(flags); -+ __l2c_op_way(base + L2X0_INV_WAY); -+ writel_relaxed(0, base + sync_reg_offset); -+ l2c_wait_mask(base + sync_reg_offset, 1); -+ local_irq_restore(flags); -+ -+ l2c_write_sec(L2X0_CTRL_EN, base, L2X0_CTRL); - } - --static void pl310_set_debug(unsigned long val) -+static void l2c_disable(void) - { -- writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); -+ void __iomem *base = l2x0_base; -+ -+ outer_cache.flush_all(); -+ l2c_write_sec(0, base, L2X0_CTRL); -+ dsb(st); - } --#else --/* Optimised out for non-errata case */ --static inline void debug_writel(unsigned long val) -+ -+#ifdef CONFIG_CACHE_PL310 -+static inline void cache_wait(void __iomem *reg, unsigned long mask) - { -+ /* cache operations by line are atomic on PL310 */ - } -- --#define pl310_set_debug NULL -+#else -+#define cache_wait l2c_wait_mask - #endif - --#ifdef CONFIG_PL310_ERRATA_588369 --static inline void l2x0_flush_line(unsigned long addr) -+static inline void cache_sync(void) - { - void __iomem *base = l2x0_base; - -- /* Clean by PA followed by Invalidate by PA */ -- cache_wait(base + L2X0_CLEAN_LINE_PA, 1); -- writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA); -- cache_wait(base + L2X0_INV_LINE_PA, 1); -- writel_relaxed(addr, base + L2X0_INV_LINE_PA); -+ writel_relaxed(0, base + sync_reg_offset); -+ cache_wait(base + L2X0_CACHE_SYNC, 1); - } --#else - --static inline void l2x0_flush_line(unsigned long addr) -+#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) -+static inline void debug_writel(unsigned long val) -+{ -+ l2c_set_debug(l2x0_base, val); -+} -+#else -+/* Optimised out for non-errata case */ -+static inline void debug_writel(unsigned long val) - { -- void __iomem *base = l2x0_base; -- cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); -- writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA); - } - #endif - -@@ -141,8 +176,7 @@ - static void __l2x0_flush_all(void) - { - debug_writel(0x03); -- writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); -- cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); -+ __l2c_op_way(l2x0_base + L2X0_CLEAN_INV_WAY); - cache_sync(); - debug_writel(0x00); - } -@@ -157,274 +191,882 @@ - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - } - --static void l2x0_clean_all(void) -+static void l2x0_disable(void) - { - unsigned long flags; - -- /* clean all ways */ - raw_spin_lock_irqsave(&l2x0_lock, flags); -- writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY); -- cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask); -- cache_sync(); -+ __l2x0_flush_all(); -+ l2c_write_sec(0, l2x0_base, L2X0_CTRL); -+ dsb(st); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - } - --static void l2x0_inv_all(void) -+static void l2c_save(void __iomem *base) - { -- unsigned long flags; -+ l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); -+} - -- /* invalidate all ways */ -- raw_spin_lock_irqsave(&l2x0_lock, flags); -- /* Invalidating when L2 is enabled is a nono */ -- BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN); -- writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); -- cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); -- cache_sync(); -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+/* -+ * L2C-210 specific code. -+ * -+ * The L2C-2x0 PA, set/way and sync operations are atomic, but we must -+ * ensure that no background operation is running. The way operations -+ * are all background tasks. -+ * -+ * While a background operation is in progress, any new operation is -+ * ignored (unspecified whether this causes an error.) Thankfully, not -+ * used on SMP. -+ * -+ * Never has a different sync register other than L2X0_CACHE_SYNC, but -+ * we use sync_reg_offset here so we can share some of this with L2C-310. -+ */ -+static void __l2c210_cache_sync(void __iomem *base) -+{ -+ writel_relaxed(0, base + sync_reg_offset); - } - --static void l2x0_inv_range(unsigned long start, unsigned long end) -+static void __l2c210_op_pa_range(void __iomem *reg, unsigned long start, -+ unsigned long end) -+{ -+ while (start < end) { -+ writel_relaxed(start, reg); -+ start += CACHE_LINE_SIZE; -+ } -+} -+ -+static void l2c210_inv_range(unsigned long start, unsigned long end) - { - void __iomem *base = l2x0_base; -- unsigned long flags; - -- raw_spin_lock_irqsave(&l2x0_lock, flags); - if (start & (CACHE_LINE_SIZE - 1)) { - start &= ~(CACHE_LINE_SIZE - 1); -- debug_writel(0x03); -- l2x0_flush_line(start); -- debug_writel(0x00); -+ writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA); - start += CACHE_LINE_SIZE; - } - - if (end & (CACHE_LINE_SIZE - 1)) { - end &= ~(CACHE_LINE_SIZE - 1); -- debug_writel(0x03); -- l2x0_flush_line(end); -- debug_writel(0x00); -+ writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA); - } - -+ __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end); -+ __l2c210_cache_sync(base); -+} -+ -+static void l2c210_clean_range(unsigned long start, unsigned long end) -+{ -+ void __iomem *base = l2x0_base; -+ -+ start &= ~(CACHE_LINE_SIZE - 1); -+ __l2c210_op_pa_range(base + L2X0_CLEAN_LINE_PA, start, end); -+ __l2c210_cache_sync(base); -+} -+ -+static void l2c210_flush_range(unsigned long start, unsigned long end) -+{ -+ void __iomem *base = l2x0_base; -+ -+ start &= ~(CACHE_LINE_SIZE - 1); -+ __l2c210_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, start, end); -+ __l2c210_cache_sync(base); -+} -+ -+static void l2c210_flush_all(void) -+{ -+ void __iomem *base = l2x0_base; -+ -+ BUG_ON(!irqs_disabled()); -+ -+ __l2c_op_way(base + L2X0_CLEAN_INV_WAY); -+ __l2c210_cache_sync(base); -+} -+ -+static void l2c210_sync(void) -+{ -+ __l2c210_cache_sync(l2x0_base); -+} -+ -+static void l2c210_resume(void) -+{ -+ void __iomem *base = l2x0_base; -+ -+ if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) -+ l2c_enable(base, l2x0_saved_regs.aux_ctrl, 1); -+} -+ -+static const struct l2c_init_data l2c210_data __initconst = { -+ .type = "L2C-210", -+ .way_size_0 = SZ_8K, -+ .num_lock = 1, -+ .enable = l2c_enable, -+ .save = l2c_save, -+ .outer_cache = { -+ .inv_range = l2c210_inv_range, -+ .clean_range = l2c210_clean_range, -+ .flush_range = l2c210_flush_range, -+ .flush_all = l2c210_flush_all, -+ .disable = l2c_disable, -+ .sync = l2c210_sync, -+ .resume = l2c210_resume, -+ }, -+}; -+ -+/* -+ * L2C-220 specific code. -+ * -+ * All operations are background operations: they have to be waited for. -+ * Conflicting requests generate a slave error (which will cause an -+ * imprecise abort.) Never uses sync_reg_offset, so we hard-code the -+ * sync register here. -+ * -+ * However, we can re-use the l2c210_resume call. -+ */ -+static inline void __l2c220_cache_sync(void __iomem *base) -+{ -+ writel_relaxed(0, base + L2X0_CACHE_SYNC); -+ l2c_wait_mask(base + L2X0_CACHE_SYNC, 1); -+} -+ -+static void l2c220_op_way(void __iomem *base, unsigned reg) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&l2x0_lock, flags); -+ __l2c_op_way(base + reg); -+ __l2c220_cache_sync(base); -+ raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+} -+ -+static unsigned long l2c220_op_pa_range(void __iomem *reg, unsigned long start, -+ unsigned long end, unsigned long flags) -+{ -+ raw_spinlock_t *lock = &l2x0_lock; -+ - while (start < end) { - unsigned long blk_end = start + min(end - start, 4096UL); - - while (start < blk_end) { -- l2x0_inv_line(start); -+ l2c_wait_mask(reg, 1); -+ writel_relaxed(start, reg); - start += CACHE_LINE_SIZE; - } - - if (blk_end < end) { -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -- raw_spin_lock_irqsave(&l2x0_lock, flags); -+ raw_spin_unlock_irqrestore(lock, flags); -+ raw_spin_lock_irqsave(lock, flags); - } - } -- cache_wait(base + L2X0_INV_LINE_PA, 1); -- cache_sync(); -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+ -+ return flags; - } - --static void l2x0_clean_range(unsigned long start, unsigned long end) -+static void l2c220_inv_range(unsigned long start, unsigned long end) - { - void __iomem *base = l2x0_base; - unsigned long flags; - -- if ((end - start) >= l2x0_size) { -- l2x0_clean_all(); -- return; -- } -- - raw_spin_lock_irqsave(&l2x0_lock, flags); -- start &= ~(CACHE_LINE_SIZE - 1); -- while (start < end) { -- unsigned long blk_end = start + min(end - start, 4096UL); -- -- while (start < blk_end) { -- l2x0_clean_line(start); -+ if ((start | end) & (CACHE_LINE_SIZE - 1)) { -+ if (start & (CACHE_LINE_SIZE - 1)) { -+ start &= ~(CACHE_LINE_SIZE - 1); -+ writel_relaxed(start, base + L2X0_CLEAN_INV_LINE_PA); - start += CACHE_LINE_SIZE; - } - -- if (blk_end < end) { -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -- raw_spin_lock_irqsave(&l2x0_lock, flags); -+ if (end & (CACHE_LINE_SIZE - 1)) { -+ end &= ~(CACHE_LINE_SIZE - 1); -+ l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); -+ writel_relaxed(end, base + L2X0_CLEAN_INV_LINE_PA); - } - } -- cache_wait(base + L2X0_CLEAN_LINE_PA, 1); -- cache_sync(); -+ -+ flags = l2c220_op_pa_range(base + L2X0_INV_LINE_PA, -+ start, end, flags); -+ l2c_wait_mask(base + L2X0_INV_LINE_PA, 1); -+ __l2c220_cache_sync(base); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - } - --static void l2x0_flush_range(unsigned long start, unsigned long end) -+static void l2c220_clean_range(unsigned long start, unsigned long end) - { - void __iomem *base = l2x0_base; - unsigned long flags; - -+ start &= ~(CACHE_LINE_SIZE - 1); - if ((end - start) >= l2x0_size) { -- l2x0_flush_all(); -+ l2c220_op_way(base, L2X0_CLEAN_WAY); - return; - } - - raw_spin_lock_irqsave(&l2x0_lock, flags); -+ flags = l2c220_op_pa_range(base + L2X0_CLEAN_LINE_PA, -+ start, end, flags); -+ l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); -+ __l2c220_cache_sync(base); -+ raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+} -+ -+static void l2c220_flush_range(unsigned long start, unsigned long end) -+{ -+ void __iomem *base = l2x0_base; -+ unsigned long flags; -+ - start &= ~(CACHE_LINE_SIZE - 1); -+ if ((end - start) >= l2x0_size) { -+ l2c220_op_way(base, L2X0_CLEAN_INV_WAY); -+ return; -+ } -+ -+ raw_spin_lock_irqsave(&l2x0_lock, flags); -+ flags = l2c220_op_pa_range(base + L2X0_CLEAN_INV_LINE_PA, -+ start, end, flags); -+ l2c_wait_mask(base + L2X0_CLEAN_INV_LINE_PA, 1); -+ __l2c220_cache_sync(base); -+ raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+} -+ -+static void l2c220_flush_all(void) -+{ -+ l2c220_op_way(l2x0_base, L2X0_CLEAN_INV_WAY); -+} -+ -+static void l2c220_sync(void) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&l2x0_lock, flags); -+ __l2c220_cache_sync(l2x0_base); -+ raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+} -+ -+static void l2c220_enable(void __iomem *base, u32 aux, unsigned num_lock) -+{ -+ /* -+ * Always enable non-secure access to the lockdown registers - -+ * we write to them as part of the L2C enable sequence so they -+ * need to be accessible. -+ */ -+ aux |= L220_AUX_CTRL_NS_LOCKDOWN; -+ -+ l2c_enable(base, aux, num_lock); -+} -+ -+static const struct l2c_init_data l2c220_data = { -+ .type = "L2C-220", -+ .way_size_0 = SZ_8K, -+ .num_lock = 1, -+ .enable = l2c220_enable, -+ .save = l2c_save, -+ .outer_cache = { -+ .inv_range = l2c220_inv_range, -+ .clean_range = l2c220_clean_range, -+ .flush_range = l2c220_flush_range, -+ .flush_all = l2c220_flush_all, -+ .disable = l2c_disable, -+ .sync = l2c220_sync, -+ .resume = l2c210_resume, -+ }, -+}; -+ -+/* -+ * L2C-310 specific code. -+ * -+ * Very similar to L2C-210, the PA, set/way and sync operations are atomic, -+ * and the way operations are all background tasks. However, issuing an -+ * operation while a background operation is in progress results in a -+ * SLVERR response. We can reuse: -+ * -+ * __l2c210_cache_sync (using sync_reg_offset) -+ * l2c210_sync -+ * l2c210_inv_range (if 588369 is not applicable) -+ * l2c210_clean_range -+ * l2c210_flush_range (if 588369 is not applicable) -+ * l2c210_flush_all (if 727915 is not applicable) -+ * -+ * Errata: -+ * 588369: PL310 R0P0->R1P0, fixed R2P0. -+ * Affects: all clean+invalidate operations -+ * clean and invalidate skips the invalidate step, so we need to issue -+ * separate operations. We also require the above debug workaround -+ * enclosing this code fragment on affected parts. On unaffected parts, -+ * we must not use this workaround without the debug register writes -+ * to avoid exposing a problem similar to 727915. -+ * -+ * 727915: PL310 R2P0->R3P0, fixed R3P1. -+ * Affects: clean+invalidate by way -+ * clean and invalidate by way runs in the background, and a store can -+ * hit the line between the clean operation and invalidate operation, -+ * resulting in the store being lost. -+ * -+ * 752271: PL310 R3P0->R3P1-50REL0, fixed R3P2. -+ * Affects: 8x64-bit (double fill) line fetches -+ * double fill line fetches can fail to cause dirty data to be evicted -+ * from the cache before the new data overwrites the second line. -+ * -+ * 753970: PL310 R3P0, fixed R3P1. -+ * Affects: sync -+ * prevents merging writes after the sync operation, until another L2C -+ * operation is performed (or a number of other conditions.) -+ * -+ * 769419: PL310 R0P0->R3P1, fixed R3P2. -+ * Affects: store buffer -+ * store buffer is not automatically drained. -+ */ -+static void l2c310_inv_range_erratum(unsigned long start, unsigned long end) -+{ -+ void __iomem *base = l2x0_base; -+ -+ if ((start | end) & (CACHE_LINE_SIZE - 1)) { -+ unsigned long flags; -+ -+ /* Erratum 588369 for both clean+invalidate operations */ -+ raw_spin_lock_irqsave(&l2x0_lock, flags); -+ l2c_set_debug(base, 0x03); -+ -+ if (start & (CACHE_LINE_SIZE - 1)) { -+ start &= ~(CACHE_LINE_SIZE - 1); -+ writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); -+ writel_relaxed(start, base + L2X0_INV_LINE_PA); -+ start += CACHE_LINE_SIZE; -+ } -+ -+ if (end & (CACHE_LINE_SIZE - 1)) { -+ end &= ~(CACHE_LINE_SIZE - 1); -+ writel_relaxed(end, base + L2X0_CLEAN_LINE_PA); -+ writel_relaxed(end, base + L2X0_INV_LINE_PA); -+ } -+ -+ l2c_set_debug(base, 0x00); -+ raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+ } -+ -+ __l2c210_op_pa_range(base + L2X0_INV_LINE_PA, start, end); -+ __l2c210_cache_sync(base); -+} -+ -+static void l2c310_flush_range_erratum(unsigned long start, unsigned long end) -+{ -+ raw_spinlock_t *lock = &l2x0_lock; -+ unsigned long flags; -+ void __iomem *base = l2x0_base; -+ -+ raw_spin_lock_irqsave(lock, flags); - while (start < end) { - unsigned long blk_end = start + min(end - start, 4096UL); - -- debug_writel(0x03); -+ l2c_set_debug(base, 0x03); - while (start < blk_end) { -- l2x0_flush_line(start); -+ writel_relaxed(start, base + L2X0_CLEAN_LINE_PA); -+ writel_relaxed(start, base + L2X0_INV_LINE_PA); - start += CACHE_LINE_SIZE; - } -- debug_writel(0x00); -+ l2c_set_debug(base, 0x00); - - if (blk_end < end) { -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -- raw_spin_lock_irqsave(&l2x0_lock, flags); -+ raw_spin_unlock_irqrestore(lock, flags); -+ raw_spin_lock_irqsave(lock, flags); - } - } -- cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); -- cache_sync(); -- raw_spin_unlock_irqrestore(&l2x0_lock, flags); -+ raw_spin_unlock_irqrestore(lock, flags); -+ __l2c210_cache_sync(base); - } - --static void l2x0_disable(void) -+static void l2c310_flush_all_erratum(void) - { -+ void __iomem *base = l2x0_base; - unsigned long flags; - - raw_spin_lock_irqsave(&l2x0_lock, flags); -- __l2x0_flush_all(); -- writel_relaxed(0, l2x0_base + L2X0_CTRL); -- dsb(st); -+ l2c_set_debug(base, 0x03); -+ __l2c_op_way(base + L2X0_CLEAN_INV_WAY); -+ l2c_set_debug(base, 0x00); -+ __l2c210_cache_sync(base); - raw_spin_unlock_irqrestore(&l2x0_lock, flags); - } - --static void l2x0_unlock(u32 cache_id) -+static void __init l2c310_save(void __iomem *base) - { -- int lockregs; -- int i; -+ unsigned revision; - -- switch (cache_id & L2X0_CACHE_ID_PART_MASK) { -- case L2X0_CACHE_ID_PART_L310: -- lockregs = 8; -- break; -- case AURORA_CACHE_ID: -- lockregs = 4; -+ l2c_save(base); -+ -+ l2x0_saved_regs.tag_latency = readl_relaxed(base + -+ L310_TAG_LATENCY_CTRL); -+ l2x0_saved_regs.data_latency = readl_relaxed(base + -+ L310_DATA_LATENCY_CTRL); -+ l2x0_saved_regs.filter_end = readl_relaxed(base + -+ L310_ADDR_FILTER_END); -+ l2x0_saved_regs.filter_start = readl_relaxed(base + -+ L310_ADDR_FILTER_START); -+ -+ revision = readl_relaxed(base + L2X0_CACHE_ID) & -+ L2X0_CACHE_ID_RTL_MASK; -+ -+ /* From r2p0, there is Prefetch offset/control register */ -+ if (revision >= L310_CACHE_ID_RTL_R2P0) -+ l2x0_saved_regs.prefetch_ctrl = readl_relaxed(base + -+ L310_PREFETCH_CTRL); -+ -+ /* From r3p0, there is Power control register */ -+ if (revision >= L310_CACHE_ID_RTL_R3P0) -+ l2x0_saved_regs.pwr_ctrl = readl_relaxed(base + -+ L310_POWER_CTRL); -+} -+ -+static void l2c310_resume(void) -+{ -+ void __iomem *base = l2x0_base; -+ -+ if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { -+ unsigned revision; -+ -+ /* restore pl310 setup */ -+ writel_relaxed(l2x0_saved_regs.tag_latency, -+ base + L310_TAG_LATENCY_CTRL); -+ writel_relaxed(l2x0_saved_regs.data_latency, -+ base + L310_DATA_LATENCY_CTRL); -+ writel_relaxed(l2x0_saved_regs.filter_end, -+ base + L310_ADDR_FILTER_END); -+ writel_relaxed(l2x0_saved_regs.filter_start, -+ base + L310_ADDR_FILTER_START); -+ -+ revision = readl_relaxed(base + L2X0_CACHE_ID) & -+ L2X0_CACHE_ID_RTL_MASK; -+ -+ if (revision >= L310_CACHE_ID_RTL_R2P0) -+ l2c_write_sec(l2x0_saved_regs.prefetch_ctrl, base, -+ L310_PREFETCH_CTRL); -+ if (revision >= L310_CACHE_ID_RTL_R3P0) -+ l2c_write_sec(l2x0_saved_regs.pwr_ctrl, base, -+ L310_POWER_CTRL); -+ -+ l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); -+ -+ /* Re-enable full-line-of-zeros for Cortex-A9 */ -+ if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) -+ set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); -+ } -+} -+ -+static int l2c310_cpu_enable_flz(struct notifier_block *nb, unsigned long act, void *data) -+{ -+ switch (act & ~CPU_TASKS_FROZEN) { -+ case CPU_STARTING: -+ set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); - break; -- default: -- /* L210 and unknown types */ -- lockregs = 1; -+ case CPU_DYING: -+ set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); - break; - } -+ return NOTIFY_OK; -+} - -- for (i = 0; i < lockregs; i++) { -- writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE + -- i * L2X0_LOCKDOWN_STRIDE); -- writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE + -- i * L2X0_LOCKDOWN_STRIDE); -+static void __init l2c310_enable(void __iomem *base, u32 aux, unsigned num_lock) -+{ -+ unsigned rev = readl_relaxed(base + L2X0_CACHE_ID) & L2X0_CACHE_ID_PART_MASK; -+ bool cortex_a9 = read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9; -+ -+ if (rev >= L310_CACHE_ID_RTL_R2P0) { -+ if (cortex_a9) { -+ aux |= L310_AUX_CTRL_EARLY_BRESP; -+ pr_info("L2C-310 enabling early BRESP for Cortex-A9\n"); -+ } else if (aux & L310_AUX_CTRL_EARLY_BRESP) { -+ pr_warn("L2C-310 early BRESP only supported with Cortex-A9\n"); -+ aux &= ~L310_AUX_CTRL_EARLY_BRESP; -+ } -+ } -+ -+ if (cortex_a9) { -+ u32 aux_cur = readl_relaxed(base + L2X0_AUX_CTRL); -+ u32 acr = get_auxcr(); -+ -+ pr_debug("Cortex-A9 ACR=0x%08x\n", acr); -+ -+ if (acr & BIT(3) && !(aux_cur & L310_AUX_CTRL_FULL_LINE_ZERO)) -+ pr_err("L2C-310: full line of zeros enabled in Cortex-A9 but not L2C-310 - invalid\n"); -+ -+ if (aux & L310_AUX_CTRL_FULL_LINE_ZERO && !(acr & BIT(3))) -+ pr_err("L2C-310: enabling full line of zeros but not enabled in Cortex-A9\n"); -+ -+ if (!(aux & L310_AUX_CTRL_FULL_LINE_ZERO) && !outer_cache.write_sec) { -+ aux |= L310_AUX_CTRL_FULL_LINE_ZERO; -+ pr_info("L2C-310 full line of zeros enabled for Cortex-A9\n"); -+ } -+ } else if (aux & (L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP)) { -+ pr_err("L2C-310: disabling Cortex-A9 specific feature bits\n"); -+ aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP); -+ } -+ -+ if (aux & (L310_AUX_CTRL_DATA_PREFETCH | L310_AUX_CTRL_INSTR_PREFETCH)) { -+ u32 prefetch = readl_relaxed(base + L310_PREFETCH_CTRL); -+ -+ pr_info("L2C-310 %s%s prefetch enabled, offset %u lines\n", -+ aux & L310_AUX_CTRL_INSTR_PREFETCH ? "I" : "", -+ aux & L310_AUX_CTRL_DATA_PREFETCH ? "D" : "", -+ 1 + (prefetch & L310_PREFETCH_CTRL_OFFSET_MASK)); -+ } -+ -+ /* r3p0 or later has power control register */ -+ if (rev >= L310_CACHE_ID_RTL_R3P0) { -+ u32 power_ctrl; -+ -+ l2c_write_sec(L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN, -+ base, L310_POWER_CTRL); -+ power_ctrl = readl_relaxed(base + L310_POWER_CTRL); -+ pr_info("L2C-310 dynamic clock gating %sabled, standby mode %sabled\n", -+ power_ctrl & L310_DYNAMIC_CLK_GATING_EN ? "en" : "dis", -+ power_ctrl & L310_STNDBY_MODE_EN ? "en" : "dis"); -+ } -+ -+ /* -+ * Always enable non-secure access to the lockdown registers - -+ * we write to them as part of the L2C enable sequence so they -+ * need to be accessible. -+ */ -+ aux |= L310_AUX_CTRL_NS_LOCKDOWN; -+ -+ l2c_enable(base, aux, num_lock); -+ -+ if (aux & L310_AUX_CTRL_FULL_LINE_ZERO) { -+ set_auxcr(get_auxcr() | BIT(3) | BIT(2) | BIT(1)); -+ cpu_notifier(l2c310_cpu_enable_flz, 0); - } - } - --void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) -+static void __init l2c310_fixup(void __iomem *base, u32 cache_id, -+ struct outer_cache_fns *fns) - { -- u32 aux; -- u32 cache_id; -- u32 way_size = 0; -- int ways; -- int way_size_shift = L2X0_WAY_SIZE_SHIFT; -- const char *type; -+ unsigned revision = cache_id & L2X0_CACHE_ID_RTL_MASK; -+ const char *errata[8]; -+ unsigned n = 0; - -- l2x0_base = base; -- if (cache_id_part_number_from_dt) -- cache_id = cache_id_part_number_from_dt; -- else -- cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); -- aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); -+ if (IS_ENABLED(CONFIG_PL310_ERRATA_588369) && -+ revision < L310_CACHE_ID_RTL_R2P0 && -+ /* For bcm compatibility */ -+ fns->inv_range == l2c210_inv_range) { -+ fns->inv_range = l2c310_inv_range_erratum; -+ fns->flush_range = l2c310_flush_range_erratum; -+ errata[n++] = "588369"; -+ } -+ -+ if (IS_ENABLED(CONFIG_PL310_ERRATA_727915) && -+ revision >= L310_CACHE_ID_RTL_R2P0 && -+ revision < L310_CACHE_ID_RTL_R3P1) { -+ fns->flush_all = l2c310_flush_all_erratum; -+ errata[n++] = "727915"; -+ } -+ -+ if (revision >= L310_CACHE_ID_RTL_R3P0 && -+ revision < L310_CACHE_ID_RTL_R3P2) { -+ u32 val = readl_relaxed(base + L310_PREFETCH_CTRL); -+ /* I don't think bit23 is required here... but iMX6 does so */ -+ if (val & (BIT(30) | BIT(23))) { -+ val &= ~(BIT(30) | BIT(23)); -+ l2c_write_sec(val, base, L310_PREFETCH_CTRL); -+ errata[n++] = "752271"; -+ } -+ } -+ -+ if (IS_ENABLED(CONFIG_PL310_ERRATA_753970) && -+ revision == L310_CACHE_ID_RTL_R3P0) { -+ sync_reg_offset = L2X0_DUMMY_REG; -+ errata[n++] = "753970"; -+ } -+ -+ if (IS_ENABLED(CONFIG_PL310_ERRATA_769419)) -+ errata[n++] = "769419"; -+ -+ if (n) { -+ unsigned i; -+ -+ pr_info("L2C-310 errat%s", n > 1 ? "a" : "um"); -+ for (i = 0; i < n; i++) -+ pr_cont(" %s", errata[i]); -+ pr_cont(" enabled\n"); -+ } -+} -+ -+static void l2c310_disable(void) -+{ -+ /* -+ * If full-line-of-zeros is enabled, we must first disable it in the -+ * Cortex-A9 auxiliary control register before disabling the L2 cache. -+ */ -+ if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_FULL_LINE_ZERO) -+ set_auxcr(get_auxcr() & ~(BIT(3) | BIT(2) | BIT(1))); - -+ l2c_disable(); -+} -+ -+static const struct l2c_init_data l2c310_init_fns __initconst = { -+ .type = "L2C-310", -+ .way_size_0 = SZ_8K, -+ .num_lock = 8, -+ .enable = l2c310_enable, -+ .fixup = l2c310_fixup, -+ .save = l2c310_save, -+ .outer_cache = { -+ .inv_range = l2c210_inv_range, -+ .clean_range = l2c210_clean_range, -+ .flush_range = l2c210_flush_range, -+ .flush_all = l2c210_flush_all, -+ .disable = l2c310_disable, -+ .sync = l2c210_sync, -+ .resume = l2c310_resume, -+ }, -+}; -+ -+static void __init __l2c_init(const struct l2c_init_data *data, -+ u32 aux_val, u32 aux_mask, u32 cache_id) -+{ -+ struct outer_cache_fns fns; -+ unsigned way_size_bits, ways; -+ u32 aux, old_aux; -+ -+ /* -+ * Sanity check the aux values. aux_mask is the bits we preserve -+ * from reading the hardware register, and aux_val is the bits we -+ * set. -+ */ -+ if (aux_val & aux_mask) -+ pr_alert("L2C: platform provided aux values permit register corruption.\n"); -+ -+ old_aux = aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); - aux &= aux_mask; - aux |= aux_val; - -+ if (old_aux != aux) -+ pr_warn("L2C: DT/platform modifies aux control register: 0x%08x -> 0x%08x\n", -+ old_aux, aux); -+ - /* Determine the number of ways */ - switch (cache_id & L2X0_CACHE_ID_PART_MASK) { - case L2X0_CACHE_ID_PART_L310: -+ if ((aux_val | ~aux_mask) & (L2C_AUX_CTRL_WAY_SIZE_MASK | L310_AUX_CTRL_ASSOCIATIVITY_16)) -+ pr_warn("L2C: DT/platform tries to modify or specify cache size\n"); - if (aux & (1 << 16)) - ways = 16; - else - ways = 8; -- type = "L310"; --#ifdef CONFIG_PL310_ERRATA_753970 -- /* Unmapped register. */ -- sync_reg_offset = L2X0_DUMMY_REG; --#endif -- if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0) -- outer_cache.set_debug = pl310_set_debug; - break; -+ - case L2X0_CACHE_ID_PART_L210: -+ case L2X0_CACHE_ID_PART_L220: - ways = (aux >> 13) & 0xf; -- type = "L210"; - break; - - case AURORA_CACHE_ID: -- sync_reg_offset = AURORA_SYNC_REG; - ways = (aux >> 13) & 0xf; - ways = 2 << ((ways + 1) >> 2); -- way_size_shift = AURORA_WAY_SIZE_SHIFT; -- type = "Aurora"; - break; -+ - default: - /* Assume unknown chips have 8 ways */ - ways = 8; -- type = "L2x0 series"; - break; - } - - l2x0_way_mask = (1 << ways) - 1; - - /* -- * L2 cache Size = Way size * Number of ways -+ * way_size_0 is the size that a way_size value of zero would be -+ * given the calculation: way_size = way_size_0 << way_size_bits. -+ * So, if way_size_bits=0 is reserved, but way_size_bits=1 is 16k, -+ * then way_size_0 would be 8k. -+ * -+ * L2 cache size = number of ways * way size. -+ */ -+ way_size_bits = (aux & L2C_AUX_CTRL_WAY_SIZE_MASK) >> -+ L2C_AUX_CTRL_WAY_SIZE_SHIFT; -+ l2x0_size = ways * (data->way_size_0 << way_size_bits); -+ -+ fns = data->outer_cache; -+ fns.write_sec = outer_cache.write_sec; -+ if (data->fixup) -+ data->fixup(l2x0_base, cache_id, &fns); -+ -+ /* -+ * Check if l2x0 controller is already enabled. If we are booting -+ * in non-secure mode accessing the below registers will fault. - */ -- way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17; -- way_size = 1 << (way_size + way_size_shift); -+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) -+ data->enable(l2x0_base, aux, data->num_lock); - -- l2x0_size = ways * way_size * SZ_1K; -+ outer_cache = fns; - - /* -- * Check if l2x0 controller is already enabled. -- * If you are booting from non-secure mode -- * accessing the below registers will fault. -+ * It is strange to save the register state before initialisation, -+ * but hey, this is what the DT implementations decided to do. - */ -- if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -- /* Make sure that I&D is not locked down when starting */ -- l2x0_unlock(cache_id); -+ if (data->save) -+ data->save(l2x0_base); -+ -+ /* Re-read it in case some bits are reserved. */ -+ aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); -+ -+ pr_info("%s cache controller enabled, %d ways, %d kB\n", -+ data->type, ways, l2x0_size >> 10); -+ pr_info("%s: CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", -+ data->type, cache_id, aux); -+} - -- /* l2x0 controller is disabled */ -- writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); -+void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) -+{ -+ const struct l2c_init_data *data; -+ u32 cache_id; - -- l2x0_inv_all(); -+ l2x0_base = base; - -- /* enable L2X0 */ -- writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); -+ cache_id = readl_relaxed(base + L2X0_CACHE_ID); -+ -+ switch (cache_id & L2X0_CACHE_ID_PART_MASK) { -+ default: -+ case L2X0_CACHE_ID_PART_L210: -+ data = &l2c210_data; -+ break; -+ -+ case L2X0_CACHE_ID_PART_L220: -+ data = &l2c220_data; -+ break; -+ -+ case L2X0_CACHE_ID_PART_L310: -+ data = &l2c310_init_fns; -+ break; - } - -- /* Re-read it in case some bits are reserved. */ -- aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); -+ __l2c_init(data, aux_val, aux_mask, cache_id); -+} -+ -+#ifdef CONFIG_OF -+static int l2_wt_override; -+ -+/* Aurora don't have the cache ID register available, so we have to -+ * pass it though the device tree */ -+static u32 cache_id_part_number_from_dt; -+ -+static void __init l2x0_of_parse(const struct device_node *np, -+ u32 *aux_val, u32 *aux_mask) -+{ -+ u32 data[2] = { 0, 0 }; -+ u32 tag = 0; -+ u32 dirty = 0; -+ u32 val = 0, mask = 0; -+ -+ of_property_read_u32(np, "arm,tag-latency", &tag); -+ if (tag) { -+ mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK; -+ val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT; -+ } -+ -+ of_property_read_u32_array(np, "arm,data-latency", -+ data, ARRAY_SIZE(data)); -+ if (data[0] && data[1]) { -+ mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | -+ L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK; -+ val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) | -+ ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT); -+ } -+ -+ of_property_read_u32(np, "arm,dirty-latency", &dirty); -+ if (dirty) { -+ mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK; -+ val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; -+ } - -- /* Save the value for resuming. */ -- l2x0_saved_regs.aux_ctrl = aux; -+ *aux_val &= ~mask; -+ *aux_val |= val; -+ *aux_mask &= ~mask; -+} -+ -+static const struct l2c_init_data of_l2c210_data __initconst = { -+ .type = "L2C-210", -+ .way_size_0 = SZ_8K, -+ .num_lock = 1, -+ .of_parse = l2x0_of_parse, -+ .enable = l2c_enable, -+ .save = l2c_save, -+ .outer_cache = { -+ .inv_range = l2c210_inv_range, -+ .clean_range = l2c210_clean_range, -+ .flush_range = l2c210_flush_range, -+ .flush_all = l2c210_flush_all, -+ .disable = l2c_disable, -+ .sync = l2c210_sync, -+ .resume = l2c210_resume, -+ }, -+}; -+ -+static const struct l2c_init_data of_l2c220_data __initconst = { -+ .type = "L2C-220", -+ .way_size_0 = SZ_8K, -+ .num_lock = 1, -+ .of_parse = l2x0_of_parse, -+ .enable = l2c220_enable, -+ .save = l2c_save, -+ .outer_cache = { -+ .inv_range = l2c220_inv_range, -+ .clean_range = l2c220_clean_range, -+ .flush_range = l2c220_flush_range, -+ .flush_all = l2c220_flush_all, -+ .disable = l2c_disable, -+ .sync = l2c220_sync, -+ .resume = l2c210_resume, -+ }, -+}; -+ -+static void __init l2c310_of_parse(const struct device_node *np, -+ u32 *aux_val, u32 *aux_mask) -+{ -+ u32 data[3] = { 0, 0, 0 }; -+ u32 tag[3] = { 0, 0, 0 }; -+ u32 filter[2] = { 0, 0 }; -+ -+ of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); -+ if (tag[0] && tag[1] && tag[2]) -+ writel_relaxed( -+ L310_LATENCY_CTRL_RD(tag[0] - 1) | -+ L310_LATENCY_CTRL_WR(tag[1] - 1) | -+ L310_LATENCY_CTRL_SETUP(tag[2] - 1), -+ l2x0_base + L310_TAG_LATENCY_CTRL); -+ -+ of_property_read_u32_array(np, "arm,data-latency", -+ data, ARRAY_SIZE(data)); -+ if (data[0] && data[1] && data[2]) -+ writel_relaxed( -+ L310_LATENCY_CTRL_RD(data[0] - 1) | -+ L310_LATENCY_CTRL_WR(data[1] - 1) | -+ L310_LATENCY_CTRL_SETUP(data[2] - 1), -+ l2x0_base + L310_DATA_LATENCY_CTRL); - -- if (!of_init) { -- outer_cache.inv_range = l2x0_inv_range; -- outer_cache.clean_range = l2x0_clean_range; -- outer_cache.flush_range = l2x0_flush_range; -- outer_cache.sync = l2x0_cache_sync; -- outer_cache.flush_all = l2x0_flush_all; -- outer_cache.inv_all = l2x0_inv_all; -- outer_cache.disable = l2x0_disable; -- } -- -- pr_info("%s cache controller enabled\n", type); -- pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n", -- ways, cache_id, aux, l2x0_size >> 10); -+ of_property_read_u32_array(np, "arm,filter-ranges", -+ filter, ARRAY_SIZE(filter)); -+ if (filter[1]) { -+ writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), -+ l2x0_base + L310_ADDR_FILTER_END); -+ writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L310_ADDR_FILTER_EN, -+ l2x0_base + L310_ADDR_FILTER_START); -+ } - } - --#ifdef CONFIG_OF --static int l2_wt_override; -+static const struct l2c_init_data of_l2c310_data __initconst = { -+ .type = "L2C-310", -+ .way_size_0 = SZ_8K, -+ .num_lock = 8, -+ .of_parse = l2c310_of_parse, -+ .enable = l2c310_enable, -+ .fixup = l2c310_fixup, -+ .save = l2c310_save, -+ .outer_cache = { -+ .inv_range = l2c210_inv_range, -+ .clean_range = l2c210_clean_range, -+ .flush_range = l2c210_flush_range, -+ .flush_all = l2c210_flush_all, -+ .disable = l2c310_disable, -+ .sync = l2c210_sync, -+ .resume = l2c310_resume, -+ }, -+}; - - /* - * Note that the end addresses passed to Linux primitives are -@@ -524,6 +1166,100 @@ - } - } - -+static void aurora_save(void __iomem *base) -+{ -+ l2x0_saved_regs.ctrl = readl_relaxed(base + L2X0_CTRL); -+ l2x0_saved_regs.aux_ctrl = readl_relaxed(base + L2X0_AUX_CTRL); -+} -+ -+static void aurora_resume(void) -+{ -+ void __iomem *base = l2x0_base; -+ -+ if (!(readl(base + L2X0_CTRL) & L2X0_CTRL_EN)) { -+ writel_relaxed(l2x0_saved_regs.aux_ctrl, base + L2X0_AUX_CTRL); -+ writel_relaxed(l2x0_saved_regs.ctrl, base + L2X0_CTRL); -+ } -+} -+ -+/* -+ * For Aurora cache in no outer mode, enable via the CP15 coprocessor -+ * broadcasting of cache commands to L2. -+ */ -+static void __init aurora_enable_no_outer(void __iomem *base, u32 aux, -+ unsigned num_lock) -+{ -+ u32 u; -+ -+ asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u)); -+ u |= AURORA_CTRL_FW; /* Set the FW bit */ -+ asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u)); -+ -+ isb(); -+ -+ l2c_enable(base, aux, num_lock); -+} -+ -+static void __init aurora_fixup(void __iomem *base, u32 cache_id, -+ struct outer_cache_fns *fns) -+{ -+ sync_reg_offset = AURORA_SYNC_REG; -+} -+ -+static void __init aurora_of_parse(const struct device_node *np, -+ u32 *aux_val, u32 *aux_mask) -+{ -+ u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; -+ u32 mask = AURORA_ACR_REPLACEMENT_MASK; -+ -+ of_property_read_u32(np, "cache-id-part", -+ &cache_id_part_number_from_dt); -+ -+ /* Determine and save the write policy */ -+ l2_wt_override = of_property_read_bool(np, "wt-override"); -+ -+ if (l2_wt_override) { -+ val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY; -+ mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; -+ } -+ -+ *aux_val &= ~mask; -+ *aux_val |= val; -+ *aux_mask &= ~mask; -+} -+ -+static const struct l2c_init_data of_aurora_with_outer_data __initconst = { -+ .type = "Aurora", -+ .way_size_0 = SZ_4K, -+ .num_lock = 4, -+ .of_parse = aurora_of_parse, -+ .enable = l2c_enable, -+ .fixup = aurora_fixup, -+ .save = aurora_save, -+ .outer_cache = { -+ .inv_range = aurora_inv_range, -+ .clean_range = aurora_clean_range, -+ .flush_range = aurora_flush_range, -+ .flush_all = l2x0_flush_all, -+ .disable = l2x0_disable, -+ .sync = l2x0_cache_sync, -+ .resume = aurora_resume, -+ }, -+}; -+ -+static const struct l2c_init_data of_aurora_no_outer_data __initconst = { -+ .type = "Aurora", -+ .way_size_0 = SZ_4K, -+ .num_lock = 4, -+ .of_parse = aurora_of_parse, -+ .enable = aurora_enable_no_outer, -+ .fixup = aurora_fixup, -+ .save = aurora_save, -+ .outer_cache = { -+ .resume = aurora_resume, -+ }, -+}; -+ - /* - * For certain Broadcom SoCs, depending on the address range, different offsets - * need to be added to the address before passing it to L2 for -@@ -588,16 +1324,16 @@ - - /* normal case, no cross section between start and end */ - if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { -- l2x0_inv_range(new_start, new_end); -+ l2c210_inv_range(new_start, new_end); - return; - } - - /* They cross sections, so it can only be a cross from section - * 2 to section 3 - */ -- l2x0_inv_range(new_start, -+ l2c210_inv_range(new_start, - bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); -- l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), -+ l2c210_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), - new_end); - } - -@@ -610,26 +1346,21 @@ - if (unlikely(end <= start)) - return; - -- if ((end - start) >= l2x0_size) { -- l2x0_clean_all(); -- return; -- } -- - new_start = bcm_l2_phys_addr(start); - new_end = bcm_l2_phys_addr(end); - - /* normal case, no cross section between start and end */ - if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { -- l2x0_clean_range(new_start, new_end); -+ l2c210_clean_range(new_start, new_end); - return; - } - - /* They cross sections, so it can only be a cross from section - * 2 to section 3 - */ -- l2x0_clean_range(new_start, -+ l2c210_clean_range(new_start, - bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); -- l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), -+ l2c210_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), - new_end); - } - -@@ -643,7 +1374,7 @@ - return; - - if ((end - start) >= l2x0_size) { -- l2x0_flush_all(); -+ outer_cache.flush_all(); - return; - } - -@@ -652,283 +1383,67 @@ - - /* normal case, no cross section between start and end */ - if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) { -- l2x0_flush_range(new_start, new_end); -+ l2c210_flush_range(new_start, new_end); - return; - } - - /* They cross sections, so it can only be a cross from section - * 2 to section 3 - */ -- l2x0_flush_range(new_start, -+ l2c210_flush_range(new_start, - bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1)); -- l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), -+ l2c210_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR), - new_end); - } - --static void __init l2x0_of_setup(const struct device_node *np, -- u32 *aux_val, u32 *aux_mask) --{ -- u32 data[2] = { 0, 0 }; -- u32 tag = 0; -- u32 dirty = 0; -- u32 val = 0, mask = 0; -- -- of_property_read_u32(np, "arm,tag-latency", &tag); -- if (tag) { -- mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK; -- val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT; -- } -- -- of_property_read_u32_array(np, "arm,data-latency", -- data, ARRAY_SIZE(data)); -- if (data[0] && data[1]) { -- mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK | -- L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK; -- val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) | -- ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT); -- } -- -- of_property_read_u32(np, "arm,dirty-latency", &dirty); -- if (dirty) { -- mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK; -- val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT; -- } -- -- *aux_val &= ~mask; -- *aux_val |= val; -- *aux_mask &= ~mask; --} -- --static void __init pl310_of_setup(const struct device_node *np, -- u32 *aux_val, u32 *aux_mask) --{ -- u32 data[3] = { 0, 0, 0 }; -- u32 tag[3] = { 0, 0, 0 }; -- u32 filter[2] = { 0, 0 }; -- -- of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag)); -- if (tag[0] && tag[1] && tag[2]) -- writel_relaxed( -- ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | -- ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | -- ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), -- l2x0_base + L2X0_TAG_LATENCY_CTRL); -- -- of_property_read_u32_array(np, "arm,data-latency", -- data, ARRAY_SIZE(data)); -- if (data[0] && data[1] && data[2]) -- writel_relaxed( -- ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) | -- ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) | -- ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT), -- l2x0_base + L2X0_DATA_LATENCY_CTRL); -- -- of_property_read_u32_array(np, "arm,filter-ranges", -- filter, ARRAY_SIZE(filter)); -- if (filter[1]) { -- writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M), -- l2x0_base + L2X0_ADDR_FILTER_END); -- writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN, -- l2x0_base + L2X0_ADDR_FILTER_START); -- } --} -- --static void __init pl310_save(void) --{ -- u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & -- L2X0_CACHE_ID_RTL_MASK; -- -- l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base + -- L2X0_TAG_LATENCY_CTRL); -- l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base + -- L2X0_DATA_LATENCY_CTRL); -- l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base + -- L2X0_ADDR_FILTER_END); -- l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base + -- L2X0_ADDR_FILTER_START); -- -- if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { -- /* -- * From r2p0, there is Prefetch offset/control register -- */ -- l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base + -- L2X0_PREFETCH_CTRL); -- /* -- * From r3p0, there is Power control register -- */ -- if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) -- l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base + -- L2X0_POWER_CTRL); -- } --} -+/* Broadcom L2C-310 start from ARMs R3P2 or later, and require no fixups */ -+static const struct l2c_init_data of_bcm_l2x0_data __initconst = { -+ .type = "BCM-L2C-310", -+ .way_size_0 = SZ_8K, -+ .num_lock = 8, -+ .of_parse = l2c310_of_parse, -+ .enable = l2c310_enable, -+ .save = l2c310_save, -+ .outer_cache = { -+ .inv_range = bcm_inv_range, -+ .clean_range = bcm_clean_range, -+ .flush_range = bcm_flush_range, -+ .flush_all = l2c210_flush_all, -+ .disable = l2c310_disable, -+ .sync = l2c210_sync, -+ .resume = l2c310_resume, -+ }, -+}; - --static void aurora_save(void) -+static void __init tauros3_save(void __iomem *base) - { -- l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL); -- l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); --} -+ l2c_save(base); - --static void __init tauros3_save(void) --{ - l2x0_saved_regs.aux2_ctrl = -- readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL); -+ readl_relaxed(base + TAUROS3_AUX2_CTRL); - l2x0_saved_regs.prefetch_ctrl = -- readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); --} -- --static void l2x0_resume(void) --{ -- if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -- /* restore aux ctrl and enable l2 */ -- l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID)); -- -- writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base + -- L2X0_AUX_CTRL); -- -- l2x0_inv_all(); -- -- writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL); -- } --} -- --static void pl310_resume(void) --{ -- u32 l2x0_revision; -- -- if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -- /* restore pl310 setup */ -- writel_relaxed(l2x0_saved_regs.tag_latency, -- l2x0_base + L2X0_TAG_LATENCY_CTRL); -- writel_relaxed(l2x0_saved_regs.data_latency, -- l2x0_base + L2X0_DATA_LATENCY_CTRL); -- writel_relaxed(l2x0_saved_regs.filter_end, -- l2x0_base + L2X0_ADDR_FILTER_END); -- writel_relaxed(l2x0_saved_regs.filter_start, -- l2x0_base + L2X0_ADDR_FILTER_START); -- -- l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) & -- L2X0_CACHE_ID_RTL_MASK; -- -- if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) { -- writel_relaxed(l2x0_saved_regs.prefetch_ctrl, -- l2x0_base + L2X0_PREFETCH_CTRL); -- if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0) -- writel_relaxed(l2x0_saved_regs.pwr_ctrl, -- l2x0_base + L2X0_POWER_CTRL); -- } -- } -- -- l2x0_resume(); --} -- --static void aurora_resume(void) --{ -- if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -- writel_relaxed(l2x0_saved_regs.aux_ctrl, -- l2x0_base + L2X0_AUX_CTRL); -- writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL); -- } -+ readl_relaxed(base + L310_PREFETCH_CTRL); - } - - static void tauros3_resume(void) - { -- if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -+ void __iomem *base = l2x0_base; -+ -+ if (!(readl_relaxed(base + L2X0_CTRL) & L2X0_CTRL_EN)) { - writel_relaxed(l2x0_saved_regs.aux2_ctrl, -- l2x0_base + TAUROS3_AUX2_CTRL); -+ base + TAUROS3_AUX2_CTRL); - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, -- l2x0_base + L2X0_PREFETCH_CTRL); -- } -- -- l2x0_resume(); --} -- --static void __init aurora_broadcast_l2_commands(void) --{ -- __u32 u; -- /* Enable Broadcasting of cache commands to L2*/ -- __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u)); -- u |= AURORA_CTRL_FW; /* Set the FW bit */ -- __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u)); -- isb(); --} -- --static void __init aurora_of_setup(const struct device_node *np, -- u32 *aux_val, u32 *aux_mask) --{ -- u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU; -- u32 mask = AURORA_ACR_REPLACEMENT_MASK; -+ base + L310_PREFETCH_CTRL); - -- of_property_read_u32(np, "cache-id-part", -- &cache_id_part_number_from_dt); -- -- /* Determine and save the write policy */ -- l2_wt_override = of_property_read_bool(np, "wt-override"); -- -- if (l2_wt_override) { -- val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY; -- mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; -+ l2c_enable(base, l2x0_saved_regs.aux_ctrl, 8); - } -- -- *aux_val &= ~mask; -- *aux_val |= val; -- *aux_mask &= ~mask; - } - --static const struct l2x0_of_data pl310_data = { -- .setup = pl310_of_setup, -- .save = pl310_save, -- .outer_cache = { -- .resume = pl310_resume, -- .inv_range = l2x0_inv_range, -- .clean_range = l2x0_clean_range, -- .flush_range = l2x0_flush_range, -- .sync = l2x0_cache_sync, -- .flush_all = l2x0_flush_all, -- .inv_all = l2x0_inv_all, -- .disable = l2x0_disable, -- }, --}; -- --static const struct l2x0_of_data l2x0_data = { -- .setup = l2x0_of_setup, -- .save = NULL, -- .outer_cache = { -- .resume = l2x0_resume, -- .inv_range = l2x0_inv_range, -- .clean_range = l2x0_clean_range, -- .flush_range = l2x0_flush_range, -- .sync = l2x0_cache_sync, -- .flush_all = l2x0_flush_all, -- .inv_all = l2x0_inv_all, -- .disable = l2x0_disable, -- }, --}; -- --static const struct l2x0_of_data aurora_with_outer_data = { -- .setup = aurora_of_setup, -- .save = aurora_save, -- .outer_cache = { -- .resume = aurora_resume, -- .inv_range = aurora_inv_range, -- .clean_range = aurora_clean_range, -- .flush_range = aurora_flush_range, -- .sync = l2x0_cache_sync, -- .flush_all = l2x0_flush_all, -- .inv_all = l2x0_inv_all, -- .disable = l2x0_disable, -- }, --}; -- --static const struct l2x0_of_data aurora_no_outer_data = { -- .setup = aurora_of_setup, -- .save = aurora_save, -- .outer_cache = { -- .resume = aurora_resume, -- }, --}; -- --static const struct l2x0_of_data tauros3_data = { -- .setup = NULL, -+static const struct l2c_init_data of_tauros3_data __initconst = { -+ .type = "Tauros3", -+ .way_size_0 = SZ_8K, -+ .num_lock = 8, -+ .enable = l2c_enable, - .save = tauros3_save, - /* Tauros3 broadcasts L1 cache operations to L2 */ - .outer_cache = { -@@ -936,43 +1451,26 @@ - }, - }; - --static const struct l2x0_of_data bcm_l2x0_data = { -- .setup = pl310_of_setup, -- .save = pl310_save, -- .outer_cache = { -- .resume = pl310_resume, -- .inv_range = bcm_inv_range, -- .clean_range = bcm_clean_range, -- .flush_range = bcm_flush_range, -- .sync = l2x0_cache_sync, -- .flush_all = l2x0_flush_all, -- .inv_all = l2x0_inv_all, -- .disable = l2x0_disable, -- }, --}; -- -+#define L2C_ID(name, fns) { .compatible = name, .data = (void *)&fns } - static const struct of_device_id l2x0_ids[] __initconst = { -- { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data }, -- { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data }, -- { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data }, -- { .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */ -- .data = (void *)&bcm_l2x0_data}, -- { .compatible = "brcm,bcm11351-a2-pl310-cache", -- .data = (void *)&bcm_l2x0_data}, -- { .compatible = "marvell,aurora-outer-cache", -- .data = (void *)&aurora_with_outer_data}, -- { .compatible = "marvell,aurora-system-cache", -- .data = (void *)&aurora_no_outer_data}, -- { .compatible = "marvell,tauros3-cache", -- .data = (void *)&tauros3_data }, -+ L2C_ID("arm,l210-cache", of_l2c210_data), -+ L2C_ID("arm,l220-cache", of_l2c220_data), -+ L2C_ID("arm,pl310-cache", of_l2c310_data), -+ L2C_ID("brcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), -+ L2C_ID("marvell,aurora-outer-cache", of_aurora_with_outer_data), -+ L2C_ID("marvell,aurora-system-cache", of_aurora_no_outer_data), -+ L2C_ID("marvell,tauros3-cache", of_tauros3_data), -+ /* Deprecated IDs */ -+ L2C_ID("bcm,bcm11351-a2-pl310-cache", of_bcm_l2x0_data), - {} - }; - - int __init l2x0_of_init(u32 aux_val, u32 aux_mask) - { -+ const struct l2c_init_data *data; - struct device_node *np; -- const struct l2x0_of_data *data; - struct resource res; -+ u32 cache_id, old_aux; - - np = of_find_matching_node(NULL, l2x0_ids); - if (!np) -@@ -989,23 +1487,29 @@ - - data = of_match_node(l2x0_ids, np)->data; - -- /* L2 configuration can only be changed if the cache is disabled */ -- if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) { -- if (data->setup) -- data->setup(np, &aux_val, &aux_mask); -- -- /* For aurora cache in no outer mode select the -- * correct mode using the coprocessor*/ -- if (data == &aurora_no_outer_data) -- aurora_broadcast_l2_commands(); -+ old_aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); -+ if (old_aux != ((old_aux & aux_mask) | aux_val)) { -+ pr_warn("L2C: platform modifies aux control register: 0x%08x -> 0x%08x\n", -+ old_aux, (old_aux & aux_mask) | aux_val); -+ } else if (aux_mask != ~0U && aux_val != 0) { -+ pr_alert("L2C: platform provided aux values match the hardware, so have no effect. Please remove them.\n"); - } - -- if (data->save) -- data->save(); -+ /* All L2 caches are unified, so this property should be specified */ -+ if (!of_property_read_bool(np, "cache-unified")) -+ pr_err("L2C: device tree omits to specify unified cache\n"); -+ -+ /* L2 configuration can only be changed if the cache is disabled */ -+ if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) -+ if (data->of_parse) -+ data->of_parse(np, &aux_val, &aux_mask); -+ -+ if (cache_id_part_number_from_dt) -+ cache_id = cache_id_part_number_from_dt; -+ else -+ cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID); - -- of_init = true; -- memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache)); -- l2x0_init(l2x0_base, aux_val, aux_mask); -+ __l2c_init(data, aux_val, aux_mask, cache_id); - - return 0; - } -diff -Nur linux-3.14.22.orig/arch/arm/mm/dma-mapping.c linux-3.14.22/arch/arm/mm/dma-mapping.c ---- linux-3.14.22.orig/arch/arm/mm/dma-mapping.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/dma-mapping.c 2014-10-22 14:55:49.934220001 -0500 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include - #include -diff -Nur linux-3.14.22.orig/arch/arm/mm/fault.c linux-3.14.22/arch/arm/mm/fault.c ---- linux-3.14.22.orig/arch/arm/mm/fault.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/fault.c 2014-10-22 14:55:49.934220001 -0500 -@@ -449,8 +449,16 @@ - - if (pud_none(*pud_k)) - goto bad_area; -- if (!pud_present(*pud)) -+ if (!pud_present(*pud)) { - set_pud(pud, *pud_k); -+ /* -+ * There is a small window during free_pgtables() where the -+ * user *pud entry is 0 but the TLB has not been invalidated -+ * and we get a level 2 (pmd) translation fault caused by the -+ * intermediate TLB caching of the old level 1 (pud) entry. -+ */ -+ flush_tlb_kernel_page(addr); -+ } - - pmd = pmd_offset(pud, addr); - pmd_k = pmd_offset(pud_k, addr); -@@ -473,8 +481,9 @@ - #endif - if (pmd_none(pmd_k[index])) - goto bad_area; -+ if (!pmd_present(pmd[index])) -+ copy_pmd(pmd, pmd_k); - -- copy_pmd(pmd, pmd_k); - return 0; - - bad_area: -diff -Nur linux-3.14.22.orig/arch/arm/mm/init.c linux-3.14.22/arch/arm/mm/init.c ---- linux-3.14.22.orig/arch/arm/mm/init.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/init.c 2014-10-22 14:55:49.934220001 -0500 -@@ -327,7 +327,7 @@ - * reserve memory for DMA contigouos allocations, - * must come from DMA area inside low memory - */ -- dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit)); -+ dma_contiguous_reserve(arm_dma_limit); - - arm_memblock_steal_permitted = false; - memblock_dump_all(); -diff -Nur linux-3.14.22.orig/arch/arm/mm/Kconfig linux-3.14.22/arch/arm/mm/Kconfig ---- linux-3.14.22.orig/arch/arm/mm/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/Kconfig 2014-10-22 14:55:49.934220001 -0500 -@@ -897,6 +897,57 @@ - This option enables optimisations for the PL310 cache - controller. - -+config PL310_ERRATA_588369 -+ bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines" -+ depends on CACHE_L2X0 -+ help -+ The PL310 L2 cache controller implements three types of Clean & -+ Invalidate maintenance operations: by Physical Address -+ (offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC). -+ They are architecturally defined to behave as the execution of a -+ clean operation followed immediately by an invalidate operation, -+ both performing to the same memory location. This functionality -+ is not correctly implemented in PL310 as clean lines are not -+ invalidated as a result of these operations. -+ -+config PL310_ERRATA_727915 -+ bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption" -+ depends on CACHE_L2X0 -+ help -+ PL310 implements the Clean & Invalidate by Way L2 cache maintenance -+ operation (offset 0x7FC). This operation runs in background so that -+ PL310 can handle normal accesses while it is in progress. Under very -+ rare circumstances, due to this erratum, write data can be lost when -+ PL310 treats a cacheable write transaction during a Clean & -+ Invalidate by Way operation. -+ -+config PL310_ERRATA_753970 -+ bool "PL310 errata: cache sync operation may be faulty" -+ depends on CACHE_PL310 -+ help -+ This option enables the workaround for the 753970 PL310 (r3p0) erratum. -+ -+ Under some condition the effect of cache sync operation on -+ the store buffer still remains when the operation completes. -+ This means that the store buffer is always asked to drain and -+ this prevents it from merging any further writes. The workaround -+ is to replace the normal offset of cache sync operation (0x730) -+ by another offset targeting an unmapped PL310 register 0x740. -+ This has the same effect as the cache sync operation: store buffer -+ drain and waiting for all buffers empty. -+ -+config PL310_ERRATA_769419 -+ bool "PL310 errata: no automatic Store Buffer drain" -+ depends on CACHE_L2X0 -+ help -+ On revisions of the PL310 prior to r3p2, the Store Buffer does -+ not automatically drain. This can cause normal, non-cacheable -+ writes to be retained when the memory system is idle, leading -+ to suboptimal I/O performance for drivers using coherent DMA. -+ This option adds a write barrier to the cpu_idle loop so that, -+ on systems with an outer cache, the store buffer is drained -+ explicitly. -+ - config CACHE_TAUROS2 - bool "Enable the Tauros2 L2 cache controller" - depends on (ARCH_DOVE || ARCH_MMP || CPU_PJ4) -diff -Nur linux-3.14.22.orig/arch/arm/mm/l2c-common.c linux-3.14.22/arch/arm/mm/l2c-common.c ---- linux-3.14.22.orig/arch/arm/mm/l2c-common.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mm/l2c-common.c 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,20 @@ -+/* -+ * Copyright (C) 2010 ARM Ltd. -+ * Written by Catalin Marinas -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include -+#include -+#include -+ -+void outer_disable(void) -+{ -+ WARN_ON(!irqs_disabled()); -+ WARN_ON(num_online_cpus() > 1); -+ -+ if (outer_cache.disable) -+ outer_cache.disable(); -+} -diff -Nur linux-3.14.22.orig/arch/arm/mm/l2c-l2x0-resume.S linux-3.14.22/arch/arm/mm/l2c-l2x0-resume.S ---- linux-3.14.22.orig/arch/arm/mm/l2c-l2x0-resume.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm/mm/l2c-l2x0-resume.S 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,58 @@ -+/* -+ * L2C-310 early resume code. This can be used by platforms to restore -+ * the settings of their L2 cache controller before restoring the -+ * processor state. -+ * -+ * This code can only be used to if you are running in the secure world. -+ */ -+#include -+#include -+ -+ .text -+ -+ENTRY(l2c310_early_resume) -+ adr r0, 1f -+ ldr r2, [r0] -+ add r0, r2, r0 -+ -+ ldmia r0, {r1, r2, r3, r4, r5, r6, r7, r8} -+ @ r1 = phys address of L2C-310 controller -+ @ r2 = aux_ctrl -+ @ r3 = tag_latency -+ @ r4 = data_latency -+ @ r5 = filter_start -+ @ r6 = filter_end -+ @ r7 = prefetch_ctrl -+ @ r8 = pwr_ctrl -+ -+ @ Check that the address has been initialised -+ teq r1, #0 -+ moveq pc, lr -+ -+ @ The prefetch and power control registers are revision dependent -+ @ and can be written whether or not the L2 cache is enabled -+ ldr r0, [r1, #L2X0_CACHE_ID] -+ and r0, r0, #L2X0_CACHE_ID_RTL_MASK -+ cmp r0, #L310_CACHE_ID_RTL_R2P0 -+ strcs r7, [r1, #L310_PREFETCH_CTRL] -+ cmp r0, #L310_CACHE_ID_RTL_R3P0 -+ strcs r8, [r1, #L310_POWER_CTRL] -+ -+ @ Don't setup the L2 cache if it is already enabled -+ ldr r0, [r1, #L2X0_CTRL] -+ tst r0, #L2X0_CTRL_EN -+ movne pc, lr -+ -+ str r3, [r1, #L310_TAG_LATENCY_CTRL] -+ str r4, [r1, #L310_DATA_LATENCY_CTRL] -+ str r6, [r1, #L310_ADDR_FILTER_END] -+ str r5, [r1, #L310_ADDR_FILTER_START] -+ -+ str r2, [r1, #L2X0_AUX_CTRL] -+ mov r9, #L2X0_CTRL_EN -+ str r9, [r1, #L2X0_CTRL] -+ mov pc, lr -+ENDPROC(l2c310_early_resume) -+ -+ .align -+1: .long l2x0_saved_regs - . -diff -Nur linux-3.14.22.orig/arch/arm/mm/Makefile linux-3.14.22/arch/arm/mm/Makefile ---- linux-3.14.22.orig/arch/arm/mm/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/Makefile 2014-10-22 14:55:49.934220001 -0500 -@@ -95,7 +95,8 @@ - AFLAGS_proc-v6.o :=-Wa,-march=armv6 - AFLAGS_proc-v7.o :=-Wa,-march=armv7-a - -+obj-$(CONFIG_OUTER_CACHE) += l2c-common.o - obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o --obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o -+obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o l2c-l2x0-resume.o - obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o - obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o -diff -Nur linux-3.14.22.orig/arch/arm/mm/proc-v7.S linux-3.14.22/arch/arm/mm/proc-v7.S ---- linux-3.14.22.orig/arch/arm/mm/proc-v7.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm/mm/proc-v7.S 2014-10-22 14:55:49.934220001 -0500 -@@ -336,6 +336,17 @@ - mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register - 1: - #endif -+#ifdef CONFIG_ARM_ERRATA_794072 -+ mrc p15, 0, r10, c15, c0, 1 @ read diagnostic register -+ orr r10, r10, #1 << 4 @ set bit #4 -+ mcr p15, 0, r10, c15, c0, 1 @ write diagnostic register -+#endif -+#ifdef CONFIG_ARM_ERRATA_761320 -+ cmp r6, #0x40 @ present prior to r4p0 -+ mrclt p15, 0, r10, c15, c0, 1 @ read diagnostic register -+ orrlt r10, r10, #1 << 21 @ set bit #21 -+ mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register -+#endif - - /* Cortex-A15 Errata */ - 3: ldr r10, =0x00000c0f @ Cortex-A15 primary part number -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/apm-mustang.dts linux-3.14.22/arch/arm64/boot/dts/apm-mustang.dts ---- linux-3.14.22.orig/arch/arm64/boot/dts/apm-mustang.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/boot/dts/apm-mustang.dts 2014-10-22 14:55:49.934220001 -0500 -@@ -24,3 +24,7 @@ - reg = < 0x1 0x00000000 0x0 0x80000000 >; /* Updated by bootloader */ - }; - }; -+ -+&serial0 { -+ status = "ok"; -+}; -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/apm-storm.dtsi linux-3.14.22/arch/arm64/boot/dts/apm-storm.dtsi ---- linux-3.14.22.orig/arch/arm64/boot/dts/apm-storm.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/boot/dts/apm-storm.dtsi 2014-10-22 14:55:49.934220001 -0500 -@@ -176,16 +176,226 @@ - reg-names = "csr-reg"; - clock-output-names = "eth8clk"; - }; -+ -+ sataphy1clk: sataphy1clk@1f21c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f21c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sataphy1clk"; -+ status = "disabled"; -+ csr-offset = <0x4>; -+ csr-mask = <0x00>; -+ enable-offset = <0x0>; -+ enable-mask = <0x06>; -+ }; -+ -+ sataphy2clk: sataphy1clk@1f22c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f22c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sataphy2clk"; -+ status = "ok"; -+ csr-offset = <0x4>; -+ csr-mask = <0x3a>; -+ enable-offset = <0x0>; -+ enable-mask = <0x06>; -+ }; -+ -+ sataphy3clk: sataphy1clk@1f23c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f23c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sataphy3clk"; -+ status = "ok"; -+ csr-offset = <0x4>; -+ csr-mask = <0x3a>; -+ enable-offset = <0x0>; -+ enable-mask = <0x06>; -+ }; -+ -+ sata01clk: sata01clk@1f21c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f21c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sata01clk"; -+ csr-offset = <0x4>; -+ csr-mask = <0x05>; -+ enable-offset = <0x0>; -+ enable-mask = <0x39>; -+ }; -+ -+ sata23clk: sata23clk@1f22c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f22c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sata23clk"; -+ csr-offset = <0x4>; -+ csr-mask = <0x05>; -+ enable-offset = <0x0>; -+ enable-mask = <0x39>; -+ }; -+ -+ sata45clk: sata45clk@1f23c000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x1f23c000 0x0 0x1000>; -+ reg-names = "csr-reg"; -+ clock-output-names = "sata45clk"; -+ csr-offset = <0x4>; -+ csr-mask = <0x05>; -+ enable-offset = <0x0>; -+ enable-mask = <0x39>; -+ }; -+ -+ rtcclk: rtcclk@17000000 { -+ compatible = "apm,xgene-device-clock"; -+ #clock-cells = <1>; -+ clocks = <&socplldiv2 0>; -+ reg = <0x0 0x17000000 0x0 0x2000>; -+ reg-names = "csr-reg"; -+ csr-offset = <0xc>; -+ csr-mask = <0x2>; -+ enable-offset = <0x10>; -+ enable-mask = <0x2>; -+ clock-output-names = "rtcclk"; -+ }; - }; - - serial0: serial@1c020000 { -+ status = "disabled"; - device_type = "serial"; -- compatible = "ns16550"; -+ compatible = "ns16550a"; - reg = <0 0x1c020000 0x0 0x1000>; - reg-shift = <2>; - clock-frequency = <10000000>; /* Updated by bootloader */ - interrupt-parent = <&gic>; - interrupts = <0x0 0x4c 0x4>; - }; -+ -+ serial1: serial@1c021000 { -+ status = "disabled"; -+ device_type = "serial"; -+ compatible = "ns16550a"; -+ reg = <0 0x1c021000 0x0 0x1000>; -+ reg-shift = <2>; -+ clock-frequency = <10000000>; /* Updated by bootloader */ -+ interrupt-parent = <&gic>; -+ interrupts = <0x0 0x4d 0x4>; -+ }; -+ -+ serial2: serial@1c022000 { -+ status = "disabled"; -+ device_type = "serial"; -+ compatible = "ns16550a"; -+ reg = <0 0x1c022000 0x0 0x1000>; -+ reg-shift = <2>; -+ clock-frequency = <10000000>; /* Updated by bootloader */ -+ interrupt-parent = <&gic>; -+ interrupts = <0x0 0x4e 0x4>; -+ }; -+ -+ serial3: serial@1c023000 { -+ status = "disabled"; -+ device_type = "serial"; -+ compatible = "ns16550a"; -+ reg = <0 0x1c023000 0x0 0x1000>; -+ reg-shift = <2>; -+ clock-frequency = <10000000>; /* Updated by bootloader */ -+ interrupt-parent = <&gic>; -+ interrupts = <0x0 0x4f 0x4>; -+ }; -+ -+ phy1: phy@1f21a000 { -+ compatible = "apm,xgene-phy"; -+ reg = <0x0 0x1f21a000 0x0 0x100>; -+ #phy-cells = <1>; -+ clocks = <&sataphy1clk 0>; -+ status = "disabled"; -+ apm,tx-boost-gain = <30 30 30 30 30 30>; -+ apm,tx-eye-tuning = <2 10 10 2 10 10>; -+ }; -+ -+ phy2: phy@1f22a000 { -+ compatible = "apm,xgene-phy"; -+ reg = <0x0 0x1f22a000 0x0 0x100>; -+ #phy-cells = <1>; -+ clocks = <&sataphy2clk 0>; -+ status = "ok"; -+ apm,tx-boost-gain = <30 30 30 30 30 30>; -+ apm,tx-eye-tuning = <1 10 10 2 10 10>; -+ }; -+ -+ phy3: phy@1f23a000 { -+ compatible = "apm,xgene-phy"; -+ reg = <0x0 0x1f23a000 0x0 0x100>; -+ #phy-cells = <1>; -+ clocks = <&sataphy3clk 0>; -+ status = "ok"; -+ apm,tx-boost-gain = <31 31 31 31 31 31>; -+ apm,tx-eye-tuning = <2 10 10 2 10 10>; -+ }; -+ -+ sata1: sata@1a000000 { -+ compatible = "apm,xgene-ahci"; -+ reg = <0x0 0x1a000000 0x0 0x1000>, -+ <0x0 0x1f210000 0x0 0x1000>, -+ <0x0 0x1f21d000 0x0 0x1000>, -+ <0x0 0x1f21e000 0x0 0x1000>, -+ <0x0 0x1f217000 0x0 0x1000>; -+ interrupts = <0x0 0x86 0x4>; -+ dma-coherent; -+ status = "disabled"; -+ clocks = <&sata01clk 0>; -+ phys = <&phy1 0>; -+ phy-names = "sata-phy"; -+ }; -+ -+ sata2: sata@1a400000 { -+ compatible = "apm,xgene-ahci"; -+ reg = <0x0 0x1a400000 0x0 0x1000>, -+ <0x0 0x1f220000 0x0 0x1000>, -+ <0x0 0x1f22d000 0x0 0x1000>, -+ <0x0 0x1f22e000 0x0 0x1000>, -+ <0x0 0x1f227000 0x0 0x1000>; -+ interrupts = <0x0 0x87 0x4>; -+ dma-coherent; -+ status = "ok"; -+ clocks = <&sata23clk 0>; -+ phys = <&phy2 0>; -+ phy-names = "sata-phy"; -+ }; -+ -+ sata3: sata@1a800000 { -+ compatible = "apm,xgene-ahci"; -+ reg = <0x0 0x1a800000 0x0 0x1000>, -+ <0x0 0x1f230000 0x0 0x1000>, -+ <0x0 0x1f23d000 0x0 0x1000>, -+ <0x0 0x1f23e000 0x0 0x1000>; -+ interrupts = <0x0 0x88 0x4>; -+ dma-coherent; -+ status = "ok"; -+ clocks = <&sata45clk 0>; -+ phys = <&phy3 0>; -+ phy-names = "sata-phy"; -+ }; -+ -+ rtc: rtc@10510000 { -+ compatible = "apm,xgene-rtc"; -+ reg = <0x0 0x10510000 0x0 0x400>; -+ interrupts = <0x0 0x46 0x4>; -+ #clock-cells = <1>; -+ clocks = <&rtcclk 0>; -+ }; - }; - }; -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/clcd-panels.dtsi linux-3.14.22/arch/arm64/boot/dts/clcd-panels.dtsi ---- linux-3.14.22.orig/arch/arm64/boot/dts/clcd-panels.dtsi 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/boot/dts/clcd-panels.dtsi 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,52 @@ -+/* -+ * ARM Ltd. Versatile Express -+ * -+ */ -+ -+/ { -+ panels { -+ panel@0 { -+ compatible = "panel"; -+ mode = "VGA"; -+ refresh = <60>; -+ xres = <640>; -+ yres = <480>; -+ pixclock = <39721>; -+ left_margin = <40>; -+ right_margin = <24>; -+ upper_margin = <32>; -+ lower_margin = <11>; -+ hsync_len = <96>; -+ vsync_len = <2>; -+ sync = <0>; -+ vmode = "FB_VMODE_NONINTERLACED"; -+ -+ tim2 = "TIM2_BCD", "TIM2_IPC"; -+ cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; -+ caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; -+ bpp = <16>; -+ }; -+ -+ panel@1 { -+ compatible = "panel"; -+ mode = "XVGA"; -+ refresh = <60>; -+ xres = <1024>; -+ yres = <768>; -+ pixclock = <15748>; -+ left_margin = <152>; -+ right_margin = <48>; -+ upper_margin = <23>; -+ lower_margin = <3>; -+ hsync_len = <104>; -+ vsync_len = <4>; -+ sync = <0>; -+ vmode = "FB_VMODE_NONINTERLACED"; -+ -+ tim2 = "TIM2_BCD", "TIM2_IPC"; -+ cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; -+ caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; -+ bpp = <16>; -+ }; -+ }; -+}; -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts linux-3.14.22/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts ---- linux-3.14.22.orig/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/boot/dts/fvp-base-gicv2-psci.dts 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,266 @@ -+/* -+ * Copyright (c) 2013, ARM Limited. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * -+ * Redistributions of source code must retain the above copyright notice, this -+ * list of conditions and the following disclaimer. -+ * -+ * Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * -+ * Neither the name of ARM nor the names of its contributors may be used -+ * to endorse or promote products derived from this software without specific -+ * prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/dts-v1/; -+ -+/memreserve/ 0x80000000 0x00010000; -+ -+/ { -+}; -+ -+/ { -+ model = "FVP Base"; -+ compatible = "arm,vfp-base", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ chosen { }; -+ -+ aliases { -+ serial0 = &v2m_serial0; -+ serial1 = &v2m_serial1; -+ serial2 = &v2m_serial2; -+ serial3 = &v2m_serial3; -+ }; -+ -+ psci { -+ compatible = "arm,psci"; -+ method = "smc"; -+ cpu_suspend = <0xc4000001>; -+ cpu_off = <0x84000002>; -+ cpu_on = <0xc4000003>; -+ }; -+ -+ cpus { -+ #address-cells = <2>; -+ #size-cells = <0>; -+ -+ big0: cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57", "arm,armv8"; -+ reg = <0x0 0x0>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ big1: cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57", "arm,armv8"; -+ reg = <0x0 0x1>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ big2: cpu@2 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57", "arm,armv8"; -+ reg = <0x0 0x2>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ big3: cpu@3 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57", "arm,armv8"; -+ reg = <0x0 0x3>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ little0: cpu@100 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ reg = <0x0 0x100>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ little1: cpu@101 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ reg = <0x0 0x101>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ little2: cpu@102 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ reg = <0x0 0x102>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ little3: cpu@103 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ reg = <0x0 0x103>; -+ enable-method = "psci"; -+ clock-frequency = <1000000>; -+ }; -+ -+ cpu-map { -+ cluster0 { -+ core0 { -+ cpu = <&big0>; -+ }; -+ core1 { -+ cpu = <&big1>; -+ }; -+ core2 { -+ cpu = <&big2>; -+ }; -+ core3 { -+ cpu = <&big3>; -+ }; -+ }; -+ cluster1 { -+ core0 { -+ cpu = <&little0>; -+ }; -+ core1 { -+ cpu = <&little1>; -+ }; -+ core2 { -+ cpu = <&little2>; -+ }; -+ core3 { -+ cpu = <&little3>; -+ }; -+ }; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x00000000 0x80000000 0 0x80000000>, -+ <0x00000008 0x80000000 0 0x80000000>; -+ }; -+ -+ gic: interrupt-controller@2f000000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x0 0x2f000000 0 0x10000>, -+ <0x0 0x2c000000 0 0x2000>, -+ <0x0 0x2c010000 0 0x2000>, -+ <0x0 0x2c02F000 0 0x2000>; -+ interrupts = <1 9 0xf04>; -+ }; -+ -+ timer { -+ compatible = "arm,armv8-timer"; -+ interrupts = <1 13 0xff01>, -+ <1 14 0xff01>, -+ <1 11 0xff01>, -+ <1 10 0xff01>; -+ clock-frequency = <100000000>; -+ }; -+ -+ timer@2a810000 { -+ compatible = "arm,armv7-timer-mem"; -+ reg = <0x0 0x2a810000 0x0 0x10000>; -+ clock-frequency = <100000000>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ ranges; -+ frame@2a820000 { -+ frame-number = <0>; -+ interrupts = <0 25 4>; -+ reg = <0x0 0x2a820000 0x0 0x10000>; -+ }; -+ }; -+ -+ pmu { -+ compatible = "arm,armv8-pmuv3"; -+ interrupts = <0 60 4>, -+ <0 61 4>, -+ <0 62 4>, -+ <0 63 4>; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 63>; -+ interrupt-map = <0 0 0 &gic 0 0 4>, -+ <0 0 1 &gic 0 1 4>, -+ <0 0 2 &gic 0 2 4>, -+ <0 0 3 &gic 0 3 4>, -+ <0 0 4 &gic 0 4 4>, -+ <0 0 5 &gic 0 5 4>, -+ <0 0 6 &gic 0 6 4>, -+ <0 0 7 &gic 0 7 4>, -+ <0 0 8 &gic 0 8 4>, -+ <0 0 9 &gic 0 9 4>, -+ <0 0 10 &gic 0 10 4>, -+ <0 0 11 &gic 0 11 4>, -+ <0 0 12 &gic 0 12 4>, -+ <0 0 13 &gic 0 13 4>, -+ <0 0 14 &gic 0 14 4>, -+ <0 0 15 &gic 0 15 4>, -+ <0 0 16 &gic 0 16 4>, -+ <0 0 17 &gic 0 17 4>, -+ <0 0 18 &gic 0 18 4>, -+ <0 0 19 &gic 0 19 4>, -+ <0 0 20 &gic 0 20 4>, -+ <0 0 21 &gic 0 21 4>, -+ <0 0 22 &gic 0 22 4>, -+ <0 0 23 &gic 0 23 4>, -+ <0 0 24 &gic 0 24 4>, -+ <0 0 25 &gic 0 25 4>, -+ <0 0 26 &gic 0 26 4>, -+ <0 0 27 &gic 0 27 4>, -+ <0 0 28 &gic 0 28 4>, -+ <0 0 29 &gic 0 29 4>, -+ <0 0 30 &gic 0 30 4>, -+ <0 0 31 &gic 0 31 4>, -+ <0 0 32 &gic 0 32 4>, -+ <0 0 33 &gic 0 33 4>, -+ <0 0 34 &gic 0 34 4>, -+ <0 0 35 &gic 0 35 4>, -+ <0 0 36 &gic 0 36 4>, -+ <0 0 37 &gic 0 37 4>, -+ <0 0 38 &gic 0 38 4>, -+ <0 0 39 &gic 0 39 4>, -+ <0 0 40 &gic 0 40 4>, -+ <0 0 41 &gic 0 41 4>, -+ <0 0 42 &gic 0 42 4>; -+ -+ /include/ "rtsm_ve-motherboard.dtsi" -+ }; -+}; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/juno.dts linux-3.14.22/arch/arm64/boot/dts/juno.dts ---- linux-3.14.22.orig/arch/arm64/boot/dts/juno.dts 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/boot/dts/juno.dts 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,498 @@ -+/* -+ * ARM Ltd. Juno Plaform -+ * -+ * Fast Models FVP v2 support -+ */ -+ -+/dts-v1/; -+ -+#include -+ -+/ { -+ model = "Juno"; -+ compatible = "arm,juno", "arm,vexpress"; -+ interrupt-parent = <&gic>; -+ #address-cells = <2>; -+ #size-cells = <2>; -+ -+ aliases { -+ serial0 = &soc_uart0; -+ }; -+ -+ cpus { -+ #address-cells = <2>; -+ #size-cells = <0>; -+ -+ cpu@100 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53","arm,armv8"; -+ reg = <0x0 0x100>; -+ enable-method = "psci"; -+ }; -+ -+ cpu@101 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53","arm,armv8"; -+ reg = <0x0 0x101>; -+ enable-method = "psci"; -+ }; -+ -+ cpu@102 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53","arm,armv8"; -+ reg = <0x0 0x102>; -+ enable-method = "psci"; -+ }; -+ -+ cpu@103 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a53","arm,armv8"; -+ reg = <0x0 0x103>; -+ enable-method = "psci"; -+ }; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57","arm,armv8"; -+ reg = <0x0 0x0>; -+ enable-method = "psci"; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a57","arm,armv8"; -+ reg = <0x0 0x1>; -+ enable-method = "psci"; -+ }; -+ }; -+ -+ memory@80000000 { -+ device_type = "memory"; -+ reg = <0x00000000 0x80000000 0x0 0x80000000>, -+ <0x00000008 0x80000000 0x1 0x80000000>; -+ }; -+ -+ /* memory@14000000 { -+ device_type = "memory"; -+ reg = <0x00000000 0x14000000 0x0 0x02000000>; -+ }; */ -+ -+ gic: interrupt-controller@2c001000 { -+ compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x0 0x2c010000 0 0x1000>, -+ <0x0 0x2c02f000 0 0x1000>, -+ <0x0 0x2c04f000 0 0x2000>, -+ <0x0 0x2c06f000 0 0x2000>; -+ interrupts = ; -+ }; -+ -+ msi0: msi@2c1c0000 { -+ compatible = "arm,gic-msi"; -+ reg = <0x0 0x2c1c0000 0 0x10000 -+ 0x0 0x2c1d0000 0 0x10000 -+ 0x0 0x2c1e0000 0 0x10000 -+ 0x0 0x2c1f0000 0 0x10000>; -+ }; -+ -+ timer { -+ compatible = "arm,armv8-timer"; -+ interrupts = , -+ , -+ , -+ ; -+ }; -+ -+ pmu { -+ compatible = "arm,armv8-pmuv3"; -+ interrupts = , -+ , -+ , -+ ; -+ }; -+ -+ psci { -+ compatible = "arm,psci"; -+ method = "smc"; -+ cpu_suspend = <0xC4000001>; -+ cpu_off = <0x84000002>; -+ cpu_on = <0xC4000003>; -+ migrate = <0xC4000005>; -+ }; -+ -+ pci0: pci@30000000 { -+ compatible = "arm,pcie-xr3"; -+ device_type = "pci"; -+ reg = <0 0x7ff30000 0 0x1000 -+ 0 0x7ff20000 0 0x10000 -+ 0 0x40000000 0 0x10000000>; -+ bus-range = <0 255>; -+ #address-cells = <3>; -+ #size-cells = <2>; -+ ranges = <0x01000000 0x0 0x00000000 0x00 0x5ff00000 0x0 0x00100000 -+ 0x02000000 0x0 0x00000000 0x40 0x00000000 0x0 0x80000000 -+ 0x42000000 0x0 0x80000000 0x40 0x80000000 0x0 0x80000000>; -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 0 7>; -+ interrupt-map = <0 0 0 1 &gic 0 136 4 -+ 0 0 0 2 &gic 0 137 4 -+ 0 0 0 3 &gic 0 138 4 -+ 0 0 0 4 &gic 0 139 4>; -+ }; -+ -+ scpi: scpi@2b1f0000 { -+ compatible = "arm,scpi-mhu"; -+ reg = <0x0 0x2b1f0000 0x0 0x10000>, /* MHU registers */ -+ <0x0 0x2e000000 0x0 0x10000>; /* Payload area */ -+ interrupts = <0 36 4>, /* low priority interrupt */ -+ <0 35 4>, /* high priority interrupt */ -+ <0 37 4>; /* secure channel interrupt */ -+ #clock-cells = <1>; -+ clock-output-names = "a57", "a53", "gpu", "hdlcd0", "hdlcd1"; -+ }; -+ -+ hdlcd0_osc: scpi_osc@3 { -+ compatible = "arm,scpi-osc"; -+ #clock-cells = <0>; -+ clocks = <&scpi 3>; -+ frequency-range = <23000000 210000000>; -+ clock-output-names = "pxlclk0"; -+ }; -+ -+ hdlcd1_osc: scpi_osc@4 { -+ compatible = "arm,scpi-osc"; -+ #clock-cells = <0>; -+ clocks = <&scpi 4>; -+ frequency-range = <23000000 210000000>; -+ clock-output-names = "pxlclk1"; -+ }; -+ -+ soc_uartclk: refclk72738khz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <7273800>; -+ clock-output-names = "juno:uartclk"; -+ }; -+ -+ soc_refclk24mhz: clk24mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <24000000>; -+ clock-output-names = "juno:clk24mhz"; -+ }; -+ -+ mb_eth25mhz: clk25mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <25000000>; -+ clock-output-names = "ethclk25mhz"; -+ }; -+ -+ soc_usb48mhz: clk48mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <48000000>; -+ clock-output-names = "clk48mhz"; -+ }; -+ -+ soc_smc50mhz: clk50mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <50000000>; -+ clock-output-names = "smc_clk"; -+ }; -+ -+ soc_refclk100mhz: refclk100mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <100000000>; -+ clock-output-names = "apb_pclk"; -+ }; -+ -+ soc_faxiclk: refclk533mhz { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <533000000>; -+ clock-output-names = "faxi_clk"; -+ }; -+ -+ soc_fixed_3v3: fixedregulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "3V3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-always-on; -+ }; -+ -+ memory-controller@7ffd0000 { -+ compatible = "arm,pl354", "arm,primecell"; -+ reg = <0 0x7ffd0000 0 0x1000>; -+ interrupts = <0 86 4>, -+ <0 87 4>; -+ clocks = <&soc_smc50mhz>; -+ clock-names = "apb_pclk"; -+ chip5-memwidth = <16>; -+ }; -+ -+ dma0: dma@0x7ff00000 { -+ compatible = "arm,pl330", "arm,primecell"; -+ reg = <0x0 0x7ff00000 0 0x1000>; -+ interrupts = <0 95 4>, -+ <0 88 4>, -+ <0 89 4>, -+ <0 90 4>, -+ <0 91 4>, -+ <0 108 4>, -+ <0 109 4>, -+ <0 110 4>, -+ <0 111 4>; -+ #dma-cells = <1>; -+ #dma-channels = <8>; -+ #dma-requests = <32>; -+ clocks = <&soc_faxiclk>; -+ clock-names = "apb_pclk"; -+ }; -+ -+ soc_uart0: uart@7ff80000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x0 0x7ff80000 0x0 0x1000>; -+ interrupts = <0 83 4>; -+ clocks = <&soc_uartclk>, <&soc_refclk100mhz>; -+ clock-names = "uartclk", "apb_pclk"; -+ dmas = <&dma0 1 -+ &dma0 2>; -+ dma-names = "rx", "tx"; -+ }; -+ -+ /* this UART is reserved for secure software. -+ soc_uart1: uart@7ff70000 { -+ compatible = "arm,pl011", "arm,primecell"; -+ reg = <0x0 0x7ff70000 0x0 0x1000>; -+ interrupts = <0 84 4>; -+ clocks = <&soc_uartclk>, <&soc_refclk100mhz>; -+ clock-names = "uartclk", "apb_pclk"; -+ }; */ -+ -+ ulpi_phy: phy@0 { -+ compatible = "phy-ulpi-generic"; -+ reg = <0x0 0x94 0x0 0x4>; -+ phy-id = <0>; -+ }; -+ -+ ehci@7ffc0000 { -+ compatible = "snps,ehci-h20ahb"; -+ /* compatible = "arm,h20ahb-ehci"; */ -+ reg = <0x0 0x7ffc0000 0x0 0x10000>; -+ interrupts = <0 117 4>; -+ clocks = <&soc_usb48mhz>; -+ clock-names = "otg"; -+ phys = <&ulpi_phy>; -+ }; -+ -+ ohci@0x7ffb0000 { -+ compatible = "generic-ohci"; -+ reg = <0x0 0x7ffb0000 0x0 0x10000>; -+ interrupts = <0 116 4>; -+ clocks = <&soc_usb48mhz>; -+ clock-names = "otg"; -+ }; -+ -+ i2c@0x7ffa0000 { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ compatible = "snps,designware-i2c"; -+ reg = <0x0 0x7ffa0000 0x0 0x1000>; -+ interrupts = <0 104 4>; -+ clock-frequency = <400000>; -+ i2c-sda-hold-time-ns = <500>; -+ clocks = <&soc_smc50mhz>; -+ -+ dvi0: dvi-transmitter@70 { -+ compatible = "nxp,tda998x"; -+ reg = <0x70>; -+ }; -+ -+ dvi1: dvi-transmitter@71 { -+ compatible = "nxp,tda998x"; -+ reg = <0x71>; -+ }; -+ }; -+ -+ /* mmci@1c050000 { -+ compatible = "arm,pl180", "arm,primecell"; -+ reg = <0x0 0x1c050000 0x0 0x1000>; -+ interrupts = <0 73 4>, -+ <0 74 4>; -+ max-frequency = <12000000>; -+ vmmc-supply = <&soc_fixed_3v3>; -+ clocks = <&soc_refclk24mhz>, <&soc_refclk100mhz>; -+ clock-names = "mclk", "apb_pclk"; -+ }; */ -+ -+ hdlcd@7ff60000 { -+ compatible = "arm,hdlcd"; -+ reg = <0 0x7ff60000 0 0x1000>; -+ interrupts = <0 85 4>; -+ clocks = <&hdlcd0_osc>; -+ clock-names = "pxlclk"; -+ i2c-slave = <&dvi0>; -+ -+ /* display-timings { -+ native-mode = <&timing0>; -+ timing0: timing@0 { -+ /* 1024 x 768 framebufer, standard VGA timings * / -+ clock-frequency = <65000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hfront-porch = <24>; -+ hback-porch = <160>; -+ hsync-len = <136>; -+ vfront-porch = <3>; -+ vback-porch = <29>; -+ vsync-len = <6>; -+ }; -+ }; */ -+ }; -+ -+ hdlcd@7ff50000 { -+ compatible = "arm,hdlcd"; -+ reg = <0 0x7ff50000 0 0x1000>; -+ interrupts = <0 93 4>; -+ clocks = <&hdlcd1_osc>; -+ clock-names = "pxlclk"; -+ i2c-slave = <&dvi1>; -+ -+ display-timings { -+ native-mode = <&timing1>; -+ timing1: timing@1 { -+ /* 1024 x 768 framebufer, standard VGA timings */ -+ clock-frequency = <65000>; -+ hactive = <1024>; -+ vactive = <768>; -+ hfront-porch = <24>; -+ hback-porch = <160>; -+ hsync-len = <136>; -+ vfront-porch = <3>; -+ vback-porch = <29>; -+ vsync-len = <6>; -+ }; -+ }; -+ }; -+ -+ smb { -+ compatible = "simple-bus"; -+ #address-cells = <2>; -+ #size-cells = <1>; -+ ranges = <0 0 0 0x08000000 0x04000000>, -+ <1 0 0 0x14000000 0x04000000>, -+ <2 0 0 0x18000000 0x04000000>, -+ <3 0 0 0x1c000000 0x04000000>, -+ <4 0 0 0x0c000000 0x04000000>, -+ <5 0 0 0x10000000 0x04000000>; -+ -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0 0 15>; -+ interrupt-map = <0 0 0 &gic 0 68 4>, -+ <0 0 1 &gic 0 69 4>, -+ <0 0 2 &gic 0 70 4>, -+ <0 0 3 &gic 0 160 4>, -+ <0 0 4 &gic 0 161 4>, -+ <0 0 5 &gic 0 162 4>, -+ <0 0 6 &gic 0 163 4>, -+ <0 0 7 &gic 0 164 4>, -+ <0 0 8 &gic 0 165 4>, -+ <0 0 9 &gic 0 166 4>, -+ <0 0 10 &gic 0 167 4>, -+ <0 0 11 &gic 0 168 4>, -+ <0 0 12 &gic 0 169 4>; -+ -+ motherboard { -+ model = "V2M-Juno"; -+ arm,hbi = <0x252>; -+ arm,vexpress,site = <0>; -+ arm,v2m-memory-map = "rs1"; -+ compatible = "arm,vexpress,v2p-p1", "simple-bus"; -+ #address-cells = <2>; /* SMB chipselect number and offset */ -+ #size-cells = <1>; -+ #interrupt-cells = <1>; -+ ranges; -+ -+ usb@5,00000000 { -+ compatible = "nxp,usb-isp1763"; -+ reg = <5 0x00000000 0x20000>; -+ bus-width = <16>; -+ interrupts = <4>; -+ }; -+ -+ ethernet@2,00000000 { -+ compatible = "smsc,lan9118", "smsc,lan9115"; -+ reg = <2 0x00000000 0x10000>; -+ interrupts = <3>; -+ phy-mode = "mii"; -+ reg-io-width = <4>; -+ smsc,irq-active-high; -+ smsc,irq-push-pull; -+ clocks = <&mb_eth25mhz>; -+ vdd33a-supply = <&soc_fixed_3v3>; /* change this */ -+ vddvario-supply = <&soc_fixed_3v3>; /* and this */ -+ }; -+ -+ iofpga@3,00000000 { -+ compatible = "arm,amba-bus", "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges = <0 3 0 0x200000>; -+ -+ kmi@060000 { -+ compatible = "arm,pl050", "arm,primecell"; -+ reg = <0x060000 0x1000>; -+ interrupts = <8>; -+ clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>; -+ clock-names = "KMIREFCLK", "apb_pclk"; -+ }; -+ -+ kmi@070000 { -+ compatible = "arm,pl050", "arm,primecell"; -+ reg = <0x070000 0x1000>; -+ interrupts = <8>; -+ clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>; -+ clock-names = "KMIREFCLK", "apb_pclk"; -+ }; -+ -+ wdt@0f0000 { -+ compatible = "arm,sp805", "arm,primecell"; -+ reg = <0x0f0000 0x10000>; -+ interrupts = <7>; -+ clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>; -+ clock-names = "wdogclk", "apb_pclk"; -+ }; -+ -+ v2m_timer01: timer@110000 { -+ compatible = "arm,sp804", "arm,primecell"; -+ reg = <0x110000 0x10000>; -+ interrupts = <9>; -+ clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>; -+ clock-names = "timclken1", "apb_pclk"; -+ }; -+ -+ v2m_timer23: timer@120000 { -+ compatible = "arm,sp804", "arm,primecell"; -+ reg = <0x120000 0x10000>; -+ interrupts = <9>; -+ clocks = <&soc_refclk24mhz>, <&soc_smc50mhz>; -+ clock-names = "timclken1", "apb_pclk"; -+ }; -+ -+ rtc@170000 { -+ compatible = "arm,pl031", "arm,primecell"; -+ reg = <0x170000 0x10000>; -+ interrupts = <0>; -+ clocks = <&soc_smc50mhz>; -+ clock-names = "apb_pclk"; -+ }; -+ }; -+ }; -+ }; -+}; -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/Makefile linux-3.14.22/arch/arm64/boot/dts/Makefile ---- linux-3.14.22.orig/arch/arm64/boot/dts/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/boot/dts/Makefile 2014-10-22 14:55:49.934220001 -0500 -@@ -1,5 +1,7 @@ --dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb -+dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb \ -+ fvp-base-gicv2-psci.dtb - dtb-$(CONFIG_ARCH_XGENE) += apm-mustang.dtb -+dtb-$(CONFIG_ARCH_VEXPRESS) += juno.dtb - - targets += dtbs - targets += $(dtb-y) -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts linux-3.14.22/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts ---- linux-3.14.22.orig/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts 2014-10-22 14:55:49.934220001 -0500 -@@ -157,3 +157,5 @@ - /include/ "rtsm_ve-motherboard.dtsi" - }; - }; -+ -+/include/ "clcd-panels.dtsi" -diff -Nur linux-3.14.22.orig/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi linux-3.14.22/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi ---- linux-3.14.22.orig/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi 2014-10-22 14:55:49.934220001 -0500 -@@ -182,6 +182,9 @@ - interrupts = <14>; - clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; - clock-names = "clcdclk", "apb_pclk"; -+ mode = "XVGA"; -+ use_dma = <0>; -+ framebuffer = <0x18000000 0x00180000>; - }; - - virtio_block@0130000 { -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-ce-ccm-core.S linux-3.14.22/arch/arm64/crypto/aes-ce-ccm-core.S ---- linux-3.14.22.orig/arch/arm64/crypto/aes-ce-ccm-core.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-ce-ccm-core.S 2014-10-22 14:55:49.934220001 -0500 -@@ -0,0 +1,222 @@ -+/* -+ * aesce-ccm-core.S - AES-CCM transform for ARMv8 with Crypto Extensions -+ * -+ * Copyright (C) 2013 - 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+ -+ .text -+ .arch armv8-a+crypto -+ -+ /* -+ * void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes, -+ * u32 *macp, u8 const rk[], u32 rounds); -+ */ -+ENTRY(ce_aes_ccm_auth_data) -+ ldr w8, [x3] /* leftover from prev round? */ -+ ld1 {v0.2d}, [x0] /* load mac */ -+ cbz w8, 1f -+ sub w8, w8, #16 -+ eor v1.16b, v1.16b, v1.16b -+0: ldrb w7, [x1], #1 /* get 1 byte of input */ -+ subs w2, w2, #1 -+ add w8, w8, #1 -+ ins v1.b[0], w7 -+ ext v1.16b, v1.16b, v1.16b, #1 /* rotate in the input bytes */ -+ beq 8f /* out of input? */ -+ cbnz w8, 0b -+ eor v0.16b, v0.16b, v1.16b -+1: ld1 {v3.2d}, [x4] /* load first round key */ -+ prfm pldl1strm, [x1] -+ cmp w5, #12 /* which key size? */ -+ add x6, x4, #16 -+ sub w7, w5, #2 /* modified # of rounds */ -+ bmi 2f -+ bne 5f -+ mov v5.16b, v3.16b -+ b 4f -+2: mov v4.16b, v3.16b -+ ld1 {v5.2d}, [x6], #16 /* load 2nd round key */ -+3: aese v0.16b, v4.16b -+ aesmc v0.16b, v0.16b -+4: ld1 {v3.2d}, [x6], #16 /* load next round key */ -+ aese v0.16b, v5.16b -+ aesmc v0.16b, v0.16b -+5: ld1 {v4.2d}, [x6], #16 /* load next round key */ -+ subs w7, w7, #3 -+ aese v0.16b, v3.16b -+ aesmc v0.16b, v0.16b -+ ld1 {v5.2d}, [x6], #16 /* load next round key */ -+ bpl 3b -+ aese v0.16b, v4.16b -+ subs w2, w2, #16 /* last data? */ -+ eor v0.16b, v0.16b, v5.16b /* final round */ -+ bmi 6f -+ ld1 {v1.16b}, [x1], #16 /* load next input block */ -+ eor v0.16b, v0.16b, v1.16b /* xor with mac */ -+ bne 1b -+6: st1 {v0.2d}, [x0] /* store mac */ -+ beq 10f -+ adds w2, w2, #16 -+ beq 10f -+ mov w8, w2 -+7: ldrb w7, [x1], #1 -+ umov w6, v0.b[0] -+ eor w6, w6, w7 -+ strb w6, [x0], #1 -+ subs w2, w2, #1 -+ beq 10f -+ ext v0.16b, v0.16b, v0.16b, #1 /* rotate out the mac bytes */ -+ b 7b -+8: mov w7, w8 -+ add w8, w8, #16 -+9: ext v1.16b, v1.16b, v1.16b, #1 -+ adds w7, w7, #1 -+ bne 9b -+ eor v0.16b, v0.16b, v1.16b -+ st1 {v0.2d}, [x0] -+10: str w8, [x3] -+ ret -+ENDPROC(ce_aes_ccm_auth_data) -+ -+ /* -+ * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[], -+ * u32 rounds); -+ */ -+ENTRY(ce_aes_ccm_final) -+ ld1 {v3.2d}, [x2], #16 /* load first round key */ -+ ld1 {v0.2d}, [x0] /* load mac */ -+ cmp w3, #12 /* which key size? */ -+ sub w3, w3, #2 /* modified # of rounds */ -+ ld1 {v1.2d}, [x1] /* load 1st ctriv */ -+ bmi 0f -+ bne 3f -+ mov v5.16b, v3.16b -+ b 2f -+0: mov v4.16b, v3.16b -+1: ld1 {v5.2d}, [x2], #16 /* load next round key */ -+ aese v0.16b, v4.16b -+ aese v1.16b, v4.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+2: ld1 {v3.2d}, [x2], #16 /* load next round key */ -+ aese v0.16b, v5.16b -+ aese v1.16b, v5.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+3: ld1 {v4.2d}, [x2], #16 /* load next round key */ -+ subs w3, w3, #3 -+ aese v0.16b, v3.16b -+ aese v1.16b, v3.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+ bpl 1b -+ aese v0.16b, v4.16b -+ aese v1.16b, v4.16b -+ /* final round key cancels out */ -+ eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */ -+ st1 {v0.2d}, [x0] /* store result */ -+ ret -+ENDPROC(ce_aes_ccm_final) -+ -+ .macro aes_ccm_do_crypt,enc -+ ldr x8, [x6, #8] /* load lower ctr */ -+ ld1 {v0.2d}, [x5] /* load mac */ -+ rev x8, x8 /* keep swabbed ctr in reg */ -+0: /* outer loop */ -+ ld1 {v1.1d}, [x6] /* load upper ctr */ -+ prfm pldl1strm, [x1] -+ add x8, x8, #1 -+ rev x9, x8 -+ cmp w4, #12 /* which key size? */ -+ sub w7, w4, #2 /* get modified # of rounds */ -+ ins v1.d[1], x9 /* no carry in lower ctr */ -+ ld1 {v3.2d}, [x3] /* load first round key */ -+ add x10, x3, #16 -+ bmi 1f -+ bne 4f -+ mov v5.16b, v3.16b -+ b 3f -+1: mov v4.16b, v3.16b -+ ld1 {v5.2d}, [x10], #16 /* load 2nd round key */ -+2: /* inner loop: 3 rounds, 2x interleaved */ -+ aese v0.16b, v4.16b -+ aese v1.16b, v4.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+3: ld1 {v3.2d}, [x10], #16 /* load next round key */ -+ aese v0.16b, v5.16b -+ aese v1.16b, v5.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+4: ld1 {v4.2d}, [x10], #16 /* load next round key */ -+ subs w7, w7, #3 -+ aese v0.16b, v3.16b -+ aese v1.16b, v3.16b -+ aesmc v0.16b, v0.16b -+ aesmc v1.16b, v1.16b -+ ld1 {v5.2d}, [x10], #16 /* load next round key */ -+ bpl 2b -+ aese v0.16b, v4.16b -+ aese v1.16b, v4.16b -+ subs w2, w2, #16 -+ bmi 6f /* partial block? */ -+ ld1 {v2.16b}, [x1], #16 /* load next input block */ -+ .if \enc == 1 -+ eor v2.16b, v2.16b, v5.16b /* final round enc+mac */ -+ eor v1.16b, v1.16b, v2.16b /* xor with crypted ctr */ -+ .else -+ eor v2.16b, v2.16b, v1.16b /* xor with crypted ctr */ -+ eor v1.16b, v2.16b, v5.16b /* final round enc */ -+ .endif -+ eor v0.16b, v0.16b, v2.16b /* xor mac with pt ^ rk[last] */ -+ st1 {v1.16b}, [x0], #16 /* write output block */ -+ bne 0b -+ rev x8, x8 -+ st1 {v0.2d}, [x5] /* store mac */ -+ str x8, [x6, #8] /* store lsb end of ctr (BE) */ -+5: ret -+ -+6: eor v0.16b, v0.16b, v5.16b /* final round mac */ -+ eor v1.16b, v1.16b, v5.16b /* final round enc */ -+ st1 {v0.2d}, [x5] /* store mac */ -+ add w2, w2, #16 /* process partial tail block */ -+7: ldrb w9, [x1], #1 /* get 1 byte of input */ -+ umov w6, v1.b[0] /* get top crypted ctr byte */ -+ umov w7, v0.b[0] /* get top mac byte */ -+ .if \enc == 1 -+ eor w7, w7, w9 -+ eor w9, w9, w6 -+ .else -+ eor w9, w9, w6 -+ eor w7, w7, w9 -+ .endif -+ strb w9, [x0], #1 /* store out byte */ -+ strb w7, [x5], #1 /* store mac byte */ -+ subs w2, w2, #1 -+ beq 5b -+ ext v0.16b, v0.16b, v0.16b, #1 /* shift out mac byte */ -+ ext v1.16b, v1.16b, v1.16b, #1 /* shift out ctr byte */ -+ b 7b -+ .endm -+ -+ /* -+ * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes, -+ * u8 const rk[], u32 rounds, u8 mac[], -+ * u8 ctr[]); -+ * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, -+ * u8 const rk[], u32 rounds, u8 mac[], -+ * u8 ctr[]); -+ */ -+ENTRY(ce_aes_ccm_encrypt) -+ aes_ccm_do_crypt 1 -+ENDPROC(ce_aes_ccm_encrypt) -+ -+ENTRY(ce_aes_ccm_decrypt) -+ aes_ccm_do_crypt 0 -+ENDPROC(ce_aes_ccm_decrypt) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-ce-ccm-glue.c linux-3.14.22/arch/arm64/crypto/aes-ce-ccm-glue.c ---- linux-3.14.22.orig/arch/arm64/crypto/aes-ce-ccm-glue.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-ce-ccm-glue.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,297 @@ -+/* -+ * aes-ccm-glue.c - AES-CCM transform for ARMv8 with Crypto Extensions -+ * -+ * Copyright (C) 2013 - 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int num_rounds(struct crypto_aes_ctx *ctx) -+{ -+ /* -+ * # of rounds specified by AES: -+ * 128 bit key 10 rounds -+ * 192 bit key 12 rounds -+ * 256 bit key 14 rounds -+ * => n byte key => 6 + (n/4) rounds -+ */ -+ return 6 + ctx->key_length / 4; -+} -+ -+asmlinkage void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes, -+ u32 *macp, u32 const rk[], u32 rounds); -+ -+asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes, -+ u32 const rk[], u32 rounds, u8 mac[], -+ u8 ctr[]); -+ -+asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, -+ u32 const rk[], u32 rounds, u8 mac[], -+ u8 ctr[]); -+ -+asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[], -+ u32 rounds); -+ -+static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key, -+ unsigned int key_len) -+{ -+ struct crypto_aes_ctx *ctx = crypto_aead_ctx(tfm); -+ int ret; -+ -+ ret = crypto_aes_expand_key(ctx, in_key, key_len); -+ if (!ret) -+ return 0; -+ -+ tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; -+ return -EINVAL; -+} -+ -+static int ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize) -+{ -+ if ((authsize & 1) || authsize < 4) -+ return -EINVAL; -+ return 0; -+} -+ -+static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ __be32 *n = (__be32 *)&maciv[AES_BLOCK_SIZE - 8]; -+ u32 l = req->iv[0] + 1; -+ -+ /* verify that CCM dimension 'L' is set correctly in the IV */ -+ if (l < 2 || l > 8) -+ return -EINVAL; -+ -+ /* verify that msglen can in fact be represented in L bytes */ -+ if (l < 4 && msglen >> (8 * l)) -+ return -EOVERFLOW; -+ -+ /* -+ * Even if the CCM spec allows L values of up to 8, the Linux cryptoapi -+ * uses a u32 type to represent msglen so the top 4 bytes are always 0. -+ */ -+ n[0] = 0; -+ n[1] = cpu_to_be32(msglen); -+ -+ memcpy(maciv, req->iv, AES_BLOCK_SIZE - l); -+ -+ /* -+ * Meaning of byte 0 according to CCM spec (RFC 3610/NIST 800-38C) -+ * - bits 0..2 : max # of bytes required to represent msglen, minus 1 -+ * (already set by caller) -+ * - bits 3..5 : size of auth tag (1 => 4 bytes, 2 => 6 bytes, etc) -+ * - bit 6 : indicates presence of authenticate-only data -+ */ -+ maciv[0] |= (crypto_aead_authsize(aead) - 2) << 2; -+ if (req->assoclen) -+ maciv[0] |= 0x40; -+ -+ memset(&req->iv[AES_BLOCK_SIZE - l], 0, l); -+ return 0; -+} -+ -+static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[]) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead); -+ struct __packed { __be16 l; __be32 h; u16 len; } ltag; -+ struct scatter_walk walk; -+ u32 len = req->assoclen; -+ u32 macp = 0; -+ -+ /* prepend the AAD with a length tag */ -+ if (len < 0xff00) { -+ ltag.l = cpu_to_be16(len); -+ ltag.len = 2; -+ } else { -+ ltag.l = cpu_to_be16(0xfffe); -+ put_unaligned_be32(len, <ag.h); -+ ltag.len = 6; -+ } -+ -+ ce_aes_ccm_auth_data(mac, (u8 *)<ag, ltag.len, &macp, ctx->key_enc, -+ num_rounds(ctx)); -+ scatterwalk_start(&walk, req->assoc); -+ -+ do { -+ u32 n = scatterwalk_clamp(&walk, len); -+ u8 *p; -+ -+ if (!n) { -+ scatterwalk_start(&walk, sg_next(walk.sg)); -+ n = scatterwalk_clamp(&walk, len); -+ } -+ p = scatterwalk_map(&walk); -+ ce_aes_ccm_auth_data(mac, p, n, &macp, ctx->key_enc, -+ num_rounds(ctx)); -+ len -= n; -+ -+ scatterwalk_unmap(p); -+ scatterwalk_advance(&walk, n); -+ scatterwalk_done(&walk, 0, len); -+ } while (len); -+} -+ -+static int ccm_encrypt(struct aead_request *req) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead); -+ struct blkcipher_desc desc = { .info = req->iv }; -+ struct blkcipher_walk walk; -+ u8 __aligned(8) mac[AES_BLOCK_SIZE]; -+ u8 buf[AES_BLOCK_SIZE]; -+ u32 len = req->cryptlen; -+ int err; -+ -+ err = ccm_init_mac(req, mac, len); -+ if (err) -+ return err; -+ -+ kernel_neon_begin_partial(6); -+ -+ if (req->assoclen) -+ ccm_calculate_auth_mac(req, mac); -+ -+ /* preserve the original iv for the final round */ -+ memcpy(buf, req->iv, AES_BLOCK_SIZE); -+ -+ blkcipher_walk_init(&walk, req->dst, req->src, len); -+ err = blkcipher_aead_walk_virt_block(&desc, &walk, aead, -+ AES_BLOCK_SIZE); -+ -+ while (walk.nbytes) { -+ u32 tail = walk.nbytes % AES_BLOCK_SIZE; -+ -+ if (walk.nbytes == len) -+ tail = 0; -+ -+ ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ walk.nbytes - tail, ctx->key_enc, -+ num_rounds(ctx), mac, walk.iv); -+ -+ len -= walk.nbytes - tail; -+ err = blkcipher_walk_done(&desc, &walk, tail); -+ } -+ if (!err) -+ ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx)); -+ -+ kernel_neon_end(); -+ -+ if (err) -+ return err; -+ -+ /* copy authtag to end of dst */ -+ scatterwalk_map_and_copy(mac, req->dst, req->cryptlen, -+ crypto_aead_authsize(aead), 1); -+ -+ return 0; -+} -+ -+static int ccm_decrypt(struct aead_request *req) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int authsize = crypto_aead_authsize(aead); -+ struct blkcipher_desc desc = { .info = req->iv }; -+ struct blkcipher_walk walk; -+ u8 __aligned(8) mac[AES_BLOCK_SIZE]; -+ u8 buf[AES_BLOCK_SIZE]; -+ u32 len = req->cryptlen - authsize; -+ int err; -+ -+ err = ccm_init_mac(req, mac, len); -+ if (err) -+ return err; -+ -+ kernel_neon_begin_partial(6); -+ -+ if (req->assoclen) -+ ccm_calculate_auth_mac(req, mac); -+ -+ /* preserve the original iv for the final round */ -+ memcpy(buf, req->iv, AES_BLOCK_SIZE); -+ -+ blkcipher_walk_init(&walk, req->dst, req->src, len); -+ err = blkcipher_aead_walk_virt_block(&desc, &walk, aead, -+ AES_BLOCK_SIZE); -+ -+ while (walk.nbytes) { -+ u32 tail = walk.nbytes % AES_BLOCK_SIZE; -+ -+ if (walk.nbytes == len) -+ tail = 0; -+ -+ ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ walk.nbytes - tail, ctx->key_enc, -+ num_rounds(ctx), mac, walk.iv); -+ -+ len -= walk.nbytes - tail; -+ err = blkcipher_walk_done(&desc, &walk, tail); -+ } -+ if (!err) -+ ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx)); -+ -+ kernel_neon_end(); -+ -+ if (err) -+ return err; -+ -+ /* compare calculated auth tag with the stored one */ -+ scatterwalk_map_and_copy(buf, req->src, req->cryptlen - authsize, -+ authsize, 0); -+ -+ if (memcmp(mac, buf, authsize)) -+ return -EBADMSG; -+ return 0; -+} -+ -+static struct crypto_alg ccm_aes_alg = { -+ .cra_name = "ccm(aes)", -+ .cra_driver_name = "ccm-aes-ce", -+ .cra_priority = 300, -+ .cra_flags = CRYPTO_ALG_TYPE_AEAD, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct crypto_aes_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_aead_type, -+ .cra_module = THIS_MODULE, -+ .cra_aead = { -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = AES_BLOCK_SIZE, -+ .setkey = ccm_setkey, -+ .setauthsize = ccm_setauthsize, -+ .encrypt = ccm_encrypt, -+ .decrypt = ccm_decrypt, -+ } -+}; -+ -+static int __init aes_mod_init(void) -+{ -+ if (!(elf_hwcap & HWCAP_AES)) -+ return -ENODEV; -+ return crypto_register_alg(&ccm_aes_alg); -+} -+ -+static void __exit aes_mod_exit(void) -+{ -+ crypto_unregister_alg(&ccm_aes_alg); -+} -+ -+module_init(aes_mod_init); -+module_exit(aes_mod_exit); -+ -+MODULE_DESCRIPTION("Synchronous AES in CCM mode using ARMv8 Crypto Extensions"); -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("ccm(aes)"); -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-ce-cipher.c linux-3.14.22/arch/arm64/crypto/aes-ce-cipher.c ---- linux-3.14.22.orig/arch/arm64/crypto/aes-ce-cipher.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-ce-cipher.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,155 @@ -+/* -+ * aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions -+ * -+ * Copyright (C) 2013 - 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions"); -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+ -+struct aes_block { -+ u8 b[AES_BLOCK_SIZE]; -+}; -+ -+static int num_rounds(struct crypto_aes_ctx *ctx) -+{ -+ /* -+ * # of rounds specified by AES: -+ * 128 bit key 10 rounds -+ * 192 bit key 12 rounds -+ * 256 bit key 14 rounds -+ * => n byte key => 6 + (n/4) rounds -+ */ -+ return 6 + ctx->key_length / 4; -+} -+ -+static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) -+{ -+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aes_block *out = (struct aes_block *)dst; -+ struct aes_block const *in = (struct aes_block *)src; -+ void *dummy0; -+ int dummy1; -+ -+ kernel_neon_begin_partial(4); -+ -+ __asm__(" ld1 {v0.16b}, %[in] ;" -+ " ld1 {v1.2d}, [%[key]], #16 ;" -+ " cmp %w[rounds], #10 ;" -+ " bmi 0f ;" -+ " bne 3f ;" -+ " mov v3.16b, v1.16b ;" -+ " b 2f ;" -+ "0: mov v2.16b, v1.16b ;" -+ " ld1 {v3.2d}, [%[key]], #16 ;" -+ "1: aese v0.16b, v2.16b ;" -+ " aesmc v0.16b, v0.16b ;" -+ "2: ld1 {v1.2d}, [%[key]], #16 ;" -+ " aese v0.16b, v3.16b ;" -+ " aesmc v0.16b, v0.16b ;" -+ "3: ld1 {v2.2d}, [%[key]], #16 ;" -+ " subs %w[rounds], %w[rounds], #3 ;" -+ " aese v0.16b, v1.16b ;" -+ " aesmc v0.16b, v0.16b ;" -+ " ld1 {v3.2d}, [%[key]], #16 ;" -+ " bpl 1b ;" -+ " aese v0.16b, v2.16b ;" -+ " eor v0.16b, v0.16b, v3.16b ;" -+ " st1 {v0.16b}, %[out] ;" -+ -+ : [out] "=Q"(*out), -+ [key] "=r"(dummy0), -+ [rounds] "=r"(dummy1) -+ : [in] "Q"(*in), -+ "1"(ctx->key_enc), -+ "2"(num_rounds(ctx) - 2) -+ : "cc"); -+ -+ kernel_neon_end(); -+} -+ -+static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) -+{ -+ struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); -+ struct aes_block *out = (struct aes_block *)dst; -+ struct aes_block const *in = (struct aes_block *)src; -+ void *dummy0; -+ int dummy1; -+ -+ kernel_neon_begin_partial(4); -+ -+ __asm__(" ld1 {v0.16b}, %[in] ;" -+ " ld1 {v1.2d}, [%[key]], #16 ;" -+ " cmp %w[rounds], #10 ;" -+ " bmi 0f ;" -+ " bne 3f ;" -+ " mov v3.16b, v1.16b ;" -+ " b 2f ;" -+ "0: mov v2.16b, v1.16b ;" -+ " ld1 {v3.2d}, [%[key]], #16 ;" -+ "1: aesd v0.16b, v2.16b ;" -+ " aesimc v0.16b, v0.16b ;" -+ "2: ld1 {v1.2d}, [%[key]], #16 ;" -+ " aesd v0.16b, v3.16b ;" -+ " aesimc v0.16b, v0.16b ;" -+ "3: ld1 {v2.2d}, [%[key]], #16 ;" -+ " subs %w[rounds], %w[rounds], #3 ;" -+ " aesd v0.16b, v1.16b ;" -+ " aesimc v0.16b, v0.16b ;" -+ " ld1 {v3.2d}, [%[key]], #16 ;" -+ " bpl 1b ;" -+ " aesd v0.16b, v2.16b ;" -+ " eor v0.16b, v0.16b, v3.16b ;" -+ " st1 {v0.16b}, %[out] ;" -+ -+ : [out] "=Q"(*out), -+ [key] "=r"(dummy0), -+ [rounds] "=r"(dummy1) -+ : [in] "Q"(*in), -+ "1"(ctx->key_dec), -+ "2"(num_rounds(ctx) - 2) -+ : "cc"); -+ -+ kernel_neon_end(); -+} -+ -+static struct crypto_alg aes_alg = { -+ .cra_name = "aes", -+ .cra_driver_name = "aes-ce", -+ .cra_priority = 300, -+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct crypto_aes_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_cipher = { -+ .cia_min_keysize = AES_MIN_KEY_SIZE, -+ .cia_max_keysize = AES_MAX_KEY_SIZE, -+ .cia_setkey = crypto_aes_set_key, -+ .cia_encrypt = aes_cipher_encrypt, -+ .cia_decrypt = aes_cipher_decrypt -+ } -+}; -+ -+static int __init aes_mod_init(void) -+{ -+ return crypto_register_alg(&aes_alg); -+} -+ -+static void __exit aes_mod_exit(void) -+{ -+ crypto_unregister_alg(&aes_alg); -+} -+ -+module_cpu_feature_match(AES, aes_mod_init); -+module_exit(aes_mod_exit); -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-ce.S linux-3.14.22/arch/arm64/crypto/aes-ce.S ---- linux-3.14.22.orig/arch/arm64/crypto/aes-ce.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-ce.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,133 @@ -+/* -+ * linux/arch/arm64/crypto/aes-ce.S - AES cipher for ARMv8 with -+ * Crypto Extensions -+ * -+ * Copyright (C) 2013 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+ -+#define AES_ENTRY(func) ENTRY(ce_ ## func) -+#define AES_ENDPROC(func) ENDPROC(ce_ ## func) -+ -+ .arch armv8-a+crypto -+ -+ /* preload all round keys */ -+ .macro load_round_keys, rounds, rk -+ cmp \rounds, #12 -+ blo 2222f /* 128 bits */ -+ beq 1111f /* 192 bits */ -+ ld1 {v17.16b-v18.16b}, [\rk], #32 -+1111: ld1 {v19.16b-v20.16b}, [\rk], #32 -+2222: ld1 {v21.16b-v24.16b}, [\rk], #64 -+ ld1 {v25.16b-v28.16b}, [\rk], #64 -+ ld1 {v29.16b-v31.16b}, [\rk] -+ .endm -+ -+ /* prepare for encryption with key in rk[] */ -+ .macro enc_prepare, rounds, rk, ignore -+ load_round_keys \rounds, \rk -+ .endm -+ -+ /* prepare for encryption (again) but with new key in rk[] */ -+ .macro enc_switch_key, rounds, rk, ignore -+ load_round_keys \rounds, \rk -+ .endm -+ -+ /* prepare for decryption with key in rk[] */ -+ .macro dec_prepare, rounds, rk, ignore -+ load_round_keys \rounds, \rk -+ .endm -+ -+ .macro do_enc_Nx, de, mc, k, i0, i1, i2, i3 -+ aes\de \i0\().16b, \k\().16b -+ .ifnb \i1 -+ aes\de \i1\().16b, \k\().16b -+ .ifnb \i3 -+ aes\de \i2\().16b, \k\().16b -+ aes\de \i3\().16b, \k\().16b -+ .endif -+ .endif -+ aes\mc \i0\().16b, \i0\().16b -+ .ifnb \i1 -+ aes\mc \i1\().16b, \i1\().16b -+ .ifnb \i3 -+ aes\mc \i2\().16b, \i2\().16b -+ aes\mc \i3\().16b, \i3\().16b -+ .endif -+ .endif -+ .endm -+ -+ /* up to 4 interleaved encryption rounds with the same round key */ -+ .macro round_Nx, enc, k, i0, i1, i2, i3 -+ .ifc \enc, e -+ do_enc_Nx e, mc, \k, \i0, \i1, \i2, \i3 -+ .else -+ do_enc_Nx d, imc, \k, \i0, \i1, \i2, \i3 -+ .endif -+ .endm -+ -+ /* up to 4 interleaved final rounds */ -+ .macro fin_round_Nx, de, k, k2, i0, i1, i2, i3 -+ aes\de \i0\().16b, \k\().16b -+ .ifnb \i1 -+ aes\de \i1\().16b, \k\().16b -+ .ifnb \i3 -+ aes\de \i2\().16b, \k\().16b -+ aes\de \i3\().16b, \k\().16b -+ .endif -+ .endif -+ eor \i0\().16b, \i0\().16b, \k2\().16b -+ .ifnb \i1 -+ eor \i1\().16b, \i1\().16b, \k2\().16b -+ .ifnb \i3 -+ eor \i2\().16b, \i2\().16b, \k2\().16b -+ eor \i3\().16b, \i3\().16b, \k2\().16b -+ .endif -+ .endif -+ .endm -+ -+ /* up to 4 interleaved blocks */ -+ .macro do_block_Nx, enc, rounds, i0, i1, i2, i3 -+ cmp \rounds, #12 -+ blo 2222f /* 128 bits */ -+ beq 1111f /* 192 bits */ -+ round_Nx \enc, v17, \i0, \i1, \i2, \i3 -+ round_Nx \enc, v18, \i0, \i1, \i2, \i3 -+1111: round_Nx \enc, v19, \i0, \i1, \i2, \i3 -+ round_Nx \enc, v20, \i0, \i1, \i2, \i3 -+2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29 -+ round_Nx \enc, \key, \i0, \i1, \i2, \i3 -+ .endr -+ fin_round_Nx \enc, v30, v31, \i0, \i1, \i2, \i3 -+ .endm -+ -+ .macro encrypt_block, in, rounds, t0, t1, t2 -+ do_block_Nx e, \rounds, \in -+ .endm -+ -+ .macro encrypt_block2x, i0, i1, rounds, t0, t1, t2 -+ do_block_Nx e, \rounds, \i0, \i1 -+ .endm -+ -+ .macro encrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 -+ do_block_Nx e, \rounds, \i0, \i1, \i2, \i3 -+ .endm -+ -+ .macro decrypt_block, in, rounds, t0, t1, t2 -+ do_block_Nx d, \rounds, \in -+ .endm -+ -+ .macro decrypt_block2x, i0, i1, rounds, t0, t1, t2 -+ do_block_Nx d, \rounds, \i0, \i1 -+ .endm -+ -+ .macro decrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 -+ do_block_Nx d, \rounds, \i0, \i1, \i2, \i3 -+ .endm -+ -+#include "aes-modes.S" -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-glue.c linux-3.14.22/arch/arm64/crypto/aes-glue.c ---- linux-3.14.22.orig/arch/arm64/crypto/aes-glue.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-glue.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,446 @@ -+/* -+ * linux/arch/arm64/crypto/aes-glue.c - wrapper code for ARMv8 AES -+ * -+ * Copyright (C) 2013 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef USE_V8_CRYPTO_EXTENSIONS -+#define MODE "ce" -+#define PRIO 300 -+#define aes_ecb_encrypt ce_aes_ecb_encrypt -+#define aes_ecb_decrypt ce_aes_ecb_decrypt -+#define aes_cbc_encrypt ce_aes_cbc_encrypt -+#define aes_cbc_decrypt ce_aes_cbc_decrypt -+#define aes_ctr_encrypt ce_aes_ctr_encrypt -+#define aes_xts_encrypt ce_aes_xts_encrypt -+#define aes_xts_decrypt ce_aes_xts_decrypt -+MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); -+#else -+#define MODE "neon" -+#define PRIO 200 -+#define aes_ecb_encrypt neon_aes_ecb_encrypt -+#define aes_ecb_decrypt neon_aes_ecb_decrypt -+#define aes_cbc_encrypt neon_aes_cbc_encrypt -+#define aes_cbc_decrypt neon_aes_cbc_decrypt -+#define aes_ctr_encrypt neon_aes_ctr_encrypt -+#define aes_xts_encrypt neon_aes_xts_encrypt -+#define aes_xts_decrypt neon_aes_xts_decrypt -+MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 NEON"); -+MODULE_ALIAS("ecb(aes)"); -+MODULE_ALIAS("cbc(aes)"); -+MODULE_ALIAS("ctr(aes)"); -+MODULE_ALIAS("xts(aes)"); -+#endif -+ -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+ -+/* defined in aes-modes.S */ -+asmlinkage void aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], -+ int rounds, int blocks, int first); -+asmlinkage void aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], -+ int rounds, int blocks, int first); -+ -+asmlinkage void aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], -+ int rounds, int blocks, u8 iv[], int first); -+asmlinkage void aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], -+ int rounds, int blocks, u8 iv[], int first); -+ -+asmlinkage void aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], -+ int rounds, int blocks, u8 ctr[], int first); -+ -+asmlinkage void aes_xts_encrypt(u8 out[], u8 const in[], u8 const rk1[], -+ int rounds, int blocks, u8 const rk2[], u8 iv[], -+ int first); -+asmlinkage void aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], -+ int rounds, int blocks, u8 const rk2[], u8 iv[], -+ int first); -+ -+struct crypto_aes_xts_ctx { -+ struct crypto_aes_ctx key1; -+ struct crypto_aes_ctx __aligned(8) key2; -+}; -+ -+static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, -+ unsigned int key_len) -+{ -+ struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm); -+ int ret; -+ -+ ret = crypto_aes_expand_key(&ctx->key1, in_key, key_len / 2); -+ if (!ret) -+ ret = crypto_aes_expand_key(&ctx->key2, &in_key[key_len / 2], -+ key_len / 2); -+ if (!ret) -+ return 0; -+ -+ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; -+ return -EINVAL; -+} -+ -+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key_enc, rounds, blocks, first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ return err; -+} -+ -+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key_dec, rounds, blocks, first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ return err; -+} -+ -+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key_enc, rounds, blocks, walk.iv, -+ first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ return err; -+} -+ -+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key_dec, rounds, blocks, walk.iv, -+ first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ return err; -+} -+ -+static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key_length / 4; -+ struct blkcipher_walk walk; -+ int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE); -+ -+ first = 1; -+ kernel_neon_begin(); -+ while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { -+ aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key_enc, rounds, blocks, walk.iv, -+ first); -+ first = 0; -+ nbytes -= blocks * AES_BLOCK_SIZE; -+ if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE) -+ break; -+ err = blkcipher_walk_done(desc, &walk, -+ walk.nbytes % AES_BLOCK_SIZE); -+ } -+ if (nbytes) { -+ u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; -+ u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; -+ u8 __aligned(8) tail[AES_BLOCK_SIZE]; -+ -+ /* -+ * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need -+ * to tell aes_ctr_encrypt() to only read half a block. -+ */ -+ blocks = (nbytes <= 8) ? -1 : 1; -+ -+ aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, rounds, -+ blocks, walk.iv, first); -+ memcpy(tdst, tail, nbytes); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ -+ return err; -+} -+ -+static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key1.key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key1.key_enc, rounds, blocks, -+ (u8 *)ctx->key2.key_enc, walk.iv, first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ -+ return err; -+} -+ -+static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, -+ struct scatterlist *src, unsigned int nbytes) -+{ -+ struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); -+ int err, first, rounds = 6 + ctx->key1.key_length / 4; -+ struct blkcipher_walk walk; -+ unsigned int blocks; -+ -+ desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; -+ blkcipher_walk_init(&walk, dst, src, nbytes); -+ err = blkcipher_walk_virt(desc, &walk); -+ -+ kernel_neon_begin(); -+ for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { -+ aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr, -+ (u8 *)ctx->key1.key_dec, rounds, blocks, -+ (u8 *)ctx->key2.key_enc, walk.iv, first); -+ err = blkcipher_walk_done(desc, &walk, 0); -+ } -+ kernel_neon_end(); -+ -+ return err; -+} -+ -+static struct crypto_alg aes_algs[] = { { -+ .cra_name = "__ecb-aes-" MODE, -+ .cra_driver_name = "__driver-ecb-aes-" MODE, -+ .cra_priority = 0, -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct crypto_aes_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = crypto_aes_set_key, -+ .encrypt = ecb_encrypt, -+ .decrypt = ecb_decrypt, -+ }, -+}, { -+ .cra_name = "__cbc-aes-" MODE, -+ .cra_driver_name = "__driver-cbc-aes-" MODE, -+ .cra_priority = 0, -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct crypto_aes_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = crypto_aes_set_key, -+ .encrypt = cbc_encrypt, -+ .decrypt = cbc_decrypt, -+ }, -+}, { -+ .cra_name = "__ctr-aes-" MODE, -+ .cra_driver_name = "__driver-ctr-aes-" MODE, -+ .cra_priority = 0, -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct crypto_aes_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_blkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = crypto_aes_set_key, -+ .encrypt = ctr_encrypt, -+ .decrypt = ctr_encrypt, -+ }, -+}, { -+ .cra_name = "__xts-aes-" MODE, -+ .cra_driver_name = "__driver-xts-aes-" MODE, -+ .cra_priority = 0, -+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_blkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_blkcipher = { -+ .min_keysize = 2 * AES_MIN_KEY_SIZE, -+ .max_keysize = 2 * AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = xts_set_key, -+ .encrypt = xts_encrypt, -+ .decrypt = xts_decrypt, -+ }, -+}, { -+ .cra_name = "ecb(aes)", -+ .cra_driver_name = "ecb-aes-" MODE, -+ .cra_priority = PRIO, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct async_helper_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_init = ablk_init, -+ .cra_exit = ablk_exit, -+ .cra_ablkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = ablk_set_key, -+ .encrypt = ablk_encrypt, -+ .decrypt = ablk_decrypt, -+ } -+}, { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "cbc-aes-" MODE, -+ .cra_priority = PRIO, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct async_helper_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_init = ablk_init, -+ .cra_exit = ablk_exit, -+ .cra_ablkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = ablk_set_key, -+ .encrypt = ablk_encrypt, -+ .decrypt = ablk_decrypt, -+ } -+}, { -+ .cra_name = "ctr(aes)", -+ .cra_driver_name = "ctr-aes-" MODE, -+ .cra_priority = PRIO, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, -+ .cra_blocksize = 1, -+ .cra_ctxsize = sizeof(struct async_helper_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_init = ablk_init, -+ .cra_exit = ablk_exit, -+ .cra_ablkcipher = { -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = ablk_set_key, -+ .encrypt = ablk_encrypt, -+ .decrypt = ablk_decrypt, -+ } -+}, { -+ .cra_name = "xts(aes)", -+ .cra_driver_name = "xts-aes-" MODE, -+ .cra_priority = PRIO, -+ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, -+ .cra_blocksize = AES_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct async_helper_ctx), -+ .cra_alignmask = 7, -+ .cra_type = &crypto_ablkcipher_type, -+ .cra_module = THIS_MODULE, -+ .cra_init = ablk_init, -+ .cra_exit = ablk_exit, -+ .cra_ablkcipher = { -+ .min_keysize = 2 * AES_MIN_KEY_SIZE, -+ .max_keysize = 2 * AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .setkey = ablk_set_key, -+ .encrypt = ablk_encrypt, -+ .decrypt = ablk_decrypt, -+ } -+} }; -+ -+static int __init aes_init(void) -+{ -+ return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs)); -+} -+ -+static void __exit aes_exit(void) -+{ -+ crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs)); -+} -+ -+#ifdef USE_V8_CRYPTO_EXTENSIONS -+module_cpu_feature_match(AES, aes_init); -+#else -+module_init(aes_init); -+#endif -+module_exit(aes_exit); -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-modes.S linux-3.14.22/arch/arm64/crypto/aes-modes.S ---- linux-3.14.22.orig/arch/arm64/crypto/aes-modes.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-modes.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,532 @@ -+/* -+ * linux/arch/arm64/crypto/aes-modes.S - chaining mode wrappers for AES -+ * -+ * Copyright (C) 2013 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+/* included by aes-ce.S and aes-neon.S */ -+ -+ .text -+ .align 4 -+ -+/* -+ * There are several ways to instantiate this code: -+ * - no interleave, all inline -+ * - 2-way interleave, 2x calls out of line (-DINTERLEAVE=2) -+ * - 2-way interleave, all inline (-DINTERLEAVE=2 -DINTERLEAVE_INLINE) -+ * - 4-way interleave, 4x calls out of line (-DINTERLEAVE=4) -+ * - 4-way interleave, all inline (-DINTERLEAVE=4 -DINTERLEAVE_INLINE) -+ * -+ * Macros imported by this code: -+ * - enc_prepare - setup NEON registers for encryption -+ * - dec_prepare - setup NEON registers for decryption -+ * - enc_switch_key - change to new key after having prepared for encryption -+ * - encrypt_block - encrypt a single block -+ * - decrypt block - decrypt a single block -+ * - encrypt_block2x - encrypt 2 blocks in parallel (if INTERLEAVE == 2) -+ * - decrypt_block2x - decrypt 2 blocks in parallel (if INTERLEAVE == 2) -+ * - encrypt_block4x - encrypt 4 blocks in parallel (if INTERLEAVE == 4) -+ * - decrypt_block4x - decrypt 4 blocks in parallel (if INTERLEAVE == 4) -+ */ -+ -+#if defined(INTERLEAVE) && !defined(INTERLEAVE_INLINE) -+#define FRAME_PUSH stp x29, x30, [sp,#-16]! ; mov x29, sp -+#define FRAME_POP ldp x29, x30, [sp],#16 -+ -+#if INTERLEAVE == 2 -+ -+aes_encrypt_block2x: -+ encrypt_block2x v0, v1, w3, x2, x6, w7 -+ ret -+ENDPROC(aes_encrypt_block2x) -+ -+aes_decrypt_block2x: -+ decrypt_block2x v0, v1, w3, x2, x6, w7 -+ ret -+ENDPROC(aes_decrypt_block2x) -+ -+#elif INTERLEAVE == 4 -+ -+aes_encrypt_block4x: -+ encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 -+ ret -+ENDPROC(aes_encrypt_block4x) -+ -+aes_decrypt_block4x: -+ decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 -+ ret -+ENDPROC(aes_decrypt_block4x) -+ -+#else -+#error INTERLEAVE should equal 2 or 4 -+#endif -+ -+ .macro do_encrypt_block2x -+ bl aes_encrypt_block2x -+ .endm -+ -+ .macro do_decrypt_block2x -+ bl aes_decrypt_block2x -+ .endm -+ -+ .macro do_encrypt_block4x -+ bl aes_encrypt_block4x -+ .endm -+ -+ .macro do_decrypt_block4x -+ bl aes_decrypt_block4x -+ .endm -+ -+#else -+#define FRAME_PUSH -+#define FRAME_POP -+ -+ .macro do_encrypt_block2x -+ encrypt_block2x v0, v1, w3, x2, x6, w7 -+ .endm -+ -+ .macro do_decrypt_block2x -+ decrypt_block2x v0, v1, w3, x2, x6, w7 -+ .endm -+ -+ .macro do_encrypt_block4x -+ encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 -+ .endm -+ -+ .macro do_decrypt_block4x -+ decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 -+ .endm -+ -+#endif -+ -+ /* -+ * aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, -+ * int blocks, int first) -+ * aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, -+ * int blocks, int first) -+ */ -+ -+AES_ENTRY(aes_ecb_encrypt) -+ FRAME_PUSH -+ cbz w5, .LecbencloopNx -+ -+ enc_prepare w3, x2, x5 -+ -+.LecbencloopNx: -+#if INTERLEAVE >= 2 -+ subs w4, w4, #INTERLEAVE -+ bmi .Lecbenc1x -+#if INTERLEAVE == 2 -+ ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ -+ do_encrypt_block2x -+ st1 {v0.16b-v1.16b}, [x0], #32 -+#else -+ ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ -+ do_encrypt_block4x -+ st1 {v0.16b-v3.16b}, [x0], #64 -+#endif -+ b .LecbencloopNx -+.Lecbenc1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lecbencout -+#endif -+.Lecbencloop: -+ ld1 {v0.16b}, [x1], #16 /* get next pt block */ -+ encrypt_block v0, w3, x2, x5, w6 -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ bne .Lecbencloop -+.Lecbencout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_ecb_encrypt) -+ -+ -+AES_ENTRY(aes_ecb_decrypt) -+ FRAME_PUSH -+ cbz w5, .LecbdecloopNx -+ -+ dec_prepare w3, x2, x5 -+ -+.LecbdecloopNx: -+#if INTERLEAVE >= 2 -+ subs w4, w4, #INTERLEAVE -+ bmi .Lecbdec1x -+#if INTERLEAVE == 2 -+ ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ -+ do_decrypt_block2x -+ st1 {v0.16b-v1.16b}, [x0], #32 -+#else -+ ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ -+ do_decrypt_block4x -+ st1 {v0.16b-v3.16b}, [x0], #64 -+#endif -+ b .LecbdecloopNx -+.Lecbdec1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lecbdecout -+#endif -+.Lecbdecloop: -+ ld1 {v0.16b}, [x1], #16 /* get next ct block */ -+ decrypt_block v0, w3, x2, x5, w6 -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ bne .Lecbdecloop -+.Lecbdecout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_ecb_decrypt) -+ -+ -+ /* -+ * aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, -+ * int blocks, u8 iv[], int first) -+ * aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, -+ * int blocks, u8 iv[], int first) -+ */ -+ -+AES_ENTRY(aes_cbc_encrypt) -+ cbz w6, .Lcbcencloop -+ -+ ld1 {v0.16b}, [x5] /* get iv */ -+ enc_prepare w3, x2, x5 -+ -+.Lcbcencloop: -+ ld1 {v1.16b}, [x1], #16 /* get next pt block */ -+ eor v0.16b, v0.16b, v1.16b /* ..and xor with iv */ -+ encrypt_block v0, w3, x2, x5, w6 -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ bne .Lcbcencloop -+ ret -+AES_ENDPROC(aes_cbc_encrypt) -+ -+ -+AES_ENTRY(aes_cbc_decrypt) -+ FRAME_PUSH -+ cbz w6, .LcbcdecloopNx -+ -+ ld1 {v7.16b}, [x5] /* get iv */ -+ dec_prepare w3, x2, x5 -+ -+.LcbcdecloopNx: -+#if INTERLEAVE >= 2 -+ subs w4, w4, #INTERLEAVE -+ bmi .Lcbcdec1x -+#if INTERLEAVE == 2 -+ ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ -+ mov v2.16b, v0.16b -+ mov v3.16b, v1.16b -+ do_decrypt_block2x -+ eor v0.16b, v0.16b, v7.16b -+ eor v1.16b, v1.16b, v2.16b -+ mov v7.16b, v3.16b -+ st1 {v0.16b-v1.16b}, [x0], #32 -+#else -+ ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ -+ mov v4.16b, v0.16b -+ mov v5.16b, v1.16b -+ mov v6.16b, v2.16b -+ do_decrypt_block4x -+ sub x1, x1, #16 -+ eor v0.16b, v0.16b, v7.16b -+ eor v1.16b, v1.16b, v4.16b -+ ld1 {v7.16b}, [x1], #16 /* reload 1 ct block */ -+ eor v2.16b, v2.16b, v5.16b -+ eor v3.16b, v3.16b, v6.16b -+ st1 {v0.16b-v3.16b}, [x0], #64 -+#endif -+ b .LcbcdecloopNx -+.Lcbcdec1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lcbcdecout -+#endif -+.Lcbcdecloop: -+ ld1 {v1.16b}, [x1], #16 /* get next ct block */ -+ mov v0.16b, v1.16b /* ...and copy to v0 */ -+ decrypt_block v0, w3, x2, x5, w6 -+ eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */ -+ mov v7.16b, v1.16b /* ct is next iv */ -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ bne .Lcbcdecloop -+.Lcbcdecout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_cbc_decrypt) -+ -+ -+ /* -+ * aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], int rounds, -+ * int blocks, u8 ctr[], int first) -+ */ -+ -+AES_ENTRY(aes_ctr_encrypt) -+ FRAME_PUSH -+ cbnz w6, .Lctrfirst /* 1st time around? */ -+ umov x5, v4.d[1] /* keep swabbed ctr in reg */ -+ rev x5, x5 -+#if INTERLEAVE >= 2 -+ cmn w5, w4 /* 32 bit overflow? */ -+ bcs .Lctrinc -+ add x5, x5, #1 /* increment BE ctr */ -+ b .LctrincNx -+#else -+ b .Lctrinc -+#endif -+.Lctrfirst: -+ enc_prepare w3, x2, x6 -+ ld1 {v4.16b}, [x5] -+ umov x5, v4.d[1] /* keep swabbed ctr in reg */ -+ rev x5, x5 -+#if INTERLEAVE >= 2 -+ cmn w5, w4 /* 32 bit overflow? */ -+ bcs .Lctrloop -+.LctrloopNx: -+ subs w4, w4, #INTERLEAVE -+ bmi .Lctr1x -+#if INTERLEAVE == 2 -+ mov v0.8b, v4.8b -+ mov v1.8b, v4.8b -+ rev x7, x5 -+ add x5, x5, #1 -+ ins v0.d[1], x7 -+ rev x7, x5 -+ add x5, x5, #1 -+ ins v1.d[1], x7 -+ ld1 {v2.16b-v3.16b}, [x1], #32 /* get 2 input blocks */ -+ do_encrypt_block2x -+ eor v0.16b, v0.16b, v2.16b -+ eor v1.16b, v1.16b, v3.16b -+ st1 {v0.16b-v1.16b}, [x0], #32 -+#else -+ ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */ -+ dup v7.4s, w5 -+ mov v0.16b, v4.16b -+ add v7.4s, v7.4s, v8.4s -+ mov v1.16b, v4.16b -+ rev32 v8.16b, v7.16b -+ mov v2.16b, v4.16b -+ mov v3.16b, v4.16b -+ mov v1.s[3], v8.s[0] -+ mov v2.s[3], v8.s[1] -+ mov v3.s[3], v8.s[2] -+ ld1 {v5.16b-v7.16b}, [x1], #48 /* get 3 input blocks */ -+ do_encrypt_block4x -+ eor v0.16b, v5.16b, v0.16b -+ ld1 {v5.16b}, [x1], #16 /* get 1 input block */ -+ eor v1.16b, v6.16b, v1.16b -+ eor v2.16b, v7.16b, v2.16b -+ eor v3.16b, v5.16b, v3.16b -+ st1 {v0.16b-v3.16b}, [x0], #64 -+ add x5, x5, #INTERLEAVE -+#endif -+ cbz w4, .LctroutNx -+.LctrincNx: -+ rev x7, x5 -+ ins v4.d[1], x7 -+ b .LctrloopNx -+.LctroutNx: -+ sub x5, x5, #1 -+ rev x7, x5 -+ ins v4.d[1], x7 -+ b .Lctrout -+.Lctr1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lctrout -+#endif -+.Lctrloop: -+ mov v0.16b, v4.16b -+ encrypt_block v0, w3, x2, x6, w7 -+ subs w4, w4, #1 -+ bmi .Lctrhalfblock /* blocks < 0 means 1/2 block */ -+ ld1 {v3.16b}, [x1], #16 -+ eor v3.16b, v0.16b, v3.16b -+ st1 {v3.16b}, [x0], #16 -+ beq .Lctrout -+.Lctrinc: -+ adds x5, x5, #1 /* increment BE ctr */ -+ rev x7, x5 -+ ins v4.d[1], x7 -+ bcc .Lctrloop /* no overflow? */ -+ umov x7, v4.d[0] /* load upper word of ctr */ -+ rev x7, x7 /* ... to handle the carry */ -+ add x7, x7, #1 -+ rev x7, x7 -+ ins v4.d[0], x7 -+ b .Lctrloop -+.Lctrhalfblock: -+ ld1 {v3.8b}, [x1] -+ eor v3.8b, v0.8b, v3.8b -+ st1 {v3.8b}, [x0] -+.Lctrout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_ctr_encrypt) -+ .ltorg -+ -+ -+ /* -+ * aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds, -+ * int blocks, u8 const rk2[], u8 iv[], int first) -+ * aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], int rounds, -+ * int blocks, u8 const rk2[], u8 iv[], int first) -+ */ -+ -+ .macro next_tweak, out, in, const, tmp -+ sshr \tmp\().2d, \in\().2d, #63 -+ and \tmp\().16b, \tmp\().16b, \const\().16b -+ add \out\().2d, \in\().2d, \in\().2d -+ ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 -+ eor \out\().16b, \out\().16b, \tmp\().16b -+ .endm -+ -+.Lxts_mul_x: -+ .word 1, 0, 0x87, 0 -+ -+AES_ENTRY(aes_xts_encrypt) -+ FRAME_PUSH -+ cbz w7, .LxtsencloopNx -+ -+ ld1 {v4.16b}, [x6] -+ enc_prepare w3, x5, x6 -+ encrypt_block v4, w3, x5, x6, w7 /* first tweak */ -+ enc_switch_key w3, x2, x6 -+ ldr q7, .Lxts_mul_x -+ b .LxtsencNx -+ -+.LxtsencloopNx: -+ ldr q7, .Lxts_mul_x -+ next_tweak v4, v4, v7, v8 -+.LxtsencNx: -+#if INTERLEAVE >= 2 -+ subs w4, w4, #INTERLEAVE -+ bmi .Lxtsenc1x -+#if INTERLEAVE == 2 -+ ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ -+ next_tweak v5, v4, v7, v8 -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ do_encrypt_block2x -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ st1 {v0.16b-v1.16b}, [x0], #32 -+ cbz w4, .LxtsencoutNx -+ next_tweak v4, v5, v7, v8 -+ b .LxtsencNx -+.LxtsencoutNx: -+ mov v4.16b, v5.16b -+ b .Lxtsencout -+#else -+ ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ -+ next_tweak v5, v4, v7, v8 -+ eor v0.16b, v0.16b, v4.16b -+ next_tweak v6, v5, v7, v8 -+ eor v1.16b, v1.16b, v5.16b -+ eor v2.16b, v2.16b, v6.16b -+ next_tweak v7, v6, v7, v8 -+ eor v3.16b, v3.16b, v7.16b -+ do_encrypt_block4x -+ eor v3.16b, v3.16b, v7.16b -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ eor v2.16b, v2.16b, v6.16b -+ st1 {v0.16b-v3.16b}, [x0], #64 -+ mov v4.16b, v7.16b -+ cbz w4, .Lxtsencout -+ b .LxtsencloopNx -+#endif -+.Lxtsenc1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lxtsencout -+#endif -+.Lxtsencloop: -+ ld1 {v1.16b}, [x1], #16 -+ eor v0.16b, v1.16b, v4.16b -+ encrypt_block v0, w3, x2, x6, w7 -+ eor v0.16b, v0.16b, v4.16b -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ beq .Lxtsencout -+ next_tweak v4, v4, v7, v8 -+ b .Lxtsencloop -+.Lxtsencout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_xts_encrypt) -+ -+ -+AES_ENTRY(aes_xts_decrypt) -+ FRAME_PUSH -+ cbz w7, .LxtsdecloopNx -+ -+ ld1 {v4.16b}, [x6] -+ enc_prepare w3, x5, x6 -+ encrypt_block v4, w3, x5, x6, w7 /* first tweak */ -+ dec_prepare w3, x2, x6 -+ ldr q7, .Lxts_mul_x -+ b .LxtsdecNx -+ -+.LxtsdecloopNx: -+ ldr q7, .Lxts_mul_x -+ next_tweak v4, v4, v7, v8 -+.LxtsdecNx: -+#if INTERLEAVE >= 2 -+ subs w4, w4, #INTERLEAVE -+ bmi .Lxtsdec1x -+#if INTERLEAVE == 2 -+ ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ -+ next_tweak v5, v4, v7, v8 -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ do_decrypt_block2x -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ st1 {v0.16b-v1.16b}, [x0], #32 -+ cbz w4, .LxtsdecoutNx -+ next_tweak v4, v5, v7, v8 -+ b .LxtsdecNx -+.LxtsdecoutNx: -+ mov v4.16b, v5.16b -+ b .Lxtsdecout -+#else -+ ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ -+ next_tweak v5, v4, v7, v8 -+ eor v0.16b, v0.16b, v4.16b -+ next_tweak v6, v5, v7, v8 -+ eor v1.16b, v1.16b, v5.16b -+ eor v2.16b, v2.16b, v6.16b -+ next_tweak v7, v6, v7, v8 -+ eor v3.16b, v3.16b, v7.16b -+ do_decrypt_block4x -+ eor v3.16b, v3.16b, v7.16b -+ eor v0.16b, v0.16b, v4.16b -+ eor v1.16b, v1.16b, v5.16b -+ eor v2.16b, v2.16b, v6.16b -+ st1 {v0.16b-v3.16b}, [x0], #64 -+ mov v4.16b, v7.16b -+ cbz w4, .Lxtsdecout -+ b .LxtsdecloopNx -+#endif -+.Lxtsdec1x: -+ adds w4, w4, #INTERLEAVE -+ beq .Lxtsdecout -+#endif -+.Lxtsdecloop: -+ ld1 {v1.16b}, [x1], #16 -+ eor v0.16b, v1.16b, v4.16b -+ decrypt_block v0, w3, x2, x6, w7 -+ eor v0.16b, v0.16b, v4.16b -+ st1 {v0.16b}, [x0], #16 -+ subs w4, w4, #1 -+ beq .Lxtsdecout -+ next_tweak v4, v4, v7, v8 -+ b .Lxtsdecloop -+.Lxtsdecout: -+ FRAME_POP -+ ret -+AES_ENDPROC(aes_xts_decrypt) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/aes-neon.S linux-3.14.22/arch/arm64/crypto/aes-neon.S ---- linux-3.14.22.orig/arch/arm64/crypto/aes-neon.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/aes-neon.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,382 @@ -+/* -+ * linux/arch/arm64/crypto/aes-neon.S - AES cipher for ARMv8 NEON -+ * -+ * Copyright (C) 2013 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+ -+#define AES_ENTRY(func) ENTRY(neon_ ## func) -+#define AES_ENDPROC(func) ENDPROC(neon_ ## func) -+ -+ /* multiply by polynomial 'x' in GF(2^8) */ -+ .macro mul_by_x, out, in, temp, const -+ sshr \temp, \in, #7 -+ add \out, \in, \in -+ and \temp, \temp, \const -+ eor \out, \out, \temp -+ .endm -+ -+ /* preload the entire Sbox */ -+ .macro prepare, sbox, shiftrows, temp -+ adr \temp, \sbox -+ movi v12.16b, #0x40 -+ ldr q13, \shiftrows -+ movi v14.16b, #0x1b -+ ld1 {v16.16b-v19.16b}, [\temp], #64 -+ ld1 {v20.16b-v23.16b}, [\temp], #64 -+ ld1 {v24.16b-v27.16b}, [\temp], #64 -+ ld1 {v28.16b-v31.16b}, [\temp] -+ .endm -+ -+ /* do preload for encryption */ -+ .macro enc_prepare, ignore0, ignore1, temp -+ prepare .LForward_Sbox, .LForward_ShiftRows, \temp -+ .endm -+ -+ .macro enc_switch_key, ignore0, ignore1, temp -+ /* do nothing */ -+ .endm -+ -+ /* do preload for decryption */ -+ .macro dec_prepare, ignore0, ignore1, temp -+ prepare .LReverse_Sbox, .LReverse_ShiftRows, \temp -+ .endm -+ -+ /* apply SubBytes transformation using the the preloaded Sbox */ -+ .macro sub_bytes, in -+ sub v9.16b, \in\().16b, v12.16b -+ tbl \in\().16b, {v16.16b-v19.16b}, \in\().16b -+ sub v10.16b, v9.16b, v12.16b -+ tbx \in\().16b, {v20.16b-v23.16b}, v9.16b -+ sub v11.16b, v10.16b, v12.16b -+ tbx \in\().16b, {v24.16b-v27.16b}, v10.16b -+ tbx \in\().16b, {v28.16b-v31.16b}, v11.16b -+ .endm -+ -+ /* apply MixColumns transformation */ -+ .macro mix_columns, in -+ mul_by_x v10.16b, \in\().16b, v9.16b, v14.16b -+ rev32 v8.8h, \in\().8h -+ eor \in\().16b, v10.16b, \in\().16b -+ shl v9.4s, v8.4s, #24 -+ shl v11.4s, \in\().4s, #24 -+ sri v9.4s, v8.4s, #8 -+ sri v11.4s, \in\().4s, #8 -+ eor v9.16b, v9.16b, v8.16b -+ eor v10.16b, v10.16b, v9.16b -+ eor \in\().16b, v10.16b, v11.16b -+ .endm -+ -+ /* Inverse MixColumns: pre-multiply by { 5, 0, 4, 0 } */ -+ .macro inv_mix_columns, in -+ mul_by_x v11.16b, \in\().16b, v10.16b, v14.16b -+ mul_by_x v11.16b, v11.16b, v10.16b, v14.16b -+ eor \in\().16b, \in\().16b, v11.16b -+ rev32 v11.8h, v11.8h -+ eor \in\().16b, \in\().16b, v11.16b -+ mix_columns \in -+ .endm -+ -+ .macro do_block, enc, in, rounds, rk, rkp, i -+ ld1 {v15.16b}, [\rk] -+ add \rkp, \rk, #16 -+ mov \i, \rounds -+1111: eor \in\().16b, \in\().16b, v15.16b /* ^round key */ -+ tbl \in\().16b, {\in\().16b}, v13.16b /* ShiftRows */ -+ sub_bytes \in -+ ld1 {v15.16b}, [\rkp], #16 -+ subs \i, \i, #1 -+ beq 2222f -+ .if \enc == 1 -+ mix_columns \in -+ .else -+ inv_mix_columns \in -+ .endif -+ b 1111b -+2222: eor \in\().16b, \in\().16b, v15.16b /* ^round key */ -+ .endm -+ -+ .macro encrypt_block, in, rounds, rk, rkp, i -+ do_block 1, \in, \rounds, \rk, \rkp, \i -+ .endm -+ -+ .macro decrypt_block, in, rounds, rk, rkp, i -+ do_block 0, \in, \rounds, \rk, \rkp, \i -+ .endm -+ -+ /* -+ * Interleaved versions: functionally equivalent to the -+ * ones above, but applied to 2 or 4 AES states in parallel. -+ */ -+ -+ .macro sub_bytes_2x, in0, in1 -+ sub v8.16b, \in0\().16b, v12.16b -+ sub v9.16b, \in1\().16b, v12.16b -+ tbl \in0\().16b, {v16.16b-v19.16b}, \in0\().16b -+ tbl \in1\().16b, {v16.16b-v19.16b}, \in1\().16b -+ sub v10.16b, v8.16b, v12.16b -+ sub v11.16b, v9.16b, v12.16b -+ tbx \in0\().16b, {v20.16b-v23.16b}, v8.16b -+ tbx \in1\().16b, {v20.16b-v23.16b}, v9.16b -+ sub v8.16b, v10.16b, v12.16b -+ sub v9.16b, v11.16b, v12.16b -+ tbx \in0\().16b, {v24.16b-v27.16b}, v10.16b -+ tbx \in1\().16b, {v24.16b-v27.16b}, v11.16b -+ tbx \in0\().16b, {v28.16b-v31.16b}, v8.16b -+ tbx \in1\().16b, {v28.16b-v31.16b}, v9.16b -+ .endm -+ -+ .macro sub_bytes_4x, in0, in1, in2, in3 -+ sub v8.16b, \in0\().16b, v12.16b -+ tbl \in0\().16b, {v16.16b-v19.16b}, \in0\().16b -+ sub v9.16b, \in1\().16b, v12.16b -+ tbl \in1\().16b, {v16.16b-v19.16b}, \in1\().16b -+ sub v10.16b, \in2\().16b, v12.16b -+ tbl \in2\().16b, {v16.16b-v19.16b}, \in2\().16b -+ sub v11.16b, \in3\().16b, v12.16b -+ tbl \in3\().16b, {v16.16b-v19.16b}, \in3\().16b -+ tbx \in0\().16b, {v20.16b-v23.16b}, v8.16b -+ tbx \in1\().16b, {v20.16b-v23.16b}, v9.16b -+ sub v8.16b, v8.16b, v12.16b -+ tbx \in2\().16b, {v20.16b-v23.16b}, v10.16b -+ sub v9.16b, v9.16b, v12.16b -+ tbx \in3\().16b, {v20.16b-v23.16b}, v11.16b -+ sub v10.16b, v10.16b, v12.16b -+ tbx \in0\().16b, {v24.16b-v27.16b}, v8.16b -+ sub v11.16b, v11.16b, v12.16b -+ tbx \in1\().16b, {v24.16b-v27.16b}, v9.16b -+ sub v8.16b, v8.16b, v12.16b -+ tbx \in2\().16b, {v24.16b-v27.16b}, v10.16b -+ sub v9.16b, v9.16b, v12.16b -+ tbx \in3\().16b, {v24.16b-v27.16b}, v11.16b -+ sub v10.16b, v10.16b, v12.16b -+ tbx \in0\().16b, {v28.16b-v31.16b}, v8.16b -+ sub v11.16b, v11.16b, v12.16b -+ tbx \in1\().16b, {v28.16b-v31.16b}, v9.16b -+ tbx \in2\().16b, {v28.16b-v31.16b}, v10.16b -+ tbx \in3\().16b, {v28.16b-v31.16b}, v11.16b -+ .endm -+ -+ .macro mul_by_x_2x, out0, out1, in0, in1, tmp0, tmp1, const -+ sshr \tmp0\().16b, \in0\().16b, #7 -+ add \out0\().16b, \in0\().16b, \in0\().16b -+ sshr \tmp1\().16b, \in1\().16b, #7 -+ and \tmp0\().16b, \tmp0\().16b, \const\().16b -+ add \out1\().16b, \in1\().16b, \in1\().16b -+ and \tmp1\().16b, \tmp1\().16b, \const\().16b -+ eor \out0\().16b, \out0\().16b, \tmp0\().16b -+ eor \out1\().16b, \out1\().16b, \tmp1\().16b -+ .endm -+ -+ .macro mix_columns_2x, in0, in1 -+ mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14 -+ rev32 v10.8h, \in0\().8h -+ rev32 v11.8h, \in1\().8h -+ eor \in0\().16b, v8.16b, \in0\().16b -+ eor \in1\().16b, v9.16b, \in1\().16b -+ shl v12.4s, v10.4s, #24 -+ shl v13.4s, v11.4s, #24 -+ eor v8.16b, v8.16b, v10.16b -+ sri v12.4s, v10.4s, #8 -+ shl v10.4s, \in0\().4s, #24 -+ eor v9.16b, v9.16b, v11.16b -+ sri v13.4s, v11.4s, #8 -+ shl v11.4s, \in1\().4s, #24 -+ sri v10.4s, \in0\().4s, #8 -+ eor \in0\().16b, v8.16b, v12.16b -+ sri v11.4s, \in1\().4s, #8 -+ eor \in1\().16b, v9.16b, v13.16b -+ eor \in0\().16b, v10.16b, \in0\().16b -+ eor \in1\().16b, v11.16b, \in1\().16b -+ .endm -+ -+ .macro inv_mix_cols_2x, in0, in1 -+ mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14 -+ mul_by_x_2x v8, v9, v8, v9, v10, v11, v14 -+ eor \in0\().16b, \in0\().16b, v8.16b -+ eor \in1\().16b, \in1\().16b, v9.16b -+ rev32 v8.8h, v8.8h -+ rev32 v9.8h, v9.8h -+ eor \in0\().16b, \in0\().16b, v8.16b -+ eor \in1\().16b, \in1\().16b, v9.16b -+ mix_columns_2x \in0, \in1 -+ .endm -+ -+ .macro inv_mix_cols_4x, in0, in1, in2, in3 -+ mul_by_x_2x v8, v9, \in0, \in1, v10, v11, v14 -+ mul_by_x_2x v10, v11, \in2, \in3, v12, v13, v14 -+ mul_by_x_2x v8, v9, v8, v9, v12, v13, v14 -+ mul_by_x_2x v10, v11, v10, v11, v12, v13, v14 -+ eor \in0\().16b, \in0\().16b, v8.16b -+ eor \in1\().16b, \in1\().16b, v9.16b -+ eor \in2\().16b, \in2\().16b, v10.16b -+ eor \in3\().16b, \in3\().16b, v11.16b -+ rev32 v8.8h, v8.8h -+ rev32 v9.8h, v9.8h -+ rev32 v10.8h, v10.8h -+ rev32 v11.8h, v11.8h -+ eor \in0\().16b, \in0\().16b, v8.16b -+ eor \in1\().16b, \in1\().16b, v9.16b -+ eor \in2\().16b, \in2\().16b, v10.16b -+ eor \in3\().16b, \in3\().16b, v11.16b -+ mix_columns_2x \in0, \in1 -+ mix_columns_2x \in2, \in3 -+ .endm -+ -+ .macro do_block_2x, enc, in0, in1 rounds, rk, rkp, i -+ ld1 {v15.16b}, [\rk] -+ add \rkp, \rk, #16 -+ mov \i, \rounds -+1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ -+ eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */ -+ sub_bytes_2x \in0, \in1 -+ tbl \in0\().16b, {\in0\().16b}, v13.16b /* ShiftRows */ -+ tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */ -+ ld1 {v15.16b}, [\rkp], #16 -+ subs \i, \i, #1 -+ beq 2222f -+ .if \enc == 1 -+ mix_columns_2x \in0, \in1 -+ ldr q13, .LForward_ShiftRows -+ .else -+ inv_mix_cols_2x \in0, \in1 -+ ldr q13, .LReverse_ShiftRows -+ .endif -+ movi v12.16b, #0x40 -+ b 1111b -+2222: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ -+ eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */ -+ .endm -+ -+ .macro do_block_4x, enc, in0, in1, in2, in3, rounds, rk, rkp, i -+ ld1 {v15.16b}, [\rk] -+ add \rkp, \rk, #16 -+ mov \i, \rounds -+1111: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ -+ eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */ -+ eor \in2\().16b, \in2\().16b, v15.16b /* ^round key */ -+ eor \in3\().16b, \in3\().16b, v15.16b /* ^round key */ -+ sub_bytes_4x \in0, \in1, \in2, \in3 -+ tbl \in0\().16b, {\in0\().16b}, v13.16b /* ShiftRows */ -+ tbl \in1\().16b, {\in1\().16b}, v13.16b /* ShiftRows */ -+ tbl \in2\().16b, {\in2\().16b}, v13.16b /* ShiftRows */ -+ tbl \in3\().16b, {\in3\().16b}, v13.16b /* ShiftRows */ -+ ld1 {v15.16b}, [\rkp], #16 -+ subs \i, \i, #1 -+ beq 2222f -+ .if \enc == 1 -+ mix_columns_2x \in0, \in1 -+ mix_columns_2x \in2, \in3 -+ ldr q13, .LForward_ShiftRows -+ .else -+ inv_mix_cols_4x \in0, \in1, \in2, \in3 -+ ldr q13, .LReverse_ShiftRows -+ .endif -+ movi v12.16b, #0x40 -+ b 1111b -+2222: eor \in0\().16b, \in0\().16b, v15.16b /* ^round key */ -+ eor \in1\().16b, \in1\().16b, v15.16b /* ^round key */ -+ eor \in2\().16b, \in2\().16b, v15.16b /* ^round key */ -+ eor \in3\().16b, \in3\().16b, v15.16b /* ^round key */ -+ .endm -+ -+ .macro encrypt_block2x, in0, in1, rounds, rk, rkp, i -+ do_block_2x 1, \in0, \in1, \rounds, \rk, \rkp, \i -+ .endm -+ -+ .macro decrypt_block2x, in0, in1, rounds, rk, rkp, i -+ do_block_2x 0, \in0, \in1, \rounds, \rk, \rkp, \i -+ .endm -+ -+ .macro encrypt_block4x, in0, in1, in2, in3, rounds, rk, rkp, i -+ do_block_4x 1, \in0, \in1, \in2, \in3, \rounds, \rk, \rkp, \i -+ .endm -+ -+ .macro decrypt_block4x, in0, in1, in2, in3, rounds, rk, rkp, i -+ do_block_4x 0, \in0, \in1, \in2, \in3, \rounds, \rk, \rkp, \i -+ .endm -+ -+#include "aes-modes.S" -+ -+ .text -+ .align 4 -+.LForward_ShiftRows: -+ .byte 0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3 -+ .byte 0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb -+ -+.LReverse_ShiftRows: -+ .byte 0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb -+ .byte 0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3 -+ -+.LForward_Sbox: -+ .byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 -+ .byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 -+ .byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 -+ .byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 -+ .byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc -+ .byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 -+ .byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a -+ .byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 -+ .byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 -+ .byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 -+ .byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b -+ .byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf -+ .byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 -+ .byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 -+ .byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 -+ .byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 -+ .byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 -+ .byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 -+ .byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 -+ .byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb -+ .byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c -+ .byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 -+ .byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 -+ .byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 -+ .byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 -+ .byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a -+ .byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e -+ .byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e -+ .byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 -+ .byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf -+ .byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 -+ .byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 -+ -+.LReverse_Sbox: -+ .byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 -+ .byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb -+ .byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 -+ .byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb -+ .byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d -+ .byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e -+ .byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 -+ .byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 -+ .byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 -+ .byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 -+ .byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda -+ .byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 -+ .byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a -+ .byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 -+ .byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 -+ .byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b -+ .byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea -+ .byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 -+ .byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 -+ .byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e -+ .byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 -+ .byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b -+ .byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 -+ .byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 -+ .byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 -+ .byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f -+ .byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d -+ .byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef -+ .byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 -+ .byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 -+ .byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 -+ .byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/ghash-ce-core.S linux-3.14.22/arch/arm64/crypto/ghash-ce-core.S ---- linux-3.14.22.orig/arch/arm64/crypto/ghash-ce-core.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/ghash-ce-core.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,79 @@ -+/* -+ * Accelerated GHASH implementation with ARMv8 PMULL instructions. -+ * -+ * Copyright (C) 2014 Linaro Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+ SHASH .req v0 -+ SHASH2 .req v1 -+ T1 .req v2 -+ T2 .req v3 -+ MASK .req v4 -+ XL .req v5 -+ XM .req v6 -+ XH .req v7 -+ IN1 .req v7 -+ -+ .text -+ .arch armv8-a+crypto -+ -+ /* -+ * void pmull_ghash_update(int blocks, u64 dg[], const char *src, -+ * struct ghash_key const *k, const char *head) -+ */ -+ENTRY(pmull_ghash_update) -+ ld1 {SHASH.16b}, [x3] -+ ld1 {XL.16b}, [x1] -+ movi MASK.16b, #0xe1 -+ ext SHASH2.16b, SHASH.16b, SHASH.16b, #8 -+ shl MASK.2d, MASK.2d, #57 -+ eor SHASH2.16b, SHASH2.16b, SHASH.16b -+ -+ /* do the head block first, if supplied */ -+ cbz x4, 0f -+ ld1 {T1.2d}, [x4] -+ b 1f -+ -+0: ld1 {T1.2d}, [x2], #16 -+ sub w0, w0, #1 -+ -+1: /* multiply XL by SHASH in GF(2^128) */ -+CPU_LE( rev64 T1.16b, T1.16b ) -+ -+ ext T2.16b, XL.16b, XL.16b, #8 -+ ext IN1.16b, T1.16b, T1.16b, #8 -+ eor T1.16b, T1.16b, T2.16b -+ eor XL.16b, XL.16b, IN1.16b -+ -+ pmull2 XH.1q, SHASH.2d, XL.2d // a1 * b1 -+ eor T1.16b, T1.16b, XL.16b -+ pmull XL.1q, SHASH.1d, XL.1d // a0 * b0 -+ pmull XM.1q, SHASH2.1d, T1.1d // (a1 + a0)(b1 + b0) -+ -+ ext T1.16b, XL.16b, XH.16b, #8 -+ eor T2.16b, XL.16b, XH.16b -+ eor XM.16b, XM.16b, T1.16b -+ eor XM.16b, XM.16b, T2.16b -+ pmull T2.1q, XL.1d, MASK.1d -+ -+ mov XH.d[0], XM.d[1] -+ mov XM.d[1], XL.d[0] -+ -+ eor XL.16b, XM.16b, T2.16b -+ ext T2.16b, XL.16b, XL.16b, #8 -+ pmull XL.1q, XL.1d, MASK.1d -+ eor T2.16b, T2.16b, XH.16b -+ eor XL.16b, XL.16b, T2.16b -+ -+ cbnz w0, 0b -+ -+ st1 {XL.16b}, [x1] -+ ret -+ENDPROC(pmull_ghash_update) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/ghash-ce-glue.c linux-3.14.22/arch/arm64/crypto/ghash-ce-glue.c ---- linux-3.14.22.orig/arch/arm64/crypto/ghash-ce-glue.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/ghash-ce-glue.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,156 @@ -+/* -+ * Accelerated GHASH implementation with ARMv8 PMULL instructions. -+ * -+ * Copyright (C) 2014 Linaro Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("GHASH secure hash using ARMv8 Crypto Extensions"); -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+ -+#define GHASH_BLOCK_SIZE 16 -+#define GHASH_DIGEST_SIZE 16 -+ -+struct ghash_key { -+ u64 a; -+ u64 b; -+}; -+ -+struct ghash_desc_ctx { -+ u64 digest[GHASH_DIGEST_SIZE/sizeof(u64)]; -+ u8 buf[GHASH_BLOCK_SIZE]; -+ u32 count; -+}; -+ -+asmlinkage void pmull_ghash_update(int blocks, u64 dg[], const char *src, -+ struct ghash_key const *k, const char *head); -+ -+static int ghash_init(struct shash_desc *desc) -+{ -+ struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); -+ -+ *ctx = (struct ghash_desc_ctx){}; -+ return 0; -+} -+ -+static int ghash_update(struct shash_desc *desc, const u8 *src, -+ unsigned int len) -+{ -+ struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); -+ unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; -+ -+ ctx->count += len; -+ -+ if ((partial + len) >= GHASH_BLOCK_SIZE) { -+ struct ghash_key *key = crypto_shash_ctx(desc->tfm); -+ int blocks; -+ -+ if (partial) { -+ int p = GHASH_BLOCK_SIZE - partial; -+ -+ memcpy(ctx->buf + partial, src, p); -+ src += p; -+ len -= p; -+ } -+ -+ blocks = len / GHASH_BLOCK_SIZE; -+ len %= GHASH_BLOCK_SIZE; -+ -+ kernel_neon_begin_partial(8); -+ pmull_ghash_update(blocks, ctx->digest, src, key, -+ partial ? ctx->buf : NULL); -+ kernel_neon_end(); -+ src += blocks * GHASH_BLOCK_SIZE; -+ partial = 0; -+ } -+ if (len) -+ memcpy(ctx->buf + partial, src, len); -+ return 0; -+} -+ -+static int ghash_final(struct shash_desc *desc, u8 *dst) -+{ -+ struct ghash_desc_ctx *ctx = shash_desc_ctx(desc); -+ unsigned int partial = ctx->count % GHASH_BLOCK_SIZE; -+ -+ if (partial) { -+ struct ghash_key *key = crypto_shash_ctx(desc->tfm); -+ -+ memset(ctx->buf + partial, 0, GHASH_BLOCK_SIZE - partial); -+ -+ kernel_neon_begin_partial(8); -+ pmull_ghash_update(1, ctx->digest, ctx->buf, key, NULL); -+ kernel_neon_end(); -+ } -+ put_unaligned_be64(ctx->digest[1], dst); -+ put_unaligned_be64(ctx->digest[0], dst + 8); -+ -+ *ctx = (struct ghash_desc_ctx){}; -+ return 0; -+} -+ -+static int ghash_setkey(struct crypto_shash *tfm, -+ const u8 *inkey, unsigned int keylen) -+{ -+ struct ghash_key *key = crypto_shash_ctx(tfm); -+ u64 a, b; -+ -+ if (keylen != GHASH_BLOCK_SIZE) { -+ crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+ } -+ -+ /* perform multiplication by 'x' in GF(2^128) */ -+ b = get_unaligned_be64(inkey); -+ a = get_unaligned_be64(inkey + 8); -+ -+ key->a = (a << 1) | (b >> 63); -+ key->b = (b << 1) | (a >> 63); -+ -+ if (b >> 63) -+ key->b ^= 0xc200000000000000UL; -+ -+ return 0; -+} -+ -+static struct shash_alg ghash_alg = { -+ .digestsize = GHASH_DIGEST_SIZE, -+ .init = ghash_init, -+ .update = ghash_update, -+ .final = ghash_final, -+ .setkey = ghash_setkey, -+ .descsize = sizeof(struct ghash_desc_ctx), -+ .base = { -+ .cra_name = "ghash", -+ .cra_driver_name = "ghash-ce", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = GHASH_BLOCK_SIZE, -+ .cra_ctxsize = sizeof(struct ghash_key), -+ .cra_module = THIS_MODULE, -+ }, -+}; -+ -+static int __init ghash_ce_mod_init(void) -+{ -+ return crypto_register_shash(&ghash_alg); -+} -+ -+static void __exit ghash_ce_mod_exit(void) -+{ -+ crypto_unregister_shash(&ghash_alg); -+} -+ -+module_cpu_feature_match(PMULL, ghash_ce_mod_init); -+module_exit(ghash_ce_mod_exit); -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/Kconfig linux-3.14.22/arch/arm64/crypto/Kconfig ---- linux-3.14.22.orig/arch/arm64/crypto/Kconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/Kconfig 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,53 @@ -+ -+menuconfig ARM64_CRYPTO -+ bool "ARM64 Accelerated Cryptographic Algorithms" -+ depends on ARM64 -+ help -+ Say Y here to choose from a selection of cryptographic algorithms -+ implemented using ARM64 specific CPU features or instructions. -+ -+if ARM64_CRYPTO -+ -+config CRYPTO_SHA1_ARM64_CE -+ tristate "SHA-1 digest algorithm (ARMv8 Crypto Extensions)" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_HASH -+ -+config CRYPTO_SHA2_ARM64_CE -+ tristate "SHA-224/SHA-256 digest algorithm (ARMv8 Crypto Extensions)" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_HASH -+ -+config CRYPTO_GHASH_ARM64_CE -+ tristate "GHASH (for GCM chaining mode) using ARMv8 Crypto Extensions" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_HASH -+ -+config CRYPTO_AES_ARM64_CE -+ tristate "AES core cipher using ARMv8 Crypto Extensions" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_ALGAPI -+ select CRYPTO_AES -+ -+config CRYPTO_AES_ARM64_CE_CCM -+ tristate "AES in CCM mode using ARMv8 Crypto Extensions" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_ALGAPI -+ select CRYPTO_AES -+ select CRYPTO_AEAD -+ -+config CRYPTO_AES_ARM64_CE_BLK -+ tristate "AES in ECB/CBC/CTR/XTS modes using ARMv8 Crypto Extensions" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_BLKCIPHER -+ select CRYPTO_AES -+ select CRYPTO_ABLK_HELPER -+ -+config CRYPTO_AES_ARM64_NEON_BLK -+ tristate "AES in ECB/CBC/CTR/XTS modes using NEON instructions" -+ depends on ARM64 && KERNEL_MODE_NEON -+ select CRYPTO_BLKCIPHER -+ select CRYPTO_AES -+ select CRYPTO_ABLK_HELPER -+ -+endif -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/Makefile linux-3.14.22/arch/arm64/crypto/Makefile ---- linux-3.14.22.orig/arch/arm64/crypto/Makefile 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/Makefile 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,38 @@ -+# -+# linux/arch/arm64/crypto/Makefile -+# -+# Copyright (C) 2014 Linaro Ltd -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License version 2 as -+# published by the Free Software Foundation. -+# -+ -+obj-$(CONFIG_CRYPTO_SHA1_ARM64_CE) += sha1-ce.o -+sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o -+ -+obj-$(CONFIG_CRYPTO_SHA2_ARM64_CE) += sha2-ce.o -+sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o -+ -+obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o -+ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o -+ -+obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o -+CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto -+ -+obj-$(CONFIG_CRYPTO_AES_ARM64_CE_CCM) += aes-ce-ccm.o -+aes-ce-ccm-y := aes-ce-ccm-glue.o aes-ce-ccm-core.o -+ -+obj-$(CONFIG_CRYPTO_AES_ARM64_CE_BLK) += aes-ce-blk.o -+aes-ce-blk-y := aes-glue-ce.o aes-ce.o -+ -+obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o -+aes-neon-blk-y := aes-glue-neon.o aes-neon.o -+ -+AFLAGS_aes-ce.o := -DINTERLEAVE=2 -DINTERLEAVE_INLINE -+AFLAGS_aes-neon.o := -DINTERLEAVE=4 -+ -+CFLAGS_aes-glue-ce.o := -DUSE_V8_CRYPTO_EXTENSIONS -+ -+$(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE -+ $(call if_changed_dep,cc_o_c) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/sha1-ce-core.S linux-3.14.22/arch/arm64/crypto/sha1-ce-core.S ---- linux-3.14.22.orig/arch/arm64/crypto/sha1-ce-core.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/sha1-ce-core.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,153 @@ -+/* -+ * sha1-ce-core.S - SHA-1 secure hash using ARMv8 Crypto Extensions -+ * -+ * Copyright (C) 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+ .text -+ .arch armv8-a+crypto -+ -+ k0 .req v0 -+ k1 .req v1 -+ k2 .req v2 -+ k3 .req v3 -+ -+ t0 .req v4 -+ t1 .req v5 -+ -+ dga .req q6 -+ dgav .req v6 -+ dgb .req s7 -+ dgbv .req v7 -+ -+ dg0q .req q12 -+ dg0s .req s12 -+ dg0v .req v12 -+ dg1s .req s13 -+ dg1v .req v13 -+ dg2s .req s14 -+ -+ .macro add_only, op, ev, rc, s0, dg1 -+ .ifc \ev, ev -+ add t1.4s, v\s0\().4s, \rc\().4s -+ sha1h dg2s, dg0s -+ .ifnb \dg1 -+ sha1\op dg0q, \dg1, t0.4s -+ .else -+ sha1\op dg0q, dg1s, t0.4s -+ .endif -+ .else -+ .ifnb \s0 -+ add t0.4s, v\s0\().4s, \rc\().4s -+ .endif -+ sha1h dg1s, dg0s -+ sha1\op dg0q, dg2s, t1.4s -+ .endif -+ .endm -+ -+ .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1 -+ sha1su0 v\s0\().4s, v\s1\().4s, v\s2\().4s -+ add_only \op, \ev, \rc, \s1, \dg1 -+ sha1su1 v\s0\().4s, v\s3\().4s -+ .endm -+ -+ /* -+ * The SHA1 round constants -+ */ -+ .align 4 -+.Lsha1_rcon: -+ .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 -+ -+ /* -+ * void sha1_ce_transform(int blocks, u8 const *src, u32 *state, -+ * u8 *head, long bytes) -+ */ -+ENTRY(sha1_ce_transform) -+ /* load round constants */ -+ adr x6, .Lsha1_rcon -+ ld1r {k0.4s}, [x6], #4 -+ ld1r {k1.4s}, [x6], #4 -+ ld1r {k2.4s}, [x6], #4 -+ ld1r {k3.4s}, [x6] -+ -+ /* load state */ -+ ldr dga, [x2] -+ ldr dgb, [x2, #16] -+ -+ /* load partial state (if supplied) */ -+ cbz x3, 0f -+ ld1 {v8.4s-v11.4s}, [x3] -+ b 1f -+ -+ /* load input */ -+0: ld1 {v8.4s-v11.4s}, [x1], #64 -+ sub w0, w0, #1 -+ -+1: -+CPU_LE( rev32 v8.16b, v8.16b ) -+CPU_LE( rev32 v9.16b, v9.16b ) -+CPU_LE( rev32 v10.16b, v10.16b ) -+CPU_LE( rev32 v11.16b, v11.16b ) -+ -+2: add t0.4s, v8.4s, k0.4s -+ mov dg0v.16b, dgav.16b -+ -+ add_update c, ev, k0, 8, 9, 10, 11, dgb -+ add_update c, od, k0, 9, 10, 11, 8 -+ add_update c, ev, k0, 10, 11, 8, 9 -+ add_update c, od, k0, 11, 8, 9, 10 -+ add_update c, ev, k1, 8, 9, 10, 11 -+ -+ add_update p, od, k1, 9, 10, 11, 8 -+ add_update p, ev, k1, 10, 11, 8, 9 -+ add_update p, od, k1, 11, 8, 9, 10 -+ add_update p, ev, k1, 8, 9, 10, 11 -+ add_update p, od, k2, 9, 10, 11, 8 -+ -+ add_update m, ev, k2, 10, 11, 8, 9 -+ add_update m, od, k2, 11, 8, 9, 10 -+ add_update m, ev, k2, 8, 9, 10, 11 -+ add_update m, od, k2, 9, 10, 11, 8 -+ add_update m, ev, k3, 10, 11, 8, 9 -+ -+ add_update p, od, k3, 11, 8, 9, 10 -+ add_only p, ev, k3, 9 -+ add_only p, od, k3, 10 -+ add_only p, ev, k3, 11 -+ add_only p, od -+ -+ /* update state */ -+ add dgbv.2s, dgbv.2s, dg1v.2s -+ add dgav.4s, dgav.4s, dg0v.4s -+ -+ cbnz w0, 0b -+ -+ /* -+ * Final block: add padding and total bit count. -+ * Skip if we have no total byte count in x4. In that case, the input -+ * size was not a round multiple of the block size, and the padding is -+ * handled by the C code. -+ */ -+ cbz x4, 3f -+ movi v9.2d, #0 -+ mov x8, #0x80000000 -+ movi v10.2d, #0 -+ ror x7, x4, #29 // ror(lsl(x4, 3), 32) -+ fmov d8, x8 -+ mov x4, #0 -+ mov v11.d[0], xzr -+ mov v11.d[1], x7 -+ b 2b -+ -+ /* store new state */ -+3: str dga, [x2] -+ str dgb, [x2, #16] -+ ret -+ENDPROC(sha1_ce_transform) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/sha1-ce-glue.c linux-3.14.22/arch/arm64/crypto/sha1-ce-glue.c ---- linux-3.14.22.orig/arch/arm64/crypto/sha1-ce-glue.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/sha1-ce-glue.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,174 @@ -+/* -+ * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions -+ * -+ * Copyright (C) 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+ -+asmlinkage void sha1_ce_transform(int blocks, u8 const *src, u32 *state, -+ u8 *head, long bytes); -+ -+static int sha1_init(struct shash_desc *desc) -+{ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ -+ *sctx = (struct sha1_state){ -+ .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }, -+ }; -+ return 0; -+} -+ -+static int sha1_update(struct shash_desc *desc, const u8 *data, -+ unsigned int len) -+{ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; -+ -+ sctx->count += len; -+ -+ if ((partial + len) >= SHA1_BLOCK_SIZE) { -+ int blocks; -+ -+ if (partial) { -+ int p = SHA1_BLOCK_SIZE - partial; -+ -+ memcpy(sctx->buffer + partial, data, p); -+ data += p; -+ len -= p; -+ } -+ -+ blocks = len / SHA1_BLOCK_SIZE; -+ len %= SHA1_BLOCK_SIZE; -+ -+ kernel_neon_begin_partial(16); -+ sha1_ce_transform(blocks, data, sctx->state, -+ partial ? sctx->buffer : NULL, 0); -+ kernel_neon_end(); -+ -+ data += blocks * SHA1_BLOCK_SIZE; -+ partial = 0; -+ } -+ if (len) -+ memcpy(sctx->buffer + partial, data, len); -+ return 0; -+} -+ -+static int sha1_final(struct shash_desc *desc, u8 *out) -+{ -+ static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; -+ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ __be64 bits = cpu_to_be64(sctx->count << 3); -+ __be32 *dst = (__be32 *)out; -+ int i; -+ -+ u32 padlen = SHA1_BLOCK_SIZE -+ - ((sctx->count + sizeof(bits)) % SHA1_BLOCK_SIZE); -+ -+ sha1_update(desc, padding, padlen); -+ sha1_update(desc, (const u8 *)&bits, sizeof(bits)); -+ -+ for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha1_state){}; -+ return 0; -+} -+ -+static int sha1_finup(struct shash_desc *desc, const u8 *data, -+ unsigned int len, u8 *out) -+{ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ __be32 *dst = (__be32 *)out; -+ int blocks; -+ int i; -+ -+ if (sctx->count || !len || (len % SHA1_BLOCK_SIZE)) { -+ sha1_update(desc, data, len); -+ return sha1_final(desc, out); -+ } -+ -+ /* -+ * Use a fast path if the input is a multiple of 64 bytes. In -+ * this case, there is no need to copy data around, and we can -+ * perform the entire digest calculation in a single invocation -+ * of sha1_ce_transform() -+ */ -+ blocks = len / SHA1_BLOCK_SIZE; -+ -+ kernel_neon_begin_partial(16); -+ sha1_ce_transform(blocks, data, sctx->state, NULL, len); -+ kernel_neon_end(); -+ -+ for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha1_state){}; -+ return 0; -+} -+ -+static int sha1_export(struct shash_desc *desc, void *out) -+{ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ struct sha1_state *dst = out; -+ -+ *dst = *sctx; -+ return 0; -+} -+ -+static int sha1_import(struct shash_desc *desc, const void *in) -+{ -+ struct sha1_state *sctx = shash_desc_ctx(desc); -+ struct sha1_state const *src = in; -+ -+ *sctx = *src; -+ return 0; -+} -+ -+static struct shash_alg alg = { -+ .init = sha1_init, -+ .update = sha1_update, -+ .final = sha1_final, -+ .finup = sha1_finup, -+ .export = sha1_export, -+ .import = sha1_import, -+ .descsize = sizeof(struct sha1_state), -+ .digestsize = SHA1_DIGEST_SIZE, -+ .statesize = sizeof(struct sha1_state), -+ .base = { -+ .cra_name = "sha1", -+ .cra_driver_name = "sha1-ce", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = SHA1_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}; -+ -+static int __init sha1_ce_mod_init(void) -+{ -+ return crypto_register_shash(&alg); -+} -+ -+static void __exit sha1_ce_mod_fini(void) -+{ -+ crypto_unregister_shash(&alg); -+} -+ -+module_cpu_feature_match(SHA1, sha1_ce_mod_init); -+module_exit(sha1_ce_mod_fini); -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/sha2-ce-core.S linux-3.14.22/arch/arm64/crypto/sha2-ce-core.S ---- linux-3.14.22.orig/arch/arm64/crypto/sha2-ce-core.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/sha2-ce-core.S 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,156 @@ -+/* -+ * sha2-ce-core.S - core SHA-224/SHA-256 transform using v8 Crypto Extensions -+ * -+ * Copyright (C) 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+ .text -+ .arch armv8-a+crypto -+ -+ dga .req q20 -+ dgav .req v20 -+ dgb .req q21 -+ dgbv .req v21 -+ -+ t0 .req v22 -+ t1 .req v23 -+ -+ dg0q .req q24 -+ dg0v .req v24 -+ dg1q .req q25 -+ dg1v .req v25 -+ dg2q .req q26 -+ dg2v .req v26 -+ -+ .macro add_only, ev, rc, s0 -+ mov dg2v.16b, dg0v.16b -+ .ifeq \ev -+ add t1.4s, v\s0\().4s, \rc\().4s -+ sha256h dg0q, dg1q, t0.4s -+ sha256h2 dg1q, dg2q, t0.4s -+ .else -+ .ifnb \s0 -+ add t0.4s, v\s0\().4s, \rc\().4s -+ .endif -+ sha256h dg0q, dg1q, t1.4s -+ sha256h2 dg1q, dg2q, t1.4s -+ .endif -+ .endm -+ -+ .macro add_update, ev, rc, s0, s1, s2, s3 -+ sha256su0 v\s0\().4s, v\s1\().4s -+ add_only \ev, \rc, \s1 -+ sha256su1 v\s0\().4s, v\s2\().4s, v\s3\().4s -+ .endm -+ -+ /* -+ * The SHA-256 round constants -+ */ -+ .align 4 -+.Lsha2_rcon: -+ .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 -+ .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 -+ .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 -+ .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 -+ .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc -+ .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da -+ .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 -+ .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 -+ .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 -+ .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 -+ .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 -+ .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 -+ .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 -+ .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 -+ .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 -+ .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -+ -+ /* -+ * void sha2_ce_transform(int blocks, u8 const *src, u32 *state, -+ * u8 *head, long bytes) -+ */ -+ENTRY(sha2_ce_transform) -+ /* load round constants */ -+ adr x8, .Lsha2_rcon -+ ld1 { v0.4s- v3.4s}, [x8], #64 -+ ld1 { v4.4s- v7.4s}, [x8], #64 -+ ld1 { v8.4s-v11.4s}, [x8], #64 -+ ld1 {v12.4s-v15.4s}, [x8] -+ -+ /* load state */ -+ ldp dga, dgb, [x2] -+ -+ /* load partial input (if supplied) */ -+ cbz x3, 0f -+ ld1 {v16.4s-v19.4s}, [x3] -+ b 1f -+ -+ /* load input */ -+0: ld1 {v16.4s-v19.4s}, [x1], #64 -+ sub w0, w0, #1 -+ -+1: -+CPU_LE( rev32 v16.16b, v16.16b ) -+CPU_LE( rev32 v17.16b, v17.16b ) -+CPU_LE( rev32 v18.16b, v18.16b ) -+CPU_LE( rev32 v19.16b, v19.16b ) -+ -+2: add t0.4s, v16.4s, v0.4s -+ mov dg0v.16b, dgav.16b -+ mov dg1v.16b, dgbv.16b -+ -+ add_update 0, v1, 16, 17, 18, 19 -+ add_update 1, v2, 17, 18, 19, 16 -+ add_update 0, v3, 18, 19, 16, 17 -+ add_update 1, v4, 19, 16, 17, 18 -+ -+ add_update 0, v5, 16, 17, 18, 19 -+ add_update 1, v6, 17, 18, 19, 16 -+ add_update 0, v7, 18, 19, 16, 17 -+ add_update 1, v8, 19, 16, 17, 18 -+ -+ add_update 0, v9, 16, 17, 18, 19 -+ add_update 1, v10, 17, 18, 19, 16 -+ add_update 0, v11, 18, 19, 16, 17 -+ add_update 1, v12, 19, 16, 17, 18 -+ -+ add_only 0, v13, 17 -+ add_only 1, v14, 18 -+ add_only 0, v15, 19 -+ add_only 1 -+ -+ /* update state */ -+ add dgav.4s, dgav.4s, dg0v.4s -+ add dgbv.4s, dgbv.4s, dg1v.4s -+ -+ /* handled all input blocks? */ -+ cbnz w0, 0b -+ -+ /* -+ * Final block: add padding and total bit count. -+ * Skip if we have no total byte count in x4. In that case, the input -+ * size was not a round multiple of the block size, and the padding is -+ * handled by the C code. -+ */ -+ cbz x4, 3f -+ movi v17.2d, #0 -+ mov x8, #0x80000000 -+ movi v18.2d, #0 -+ ror x7, x4, #29 // ror(lsl(x4, 3), 32) -+ fmov d16, x8 -+ mov x4, #0 -+ mov v19.d[0], xzr -+ mov v19.d[1], x7 -+ b 2b -+ -+ /* store new state */ -+3: stp dga, dgb, [x2] -+ ret -+ENDPROC(sha2_ce_transform) -diff -Nur linux-3.14.22.orig/arch/arm64/crypto/sha2-ce-glue.c linux-3.14.22/arch/arm64/crypto/sha2-ce-glue.c ---- linux-3.14.22.orig/arch/arm64/crypto/sha2-ce-glue.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/crypto/sha2-ce-glue.c 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,255 @@ -+/* -+ * sha2-ce-glue.c - SHA-224/SHA-256 using ARMv8 Crypto Extensions -+ * -+ * Copyright (C) 2014 Linaro Ltd -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions"); -+MODULE_AUTHOR("Ard Biesheuvel "); -+MODULE_LICENSE("GPL v2"); -+ -+asmlinkage int sha2_ce_transform(int blocks, u8 const *src, u32 *state, -+ u8 *head, long bytes); -+ -+static int sha224_init(struct shash_desc *desc) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ -+ *sctx = (struct sha256_state){ -+ .state = { -+ SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3, -+ SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7, -+ } -+ }; -+ return 0; -+} -+ -+static int sha256_init(struct shash_desc *desc) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ -+ *sctx = (struct sha256_state){ -+ .state = { -+ SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, -+ SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7, -+ } -+ }; -+ return 0; -+} -+ -+static int sha2_update(struct shash_desc *desc, const u8 *data, -+ unsigned int len) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ unsigned int partial = sctx->count % SHA256_BLOCK_SIZE; -+ -+ sctx->count += len; -+ -+ if ((partial + len) >= SHA256_BLOCK_SIZE) { -+ int blocks; -+ -+ if (partial) { -+ int p = SHA256_BLOCK_SIZE - partial; -+ -+ memcpy(sctx->buf + partial, data, p); -+ data += p; -+ len -= p; -+ } -+ -+ blocks = len / SHA256_BLOCK_SIZE; -+ len %= SHA256_BLOCK_SIZE; -+ -+ kernel_neon_begin_partial(28); -+ sha2_ce_transform(blocks, data, sctx->state, -+ partial ? sctx->buf : NULL, 0); -+ kernel_neon_end(); -+ -+ data += blocks * SHA256_BLOCK_SIZE; -+ partial = 0; -+ } -+ if (len) -+ memcpy(sctx->buf + partial, data, len); -+ return 0; -+} -+ -+static void sha2_final(struct shash_desc *desc) -+{ -+ static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, }; -+ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ __be64 bits = cpu_to_be64(sctx->count << 3); -+ u32 padlen = SHA256_BLOCK_SIZE -+ - ((sctx->count + sizeof(bits)) % SHA256_BLOCK_SIZE); -+ -+ sha2_update(desc, padding, padlen); -+ sha2_update(desc, (const u8 *)&bits, sizeof(bits)); -+} -+ -+static int sha224_final(struct shash_desc *desc, u8 *out) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ __be32 *dst = (__be32 *)out; -+ int i; -+ -+ sha2_final(desc); -+ -+ for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha256_state){}; -+ return 0; -+} -+ -+static int sha256_final(struct shash_desc *desc, u8 *out) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ __be32 *dst = (__be32 *)out; -+ int i; -+ -+ sha2_final(desc); -+ -+ for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha256_state){}; -+ return 0; -+} -+ -+static void sha2_finup(struct shash_desc *desc, const u8 *data, -+ unsigned int len) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ int blocks; -+ -+ if (sctx->count || !len || (len % SHA256_BLOCK_SIZE)) { -+ sha2_update(desc, data, len); -+ sha2_final(desc); -+ return; -+ } -+ -+ /* -+ * Use a fast path if the input is a multiple of 64 bytes. In -+ * this case, there is no need to copy data around, and we can -+ * perform the entire digest calculation in a single invocation -+ * of sha2_ce_transform() -+ */ -+ blocks = len / SHA256_BLOCK_SIZE; -+ -+ kernel_neon_begin_partial(28); -+ sha2_ce_transform(blocks, data, sctx->state, NULL, len); -+ kernel_neon_end(); -+ data += blocks * SHA256_BLOCK_SIZE; -+} -+ -+static int sha224_finup(struct shash_desc *desc, const u8 *data, -+ unsigned int len, u8 *out) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ __be32 *dst = (__be32 *)out; -+ int i; -+ -+ sha2_finup(desc, data, len); -+ -+ for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha256_state){}; -+ return 0; -+} -+ -+static int sha256_finup(struct shash_desc *desc, const u8 *data, -+ unsigned int len, u8 *out) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ __be32 *dst = (__be32 *)out; -+ int i; -+ -+ sha2_finup(desc, data, len); -+ -+ for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(__be32); i++) -+ put_unaligned_be32(sctx->state[i], dst++); -+ -+ *sctx = (struct sha256_state){}; -+ return 0; -+} -+ -+static int sha2_export(struct shash_desc *desc, void *out) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ struct sha256_state *dst = out; -+ -+ *dst = *sctx; -+ return 0; -+} -+ -+static int sha2_import(struct shash_desc *desc, const void *in) -+{ -+ struct sha256_state *sctx = shash_desc_ctx(desc); -+ struct sha256_state const *src = in; -+ -+ *sctx = *src; -+ return 0; -+} -+ -+static struct shash_alg algs[] = { { -+ .init = sha224_init, -+ .update = sha2_update, -+ .final = sha224_final, -+ .finup = sha224_finup, -+ .export = sha2_export, -+ .import = sha2_import, -+ .descsize = sizeof(struct sha256_state), -+ .digestsize = SHA224_DIGEST_SIZE, -+ .statesize = sizeof(struct sha256_state), -+ .base = { -+ .cra_name = "sha224", -+ .cra_driver_name = "sha224-ce", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = SHA256_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+}, { -+ .init = sha256_init, -+ .update = sha2_update, -+ .final = sha256_final, -+ .finup = sha256_finup, -+ .export = sha2_export, -+ .import = sha2_import, -+ .descsize = sizeof(struct sha256_state), -+ .digestsize = SHA256_DIGEST_SIZE, -+ .statesize = sizeof(struct sha256_state), -+ .base = { -+ .cra_name = "sha256", -+ .cra_driver_name = "sha256-ce", -+ .cra_priority = 200, -+ .cra_flags = CRYPTO_ALG_TYPE_SHASH, -+ .cra_blocksize = SHA256_BLOCK_SIZE, -+ .cra_module = THIS_MODULE, -+ } -+} }; -+ -+static int __init sha2_ce_mod_init(void) -+{ -+ return crypto_register_shashes(algs, ARRAY_SIZE(algs)); -+} -+ -+static void __exit sha2_ce_mod_fini(void) -+{ -+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); -+} -+ -+module_cpu_feature_match(SHA2, sha2_ce_mod_init); -+module_exit(sha2_ce_mod_fini); -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/bL_switcher.h linux-3.14.22/arch/arm64/include/asm/bL_switcher.h ---- linux-3.14.22.orig/arch/arm64/include/asm/bL_switcher.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/asm/bL_switcher.h 2014-10-22 14:55:49.938220001 -0500 -@@ -0,0 +1,54 @@ -+/* -+ * Based on the stubs for the ARM implementation which is: -+ * -+ * Created by: Nicolas Pitre, April 2012 -+ * Copyright: (C) 2012-2013 Linaro Limited -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef ASM_BL_SWITCHER_H -+#define ASM_BL_SWITCHER_H -+ -+#include -+#include -+ -+typedef void (*bL_switch_completion_handler)(void *cookie); -+ -+static inline int bL_switch_request(unsigned int cpu, -+ unsigned int new_cluster_id) -+{ -+ return -ENOTSUPP; -+} -+ -+/* -+ * Register here to be notified about runtime enabling/disabling of -+ * the switcher. -+ * -+ * The notifier chain is called with the switcher activation lock held: -+ * the switcher will not be enabled or disabled during callbacks. -+ * Callbacks must not call bL_switcher_{get,put}_enabled(). -+ */ -+#define BL_NOTIFY_PRE_ENABLE 0 -+#define BL_NOTIFY_POST_ENABLE 1 -+#define BL_NOTIFY_PRE_DISABLE 2 -+#define BL_NOTIFY_POST_DISABLE 3 -+ -+static inline int bL_switcher_register_notifier(struct notifier_block *nb) -+{ -+ return 0; -+} -+ -+static inline int bL_switcher_unregister_notifier(struct notifier_block *nb) -+{ -+ return 0; -+} -+ -+static inline bool bL_switcher_get_enabled(void) { return false; } -+static inline void bL_switcher_put_enabled(void) { } -+static inline int bL_switcher_trace_trigger(void) { return 0; } -+static inline int bL_switcher_get_logical_index(u32 mpidr) { return -EUNATCH; } -+ -+#endif -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/cacheflush.h linux-3.14.22/arch/arm64/include/asm/cacheflush.h ---- linux-3.14.22.orig/arch/arm64/include/asm/cacheflush.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/cacheflush.h 2014-10-22 14:55:49.938220001 -0500 -@@ -85,6 +85,13 @@ - } - - /* -+ * Cache maintenance functions used by the DMA API. No to be used directly. -+ */ -+extern void __dma_map_area(const void *, size_t, int); -+extern void __dma_unmap_area(const void *, size_t, int); -+extern void __dma_flush_range(const void *, const void *); -+ -+/* - * Copy user data from/to a page which is mapped into a different - * processes address space. Really, we want to allow our "user - * space" model to handle this. -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/compat.h linux-3.14.22/arch/arm64/include/asm/compat.h ---- linux-3.14.22.orig/arch/arm64/include/asm/compat.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/compat.h 2014-10-22 14:55:50.170220001 -0500 -@@ -228,7 +228,7 @@ - return (u32)(unsigned long)uptr; - } - --#define compat_user_stack_pointer() (current_pt_regs()->compat_sp) -+#define compat_user_stack_pointer() (user_stack_pointer(current_pt_regs())) - - static inline void __user *arch_compat_alloc_user_space(long len) - { -@@ -305,11 +305,6 @@ - - #else /* !CONFIG_COMPAT */ - --static inline int is_compat_task(void) --{ -- return 0; --} -- - static inline int is_compat_thread(struct thread_info *thread) - { - return 0; -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/cpufeature.h linux-3.14.22/arch/arm64/include/asm/cpufeature.h ---- linux-3.14.22.orig/arch/arm64/include/asm/cpufeature.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/asm/cpufeature.h 2014-10-22 14:55:50.170220001 -0500 -@@ -0,0 +1,29 @@ -+/* -+ * Copyright (C) 2014 Linaro Ltd. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#ifndef __ASM_CPUFEATURE_H -+#define __ASM_CPUFEATURE_H -+ -+#include -+ -+/* -+ * In the arm64 world (as in the ARM world), elf_hwcap is used both internally -+ * in the kernel and for user space to keep track of which optional features -+ * are supported by the current system. So let's map feature 'x' to HWCAP_x. -+ * Note that HWCAP_x constants are bit fields so we need to take the log. -+ */ -+ -+#define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap)) -+#define cpu_feature(x) ilog2(HWCAP_ ## x) -+ -+static inline bool cpu_have_feature(unsigned int num) -+{ -+ return elf_hwcap & (1UL << num); -+} -+ -+#endif -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/debug-monitors.h linux-3.14.22/arch/arm64/include/asm/debug-monitors.h ---- linux-3.14.22.orig/arch/arm64/include/asm/debug-monitors.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/debug-monitors.h 2014-10-22 14:55:50.170220001 -0500 -@@ -26,6 +26,53 @@ - #define DBG_ESR_EVT_HWWP 0x2 - #define DBG_ESR_EVT_BRK 0x6 - -+/* -+ * Break point instruction encoding -+ */ -+#define BREAK_INSTR_SIZE 4 -+ -+/* -+ * ESR values expected for dynamic and compile time BRK instruction -+ */ -+#define DBG_ESR_VAL_BRK(x) (0xf2000000 | ((x) & 0xfffff)) -+ -+/* -+ * #imm16 values used for BRK instruction generation -+ * Allowed values for kgbd are 0x400 - 0x7ff -+ * 0x400: for dynamic BRK instruction -+ * 0x401: for compile time BRK instruction -+ */ -+#define KGDB_DYN_DGB_BRK_IMM 0x400 -+#define KDBG_COMPILED_DBG_BRK_IMM 0x401 -+ -+/* -+ * BRK instruction encoding -+ * The #imm16 value should be placed at bits[20:5] within BRK ins -+ */ -+#define AARCH64_BREAK_MON 0xd4200000 -+ -+/* -+ * Extract byte from BRK instruction -+ */ -+#define KGDB_DYN_DGB_BRK_INS_BYTE(x) \ -+ ((((AARCH64_BREAK_MON) & 0xffe0001f) >> (x * 8)) & 0xff) -+ -+/* -+ * Extract byte from BRK #imm16 -+ */ -+#define KGBD_DYN_DGB_BRK_IMM_BYTE(x) \ -+ (((((KGDB_DYN_DGB_BRK_IMM) & 0xffff) << 5) >> (x * 8)) & 0xff) -+ -+#define KGDB_DYN_DGB_BRK_BYTE(x) \ -+ (KGDB_DYN_DGB_BRK_INS_BYTE(x) | KGBD_DYN_DGB_BRK_IMM_BYTE(x)) -+ -+#define KGDB_DYN_BRK_INS_BYTE0 KGDB_DYN_DGB_BRK_BYTE(0) -+#define KGDB_DYN_BRK_INS_BYTE1 KGDB_DYN_DGB_BRK_BYTE(1) -+#define KGDB_DYN_BRK_INS_BYTE2 KGDB_DYN_DGB_BRK_BYTE(2) -+#define KGDB_DYN_BRK_INS_BYTE3 KGDB_DYN_DGB_BRK_BYTE(3) -+ -+#define CACHE_FLUSH_IS_SAFE 1 -+ - enum debug_el { - DBG_ACTIVE_EL0 = 0, - DBG_ACTIVE_EL1, -@@ -43,23 +90,6 @@ - #ifndef __ASSEMBLY__ - struct task_struct; - --#define local_dbg_save(flags) \ -- do { \ -- typecheck(unsigned long, flags); \ -- asm volatile( \ -- "mrs %0, daif // local_dbg_save\n" \ -- "msr daifset, #8" \ -- : "=r" (flags) : : "memory"); \ -- } while (0) -- --#define local_dbg_restore(flags) \ -- do { \ -- typecheck(unsigned long, flags); \ -- asm volatile( \ -- "msr daif, %0 // local_dbg_restore\n" \ -- : : "r" (flags) : "memory"); \ -- } while (0) -- - #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ - - #define DBG_HOOK_HANDLED 0 -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/dma-mapping.h linux-3.14.22/arch/arm64/include/asm/dma-mapping.h ---- linux-3.14.22.orig/arch/arm64/include/asm/dma-mapping.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/dma-mapping.h 2014-10-22 14:55:50.170220001 -0500 -@@ -28,6 +28,8 @@ - - #define DMA_ERROR_CODE (~(dma_addr_t)0) - extern struct dma_map_ops *dma_ops; -+extern struct dma_map_ops coherent_swiotlb_dma_ops; -+extern struct dma_map_ops noncoherent_swiotlb_dma_ops; - - static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) - { -@@ -45,6 +47,11 @@ - return __generic_dma_ops(dev); - } - -+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) -+{ -+ dev->archdata.dma_ops = ops; -+} -+ - #include - - static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr) -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/ftrace.h linux-3.14.22/arch/arm64/include/asm/ftrace.h ---- linux-3.14.22.orig/arch/arm64/include/asm/ftrace.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/asm/ftrace.h 2014-10-22 14:55:50.170220001 -0500 -@@ -0,0 +1,59 @@ -+/* -+ * arch/arm64/include/asm/ftrace.h -+ * -+ * Copyright (C) 2013 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#ifndef __ASM_FTRACE_H -+#define __ASM_FTRACE_H -+ -+#include -+ -+#define MCOUNT_ADDR ((unsigned long)_mcount) -+#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE -+ -+#ifndef __ASSEMBLY__ -+#include -+ -+extern void _mcount(unsigned long); -+extern void *return_address(unsigned int); -+ -+struct dyn_arch_ftrace { -+ /* No extra data needed for arm64 */ -+}; -+ -+extern unsigned long ftrace_graph_call; -+ -+static inline unsigned long ftrace_call_adjust(unsigned long addr) -+{ -+ /* -+ * addr is the address of the mcount call instruction. -+ * recordmcount does the necessary offset calculation. -+ */ -+ return addr; -+} -+ -+#define ftrace_return_address(n) return_address(n) -+ -+/* -+ * Because AArch32 mode does not share the same syscall table with AArch64, -+ * tracing compat syscalls may result in reporting bogus syscalls or even -+ * hang-up, so just do not trace them. -+ * See kernel/trace/trace_syscalls.c -+ * -+ * x86 code says: -+ * If the user realy wants these, then they should use the -+ * raw syscall tracepoints with filtering. -+ */ -+#define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS -+static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) -+{ -+ return is_compat_task(); -+} -+#endif /* ifndef __ASSEMBLY__ */ -+ -+#endif /* __ASM_FTRACE_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/hwcap.h linux-3.14.22/arch/arm64/include/asm/hwcap.h ---- linux-3.14.22.orig/arch/arm64/include/asm/hwcap.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/hwcap.h 2014-10-22 14:55:50.170220001 -0500 -@@ -32,6 +32,12 @@ - #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) - #define COMPAT_HWCAP_EVTSTRM (1 << 21) - -+#define COMPAT_HWCAP2_AES (1 << 0) -+#define COMPAT_HWCAP2_PMULL (1 << 1) -+#define COMPAT_HWCAP2_SHA1 (1 << 2) -+#define COMPAT_HWCAP2_SHA2 (1 << 3) -+#define COMPAT_HWCAP2_CRC32 (1 << 4) -+ - #ifndef __ASSEMBLY__ - /* - * This yields a mask that user programs can use to figure out what -@@ -41,7 +47,8 @@ - - #ifdef CONFIG_COMPAT - #define COMPAT_ELF_HWCAP (compat_elf_hwcap) --extern unsigned int compat_elf_hwcap; -+#define COMPAT_ELF_HWCAP2 (compat_elf_hwcap2) -+extern unsigned int compat_elf_hwcap, compat_elf_hwcap2; - #endif - - extern unsigned long elf_hwcap; -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/insn.h linux-3.14.22/arch/arm64/include/asm/insn.h ---- linux-3.14.22.orig/arch/arm64/include/asm/insn.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/insn.h 2014-10-22 14:55:50.174220001 -0500 -@@ -16,11 +16,14 @@ - */ - #ifndef __ASM_INSN_H - #define __ASM_INSN_H -+ - #include - - /* A64 instructions are always 32 bits. */ - #define AARCH64_INSN_SIZE 4 - -+#ifndef __ASSEMBLY__ -+ - /* - * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a - * Section C3.1 "A64 instruction index by encoding": -@@ -105,4 +108,6 @@ - int aarch64_insn_patch_text_sync(void *addrs[], u32 insns[], int cnt); - int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt); - -+#endif /* __ASSEMBLY__ */ -+ - #endif /* __ASM_INSN_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/irqflags.h linux-3.14.22/arch/arm64/include/asm/irqflags.h ---- linux-3.14.22.orig/arch/arm64/include/asm/irqflags.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/irqflags.h 2014-10-22 14:55:50.174220001 -0500 -@@ -90,5 +90,28 @@ - return flags & PSR_I_BIT; - } - -+/* -+ * save and restore debug state -+ */ -+#define local_dbg_save(flags) \ -+ do { \ -+ typecheck(unsigned long, flags); \ -+ asm volatile( \ -+ "mrs %0, daif // local_dbg_save\n" \ -+ "msr daifset, #8" \ -+ : "=r" (flags) : : "memory"); \ -+ } while (0) -+ -+#define local_dbg_restore(flags) \ -+ do { \ -+ typecheck(unsigned long, flags); \ -+ asm volatile( \ -+ "msr daif, %0 // local_dbg_restore\n" \ -+ : : "r" (flags) : "memory"); \ -+ } while (0) -+ -+#define local_dbg_enable() asm("msr daifclr, #8" : : : "memory") -+#define local_dbg_disable() asm("msr daifset, #8" : : : "memory") -+ - #endif - #endif -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/Kbuild linux-3.14.22/arch/arm64/include/asm/Kbuild ---- linux-3.14.22.orig/arch/arm64/include/asm/Kbuild 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/Kbuild 2014-10-22 14:55:50.174220001 -0500 -@@ -35,6 +35,7 @@ - generic-y += sembuf.h - generic-y += serial.h - generic-y += shmbuf.h -+generic-y += simd.h - generic-y += sizes.h - generic-y += socket.h - generic-y += sockios.h -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/kgdb.h linux-3.14.22/arch/arm64/include/asm/kgdb.h ---- linux-3.14.22.orig/arch/arm64/include/asm/kgdb.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/asm/kgdb.h 2014-10-22 14:55:50.174220001 -0500 -@@ -0,0 +1,84 @@ -+/* -+ * AArch64 KGDB support -+ * -+ * Based on arch/arm/include/kgdb.h -+ * -+ * Copyright (C) 2013 Cavium Inc. -+ * Author: Vijaya Kumar K -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#ifndef __ARM_KGDB_H -+#define __ARM_KGDB_H -+ -+#include -+#include -+ -+#ifndef __ASSEMBLY__ -+ -+static inline void arch_kgdb_breakpoint(void) -+{ -+ asm ("brk %0" : : "I" (KDBG_COMPILED_DBG_BRK_IMM)); -+} -+ -+extern void kgdb_handle_bus_error(void); -+extern int kgdb_fault_expected; -+ -+#endif /* !__ASSEMBLY__ */ -+ -+/* -+ * gdb is expecting the following registers layout. -+ * -+ * General purpose regs: -+ * r0-r30: 64 bit -+ * sp,pc : 64 bit -+ * pstate : 64 bit -+ * Total: 34 -+ * FPU regs: -+ * f0-f31: 128 bit -+ * Total: 32 -+ * Extra regs -+ * fpsr & fpcr: 32 bit -+ * Total: 2 -+ * -+ */ -+ -+#define _GP_REGS 34 -+#define _FP_REGS 32 -+#define _EXTRA_REGS 2 -+/* -+ * general purpose registers size in bytes. -+ * pstate is only 4 bytes. subtract 4 bytes -+ */ -+#define GP_REG_BYTES (_GP_REGS * 8) -+#define DBG_MAX_REG_NUM (_GP_REGS + _FP_REGS + _EXTRA_REGS) -+ -+/* -+ * Size of I/O buffer for gdb packet. -+ * considering to hold all register contents, size is set -+ */ -+ -+#define BUFMAX 2048 -+ -+/* -+ * Number of bytes required for gdb_regs buffer. -+ * _GP_REGS: 8 bytes, _FP_REGS: 16 bytes and _EXTRA_REGS: 4 bytes each -+ * GDB fails to connect for size beyond this with error -+ * "'g' packet reply is too long" -+ */ -+ -+#define NUMREGBYTES ((_GP_REGS * 8) + (_FP_REGS * 16) + \ -+ (_EXTRA_REGS * 4)) -+ -+#endif /* __ASM_KGDB_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/page.h linux-3.14.22/arch/arm64/include/asm/page.h ---- linux-3.14.22.orig/arch/arm64/include/asm/page.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/page.h 2014-10-22 14:55:50.174220001 -0500 -@@ -31,6 +31,15 @@ - /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ - #define __HAVE_ARCH_GATE_AREA 1 - -+/* -+ * The idmap and swapper page tables need some space reserved in the kernel -+ * image. The idmap only requires a pgd and a next level table to (section) map -+ * the kernel, while the swapper also maps the FDT and requires an additional -+ * table to map an early UART. See __create_page_tables for more information. -+ */ -+#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) -+#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) -+ - #ifndef __ASSEMBLY__ - - #ifdef CONFIG_ARM64_64K_PAGES -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/pgtable.h linux-3.14.22/arch/arm64/include/asm/pgtable.h ---- linux-3.14.22.orig/arch/arm64/include/asm/pgtable.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/pgtable.h 2014-10-22 14:55:50.174220001 -0500 -@@ -227,36 +227,36 @@ - - #define __HAVE_ARCH_PTE_SPECIAL - --/* -- * Software PMD bits for THP -- */ -+static inline pte_t pmd_pte(pmd_t pmd) -+{ -+ return __pte(pmd_val(pmd)); -+} - --#define PMD_SECT_DIRTY (_AT(pmdval_t, 1) << 55) --#define PMD_SECT_SPLITTING (_AT(pmdval_t, 1) << 57) -+static inline pmd_t pte_pmd(pte_t pte) -+{ -+ return __pmd(pte_val(pte)); -+} - - /* - * THP definitions. - */ --#define pmd_young(pmd) (pmd_val(pmd) & PMD_SECT_AF) -- --#define __HAVE_ARCH_PMD_WRITE --#define pmd_write(pmd) (!(pmd_val(pmd) & PMD_SECT_RDONLY)) - - #ifdef CONFIG_TRANSPARENT_HUGEPAGE - #define pmd_trans_huge(pmd) (pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT)) --#define pmd_trans_splitting(pmd) (pmd_val(pmd) & PMD_SECT_SPLITTING) -+#define pmd_trans_splitting(pmd) pte_special(pmd_pte(pmd)) - #endif - --#define PMD_BIT_FUNC(fn,op) \ --static inline pmd_t pmd_##fn(pmd_t pmd) { pmd_val(pmd) op; return pmd; } -+#define pmd_young(pmd) pte_young(pmd_pte(pmd)) -+#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd))) -+#define pmd_mksplitting(pmd) pte_pmd(pte_mkspecial(pmd_pte(pmd))) -+#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd))) -+#define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) -+#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) -+#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) -+#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) &= ~PMD_TYPE_MASK)) - --PMD_BIT_FUNC(wrprotect, |= PMD_SECT_RDONLY); --PMD_BIT_FUNC(mkold, &= ~PMD_SECT_AF); --PMD_BIT_FUNC(mksplitting, |= PMD_SECT_SPLITTING); --PMD_BIT_FUNC(mkwrite, &= ~PMD_SECT_RDONLY); --PMD_BIT_FUNC(mkdirty, |= PMD_SECT_DIRTY); --PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF); --PMD_BIT_FUNC(mknotpresent, &= ~PMD_TYPE_MASK); -+#define __HAVE_ARCH_PMD_WRITE -+#define pmd_write(pmd) pte_write(pmd_pte(pmd)) - - #define pmd_mkhuge(pmd) (__pmd(pmd_val(pmd) & ~PMD_TABLE_BIT)) - -@@ -266,16 +266,7 @@ - - #define pmd_page(pmd) pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK)) - --static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) --{ -- const pmdval_t mask = PMD_SECT_USER | PMD_SECT_PXN | PMD_SECT_UXN | -- PMD_SECT_RDONLY | PMD_SECT_PROT_NONE | -- PMD_SECT_VALID; -- pmd_val(pmd) = (pmd_val(pmd) & ~mask) | (pgprot_val(newprot) & mask); -- return pmd; --} -- --#define set_pmd_at(mm, addr, pmdp, pmd) set_pmd(pmdp, pmd) -+#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) - - static inline int has_transparent_hugepage(void) - { -@@ -383,12 +374,14 @@ - return pte; - } - -+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) -+{ -+ return pte_pmd(pte_modify(pmd_pte(pmd), newprot)); -+} -+ - extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; - extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; - --#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) --#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) -- - /* - * Encode and decode a swap entry: - * bits 0-1: present (must be zero) -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/ptrace.h linux-3.14.22/arch/arm64/include/asm/ptrace.h ---- linux-3.14.22.orig/arch/arm64/include/asm/ptrace.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/ptrace.h 2014-10-22 14:55:50.174220001 -0500 -@@ -68,6 +68,7 @@ - - /* Architecturally defined mapping between AArch32 and AArch64 registers */ - #define compat_usr(x) regs[(x)] -+#define compat_fp regs[11] - #define compat_sp regs[13] - #define compat_lr regs[14] - #define compat_sp_hyp regs[15] -@@ -132,7 +133,12 @@ - (!((regs)->pstate & PSR_F_BIT)) - - #define user_stack_pointer(regs) \ -- ((regs)->sp) -+ (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp) -+ -+static inline unsigned long regs_return_value(struct pt_regs *regs) -+{ -+ return regs->regs[0]; -+} - - /* - * Are the current registers suitable for user mode? (used to maintain -@@ -164,7 +170,7 @@ - return 0; - } - --#define instruction_pointer(regs) (regs)->pc -+#define instruction_pointer(regs) ((unsigned long)(regs)->pc) - - #ifdef CONFIG_SMP - extern unsigned long profile_pc(struct pt_regs *regs); -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/syscall.h linux-3.14.22/arch/arm64/include/asm/syscall.h ---- linux-3.14.22.orig/arch/arm64/include/asm/syscall.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/syscall.h 2014-10-22 14:55:50.178220001 -0500 -@@ -18,6 +18,7 @@ - - #include - -+extern const void *sys_call_table[]; - - static inline int syscall_get_nr(struct task_struct *task, - struct pt_regs *regs) -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/thread_info.h linux-3.14.22/arch/arm64/include/asm/thread_info.h ---- linux-3.14.22.orig/arch/arm64/include/asm/thread_info.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/thread_info.h 2014-10-22 14:55:50.178220001 -0500 -@@ -91,6 +91,9 @@ - /* - * thread information flags: - * TIF_SYSCALL_TRACE - syscall trace active -+ * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace -+ * TIF_SYSCALL_AUDIT - syscall auditing -+ * TIF_SECOMP - syscall secure computing - * TIF_SIGPENDING - signal pending - * TIF_NEED_RESCHED - rescheduling necessary - * TIF_NOTIFY_RESUME - callback before returning to user -@@ -101,6 +104,9 @@ - #define TIF_NEED_RESCHED 1 - #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ - #define TIF_SYSCALL_TRACE 8 -+#define TIF_SYSCALL_AUDIT 9 -+#define TIF_SYSCALL_TRACEPOINT 10 -+#define TIF_SECCOMP 11 - #define TIF_POLLING_NRFLAG 16 - #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ - #define TIF_FREEZE 19 -@@ -112,10 +118,17 @@ - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) - #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) -+#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -+#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -+#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) -+#define _TIF_SECCOMP (1 << TIF_SECCOMP) - #define _TIF_32BIT (1 << TIF_32BIT) - - #define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \ - _TIF_NOTIFY_RESUME) - -+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ -+ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP) -+ - #endif /* __KERNEL__ */ - #endif /* __ASM_THREAD_INFO_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/topology.h linux-3.14.22/arch/arm64/include/asm/topology.h ---- linux-3.14.22.orig/arch/arm64/include/asm/topology.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/asm/topology.h 2014-10-22 14:55:50.178220001 -0500 -@@ -0,0 +1,70 @@ -+#ifndef __ASM_TOPOLOGY_H -+#define __ASM_TOPOLOGY_H -+ -+#ifdef CONFIG_SMP -+ -+#include -+ -+struct cpu_topology { -+ int thread_id; -+ int core_id; -+ int cluster_id; -+ cpumask_t thread_sibling; -+ cpumask_t core_sibling; -+}; -+ -+extern struct cpu_topology cpu_topology[NR_CPUS]; -+ -+#define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id) -+#define topology_core_id(cpu) (cpu_topology[cpu].core_id) -+#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) -+#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) -+ -+#define mc_capable() (cpu_topology[0].cluster_id != -1) -+#define smt_capable() (cpu_topology[0].thread_id != -1) -+ -+void init_cpu_topology(void); -+void store_cpu_topology(unsigned int cpuid); -+const struct cpumask *cpu_coregroup_mask(int cpu); -+ -+#ifdef CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE -+/* Common values for CPUs */ -+#ifndef SD_CPU_INIT -+#define SD_CPU_INIT (struct sched_domain) { \ -+ .min_interval = 1, \ -+ .max_interval = 4, \ -+ .busy_factor = 64, \ -+ .imbalance_pct = 125, \ -+ .cache_nice_tries = 1, \ -+ .busy_idx = 2, \ -+ .idle_idx = 1, \ -+ .newidle_idx = 0, \ -+ .wake_idx = 0, \ -+ .forkexec_idx = 0, \ -+ \ -+ .flags = 0*SD_LOAD_BALANCE \ -+ | 1*SD_BALANCE_NEWIDLE \ -+ | 1*SD_BALANCE_EXEC \ -+ | 1*SD_BALANCE_FORK \ -+ | 0*SD_BALANCE_WAKE \ -+ | 1*SD_WAKE_AFFINE \ -+ | 0*SD_SHARE_CPUPOWER \ -+ | 0*SD_SHARE_PKG_RESOURCES \ -+ | 0*SD_SERIALIZE \ -+ , \ -+ .last_balance = jiffies, \ -+ .balance_interval = 1, \ -+} -+#endif -+#endif /* CONFIG_DISABLE_CPU_SCHED_DOMAIN_BALANCE */ -+ -+#else -+ -+static inline void init_cpu_topology(void) { } -+static inline void store_cpu_topology(unsigned int cpuid) { } -+ -+#endif -+ -+#include -+ -+#endif /* _ASM_ARM_TOPOLOGY_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/include/asm/unistd.h linux-3.14.22/arch/arm64/include/asm/unistd.h ---- linux-3.14.22.orig/arch/arm64/include/asm/unistd.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/asm/unistd.h 2014-10-22 14:55:50.178220001 -0500 -@@ -28,3 +28,5 @@ - #endif - #define __ARCH_WANT_SYS_CLONE - #include -+ -+#define NR_syscalls (__NR_syscalls) -diff -Nur linux-3.14.22.orig/arch/arm64/include/uapi/asm/Kbuild linux-3.14.22/arch/arm64/include/uapi/asm/Kbuild ---- linux-3.14.22.orig/arch/arm64/include/uapi/asm/Kbuild 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/include/uapi/asm/Kbuild 2014-10-22 14:55:50.178220001 -0500 -@@ -9,6 +9,7 @@ - header-y += fcntl.h - header-y += hwcap.h - header-y += kvm_para.h -+header-y += perf_regs.h - header-y += param.h - header-y += ptrace.h - header-y += setup.h -diff -Nur linux-3.14.22.orig/arch/arm64/include/uapi/asm/perf_regs.h linux-3.14.22/arch/arm64/include/uapi/asm/perf_regs.h ---- linux-3.14.22.orig/arch/arm64/include/uapi/asm/perf_regs.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/include/uapi/asm/perf_regs.h 2014-10-22 14:55:50.178220001 -0500 -@@ -0,0 +1,40 @@ -+#ifndef _ASM_ARM64_PERF_REGS_H -+#define _ASM_ARM64_PERF_REGS_H -+ -+enum perf_event_arm_regs { -+ PERF_REG_ARM64_X0, -+ PERF_REG_ARM64_X1, -+ PERF_REG_ARM64_X2, -+ PERF_REG_ARM64_X3, -+ PERF_REG_ARM64_X4, -+ PERF_REG_ARM64_X5, -+ PERF_REG_ARM64_X6, -+ PERF_REG_ARM64_X7, -+ PERF_REG_ARM64_X8, -+ PERF_REG_ARM64_X9, -+ PERF_REG_ARM64_X10, -+ PERF_REG_ARM64_X11, -+ PERF_REG_ARM64_X12, -+ PERF_REG_ARM64_X13, -+ PERF_REG_ARM64_X14, -+ PERF_REG_ARM64_X15, -+ PERF_REG_ARM64_X16, -+ PERF_REG_ARM64_X17, -+ PERF_REG_ARM64_X18, -+ PERF_REG_ARM64_X19, -+ PERF_REG_ARM64_X20, -+ PERF_REG_ARM64_X21, -+ PERF_REG_ARM64_X22, -+ PERF_REG_ARM64_X23, -+ PERF_REG_ARM64_X24, -+ PERF_REG_ARM64_X25, -+ PERF_REG_ARM64_X26, -+ PERF_REG_ARM64_X27, -+ PERF_REG_ARM64_X28, -+ PERF_REG_ARM64_X29, -+ PERF_REG_ARM64_LR, -+ PERF_REG_ARM64_SP, -+ PERF_REG_ARM64_PC, -+ PERF_REG_ARM64_MAX, -+}; -+#endif /* _ASM_ARM64_PERF_REGS_H */ -diff -Nur linux-3.14.22.orig/arch/arm64/Kconfig linux-3.14.22/arch/arm64/Kconfig ---- linux-3.14.22.orig/arch/arm64/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/Kconfig 2014-10-22 14:55:50.178220001 -0500 -@@ -4,6 +4,7 @@ - select ARCH_USE_CMPXCHG_LOCKREF - select ARCH_SUPPORTS_ATOMIC_RMW - select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST -+ select ARCH_HAS_OPP - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARCH_WANT_COMPAT_IPC_PARSE_VERSION - select ARCH_WANT_FRAME_POINTERS -@@ -17,6 +18,7 @@ - select DCACHE_WORD_ACCESS - select GENERIC_CLOCKEVENTS - select GENERIC_CLOCKEVENTS_BROADCAST if SMP -+ select GENERIC_CPU_AUTOPROBE - select GENERIC_IOMAP - select GENERIC_IRQ_PROBE - select GENERIC_IRQ_SHOW -@@ -27,18 +29,27 @@ - select GENERIC_TIME_VSYSCALL - select HARDIRQS_SW_RESEND - select HAVE_ARCH_JUMP_LABEL -+ select HAVE_ARCH_KGDB - select HAVE_ARCH_TRACEHOOK -+ select HAVE_C_RECORDMCOUNT - select HAVE_DEBUG_BUGVERBOSE - select HAVE_DEBUG_KMEMLEAK - select HAVE_DMA_API_DEBUG - select HAVE_DMA_ATTRS - select HAVE_DMA_CONTIGUOUS - select HAVE_EFFICIENT_UNALIGNED_ACCESS -+ select HAVE_DYNAMIC_FTRACE -+ select HAVE_FTRACE_MCOUNT_RECORD -+ select HAVE_FUNCTION_TRACER -+ select HAVE_FUNCTION_GRAPH_TRACER - select HAVE_GENERIC_DMA_COHERENT - select HAVE_HW_BREAKPOINT if PERF_EVENTS - select HAVE_MEMBLOCK - select HAVE_PATA_PLATFORM - select HAVE_PERF_EVENTS -+ select HAVE_PERF_REGS -+ select HAVE_PERF_USER_STACK_DUMP -+ select HAVE_SYSCALL_TRACEPOINTS - select IRQ_DOMAIN - select MODULES_USE_ELF_RELA - select NO_BOOTMEM -@@ -86,7 +97,7 @@ - config GENERIC_CALIBRATE_DELAY - def_bool y - --config ZONE_DMA32 -+config ZONE_DMA - def_bool y - - config ARCH_DMA_ADDR_T_64BIT -@@ -165,6 +176,134 @@ - - If you don't know what to do here, say N. - -+config SCHED_MC -+ bool "Multi-core scheduler support" -+ depends on SMP -+ help -+ Multi-core scheduler support improves the CPU scheduler's decision -+ making when dealing with multi-core CPU chips at a cost of slightly -+ increased overhead in some places. If unsure say N here. -+ -+config SCHED_SMT -+ bool "SMT scheduler support" -+ depends on SMP -+ help -+ Improves the CPU scheduler's decision making when dealing with -+ MultiThreading at a cost of slightly increased overhead in some -+ places. If unsure say N here. -+ -+config SCHED_MC -+ bool "Multi-core scheduler support" -+ depends on ARM_CPU_TOPOLOGY -+ help -+ Multi-core scheduler support improves the CPU scheduler's decision -+ making when dealing with multi-core CPU chips at a cost of slightly -+ increased overhead in some places. If unsure say N here. -+ -+config SCHED_SMT -+ bool "SMT scheduler support" -+ depends on ARM_CPU_TOPOLOGY -+ help -+ Improves the CPU scheduler's decision making when dealing with -+ MultiThreading at a cost of slightly increased overhead in some -+ places. If unsure say N here. -+ -+config DISABLE_CPU_SCHED_DOMAIN_BALANCE -+ bool "(EXPERIMENTAL) Disable CPU level scheduler load-balancing" -+ help -+ Disables scheduler load-balancing at CPU sched domain level. -+ -+config SCHED_HMP -+ bool "(EXPERIMENTAL) Heterogenous multiprocessor scheduling" -+ depends on DISABLE_CPU_SCHED_DOMAIN_BALANCE && SCHED_MC && FAIR_GROUP_SCHED && !SCHED_AUTOGROUP -+ help -+ Experimental scheduler optimizations for heterogeneous platforms. -+ Attempts to introspectively select task affinity to optimize power -+ and performance. Basic support for multiple (>2) cpu types is in place, -+ but it has only been tested with two types of cpus. -+ There is currently no support for migration of task groups, hence -+ !SCHED_AUTOGROUP. Furthermore, normal load-balancing must be disabled -+ between cpus of different type (DISABLE_CPU_SCHED_DOMAIN_BALANCE). -+ -+config SCHED_HMP_PRIO_FILTER -+ bool "(EXPERIMENTAL) Filter HMP migrations by task priority" -+ depends on SCHED_HMP -+ help -+ Enables task priority based HMP migration filter. Any task with -+ a NICE value above the threshold will always be on low-power cpus -+ with less compute capacity. -+ -+config SCHED_HMP_PRIO_FILTER_VAL -+ int "NICE priority threshold" -+ default 5 -+ depends on SCHED_HMP_PRIO_FILTER -+ -+config HMP_FAST_CPU_MASK -+ string "HMP scheduler fast CPU mask" -+ depends on SCHED_HMP -+ help -+ Leave empty to use device tree information. -+ Specify the cpuids of the fast CPUs in the system as a list string, -+ e.g. cpuid 0+1 should be specified as 0-1. -+ -+config HMP_SLOW_CPU_MASK -+ string "HMP scheduler slow CPU mask" -+ depends on SCHED_HMP -+ help -+ Leave empty to use device tree information. -+ Specify the cpuids of the slow CPUs in the system as a list string, -+ e.g. cpuid 0+1 should be specified as 0-1. -+ -+config HMP_VARIABLE_SCALE -+ bool "Allows changing the load tracking scale through sysfs" -+ depends on SCHED_HMP -+ help -+ When turned on, this option exports the thresholds and load average -+ period value for the load tracking patches through sysfs. -+ The values can be modified to change the rate of load accumulation -+ and the thresholds used for HMP migration. -+ The load_avg_period_ms is the time in ms to reach a load average of -+ 0.5 for an idle task of 0 load average ratio that start a busy loop. -+ The up_threshold and down_threshold is the value to go to a faster -+ CPU or to go back to a slower cpu. -+ The {up,down}_threshold are devided by 1024 before being compared -+ to the load average. -+ For examples, with load_avg_period_ms = 128 and up_threshold = 512, -+ a running task with a load of 0 will be migrated to a bigger CPU after -+ 128ms, because after 128ms its load_avg_ratio is 0.5 and the real -+ up_threshold is 0.5. -+ This patch has the same behavior as changing the Y of the load -+ average computation to -+ (1002/1024)^(LOAD_AVG_PERIOD/load_avg_period_ms) -+ but it remove intermadiate overflows in computation. -+ -+config HMP_FREQUENCY_INVARIANT_SCALE -+ bool "(EXPERIMENTAL) Frequency-Invariant Tracked Load for HMP" -+ depends on HMP_VARIABLE_SCALE && CPU_FREQ -+ help -+ Scales the current load contribution in line with the frequency -+ of the CPU that the task was executed on. -+ In this version, we use a simple linear scale derived from the -+ maximum frequency reported by CPUFreq. -+ Restricting tracked load to be scaled by the CPU's frequency -+ represents the consumption of possible compute capacity -+ (rather than consumption of actual instantaneous capacity as -+ normal) and allows the HMP migration's simple threshold -+ migration strategy to interact more predictably with CPUFreq's -+ asynchronous compute capacity changes. -+ -+config SCHED_HMP_LITTLE_PACKING -+ bool "Small task packing for HMP" -+ depends on SCHED_HMP -+ default n -+ help -+ Allows the HMP Scheduler to pack small tasks into CPUs in the -+ smallest HMP domain. -+ Controlled by two sysfs files in sys/kernel/hmp. -+ packing_enable: 1 to enable, 0 to disable packing. Default 1. -+ packing_limit: runqueue load ratio where a RQ is considered -+ to be full. Default is NICE_0_LOAD * 9/8. -+ - config NR_CPUS - int "Maximum number of CPUs (2-32)" - range 2 32 -@@ -317,5 +456,8 @@ - source "security/Kconfig" - - source "crypto/Kconfig" -+if CRYPTO -+source "arch/arm64/crypto/Kconfig" -+endif - - source "lib/Kconfig" -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/arm64ksyms.c linux-3.14.22/arch/arm64/kernel/arm64ksyms.c ---- linux-3.14.22.orig/arch/arm64/kernel/arm64ksyms.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/arm64ksyms.c 2014-10-22 14:55:50.182220001 -0500 -@@ -56,3 +56,7 @@ - EXPORT_SYMBOL(test_and_clear_bit); - EXPORT_SYMBOL(change_bit); - EXPORT_SYMBOL(test_and_change_bit); -+ -+#ifdef CONFIG_FUNCTION_TRACER -+EXPORT_SYMBOL(_mcount); -+#endif -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/debug-monitors.c linux-3.14.22/arch/arm64/kernel/debug-monitors.c ---- linux-3.14.22.orig/arch/arm64/kernel/debug-monitors.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/debug-monitors.c 2014-10-22 14:55:50.182220001 -0500 -@@ -138,6 +138,7 @@ - { - asm volatile("msr oslar_el1, %0" : : "r" (0)); - isb(); -+ local_dbg_enable(); - } - - static int os_lock_notify(struct notifier_block *self, -@@ -314,9 +315,6 @@ - if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED) - return 0; - -- pr_warn("unexpected brk exception at %lx, esr=0x%x\n", -- (long)instruction_pointer(regs), esr); -- - if (!user_mode(regs)) - return -EFAULT; - -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/entry-ftrace.S linux-3.14.22/arch/arm64/kernel/entry-ftrace.S ---- linux-3.14.22.orig/arch/arm64/kernel/entry-ftrace.S 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/entry-ftrace.S 2014-10-22 14:55:50.182220001 -0500 -@@ -0,0 +1,218 @@ -+/* -+ * arch/arm64/kernel/entry-ftrace.S -+ * -+ * Copyright (C) 2013 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+ -+/* -+ * Gcc with -pg will put the following code in the beginning of each function: -+ * mov x0, x30 -+ * bl _mcount -+ * [function's body ...] -+ * "bl _mcount" may be replaced to "bl ftrace_caller" or NOP if dynamic -+ * ftrace is enabled. -+ * -+ * Please note that x0 as an argument will not be used here because we can -+ * get lr(x30) of instrumented function at any time by winding up call stack -+ * as long as the kernel is compiled without -fomit-frame-pointer. -+ * (or CONFIG_FRAME_POINTER, this is forced on arm64) -+ * -+ * stack layout after mcount_enter in _mcount(): -+ * -+ * current sp/fp => 0:+-----+ -+ * in _mcount() | x29 | -> instrumented function's fp -+ * +-----+ -+ * | x30 | -> _mcount()'s lr (= instrumented function's pc) -+ * old sp => +16:+-----+ -+ * when instrumented | | -+ * function calls | ... | -+ * _mcount() | | -+ * | | -+ * instrumented => +xx:+-----+ -+ * function's fp | x29 | -> parent's fp -+ * +-----+ -+ * | x30 | -> instrumented function's lr (= parent's pc) -+ * +-----+ -+ * | ... | -+ */ -+ -+ .macro mcount_enter -+ stp x29, x30, [sp, #-16]! -+ mov x29, sp -+ .endm -+ -+ .macro mcount_exit -+ ldp x29, x30, [sp], #16 -+ ret -+ .endm -+ -+ .macro mcount_adjust_addr rd, rn -+ sub \rd, \rn, #AARCH64_INSN_SIZE -+ .endm -+ -+ /* for instrumented function's parent */ -+ .macro mcount_get_parent_fp reg -+ ldr \reg, [x29] -+ ldr \reg, [\reg] -+ .endm -+ -+ /* for instrumented function */ -+ .macro mcount_get_pc0 reg -+ mcount_adjust_addr \reg, x30 -+ .endm -+ -+ .macro mcount_get_pc reg -+ ldr \reg, [x29, #8] -+ mcount_adjust_addr \reg, \reg -+ .endm -+ -+ .macro mcount_get_lr reg -+ ldr \reg, [x29] -+ ldr \reg, [\reg, #8] -+ mcount_adjust_addr \reg, \reg -+ .endm -+ -+ .macro mcount_get_lr_addr reg -+ ldr \reg, [x29] -+ add \reg, \reg, #8 -+ .endm -+ -+#ifndef CONFIG_DYNAMIC_FTRACE -+/* -+ * void _mcount(unsigned long return_address) -+ * @return_address: return address to instrumented function -+ * -+ * This function makes calls, if enabled, to: -+ * - tracer function to probe instrumented function's entry, -+ * - ftrace_graph_caller to set up an exit hook -+ */ -+ENTRY(_mcount) -+#ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST -+ ldr x0, =ftrace_trace_stop -+ ldr x0, [x0] // if ftrace_trace_stop -+ ret // return; -+#endif -+ mcount_enter -+ -+ ldr x0, =ftrace_trace_function -+ ldr x2, [x0] -+ adr x0, ftrace_stub -+ cmp x0, x2 // if (ftrace_trace_function -+ b.eq skip_ftrace_call // != ftrace_stub) { -+ -+ mcount_get_pc x0 // function's pc -+ mcount_get_lr x1 // function's lr (= parent's pc) -+ blr x2 // (*ftrace_trace_function)(pc, lr); -+ -+#ifndef CONFIG_FUNCTION_GRAPH_TRACER -+skip_ftrace_call: // return; -+ mcount_exit // } -+#else -+ mcount_exit // return; -+ // } -+skip_ftrace_call: -+ ldr x1, =ftrace_graph_return -+ ldr x2, [x1] // if ((ftrace_graph_return -+ cmp x0, x2 // != ftrace_stub) -+ b.ne ftrace_graph_caller -+ -+ ldr x1, =ftrace_graph_entry // || (ftrace_graph_entry -+ ldr x2, [x1] // != ftrace_graph_entry_stub)) -+ ldr x0, =ftrace_graph_entry_stub -+ cmp x0, x2 -+ b.ne ftrace_graph_caller // ftrace_graph_caller(); -+ -+ mcount_exit -+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -+ENDPROC(_mcount) -+ -+#else /* CONFIG_DYNAMIC_FTRACE */ -+/* -+ * _mcount() is used to build the kernel with -pg option, but all the branch -+ * instructions to _mcount() are replaced to NOP initially at kernel start up, -+ * and later on, NOP to branch to ftrace_caller() when enabled or branch to -+ * NOP when disabled per-function base. -+ */ -+ENTRY(_mcount) -+ ret -+ENDPROC(_mcount) -+ -+/* -+ * void ftrace_caller(unsigned long return_address) -+ * @return_address: return address to instrumented function -+ * -+ * This function is a counterpart of _mcount() in 'static' ftrace, and -+ * makes calls to: -+ * - tracer function to probe instrumented function's entry, -+ * - ftrace_graph_caller to set up an exit hook -+ */ -+ENTRY(ftrace_caller) -+ mcount_enter -+ -+ mcount_get_pc0 x0 // function's pc -+ mcount_get_lr x1 // function's lr -+ -+ .global ftrace_call -+ftrace_call: // tracer(pc, lr); -+ nop // This will be replaced with "bl xxx" -+ // where xxx can be any kind of tracer. -+ -+#ifdef CONFIG_FUNCTION_GRAPH_TRACER -+ .global ftrace_graph_call -+ftrace_graph_call: // ftrace_graph_caller(); -+ nop // If enabled, this will be replaced -+ // "b ftrace_graph_caller" -+#endif -+ -+ mcount_exit -+ENDPROC(ftrace_caller) -+#endif /* CONFIG_DYNAMIC_FTRACE */ -+ -+ENTRY(ftrace_stub) -+ ret -+ENDPROC(ftrace_stub) -+ -+#ifdef CONFIG_FUNCTION_GRAPH_TRACER -+/* -+ * void ftrace_graph_caller(void) -+ * -+ * Called from _mcount() or ftrace_caller() when function_graph tracer is -+ * selected. -+ * This function w/ prepare_ftrace_return() fakes link register's value on -+ * the call stack in order to intercept instrumented function's return path -+ * and run return_to_handler() later on its exit. -+ */ -+ENTRY(ftrace_graph_caller) -+ mcount_get_lr_addr x0 // pointer to function's saved lr -+ mcount_get_pc x1 // function's pc -+ mcount_get_parent_fp x2 // parent's fp -+ bl prepare_ftrace_return // prepare_ftrace_return(&lr, pc, fp) -+ -+ mcount_exit -+ENDPROC(ftrace_graph_caller) -+ -+/* -+ * void return_to_handler(void) -+ * -+ * Run ftrace_return_to_handler() before going back to parent. -+ * @fp is checked against the value passed by ftrace_graph_caller() -+ * only when CONFIG_FUNCTION_GRAPH_FP_TEST is enabled. -+ */ -+ENTRY(return_to_handler) -+ str x0, [sp, #-16]! -+ mov x0, x29 // parent's fp -+ bl ftrace_return_to_handler// addr = ftrace_return_to_hander(fp); -+ mov x30, x0 // restore the original return address -+ ldr x0, [sp], #16 -+ ret -+END(return_to_handler) -+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/entry.S linux-3.14.22/arch/arm64/kernel/entry.S ---- linux-3.14.22.orig/arch/arm64/kernel/entry.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/entry.S 2014-10-22 14:55:50.182220001 -0500 -@@ -630,8 +630,9 @@ - enable_irq - - get_thread_info tsk -- ldr x16, [tsk, #TI_FLAGS] // check for syscall tracing -- tbnz x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls? -+ ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks -+ tst x16, #_TIF_SYSCALL_WORK -+ b.ne __sys_trace - adr lr, ret_fast_syscall // return address - cmp scno, sc_nr // check upper syscall limit - b.hs ni_sys -@@ -647,9 +648,8 @@ - * switches, and waiting for our parent to respond. - */ - __sys_trace: -- mov x1, sp -- mov w0, #0 // trace entry -- bl syscall_trace -+ mov x0, sp -+ bl syscall_trace_enter - adr lr, __sys_trace_return // return address - uxtw scno, w0 // syscall number (possibly new) - mov x1, sp // pointer to regs -@@ -664,9 +664,8 @@ - - __sys_trace_return: - str x0, [sp] // save returned x0 -- mov x1, sp -- mov w0, #1 // trace exit -- bl syscall_trace -+ mov x0, sp -+ bl syscall_trace_exit - b ret_to_user - - /* -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/ftrace.c linux-3.14.22/arch/arm64/kernel/ftrace.c ---- linux-3.14.22.orig/arch/arm64/kernel/ftrace.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/ftrace.c 2014-10-22 14:55:50.182220001 -0500 -@@ -0,0 +1,177 @@ -+/* -+ * arch/arm64/kernel/ftrace.c -+ * -+ * Copyright (C) 2013 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifdef CONFIG_DYNAMIC_FTRACE -+/* -+ * Replace a single instruction, which may be a branch or NOP. -+ * If @validate == true, a replaced instruction is checked against 'old'. -+ */ -+static int ftrace_modify_code(unsigned long pc, u32 old, u32 new, -+ bool validate) -+{ -+ u32 replaced; -+ -+ /* -+ * Note: -+ * Due to modules and __init, code can disappear and change, -+ * we need to protect against faulting as well as code changing. -+ * We do this by aarch64_insn_*() which use the probe_kernel_*(). -+ * -+ * No lock is held here because all the modifications are run -+ * through stop_machine(). -+ */ -+ if (validate) { -+ if (aarch64_insn_read((void *)pc, &replaced)) -+ return -EFAULT; -+ -+ if (replaced != old) -+ return -EINVAL; -+ } -+ if (aarch64_insn_patch_text_nosync((void *)pc, new)) -+ return -EPERM; -+ -+ return 0; -+} -+ -+/* -+ * Replace tracer function in ftrace_caller() -+ */ -+int ftrace_update_ftrace_func(ftrace_func_t func) -+{ -+ unsigned long pc; -+ u32 new; -+ -+ pc = (unsigned long)&ftrace_call; -+ new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, true); -+ -+ return ftrace_modify_code(pc, 0, new, false); -+} -+ -+/* -+ * Turn on the call to ftrace_caller() in instrumented function -+ */ -+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) -+{ -+ unsigned long pc = rec->ip; -+ u32 old, new; -+ -+ old = aarch64_insn_gen_nop(); -+ new = aarch64_insn_gen_branch_imm(pc, addr, true); -+ -+ return ftrace_modify_code(pc, old, new, true); -+} -+ -+/* -+ * Turn off the call to ftrace_caller() in instrumented function -+ */ -+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, -+ unsigned long addr) -+{ -+ unsigned long pc = rec->ip; -+ u32 old, new; -+ -+ old = aarch64_insn_gen_branch_imm(pc, addr, true); -+ new = aarch64_insn_gen_nop(); -+ -+ return ftrace_modify_code(pc, old, new, true); -+} -+ -+int __init ftrace_dyn_arch_init(void *data) -+{ -+ *(unsigned long *)data = 0; -+ return 0; -+} -+#endif /* CONFIG_DYNAMIC_FTRACE */ -+ -+#ifdef CONFIG_FUNCTION_GRAPH_TRACER -+/* -+ * function_graph tracer expects ftrace_return_to_handler() to be called -+ * on the way back to parent. For this purpose, this function is called -+ * in _mcount() or ftrace_caller() to replace return address (*parent) on -+ * the call stack to return_to_handler. -+ * -+ * Note that @frame_pointer is used only for sanity check later. -+ */ -+void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, -+ unsigned long frame_pointer) -+{ -+ unsigned long return_hooker = (unsigned long)&return_to_handler; -+ unsigned long old; -+ struct ftrace_graph_ent trace; -+ int err; -+ -+ if (unlikely(atomic_read(¤t->tracing_graph_pause))) -+ return; -+ -+ /* -+ * Note: -+ * No protection against faulting at *parent, which may be seen -+ * on other archs. It's unlikely on AArch64. -+ */ -+ old = *parent; -+ *parent = return_hooker; -+ -+ trace.func = self_addr; -+ trace.depth = current->curr_ret_stack + 1; -+ -+ /* Only trace if the calling function expects to */ -+ if (!ftrace_graph_entry(&trace)) { -+ *parent = old; -+ return; -+ } -+ -+ err = ftrace_push_return_trace(old, self_addr, &trace.depth, -+ frame_pointer); -+ if (err == -EBUSY) { -+ *parent = old; -+ return; -+ } -+} -+ -+#ifdef CONFIG_DYNAMIC_FTRACE -+/* -+ * Turn on/off the call to ftrace_graph_caller() in ftrace_caller() -+ * depending on @enable. -+ */ -+static int ftrace_modify_graph_caller(bool enable) -+{ -+ unsigned long pc = (unsigned long)&ftrace_graph_call; -+ u32 branch, nop; -+ -+ branch = aarch64_insn_gen_branch_imm(pc, -+ (unsigned long)ftrace_graph_caller, false); -+ nop = aarch64_insn_gen_nop(); -+ -+ if (enable) -+ return ftrace_modify_code(pc, nop, branch, true); -+ else -+ return ftrace_modify_code(pc, branch, nop, true); -+} -+ -+int ftrace_enable_ftrace_graph_caller(void) -+{ -+ return ftrace_modify_graph_caller(true); -+} -+ -+int ftrace_disable_ftrace_graph_caller(void) -+{ -+ return ftrace_modify_graph_caller(false); -+} -+#endif /* CONFIG_DYNAMIC_FTRACE */ -+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/head.S linux-3.14.22/arch/arm64/kernel/head.S ---- linux-3.14.22.orig/arch/arm64/kernel/head.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/head.S 2014-10-22 14:55:50.182220001 -0500 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -34,29 +35,17 @@ - #include - #include - --/* -- * swapper_pg_dir is the virtual address of the initial page table. We place -- * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has -- * 2 pages and is placed below swapper_pg_dir. -- */ - #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) - - #if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000 - #error KERNEL_RAM_VADDR must start at 0xXXX80000 - #endif - --#define SWAPPER_DIR_SIZE (3 * PAGE_SIZE) --#define IDMAP_DIR_SIZE (2 * PAGE_SIZE) -- -- .globl swapper_pg_dir -- .equ swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE -- -- .globl idmap_pg_dir -- .equ idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE -- -- .macro pgtbl, ttb0, ttb1, phys -- add \ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE -- sub \ttb0, \ttb1, #IDMAP_DIR_SIZE -+ .macro pgtbl, ttb0, ttb1, virt_to_phys -+ ldr \ttb1, =swapper_pg_dir -+ ldr \ttb0, =idmap_pg_dir -+ add \ttb1, \ttb1, \virt_to_phys -+ add \ttb0, \ttb0, \virt_to_phys - .endm - - #ifdef CONFIG_ARM64_64K_PAGES -@@ -229,7 +218,11 @@ - cmp w20, #BOOT_CPU_MODE_EL2 - b.ne 1f - add x1, x1, #4 --1: str w20, [x1] // This CPU has booted in EL1 -+1: dc cvac, x1 // Clean potentially dirty cache line -+ dsb sy -+ str w20, [x1] // This CPU has booted in EL1 -+ dc civac, x1 // Clean&invalidate potentially stale cache line -+ dsb sy - ret - ENDPROC(set_cpu_boot_mode_flag) - -@@ -240,8 +233,9 @@ - * This is not in .bss, because we set it sufficiently early that the boot-time - * zeroing of .bss would clobber it. - */ -- .pushsection .data -+ .pushsection .data..cacheline_aligned - ENTRY(__boot_cpu_mode) -+ .align L1_CACHE_SHIFT - .long BOOT_CPU_MODE_EL2 - .long 0 - .popsection -@@ -298,7 +292,7 @@ - mov x23, x0 // x23=current cpu_table - cbz x23, __error_p // invalid processor (x23=0)? - -- pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1 -+ pgtbl x25, x26, x28 // x25=TTBR0, x26=TTBR1 - ldr x12, [x23, #CPU_INFO_SETUP] - add x12, x12, x28 // __virt_to_phys - blr x12 // initialise processor -@@ -340,8 +334,13 @@ - * x27 = *virtual* address to jump to upon completion - * - * other registers depend on the function called upon completion -+ * -+ * We align the entire function to the smallest power of two larger than it to -+ * ensure it fits within a single block map entry. Otherwise were PHYS_OFFSET -+ * close to the end of a 512MB or 1GB block we might require an additional -+ * table to map the entire function. - */ -- .align 6 -+ .align 4 - __turn_mmu_on: - msr sctlr_el1, x0 - isb -@@ -384,26 +383,18 @@ - * Preserves: tbl, flags - * Corrupts: phys, start, end, pstate - */ -- .macro create_block_map, tbl, flags, phys, start, end, idmap=0 -+ .macro create_block_map, tbl, flags, phys, start, end - lsr \phys, \phys, #BLOCK_SHIFT -- .if \idmap -- and \start, \phys, #PTRS_PER_PTE - 1 // table index -- .else - lsr \start, \start, #BLOCK_SHIFT - and \start, \start, #PTRS_PER_PTE - 1 // table index -- .endif - orr \phys, \flags, \phys, lsl #BLOCK_SHIFT // table entry -- .ifnc \start,\end - lsr \end, \end, #BLOCK_SHIFT - and \end, \end, #PTRS_PER_PTE - 1 // table end index -- .endif - 9999: str \phys, [\tbl, \start, lsl #3] // store the entry -- .ifnc \start,\end - add \start, \start, #1 // next entry - add \phys, \phys, #BLOCK_SIZE // next block - cmp \start, \end - b.ls 9999b -- .endif - .endm - - /* -@@ -415,7 +406,16 @@ - * - UART mapping if CONFIG_EARLY_PRINTK is enabled (TTBR1) - */ - __create_page_tables: -- pgtbl x25, x26, x24 // idmap_pg_dir and swapper_pg_dir addresses -+ pgtbl x25, x26, x28 // idmap_pg_dir and swapper_pg_dir addresses -+ mov x27, lr -+ -+ /* -+ * Invalidate the idmap and swapper page tables to avoid potential -+ * dirty cache lines being evicted. -+ */ -+ mov x0, x25 -+ add x1, x26, #SWAPPER_DIR_SIZE -+ bl __inval_cache_range - - /* - * Clear the idmap and swapper page tables. -@@ -435,9 +435,13 @@ - * Create the identity mapping. - */ - add x0, x25, #PAGE_SIZE // section table address -- adr x3, __turn_mmu_on // virtual/physical address -+ ldr x3, =KERNEL_START -+ add x3, x3, x28 // __pa(KERNEL_START) - create_pgd_entry x25, x0, x3, x5, x6 -- create_block_map x0, x7, x3, x5, x5, idmap=1 -+ ldr x6, =KERNEL_END -+ mov x5, x3 // __pa(KERNEL_START) -+ add x6, x6, x28 // __pa(KERNEL_END) -+ create_block_map x0, x7, x3, x5, x6 - - /* - * Map the kernel image (starting with PHYS_OFFSET). -@@ -445,7 +449,7 @@ - add x0, x26, #PAGE_SIZE // section table address - mov x5, #PAGE_OFFSET - create_pgd_entry x26, x0, x5, x3, x6 -- ldr x6, =KERNEL_END - 1 -+ ldr x6, =KERNEL_END - mov x3, x24 // phys offset - create_block_map x0, x7, x3, x5, x6 - -@@ -474,6 +478,17 @@ - add x0, x26, #2 * PAGE_SIZE // section table address - create_pgd_entry x26, x0, x5, x6, x7 - #endif -+ -+ /* -+ * Since the page tables have been populated with non-cacheable -+ * accesses (MMU disabled), invalidate the idmap and swapper page -+ * tables again to remove any speculatively loaded cache lines. -+ */ -+ mov x0, x25 -+ add x1, x26, #SWAPPER_DIR_SIZE -+ bl __inval_cache_range -+ -+ mov lr, x27 - ret - ENDPROC(__create_page_tables) - .ltorg -@@ -483,7 +498,7 @@ - __switch_data: - .quad __mmap_switched - .quad __bss_start // x6 -- .quad _end // x7 -+ .quad __bss_stop // x7 - .quad processor_id // x4 - .quad __fdt_pointer // x5 - .quad memstart_addr // x6 -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/hw_breakpoint.c linux-3.14.22/arch/arm64/kernel/hw_breakpoint.c ---- linux-3.14.22.orig/arch/arm64/kernel/hw_breakpoint.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/hw_breakpoint.c 2014-10-22 14:55:50.182220001 -0500 -@@ -20,6 +20,7 @@ - - #define pr_fmt(fmt) "hw-breakpoint: " fmt - -+#include - #include - #include - #include -@@ -27,7 +28,6 @@ - #include - #include - --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/kgdb.c linux-3.14.22/arch/arm64/kernel/kgdb.c ---- linux-3.14.22.orig/arch/arm64/kernel/kgdb.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/kgdb.c 2014-10-22 14:55:50.182220001 -0500 -@@ -0,0 +1,336 @@ -+/* -+ * AArch64 KGDB support -+ * -+ * Based on arch/arm/kernel/kgdb.c -+ * -+ * Copyright (C) 2013 Cavium Inc. -+ * Author: Vijaya Kumar K -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+ -+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { -+ { "x0", 8, offsetof(struct pt_regs, regs[0])}, -+ { "x1", 8, offsetof(struct pt_regs, regs[1])}, -+ { "x2", 8, offsetof(struct pt_regs, regs[2])}, -+ { "x3", 8, offsetof(struct pt_regs, regs[3])}, -+ { "x4", 8, offsetof(struct pt_regs, regs[4])}, -+ { "x5", 8, offsetof(struct pt_regs, regs[5])}, -+ { "x6", 8, offsetof(struct pt_regs, regs[6])}, -+ { "x7", 8, offsetof(struct pt_regs, regs[7])}, -+ { "x8", 8, offsetof(struct pt_regs, regs[8])}, -+ { "x9", 8, offsetof(struct pt_regs, regs[9])}, -+ { "x10", 8, offsetof(struct pt_regs, regs[10])}, -+ { "x11", 8, offsetof(struct pt_regs, regs[11])}, -+ { "x12", 8, offsetof(struct pt_regs, regs[12])}, -+ { "x13", 8, offsetof(struct pt_regs, regs[13])}, -+ { "x14", 8, offsetof(struct pt_regs, regs[14])}, -+ { "x15", 8, offsetof(struct pt_regs, regs[15])}, -+ { "x16", 8, offsetof(struct pt_regs, regs[16])}, -+ { "x17", 8, offsetof(struct pt_regs, regs[17])}, -+ { "x18", 8, offsetof(struct pt_regs, regs[18])}, -+ { "x19", 8, offsetof(struct pt_regs, regs[19])}, -+ { "x20", 8, offsetof(struct pt_regs, regs[20])}, -+ { "x21", 8, offsetof(struct pt_regs, regs[21])}, -+ { "x22", 8, offsetof(struct pt_regs, regs[22])}, -+ { "x23", 8, offsetof(struct pt_regs, regs[23])}, -+ { "x24", 8, offsetof(struct pt_regs, regs[24])}, -+ { "x25", 8, offsetof(struct pt_regs, regs[25])}, -+ { "x26", 8, offsetof(struct pt_regs, regs[26])}, -+ { "x27", 8, offsetof(struct pt_regs, regs[27])}, -+ { "x28", 8, offsetof(struct pt_regs, regs[28])}, -+ { "x29", 8, offsetof(struct pt_regs, regs[29])}, -+ { "x30", 8, offsetof(struct pt_regs, regs[30])}, -+ { "sp", 8, offsetof(struct pt_regs, sp)}, -+ { "pc", 8, offsetof(struct pt_regs, pc)}, -+ { "pstate", 8, offsetof(struct pt_regs, pstate)}, -+ { "v0", 16, -1 }, -+ { "v1", 16, -1 }, -+ { "v2", 16, -1 }, -+ { "v3", 16, -1 }, -+ { "v4", 16, -1 }, -+ { "v5", 16, -1 }, -+ { "v6", 16, -1 }, -+ { "v7", 16, -1 }, -+ { "v8", 16, -1 }, -+ { "v9", 16, -1 }, -+ { "v10", 16, -1 }, -+ { "v11", 16, -1 }, -+ { "v12", 16, -1 }, -+ { "v13", 16, -1 }, -+ { "v14", 16, -1 }, -+ { "v15", 16, -1 }, -+ { "v16", 16, -1 }, -+ { "v17", 16, -1 }, -+ { "v18", 16, -1 }, -+ { "v19", 16, -1 }, -+ { "v20", 16, -1 }, -+ { "v21", 16, -1 }, -+ { "v22", 16, -1 }, -+ { "v23", 16, -1 }, -+ { "v24", 16, -1 }, -+ { "v25", 16, -1 }, -+ { "v26", 16, -1 }, -+ { "v27", 16, -1 }, -+ { "v28", 16, -1 }, -+ { "v29", 16, -1 }, -+ { "v30", 16, -1 }, -+ { "v31", 16, -1 }, -+ { "fpsr", 4, -1 }, -+ { "fpcr", 4, -1 }, -+}; -+ -+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) -+{ -+ if (regno >= DBG_MAX_REG_NUM || regno < 0) -+ return NULL; -+ -+ if (dbg_reg_def[regno].offset != -1) -+ memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, -+ dbg_reg_def[regno].size); -+ else -+ memset(mem, 0, dbg_reg_def[regno].size); -+ return dbg_reg_def[regno].name; -+} -+ -+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) -+{ -+ if (regno >= DBG_MAX_REG_NUM || regno < 0) -+ return -EINVAL; -+ -+ if (dbg_reg_def[regno].offset != -1) -+ memcpy((void *)regs + dbg_reg_def[regno].offset, mem, -+ dbg_reg_def[regno].size); -+ return 0; -+} -+ -+void -+sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) -+{ -+ struct pt_regs *thread_regs; -+ -+ /* Initialize to zero */ -+ memset((char *)gdb_regs, 0, NUMREGBYTES); -+ thread_regs = task_pt_regs(task); -+ memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES); -+} -+ -+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) -+{ -+ regs->pc = pc; -+} -+ -+static int compiled_break; -+ -+static void kgdb_arch_update_addr(struct pt_regs *regs, -+ char *remcom_in_buffer) -+{ -+ unsigned long addr; -+ char *ptr; -+ -+ ptr = &remcom_in_buffer[1]; -+ if (kgdb_hex2long(&ptr, &addr)) -+ kgdb_arch_set_pc(regs, addr); -+ else if (compiled_break == 1) -+ kgdb_arch_set_pc(regs, regs->pc + 4); -+ -+ compiled_break = 0; -+} -+ -+int kgdb_arch_handle_exception(int exception_vector, int signo, -+ int err_code, char *remcom_in_buffer, -+ char *remcom_out_buffer, -+ struct pt_regs *linux_regs) -+{ -+ int err; -+ -+ switch (remcom_in_buffer[0]) { -+ case 'D': -+ case 'k': -+ /* -+ * Packet D (Detach), k (kill). No special handling -+ * is required here. Handle same as c packet. -+ */ -+ case 'c': -+ /* -+ * Packet c (Continue) to continue executing. -+ * Set pc to required address. -+ * Try to read optional parameter and set pc. -+ * If this was a compiled breakpoint, we need to move -+ * to the next instruction else we will just breakpoint -+ * over and over again. -+ */ -+ kgdb_arch_update_addr(linux_regs, remcom_in_buffer); -+ atomic_set(&kgdb_cpu_doing_single_step, -1); -+ kgdb_single_step = 0; -+ -+ /* -+ * Received continue command, disable single step -+ */ -+ if (kernel_active_single_step()) -+ kernel_disable_single_step(); -+ -+ err = 0; -+ break; -+ case 's': -+ /* -+ * Update step address value with address passed -+ * with step packet. -+ * On debug exception return PC is copied to ELR -+ * So just update PC. -+ * If no step address is passed, resume from the address -+ * pointed by PC. Do not update PC -+ */ -+ kgdb_arch_update_addr(linux_regs, remcom_in_buffer); -+ atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); -+ kgdb_single_step = 1; -+ -+ /* -+ * Enable single step handling -+ */ -+ if (!kernel_active_single_step()) -+ kernel_enable_single_step(linux_regs); -+ err = 0; -+ break; -+ default: -+ err = -1; -+ } -+ return err; -+} -+ -+static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) -+{ -+ kgdb_handle_exception(1, SIGTRAP, 0, regs); -+ return 0; -+} -+ -+static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) -+{ -+ compiled_break = 1; -+ kgdb_handle_exception(1, SIGTRAP, 0, regs); -+ -+ return 0; -+} -+ -+static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) -+{ -+ kgdb_handle_exception(1, SIGTRAP, 0, regs); -+ return 0; -+} -+ -+static struct break_hook kgdb_brkpt_hook = { -+ .esr_mask = 0xffffffff, -+ .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM), -+ .fn = kgdb_brk_fn -+}; -+ -+static struct break_hook kgdb_compiled_brkpt_hook = { -+ .esr_mask = 0xffffffff, -+ .esr_val = DBG_ESR_VAL_BRK(KDBG_COMPILED_DBG_BRK_IMM), -+ .fn = kgdb_compiled_brk_fn -+}; -+ -+static struct step_hook kgdb_step_hook = { -+ .fn = kgdb_step_brk_fn -+}; -+ -+static void kgdb_call_nmi_hook(void *ignored) -+{ -+ kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); -+} -+ -+void kgdb_roundup_cpus(unsigned long flags) -+{ -+ local_irq_enable(); -+ smp_call_function(kgdb_call_nmi_hook, NULL, 0); -+ local_irq_disable(); -+} -+ -+static int __kgdb_notify(struct die_args *args, unsigned long cmd) -+{ -+ struct pt_regs *regs = args->regs; -+ -+ if (kgdb_handle_exception(1, args->signr, cmd, regs)) -+ return NOTIFY_DONE; -+ return NOTIFY_STOP; -+} -+ -+static int -+kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) -+{ -+ unsigned long flags; -+ int ret; -+ -+ local_irq_save(flags); -+ ret = __kgdb_notify(ptr, cmd); -+ local_irq_restore(flags); -+ -+ return ret; -+} -+ -+static struct notifier_block kgdb_notifier = { -+ .notifier_call = kgdb_notify, -+ /* -+ * Want to be lowest priority -+ */ -+ .priority = -INT_MAX, -+}; -+ -+/* -+ * kgdb_arch_init - Perform any architecture specific initalization. -+ * This function will handle the initalization of any architecture -+ * specific callbacks. -+ */ -+int kgdb_arch_init(void) -+{ -+ int ret = register_die_notifier(&kgdb_notifier); -+ -+ if (ret != 0) -+ return ret; -+ -+ register_break_hook(&kgdb_brkpt_hook); -+ register_break_hook(&kgdb_compiled_brkpt_hook); -+ register_step_hook(&kgdb_step_hook); -+ return 0; -+} -+ -+/* -+ * kgdb_arch_exit - Perform any architecture specific uninitalization. -+ * This function will handle the uninitalization of any architecture -+ * specific callbacks, for dynamic registration and unregistration. -+ */ -+void kgdb_arch_exit(void) -+{ -+ unregister_break_hook(&kgdb_brkpt_hook); -+ unregister_break_hook(&kgdb_compiled_brkpt_hook); -+ unregister_step_hook(&kgdb_step_hook); -+ unregister_die_notifier(&kgdb_notifier); -+} -+ -+/* -+ * ARM instructions are always in LE. -+ * Break instruction is encoded in LE format -+ */ -+struct kgdb_arch arch_kgdb_ops = { -+ .gdb_bpt_instr = { -+ KGDB_DYN_BRK_INS_BYTE0, -+ KGDB_DYN_BRK_INS_BYTE1, -+ KGDB_DYN_BRK_INS_BYTE2, -+ KGDB_DYN_BRK_INS_BYTE3, -+ } -+}; -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/Makefile linux-3.14.22/arch/arm64/kernel/Makefile ---- linux-3.14.22.orig/arch/arm64/kernel/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/Makefile 2014-10-22 14:55:50.182220001 -0500 -@@ -5,21 +5,29 @@ - CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) - AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) - -+CFLAGS_REMOVE_ftrace.o = -pg -+CFLAGS_REMOVE_insn.o = -pg -+CFLAGS_REMOVE_return_address.o = -pg -+ - # Object file lists. - arm64-obj-y := cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ - entry-fpsimd.o process.o ptrace.o setup.o signal.o \ - sys.o stacktrace.o time.o traps.o io.o vdso.o \ -- hyp-stub.o psci.o cpu_ops.o insn.o -+ hyp-stub.o psci.o cpu_ops.o insn.o return_address.o - - arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ - sys_compat.o -+arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o - arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o -+arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o topology.o - arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o -+arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o - arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o --arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o -+arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o - arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o - arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o -+arm64-obj-$(CONFIG_KGDB) += kgdb.o - - obj-y += $(arm64-obj-y) vdso/ - obj-m += $(arm64-obj-m) -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/perf_event.c linux-3.14.22/arch/arm64/kernel/perf_event.c ---- linux-3.14.22.orig/arch/arm64/kernel/perf_event.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/perf_event.c 2014-10-22 14:55:50.182220001 -0500 -@@ -1348,8 +1348,8 @@ - * Callchain handling code. - */ - struct frame_tail { -- struct frame_tail __user *fp; -- unsigned long lr; -+ struct frame_tail __user *fp; -+ unsigned long lr; - } __attribute__((packed)); - - /* -@@ -1386,22 +1386,84 @@ - return buftail.fp; - } - -+#ifdef CONFIG_COMPAT -+/* -+ * The registers we're interested in are at the end of the variable -+ * length saved register structure. The fp points at the end of this -+ * structure so the address of this struct is: -+ * (struct compat_frame_tail *)(xxx->fp)-1 -+ * -+ * This code has been adapted from the ARM OProfile support. -+ */ -+struct compat_frame_tail { -+ compat_uptr_t fp; /* a (struct compat_frame_tail *) in compat mode */ -+ u32 sp; -+ u32 lr; -+} __attribute__((packed)); -+ -+static struct compat_frame_tail __user * -+compat_user_backtrace(struct compat_frame_tail __user *tail, -+ struct perf_callchain_entry *entry) -+{ -+ struct compat_frame_tail buftail; -+ unsigned long err; -+ -+ /* Also check accessibility of one struct frame_tail beyond */ -+ if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) -+ return NULL; -+ -+ pagefault_disable(); -+ err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); -+ pagefault_enable(); -+ -+ if (err) -+ return NULL; -+ -+ perf_callchain_store(entry, buftail.lr); -+ -+ /* -+ * Frame pointers should strictly progress back up the stack -+ * (towards higher addresses). -+ */ -+ if (tail + 1 >= (struct compat_frame_tail __user *) -+ compat_ptr(buftail.fp)) -+ return NULL; -+ -+ return (struct compat_frame_tail __user *)compat_ptr(buftail.fp) - 1; -+} -+#endif /* CONFIG_COMPAT */ -+ - void perf_callchain_user(struct perf_callchain_entry *entry, - struct pt_regs *regs) - { -- struct frame_tail __user *tail; -- - if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { - /* We don't support guest os callchain now */ - return; - } - - perf_callchain_store(entry, regs->pc); -- tail = (struct frame_tail __user *)regs->regs[29]; - -- while (entry->nr < PERF_MAX_STACK_DEPTH && -- tail && !((unsigned long)tail & 0xf)) -- tail = user_backtrace(tail, entry); -+ if (!compat_user_mode(regs)) { -+ /* AARCH64 mode */ -+ struct frame_tail __user *tail; -+ -+ tail = (struct frame_tail __user *)regs->regs[29]; -+ -+ while (entry->nr < PERF_MAX_STACK_DEPTH && -+ tail && !((unsigned long)tail & 0xf)) -+ tail = user_backtrace(tail, entry); -+ } else { -+#ifdef CONFIG_COMPAT -+ /* AARCH32 compat mode */ -+ struct compat_frame_tail __user *tail; -+ -+ tail = (struct compat_frame_tail __user *)regs->compat_fp - 1; -+ -+ while ((entry->nr < PERF_MAX_STACK_DEPTH) && -+ tail && !((unsigned long)tail & 0x3)) -+ tail = compat_user_backtrace(tail, entry); -+#endif -+ } - } - - /* -@@ -1429,6 +1491,7 @@ - frame.fp = regs->regs[29]; - frame.sp = regs->sp; - frame.pc = regs->pc; -+ - walk_stackframe(&frame, callchain_trace, entry); - } - -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/perf_regs.c linux-3.14.22/arch/arm64/kernel/perf_regs.c ---- linux-3.14.22.orig/arch/arm64/kernel/perf_regs.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/perf_regs.c 2014-10-22 14:55:50.182220001 -0500 -@@ -0,0 +1,46 @@ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+u64 perf_reg_value(struct pt_regs *regs, int idx) -+{ -+ if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX)) -+ return 0; -+ -+ /* -+ * Compat (i.e. 32 bit) mode: -+ * - PC has been set in the pt_regs struct in kernel_entry, -+ * - Handle SP and LR here. -+ */ -+ if (compat_user_mode(regs)) { -+ if ((u32)idx == PERF_REG_ARM64_SP) -+ return regs->compat_sp; -+ if ((u32)idx == PERF_REG_ARM64_LR) -+ return regs->compat_lr; -+ } -+ -+ return regs->regs[idx]; -+} -+ -+#define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1)) -+ -+int perf_reg_validate(u64 mask) -+{ -+ if (!mask || mask & REG_RESERVED) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+u64 perf_reg_abi(struct task_struct *task) -+{ -+ if (is_compat_thread(task_thread_info(task))) -+ return PERF_SAMPLE_REGS_ABI_32; -+ else -+ return PERF_SAMPLE_REGS_ABI_64; -+} -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/process.c linux-3.14.22/arch/arm64/kernel/process.c ---- linux-3.14.22.orig/arch/arm64/kernel/process.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/process.c 2014-10-22 14:55:50.182220001 -0500 -@@ -20,6 +20,7 @@ - - #include - -+#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/ptrace.c linux-3.14.22/arch/arm64/kernel/ptrace.c ---- linux-3.14.22.orig/arch/arm64/kernel/ptrace.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/ptrace.c 2014-10-22 14:55:51.062220001 -0500 -@@ -19,6 +19,7 @@ - * along with this program. If not, see . - */ - -+#include - #include - #include - #include -@@ -41,6 +42,9 @@ - #include - #include - -+#define CREATE_TRACE_POINTS -+#include -+ - /* - * TODO: does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. -@@ -1073,35 +1077,49 @@ - return ptrace_request(child, request, addr, data); - } - --asmlinkage int syscall_trace(int dir, struct pt_regs *regs) -+enum ptrace_syscall_dir { -+ PTRACE_SYSCALL_ENTER = 0, -+ PTRACE_SYSCALL_EXIT, -+}; -+ -+static void tracehook_report_syscall(struct pt_regs *regs, -+ enum ptrace_syscall_dir dir) - { -+ int regno; - unsigned long saved_reg; - -- if (!test_thread_flag(TIF_SYSCALL_TRACE)) -- return regs->syscallno; -- -- if (is_compat_task()) { -- /* AArch32 uses ip (r12) for scratch */ -- saved_reg = regs->regs[12]; -- regs->regs[12] = dir; -- } else { -- /* -- * Save X7. X7 is used to denote syscall entry/exit: -- * X7 = 0 -> entry, = 1 -> exit -- */ -- saved_reg = regs->regs[7]; -- regs->regs[7] = dir; -- } -+ /* -+ * A scratch register (ip(r12) on AArch32, x7 on AArch64) is -+ * used to denote syscall entry/exit: -+ */ -+ regno = (is_compat_task() ? 12 : 7); -+ saved_reg = regs->regs[regno]; -+ regs->regs[regno] = dir; - -- if (dir) -+ if (dir == PTRACE_SYSCALL_EXIT) - tracehook_report_syscall_exit(regs, 0); - else if (tracehook_report_syscall_entry(regs)) - regs->syscallno = ~0UL; - -- if (is_compat_task()) -- regs->regs[12] = saved_reg; -- else -- regs->regs[7] = saved_reg; -+ regs->regs[regno] = saved_reg; -+} -+ -+asmlinkage int syscall_trace_enter(struct pt_regs *regs) -+{ -+ if (test_thread_flag(TIF_SYSCALL_TRACE)) -+ tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); -+ -+ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) -+ trace_sys_enter(regs, regs->syscallno); - - return regs->syscallno; - } -+ -+asmlinkage void syscall_trace_exit(struct pt_regs *regs) -+{ -+ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) -+ trace_sys_exit(regs, regs_return_value(regs)); -+ -+ if (test_thread_flag(TIF_SYSCALL_TRACE)) -+ tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT); -+} -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/return_address.c linux-3.14.22/arch/arm64/kernel/return_address.c ---- linux-3.14.22.orig/arch/arm64/kernel/return_address.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/return_address.c 2014-10-22 14:55:51.062220001 -0500 -@@ -0,0 +1,55 @@ -+/* -+ * arch/arm64/kernel/return_address.c -+ * -+ * Copyright (C) 2013 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+ -+#include -+ -+struct return_address_data { -+ unsigned int level; -+ void *addr; -+}; -+ -+static int save_return_addr(struct stackframe *frame, void *d) -+{ -+ struct return_address_data *data = d; -+ -+ if (!data->level) { -+ data->addr = (void *)frame->pc; -+ return 1; -+ } else { -+ --data->level; -+ return 0; -+ } -+} -+ -+void *return_address(unsigned int level) -+{ -+ struct return_address_data data; -+ struct stackframe frame; -+ register unsigned long current_sp asm ("sp"); -+ -+ data.level = level + 2; -+ data.addr = NULL; -+ -+ frame.fp = (unsigned long)__builtin_frame_address(0); -+ frame.sp = current_sp; -+ frame.pc = (unsigned long)return_address; /* dummy */ -+ -+ walk_stackframe(&frame, save_return_addr, &data); -+ -+ if (!data.level) -+ return data.addr; -+ else -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(return_address); -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/setup.c linux-3.14.22/arch/arm64/kernel/setup.c ---- linux-3.14.22.orig/arch/arm64/kernel/setup.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/setup.c 2014-10-22 14:55:51.062220001 -0500 -@@ -69,6 +69,7 @@ - COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ - COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV) - unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; -+unsigned int compat_elf_hwcap2 __read_mostly; - #endif - - static const char *cpu_name; -@@ -242,6 +243,38 @@ - block = (features >> 16) & 0xf; - if (block && !(block & 0x8)) - elf_hwcap |= HWCAP_CRC32; -+ -+#ifdef CONFIG_COMPAT -+ /* -+ * ID_ISAR5_EL1 carries similar information as above, but pertaining to -+ * the Aarch32 32-bit execution state. -+ */ -+ features = read_cpuid(ID_ISAR5_EL1); -+ block = (features >> 4) & 0xf; -+ if (!(block & 0x8)) { -+ switch (block) { -+ default: -+ case 2: -+ compat_elf_hwcap2 |= COMPAT_HWCAP2_PMULL; -+ case 1: -+ compat_elf_hwcap2 |= COMPAT_HWCAP2_AES; -+ case 0: -+ break; -+ } -+ } -+ -+ block = (features >> 8) & 0xf; -+ if (block && !(block & 0x8)) -+ compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA1; -+ -+ block = (features >> 12) & 0xf; -+ if (block && !(block & 0x8)) -+ compat_elf_hwcap2 |= COMPAT_HWCAP2_SHA2; -+ -+ block = (features >> 16) & 0xf; -+ if (block && !(block & 0x8)) -+ compat_elf_hwcap2 |= COMPAT_HWCAP2_CRC32; -+#endif - } - - static void __init setup_machine_fdt(phys_addr_t dt_phys) -@@ -360,7 +393,7 @@ - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - return 0; - } --arch_initcall(arm64_device_init); -+arch_initcall_sync(arm64_device_init); - - static DEFINE_PER_CPU(struct cpu, cpu_data); - -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/signal.c linux-3.14.22/arch/arm64/kernel/signal.c ---- linux-3.14.22.orig/arch/arm64/kernel/signal.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/signal.c 2014-10-22 14:55:51.062220001 -0500 -@@ -17,6 +17,7 @@ - * along with this program. If not, see . - */ - -+#include - #include - #include - #include -@@ -25,7 +26,6 @@ - #include - #include - --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/smp.c linux-3.14.22/arch/arm64/kernel/smp.c ---- linux-3.14.22.orig/arch/arm64/kernel/smp.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/smp.c 2014-10-22 14:55:51.066220001 -0500 -@@ -114,6 +114,11 @@ - return ret; - } - -+static void smp_store_cpu_info(unsigned int cpuid) -+{ -+ store_cpu_topology(cpuid); -+} -+ - /* - * This is the secondary CPU boot entry. We're using this CPUs - * idle thread stack, but a set of temporary page tables. -@@ -152,6 +157,8 @@ - */ - notify_cpu_starting(cpu); - -+ smp_store_cpu_info(cpu); -+ - /* - * OK, now it's safe to let the boot CPU continue. Wait for - * the CPU migration code to notice that the CPU is online -@@ -390,6 +397,10 @@ - int err; - unsigned int cpu, ncores = num_possible_cpus(); - -+ init_cpu_topology(); -+ -+ smp_store_cpu_info(smp_processor_id()); -+ - /* - * are we trying to boot more cores than exist? - */ -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/stacktrace.c linux-3.14.22/arch/arm64/kernel/stacktrace.c ---- linux-3.14.22.orig/arch/arm64/kernel/stacktrace.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/stacktrace.c 2014-10-22 14:55:51.066220001 -0500 -@@ -35,7 +35,7 @@ - * ldp x29, x30, [sp] - * add sp, sp, #0x10 - */ --int unwind_frame(struct stackframe *frame) -+int notrace unwind_frame(struct stackframe *frame) - { - unsigned long high, low; - unsigned long fp = frame->fp; -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/topology.c linux-3.14.22/arch/arm64/kernel/topology.c ---- linux-3.14.22.orig/arch/arm64/kernel/topology.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/arch/arm64/kernel/topology.c 2014-10-22 14:55:51.066220001 -0500 -@@ -0,0 +1,558 @@ -+/* -+ * arch/arm64/kernel/topology.c -+ * -+ * Copyright (C) 2011,2013,2014 Linaro Limited. -+ * -+ * Based on the arm32 version written by Vincent Guittot in turn based on -+ * arch/sh/kernel/topology.c -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* -+ * cpu power table -+ * This per cpu data structure describes the relative capacity of each core. -+ * On a heteregenous system, cores don't have the same computation capacity -+ * and we reflect that difference in the cpu_power field so the scheduler can -+ * take this difference into account during load balance. A per cpu structure -+ * is preferred because each CPU updates its own cpu_power field during the -+ * load balance except for idle cores. One idle core is selected to run the -+ * rebalance_domains for all idle cores and the cpu_power can be updated -+ * during this sequence. -+ */ -+static DEFINE_PER_CPU(unsigned long, cpu_scale); -+ -+unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) -+{ -+ return per_cpu(cpu_scale, cpu); -+} -+ -+static void set_power_scale(unsigned int cpu, unsigned long power) -+{ -+ per_cpu(cpu_scale, cpu) = power; -+} -+ -+static int __init get_cpu_for_node(struct device_node *node) -+{ -+ struct device_node *cpu_node; -+ int cpu; -+ -+ cpu_node = of_parse_phandle(node, "cpu", 0); -+ if (!cpu_node) -+ return -1; -+ -+ for_each_possible_cpu(cpu) { -+ if (of_get_cpu_node(cpu, NULL) == cpu_node) { -+ of_node_put(cpu_node); -+ return cpu; -+ } -+ } -+ -+ pr_crit("Unable to find CPU node for %s\n", cpu_node->full_name); -+ -+ of_node_put(cpu_node); -+ return -1; -+} -+ -+static int __init parse_core(struct device_node *core, int cluster_id, -+ int core_id) -+{ -+ char name[10]; -+ bool leaf = true; -+ int i = 0; -+ int cpu; -+ struct device_node *t; -+ -+ do { -+ snprintf(name, sizeof(name), "thread%d", i); -+ t = of_get_child_by_name(core, name); -+ if (t) { -+ leaf = false; -+ cpu = get_cpu_for_node(t); -+ if (cpu >= 0) { -+ cpu_topology[cpu].cluster_id = cluster_id; -+ cpu_topology[cpu].core_id = core_id; -+ cpu_topology[cpu].thread_id = i; -+ } else { -+ pr_err("%s: Can't get CPU for thread\n", -+ t->full_name); -+ of_node_put(t); -+ return -EINVAL; -+ } -+ of_node_put(t); -+ } -+ i++; -+ } while (t); -+ -+ cpu = get_cpu_for_node(core); -+ if (cpu >= 0) { -+ if (!leaf) { -+ pr_err("%s: Core has both threads and CPU\n", -+ core->full_name); -+ return -EINVAL; -+ } -+ -+ cpu_topology[cpu].cluster_id = cluster_id; -+ cpu_topology[cpu].core_id = core_id; -+ } else if (leaf) { -+ pr_err("%s: Can't get CPU for leaf core\n", core->full_name); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int __init parse_cluster(struct device_node *cluster, int depth) -+{ -+ char name[10]; -+ bool leaf = true; -+ bool has_cores = false; -+ struct device_node *c; -+ static int cluster_id __initdata; -+ int core_id = 0; -+ int i, ret; -+ -+ /* -+ * First check for child clusters; we currently ignore any -+ * information about the nesting of clusters and present the -+ * scheduler with a flat list of them. -+ */ -+ i = 0; -+ do { -+ snprintf(name, sizeof(name), "cluster%d", i); -+ c = of_get_child_by_name(cluster, name); -+ if (c) { -+ leaf = false; -+ ret = parse_cluster(c, depth + 1); -+ of_node_put(c); -+ if (ret != 0) -+ return ret; -+ } -+ i++; -+ } while (c); -+ -+ /* Now check for cores */ -+ i = 0; -+ do { -+ snprintf(name, sizeof(name), "core%d", i); -+ c = of_get_child_by_name(cluster, name); -+ if (c) { -+ has_cores = true; -+ -+ if (depth == 0) { -+ pr_err("%s: cpu-map children should be clusters\n", -+ c->full_name); -+ of_node_put(c); -+ return -EINVAL; -+ } -+ -+ if (leaf) { -+ ret = parse_core(c, cluster_id, core_id++); -+ } else { -+ pr_err("%s: Non-leaf cluster with core %s\n", -+ cluster->full_name, name); -+ ret = -EINVAL; -+ } -+ -+ of_node_put(c); -+ if (ret != 0) -+ return ret; -+ } -+ i++; -+ } while (c); -+ -+ if (leaf && !has_cores) -+ pr_warn("%s: empty cluster\n", cluster->full_name); -+ -+ if (leaf) -+ cluster_id++; -+ -+ return 0; -+} -+ -+struct cpu_efficiency { -+ const char *compatible; -+ unsigned long efficiency; -+}; -+ -+/* -+ * Table of relative efficiency of each processors -+ * The efficiency value must fit in 20bit and the final -+ * cpu_scale value must be in the range -+ * 0 < cpu_scale < 3*SCHED_POWER_SCALE/2 -+ * in order to return at most 1 when DIV_ROUND_CLOSEST -+ * is used to compute the capacity of a CPU. -+ * Processors that are not defined in the table, -+ * use the default SCHED_POWER_SCALE value for cpu_scale. -+ */ -+static const struct cpu_efficiency table_efficiency[] = { -+ { "arm,cortex-a57", 3891 }, -+ { "arm,cortex-a53", 2048 }, -+ { NULL, }, -+}; -+ -+static unsigned long *__cpu_capacity; -+#define cpu_capacity(cpu) __cpu_capacity[cpu] -+ -+static unsigned long middle_capacity = 1; -+ -+/* -+ * Iterate all CPUs' descriptor in DT and compute the efficiency -+ * (as per table_efficiency). Also calculate a middle efficiency -+ * as close as possible to (max{eff_i} - min{eff_i}) / 2 -+ * This is later used to scale the cpu_power field such that an -+ * 'average' CPU is of middle power. Also see the comments near -+ * table_efficiency[] and update_cpu_power(). -+ */ -+static int __init parse_dt_topology(void) -+{ -+ struct device_node *cn, *map; -+ int ret = 0; -+ int cpu; -+ -+ cn = of_find_node_by_path("/cpus"); -+ if (!cn) { -+ pr_err("No CPU information found in DT\n"); -+ return 0; -+ } -+ -+ /* -+ * When topology is provided cpu-map is essentially a root -+ * cluster with restricted subnodes. -+ */ -+ map = of_get_child_by_name(cn, "cpu-map"); -+ if (!map) -+ goto out; -+ -+ ret = parse_cluster(map, 0); -+ if (ret != 0) -+ goto out_map; -+ -+ /* -+ * Check that all cores are in the topology; the SMP code will -+ * only mark cores described in the DT as possible. -+ */ -+ for_each_possible_cpu(cpu) { -+ if (cpu_topology[cpu].cluster_id == -1) { -+ pr_err("CPU%d: No topology information specified\n", -+ cpu); -+ ret = -EINVAL; -+ } -+ } -+ -+out_map: -+ of_node_put(map); -+out: -+ of_node_put(cn); -+ return ret; -+} -+ -+static void __init parse_dt_cpu_power(void) -+{ -+ const struct cpu_efficiency *cpu_eff; -+ struct device_node *cn; -+ unsigned long min_capacity = ULONG_MAX; -+ unsigned long max_capacity = 0; -+ unsigned long capacity = 0; -+ int cpu; -+ -+ __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity), -+ GFP_NOWAIT); -+ -+ for_each_possible_cpu(cpu) { -+ const u32 *rate; -+ int len; -+ -+ /* Too early to use cpu->of_node */ -+ cn = of_get_cpu_node(cpu, NULL); -+ if (!cn) { -+ pr_err("Missing device node for CPU %d\n", cpu); -+ continue; -+ } -+ -+ for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) -+ if (of_device_is_compatible(cn, cpu_eff->compatible)) -+ break; -+ -+ if (cpu_eff->compatible == NULL) { -+ pr_warn("%s: Unknown CPU type\n", cn->full_name); -+ continue; -+ } -+ -+ rate = of_get_property(cn, "clock-frequency", &len); -+ if (!rate || len != 4) { -+ pr_err("%s: Missing clock-frequency property\n", -+ cn->full_name); -+ continue; -+ } -+ -+ capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; -+ -+ /* Save min capacity of the system */ -+ if (capacity < min_capacity) -+ min_capacity = capacity; -+ -+ /* Save max capacity of the system */ -+ if (capacity > max_capacity) -+ max_capacity = capacity; -+ -+ cpu_capacity(cpu) = capacity; -+ } -+ -+ /* If min and max capacities are equal we bypass the update of the -+ * cpu_scale because all CPUs have the same capacity. Otherwise, we -+ * compute a middle_capacity factor that will ensure that the capacity -+ * of an 'average' CPU of the system will be as close as possible to -+ * SCHED_POWER_SCALE, which is the default value, but with the -+ * constraint explained near table_efficiency[]. -+ */ -+ if (min_capacity == max_capacity) -+ return; -+ else if (4 * max_capacity < (3 * (max_capacity + min_capacity))) -+ middle_capacity = (min_capacity + max_capacity) -+ >> (SCHED_POWER_SHIFT+1); -+ else -+ middle_capacity = ((max_capacity / 3) -+ >> (SCHED_POWER_SHIFT-1)) + 1; -+} -+ -+/* -+ * Look for a customed capacity of a CPU in the cpu_topo_data table during the -+ * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the -+ * function returns directly for SMP system. -+ */ -+static void update_cpu_power(unsigned int cpu) -+{ -+ if (!cpu_capacity(cpu)) -+ return; -+ -+ set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity); -+ -+ pr_info("CPU%u: update cpu_power %lu\n", -+ cpu, arch_scale_freq_power(NULL, cpu)); -+} -+ -+/* -+ * cpu topology table -+ */ -+struct cpu_topology cpu_topology[NR_CPUS]; -+EXPORT_SYMBOL_GPL(cpu_topology); -+ -+const struct cpumask *cpu_coregroup_mask(int cpu) -+{ -+ return &cpu_topology[cpu].core_sibling; -+} -+ -+static void update_siblings_masks(unsigned int cpuid) -+{ -+ struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; -+ int cpu; -+ -+ if (cpuid_topo->cluster_id == -1) { -+ /* -+ * DT does not contain topology information for this cpu. -+ */ -+ pr_debug("CPU%u: No topology information configured\n", cpuid); -+ return; -+ } -+ -+ /* update core and thread sibling masks */ -+ for_each_possible_cpu(cpu) { -+ cpu_topo = &cpu_topology[cpu]; -+ -+ if (cpuid_topo->cluster_id != cpu_topo->cluster_id) -+ continue; -+ -+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); -+ if (cpu != cpuid) -+ cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); -+ -+ if (cpuid_topo->core_id != cpu_topo->core_id) -+ continue; -+ -+ cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); -+ if (cpu != cpuid) -+ cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); -+ } -+} -+ -+void store_cpu_topology(unsigned int cpuid) -+{ -+ update_siblings_masks(cpuid); -+ update_cpu_power(cpuid); -+} -+ -+#ifdef CONFIG_SCHED_HMP -+ -+/* -+ * Retrieve logical cpu index corresponding to a given MPIDR[23:0] -+ * - mpidr: MPIDR[23:0] to be used for the look-up -+ * -+ * Returns the cpu logical index or -EINVAL on look-up error -+ */ -+static inline int get_logical_index(u32 mpidr) -+{ -+ int cpu; -+ for (cpu = 0; cpu < nr_cpu_ids; cpu++) -+ if (cpu_logical_map(cpu) == mpidr) -+ return cpu; -+ return -EINVAL; -+} -+ -+static const char * const little_cores[] = { -+ "arm,cortex-a53", -+ NULL, -+}; -+ -+static bool is_little_cpu(struct device_node *cn) -+{ -+ const char * const *lc; -+ for (lc = little_cores; *lc; lc++) -+ if (of_device_is_compatible(cn, *lc)) -+ return true; -+ return false; -+} -+ -+void __init arch_get_fast_and_slow_cpus(struct cpumask *fast, -+ struct cpumask *slow) -+{ -+ struct device_node *cn = NULL; -+ int cpu; -+ -+ cpumask_clear(fast); -+ cpumask_clear(slow); -+ -+ /* -+ * Use the config options if they are given. This helps testing -+ * HMP scheduling on systems without a big.LITTLE architecture. -+ */ -+ if (strlen(CONFIG_HMP_FAST_CPU_MASK) && strlen(CONFIG_HMP_SLOW_CPU_MASK)) { -+ if (cpulist_parse(CONFIG_HMP_FAST_CPU_MASK, fast)) -+ WARN(1, "Failed to parse HMP fast cpu mask!\n"); -+ if (cpulist_parse(CONFIG_HMP_SLOW_CPU_MASK, slow)) -+ WARN(1, "Failed to parse HMP slow cpu mask!\n"); -+ return; -+ } -+ -+ /* -+ * Else, parse device tree for little cores. -+ */ -+ while ((cn = of_find_node_by_type(cn, "cpu"))) { -+ -+ const u32 *mpidr; -+ int len; -+ -+ mpidr = of_get_property(cn, "reg", &len); -+ if (!mpidr || len != 8) { -+ pr_err("%s missing reg property\n", cn->full_name); -+ continue; -+ } -+ -+ cpu = get_logical_index(be32_to_cpup(mpidr+1)); -+ if (cpu == -EINVAL) { -+ pr_err("couldn't get logical index for mpidr %x\n", -+ be32_to_cpup(mpidr+1)); -+ break; -+ } -+ -+ if (is_little_cpu(cn)) -+ cpumask_set_cpu(cpu, slow); -+ else -+ cpumask_set_cpu(cpu, fast); -+ } -+ -+ if (!cpumask_empty(fast) && !cpumask_empty(slow)) -+ return; -+ -+ /* -+ * We didn't find both big and little cores so let's call all cores -+ * fast as this will keep the system running, with all cores being -+ * treated equal. -+ */ -+ cpumask_setall(fast); -+ cpumask_clear(slow); -+} -+ -+struct cpumask hmp_slow_cpu_mask; -+ -+void __init arch_get_hmp_domains(struct list_head *hmp_domains_list) -+{ -+ struct cpumask hmp_fast_cpu_mask; -+ struct hmp_domain *domain; -+ -+ arch_get_fast_and_slow_cpus(&hmp_fast_cpu_mask, &hmp_slow_cpu_mask); -+ -+ /* -+ * Initialize hmp_domains -+ * Must be ordered with respect to compute capacity. -+ * Fastest domain at head of list. -+ */ -+ if(!cpumask_empty(&hmp_slow_cpu_mask)) { -+ domain = (struct hmp_domain *) -+ kmalloc(sizeof(struct hmp_domain), GFP_KERNEL); -+ cpumask_copy(&domain->possible_cpus, &hmp_slow_cpu_mask); -+ cpumask_and(&domain->cpus, cpu_online_mask, &domain->possible_cpus); -+ list_add(&domain->hmp_domains, hmp_domains_list); -+ } -+ domain = (struct hmp_domain *) -+ kmalloc(sizeof(struct hmp_domain), GFP_KERNEL); -+ cpumask_copy(&domain->possible_cpus, &hmp_fast_cpu_mask); -+ cpumask_and(&domain->cpus, cpu_online_mask, &domain->possible_cpus); -+ list_add(&domain->hmp_domains, hmp_domains_list); -+} -+#endif /* CONFIG_SCHED_HMP */ -+ -+static void __init reset_cpu_topology(void) -+{ -+ unsigned int cpu; -+ -+ for_each_possible_cpu(cpu) { -+ struct cpu_topology *cpu_topo = &cpu_topology[cpu]; -+ -+ cpu_topo->thread_id = -1; -+ cpu_topo->core_id = 0; -+ cpu_topo->cluster_id = -1; -+ -+ cpumask_clear(&cpu_topo->core_sibling); -+ cpumask_set_cpu(cpu, &cpu_topo->core_sibling); -+ cpumask_clear(&cpu_topo->thread_sibling); -+ cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); -+ } -+} -+ -+static void __init reset_cpu_power(void) -+{ -+ unsigned int cpu; -+ -+ for_each_possible_cpu(cpu) -+ set_power_scale(cpu, SCHED_POWER_SCALE); -+} -+ -+void __init init_cpu_topology(void) -+{ -+ reset_cpu_topology(); -+ -+ /* -+ * Discard anything that was parsed if we hit an error so we -+ * don't use partial information. -+ */ -+ if (parse_dt_topology()) -+ reset_cpu_topology(); -+ -+ reset_cpu_power(); -+ parse_dt_cpu_power(); -+} -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/vdso/Makefile linux-3.14.22/arch/arm64/kernel/vdso/Makefile ---- linux-3.14.22.orig/arch/arm64/kernel/vdso/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/vdso/Makefile 2014-10-22 14:55:51.066220001 -0500 -@@ -47,9 +47,9 @@ - $(call if_changed_dep,vdsoas) - - # Actual build commands --quiet_cmd_vdsold = VDSOL $@ -+quiet_cmd_vdsold = VDSOL $@ - cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@ --quiet_cmd_vdsoas = VDSOA $@ -+quiet_cmd_vdsoas = VDSOA $@ - cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $< - - # Install commands for the unstripped file -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/vdso.c linux-3.14.22/arch/arm64/kernel/vdso.c ---- linux-3.14.22.orig/arch/arm64/kernel/vdso.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/vdso.c 2014-10-22 14:55:51.066220001 -0500 -@@ -156,11 +156,12 @@ - int uses_interp) - { - struct mm_struct *mm = current->mm; -- unsigned long vdso_base, vdso_mapping_len; -+ unsigned long vdso_base, vdso_text_len, vdso_mapping_len; - int ret; - -+ vdso_text_len = vdso_pages << PAGE_SHIFT; - /* Be sure to map the data page */ -- vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT; -+ vdso_mapping_len = vdso_text_len + PAGE_SIZE; - - down_write(&mm->mmap_sem); - vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0); -@@ -170,35 +171,52 @@ - } - mm->context.vdso = (void *)vdso_base; - -- ret = install_special_mapping(mm, vdso_base, vdso_mapping_len, -+ ret = install_special_mapping(mm, vdso_base, vdso_text_len, - VM_READ|VM_EXEC| - VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - vdso_pagelist); -- if (ret) { -- mm->context.vdso = NULL; -+ if (ret) -+ goto up_fail; -+ -+ vdso_base += vdso_text_len; -+ ret = install_special_mapping(mm, vdso_base, PAGE_SIZE, -+ VM_READ|VM_MAYREAD, -+ vdso_pagelist + vdso_pages); -+ if (ret) - goto up_fail; -- } - --up_fail: - up_write(&mm->mmap_sem); -+ return 0; - -+up_fail: -+ mm->context.vdso = NULL; -+ up_write(&mm->mmap_sem); - return ret; - } - - const char *arch_vma_name(struct vm_area_struct *vma) - { -+ unsigned long vdso_text; -+ -+ if (!vma->vm_mm) -+ return NULL; -+ -+ vdso_text = (unsigned long)vma->vm_mm->context.vdso; -+ - /* - * We can re-use the vdso pointer in mm_context_t for identifying - * the vectors page for compat applications. The vDSO will always - * sit above TASK_UNMAPPED_BASE and so we don't need to worry about - * it conflicting with the vectors base. - */ -- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) { -+ if (vma->vm_start == vdso_text) { - #ifdef CONFIG_COMPAT - if (vma->vm_start == AARCH32_VECTORS_BASE) - return "[vectors]"; - #endif - return "[vdso]"; -+ } else if (vma->vm_start == (vdso_text + (vdso_pages << PAGE_SHIFT))) { -+ return "[vvar]"; - } - - return NULL; -diff -Nur linux-3.14.22.orig/arch/arm64/kernel/vmlinux.lds.S linux-3.14.22/arch/arm64/kernel/vmlinux.lds.S ---- linux-3.14.22.orig/arch/arm64/kernel/vmlinux.lds.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/kernel/vmlinux.lds.S 2014-10-22 14:55:51.066220001 -0500 -@@ -104,6 +104,13 @@ - _edata = .; - - BSS_SECTION(0, 0, 0) -+ -+ . = ALIGN(PAGE_SIZE); -+ idmap_pg_dir = .; -+ . += IDMAP_DIR_SIZE; -+ swapper_pg_dir = .; -+ . += SWAPPER_DIR_SIZE; -+ - _end = .; - - STABS_DEBUG -diff -Nur linux-3.14.22.orig/arch/arm64/Makefile linux-3.14.22/arch/arm64/Makefile ---- linux-3.14.22.orig/arch/arm64/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/Makefile 2014-10-22 14:55:51.066220001 -0500 -@@ -45,6 +45,7 @@ - core-y += arch/arm64/kernel/ arch/arm64/mm/ - core-$(CONFIG_KVM) += arch/arm64/kvm/ - core-$(CONFIG_XEN) += arch/arm64/xen/ -+core-$(CONFIG_CRYPTO) += arch/arm64/crypto/ - libs-y := arch/arm64/lib/ $(libs-y) - libs-y += $(LIBGCC) - -diff -Nur linux-3.14.22.orig/arch/arm64/mm/cache.S linux-3.14.22/arch/arm64/mm/cache.S ---- linux-3.14.22.orig/arch/arm64/mm/cache.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/mm/cache.S 2014-10-22 14:55:51.070220001 -0500 -@@ -30,7 +30,7 @@ - * - * Corrupted registers: x0-x7, x9-x11 - */ --ENTRY(__flush_dcache_all) -+__flush_dcache_all: - dsb sy // ensure ordering with previous memory accesses - mrs x0, clidr_el1 // read clidr - and x3, x0, #0x7000000 // extract loc from clidr -@@ -166,3 +166,97 @@ - dsb sy - ret - ENDPROC(__flush_dcache_area) -+ -+/* -+ * __inval_cache_range(start, end) -+ * - start - start address of region -+ * - end - end address of region -+ */ -+ENTRY(__inval_cache_range) -+ /* FALLTHROUGH */ -+ -+/* -+ * __dma_inv_range(start, end) -+ * - start - virtual start address of region -+ * - end - virtual end address of region -+ */ -+__dma_inv_range: -+ dcache_line_size x2, x3 -+ sub x3, x2, #1 -+ tst x1, x3 // end cache line aligned? -+ bic x1, x1, x3 -+ b.eq 1f -+ dc civac, x1 // clean & invalidate D / U line -+1: tst x0, x3 // start cache line aligned? -+ bic x0, x0, x3 -+ b.eq 2f -+ dc civac, x0 // clean & invalidate D / U line -+ b 3f -+2: dc ivac, x0 // invalidate D / U line -+3: add x0, x0, x2 -+ cmp x0, x1 -+ b.lo 2b -+ dsb sy -+ ret -+ENDPROC(__inval_cache_range) -+ENDPROC(__dma_inv_range) -+ -+/* -+ * __dma_clean_range(start, end) -+ * - start - virtual start address of region -+ * - end - virtual end address of region -+ */ -+__dma_clean_range: -+ dcache_line_size x2, x3 -+ sub x3, x2, #1 -+ bic x0, x0, x3 -+1: dc cvac, x0 // clean D / U line -+ add x0, x0, x2 -+ cmp x0, x1 -+ b.lo 1b -+ dsb sy -+ ret -+ENDPROC(__dma_clean_range) -+ -+/* -+ * __dma_flush_range(start, end) -+ * - start - virtual start address of region -+ * - end - virtual end address of region -+ */ -+ENTRY(__dma_flush_range) -+ dcache_line_size x2, x3 -+ sub x3, x2, #1 -+ bic x0, x0, x3 -+1: dc civac, x0 // clean & invalidate D / U line -+ add x0, x0, x2 -+ cmp x0, x1 -+ b.lo 1b -+ dsb sy -+ ret -+ENDPROC(__dma_flush_range) -+ -+/* -+ * __dma_map_area(start, size, dir) -+ * - start - kernel virtual start address -+ * - size - size of region -+ * - dir - DMA direction -+ */ -+ENTRY(__dma_map_area) -+ add x1, x1, x0 -+ cmp w2, #DMA_FROM_DEVICE -+ b.eq __dma_inv_range -+ b __dma_clean_range -+ENDPROC(__dma_map_area) -+ -+/* -+ * __dma_unmap_area(start, size, dir) -+ * - start - kernel virtual start address -+ * - size - size of region -+ * - dir - DMA direction -+ */ -+ENTRY(__dma_unmap_area) -+ add x1, x1, x0 -+ cmp w2, #DMA_TO_DEVICE -+ b.ne __dma_inv_range -+ ret -+ENDPROC(__dma_unmap_area) -diff -Nur linux-3.14.22.orig/arch/arm64/mm/copypage.c linux-3.14.22/arch/arm64/mm/copypage.c ---- linux-3.14.22.orig/arch/arm64/mm/copypage.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/mm/copypage.c 2014-10-22 14:55:51.070220001 -0500 -@@ -27,8 +27,10 @@ - copy_page(kto, kfrom); - __flush_dcache_area(kto, PAGE_SIZE); - } -+EXPORT_SYMBOL_GPL(__cpu_copy_user_page); - - void __cpu_clear_user_page(void *kaddr, unsigned long vaddr) - { - clear_page(kaddr); - } -+EXPORT_SYMBOL_GPL(__cpu_clear_user_page); -diff -Nur linux-3.14.22.orig/arch/arm64/mm/dma-mapping.c linux-3.14.22/arch/arm64/mm/dma-mapping.c ---- linux-3.14.22.orig/arch/arm64/mm/dma-mapping.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/mm/dma-mapping.c 2014-10-22 14:55:51.070220001 -0500 -@@ -22,26 +22,39 @@ - #include - #include - #include -+#include -+#include - #include - #include -+#include - - #include - - struct dma_map_ops *dma_ops; - EXPORT_SYMBOL(dma_ops); - --static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t *dma_handle, gfp_t flags, -- struct dma_attrs *attrs) -+static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot, -+ bool coherent) -+{ -+ if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) -+ return pgprot_writecombine(prot); -+ else if (!coherent) -+ return pgprot_dmacoherent(prot); -+ return prot; -+} -+ -+static void *__dma_alloc_coherent(struct device *dev, size_t size, -+ dma_addr_t *dma_handle, gfp_t flags, -+ struct dma_attrs *attrs) - { - if (dev == NULL) { - WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); - return NULL; - } - -- if (IS_ENABLED(CONFIG_ZONE_DMA32) && -+ if (IS_ENABLED(CONFIG_ZONE_DMA) && - dev->coherent_dma_mask <= DMA_BIT_MASK(32)) -- flags |= GFP_DMA32; -+ flags |= GFP_DMA; - if (IS_ENABLED(CONFIG_DMA_CMA)) { - struct page *page; - -@@ -58,9 +71,9 @@ - } - } - --static void arm64_swiotlb_free_coherent(struct device *dev, size_t size, -- void *vaddr, dma_addr_t dma_handle, -- struct dma_attrs *attrs) -+static void __dma_free_coherent(struct device *dev, size_t size, -+ void *vaddr, dma_addr_t dma_handle, -+ struct dma_attrs *attrs) - { - if (dev == NULL) { - WARN_ONCE(1, "Use an actual device structure for DMA allocation\n"); -@@ -78,9 +91,212 @@ - } - } - --static struct dma_map_ops arm64_swiotlb_dma_ops = { -- .alloc = arm64_swiotlb_alloc_coherent, -- .free = arm64_swiotlb_free_coherent, -+static void *__dma_alloc_noncoherent(struct device *dev, size_t size, -+ dma_addr_t *dma_handle, gfp_t flags, -+ struct dma_attrs *attrs) -+{ -+ struct page *page, **map; -+ void *ptr, *coherent_ptr; -+ int order, i; -+ -+ size = PAGE_ALIGN(size); -+ order = get_order(size); -+ -+ ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs); -+ if (!ptr) -+ goto no_mem; -+ map = kmalloc(sizeof(struct page *) << order, flags & ~GFP_DMA); -+ if (!map) -+ goto no_map; -+ -+ /* remove any dirty cache lines on the kernel alias */ -+ __dma_flush_range(ptr, ptr + size); -+ -+ /* create a coherent mapping */ -+ page = virt_to_page(ptr); -+ for (i = 0; i < (size >> PAGE_SHIFT); i++) -+ map[i] = page + i; -+ coherent_ptr = vmap(map, size >> PAGE_SHIFT, VM_MAP, -+ __get_dma_pgprot(attrs, pgprot_default, false)); -+ kfree(map); -+ if (!coherent_ptr) -+ goto no_map; -+ -+ return coherent_ptr; -+ -+no_map: -+ __dma_free_coherent(dev, size, ptr, *dma_handle, attrs); -+no_mem: -+ *dma_handle = ~0; -+ return NULL; -+} -+ -+static void __dma_free_noncoherent(struct device *dev, size_t size, -+ void *vaddr, dma_addr_t dma_handle, -+ struct dma_attrs *attrs) -+{ -+ void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle)); -+ -+ vunmap(vaddr); -+ __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs); -+} -+ -+static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page, -+ unsigned long offset, size_t size, -+ enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ dma_addr_t dev_addr; -+ -+ dev_addr = swiotlb_map_page(dev, page, offset, size, dir, attrs); -+ __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); -+ -+ return dev_addr; -+} -+ -+ -+static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr, -+ size_t size, enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); -+ swiotlb_unmap_page(dev, dev_addr, size, dir, attrs); -+} -+ -+static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl, -+ int nelems, enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ struct scatterlist *sg; -+ int i, ret; -+ -+ ret = swiotlb_map_sg_attrs(dev, sgl, nelems, dir, attrs); -+ for_each_sg(sgl, sg, ret, i) -+ __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), -+ sg->length, dir); -+ -+ return ret; -+} -+ -+static void __swiotlb_unmap_sg_attrs(struct device *dev, -+ struct scatterlist *sgl, int nelems, -+ enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ struct scatterlist *sg; -+ int i; -+ -+ for_each_sg(sgl, sg, nelems, i) -+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), -+ sg->length, dir); -+ swiotlb_unmap_sg_attrs(dev, sgl, nelems, dir, attrs); -+} -+ -+static void __swiotlb_sync_single_for_cpu(struct device *dev, -+ dma_addr_t dev_addr, size_t size, -+ enum dma_data_direction dir) -+{ -+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); -+ swiotlb_sync_single_for_cpu(dev, dev_addr, size, dir); -+} -+ -+static void __swiotlb_sync_single_for_device(struct device *dev, -+ dma_addr_t dev_addr, size_t size, -+ enum dma_data_direction dir) -+{ -+ swiotlb_sync_single_for_device(dev, dev_addr, size, dir); -+ __dma_map_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir); -+} -+ -+static void __swiotlb_sync_sg_for_cpu(struct device *dev, -+ struct scatterlist *sgl, int nelems, -+ enum dma_data_direction dir) -+{ -+ struct scatterlist *sg; -+ int i; -+ -+ for_each_sg(sgl, sg, nelems, i) -+ __dma_unmap_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), -+ sg->length, dir); -+ swiotlb_sync_sg_for_cpu(dev, sgl, nelems, dir); -+} -+ -+static void __swiotlb_sync_sg_for_device(struct device *dev, -+ struct scatterlist *sgl, int nelems, -+ enum dma_data_direction dir) -+{ -+ struct scatterlist *sg; -+ int i; -+ -+ swiotlb_sync_sg_for_device(dev, sgl, nelems, dir); -+ for_each_sg(sgl, sg, nelems, i) -+ __dma_map_area(phys_to_virt(dma_to_phys(dev, sg->dma_address)), -+ sg->length, dir); -+} -+ -+/* vma->vm_page_prot must be set appropriately before calling this function */ -+static int __dma_common_mmap(struct device *dev, struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size) -+{ -+ int ret = -ENXIO; -+ unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >> -+ PAGE_SHIFT; -+ unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; -+ unsigned long pfn = dma_to_phys(dev, dma_addr) >> PAGE_SHIFT; -+ unsigned long off = vma->vm_pgoff; -+ -+ if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret)) -+ return ret; -+ -+ if (off < nr_pages && nr_vma_pages <= (nr_pages - off)) { -+ ret = remap_pfn_range(vma, vma->vm_start, -+ pfn + off, -+ vma->vm_end - vma->vm_start, -+ vma->vm_page_prot); -+ } -+ -+ return ret; -+} -+ -+static int __swiotlb_mmap_noncoherent(struct device *dev, -+ struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size, -+ struct dma_attrs *attrs) -+{ -+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot, false); -+ return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); -+} -+ -+static int __swiotlb_mmap_coherent(struct device *dev, -+ struct vm_area_struct *vma, -+ void *cpu_addr, dma_addr_t dma_addr, size_t size, -+ struct dma_attrs *attrs) -+{ -+ /* Just use whatever page_prot attributes were specified */ -+ return __dma_common_mmap(dev, vma, cpu_addr, dma_addr, size); -+} -+ -+struct dma_map_ops noncoherent_swiotlb_dma_ops = { -+ .alloc = __dma_alloc_noncoherent, -+ .free = __dma_free_noncoherent, -+ .mmap = __swiotlb_mmap_noncoherent, -+ .map_page = __swiotlb_map_page, -+ .unmap_page = __swiotlb_unmap_page, -+ .map_sg = __swiotlb_map_sg_attrs, -+ .unmap_sg = __swiotlb_unmap_sg_attrs, -+ .sync_single_for_cpu = __swiotlb_sync_single_for_cpu, -+ .sync_single_for_device = __swiotlb_sync_single_for_device, -+ .sync_sg_for_cpu = __swiotlb_sync_sg_for_cpu, -+ .sync_sg_for_device = __swiotlb_sync_sg_for_device, -+ .dma_supported = swiotlb_dma_supported, -+ .mapping_error = swiotlb_dma_mapping_error, -+}; -+EXPORT_SYMBOL(noncoherent_swiotlb_dma_ops); -+ -+struct dma_map_ops coherent_swiotlb_dma_ops = { -+ .alloc = __dma_alloc_coherent, -+ .free = __dma_free_coherent, -+ .mmap = __swiotlb_mmap_coherent, - .map_page = swiotlb_map_page, - .unmap_page = swiotlb_unmap_page, - .map_sg = swiotlb_map_sg_attrs, -@@ -92,12 +308,47 @@ - .dma_supported = swiotlb_dma_supported, - .mapping_error = swiotlb_dma_mapping_error, - }; -+EXPORT_SYMBOL(coherent_swiotlb_dma_ops); - --void __init arm64_swiotlb_init(void) -+static int dma_bus_notifier(struct notifier_block *nb, -+ unsigned long event, void *_dev) - { -- dma_ops = &arm64_swiotlb_dma_ops; -- swiotlb_init(1); -+ struct device *dev = _dev; -+ -+ if (event != BUS_NOTIFY_ADD_DEVICE) -+ return NOTIFY_DONE; -+ -+ if (of_property_read_bool(dev->of_node, "dma-coherent")) -+ set_dma_ops(dev, &coherent_swiotlb_dma_ops); -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block platform_bus_nb = { -+ .notifier_call = dma_bus_notifier, -+}; -+ -+static struct notifier_block amba_bus_nb = { -+ .notifier_call = dma_bus_notifier, -+}; -+ -+extern int swiotlb_late_init_with_default_size(size_t default_size); -+ -+static int __init swiotlb_late_init(void) -+{ -+ size_t swiotlb_size = min(SZ_64M, MAX_ORDER_NR_PAGES << PAGE_SHIFT); -+ -+ /* -+ * These must be registered before of_platform_populate(). -+ */ -+ bus_register_notifier(&platform_bus_type, &platform_bus_nb); -+ bus_register_notifier(&amba_bustype, &amba_bus_nb); -+ -+ dma_ops = &noncoherent_swiotlb_dma_ops; -+ -+ return swiotlb_late_init_with_default_size(swiotlb_size); - } -+arch_initcall(swiotlb_late_init); - - #define PREALLOC_DMA_DEBUG_ENTRIES 4096 - -diff -Nur linux-3.14.22.orig/arch/arm64/mm/init.c linux-3.14.22/arch/arm64/mm/init.c ---- linux-3.14.22.orig/arch/arm64/mm/init.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/mm/init.c 2014-10-22 14:55:51.070220001 -0500 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -59,22 +60,22 @@ - early_param("initrd", early_initrd); - #endif - --#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) -- - static void __init zone_sizes_init(unsigned long min, unsigned long max) - { - struct memblock_region *reg; - unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; -- unsigned long max_dma32 = min; -+ unsigned long max_dma = min; - - memset(zone_size, 0, sizeof(zone_size)); - --#ifdef CONFIG_ZONE_DMA32 - /* 4GB maximum for 32-bit only capable devices */ -- max_dma32 = max(min, min(max, MAX_DMA32_PFN)); -- zone_size[ZONE_DMA32] = max_dma32 - min; --#endif -- zone_size[ZONE_NORMAL] = max - max_dma32; -+ if (IS_ENABLED(CONFIG_ZONE_DMA)) { -+ unsigned long max_dma_phys = -+ (unsigned long)dma_to_phys(NULL, DMA_BIT_MASK(32) + 1); -+ max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT)); -+ zone_size[ZONE_DMA] = max_dma - min; -+ } -+ zone_size[ZONE_NORMAL] = max - max_dma; - - memcpy(zhole_size, zone_size, sizeof(zhole_size)); - -@@ -84,15 +85,15 @@ - - if (start >= max) - continue; --#ifdef CONFIG_ZONE_DMA32 -- if (start < max_dma32) { -- unsigned long dma_end = min(end, max_dma32); -- zhole_size[ZONE_DMA32] -= dma_end - start; -+ -+ if (IS_ENABLED(CONFIG_ZONE_DMA) && start < max_dma) { -+ unsigned long dma_end = min(end, max_dma); -+ zhole_size[ZONE_DMA] -= dma_end - start; - } --#endif -- if (end > max_dma32) { -+ -+ if (end > max_dma) { - unsigned long normal_end = min(end, max); -- unsigned long normal_start = max(start, max_dma32); -+ unsigned long normal_start = max(start, max_dma); - zhole_size[ZONE_NORMAL] -= normal_end - normal_start; - } - } -@@ -127,20 +128,16 @@ - { - u64 *reserve_map, base, size; - -- /* Register the kernel text, kernel data and initrd with memblock */ -+ /* -+ * Register the kernel text, kernel data, initrd, and initial -+ * pagetables with memblock. -+ */ - memblock_reserve(__pa(_text), _end - _text); - #ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start); - #endif - -- /* -- * Reserve the page tables. These are already in use, -- * and can only be in node 0. -- */ -- memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); -- memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE); -- - /* Reserve the dtb region */ - memblock_reserve(virt_to_phys(initial_boot_params), - be32_to_cpu(initial_boot_params->totalsize)); -@@ -261,8 +258,6 @@ - */ - void __init mem_init(void) - { -- arm64_swiotlb_init(); -- - max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; - - #ifndef CONFIG_SPARSEMEM_VMEMMAP -diff -Nur linux-3.14.22.orig/arch/arm64/mm/proc.S linux-3.14.22/arch/arm64/mm/proc.S ---- linux-3.14.22.orig/arch/arm64/mm/proc.S 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/arm64/mm/proc.S 2014-10-22 14:55:51.070220001 -0500 -@@ -173,12 +173,6 @@ - * value of the SCTLR_EL1 register. - */ - ENTRY(__cpu_setup) -- /* -- * Preserve the link register across the function call. -- */ -- mov x28, lr -- bl __flush_dcache_all -- mov lr, x28 - ic iallu // I+BTB cache invalidate - tlbi vmalle1is // invalidate I + D TLBs - dsb sy -diff -Nur linux-3.14.22.orig/arch/avr32/kernel/cpu.c linux-3.14.22/arch/avr32/kernel/cpu.c ---- linux-3.14.22.orig/arch/avr32/kernel/cpu.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/avr32/kernel/cpu.c 2014-10-22 14:55:51.070220001 -0500 -@@ -39,10 +39,12 @@ - size_t count) - { - unsigned long val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf || val > 0x3f) -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; -+ if (val > 0x3f) - return -EINVAL; - val = (val << 12) | (sysreg_read(PCCR) & 0xfffc0fff); - sysreg_write(PCCR, val); -@@ -61,11 +63,11 @@ - const char *buf, size_t count) - { - unsigned long val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf) -- return -EINVAL; -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; - sysreg_write(PCNT0, val); - - return count; -@@ -84,10 +86,12 @@ - size_t count) - { - unsigned long val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf || val > 0x3f) -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; -+ if (val > 0x3f) - return -EINVAL; - val = (val << 18) | (sysreg_read(PCCR) & 0xff03ffff); - sysreg_write(PCCR, val); -@@ -106,11 +110,11 @@ - size_t count) - { - unsigned long val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf) -- return -EINVAL; -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; - sysreg_write(PCNT1, val); - - return count; -@@ -129,11 +133,11 @@ - size_t count) - { - unsigned long val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf) -- return -EINVAL; -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; - sysreg_write(PCCNT, val); - - return count; -@@ -152,11 +156,11 @@ - size_t count) - { - unsigned long pccr, val; -- char *endp; -+ int ret; - -- val = simple_strtoul(buf, &endp, 0); -- if (endp == buf) -- return -EINVAL; -+ ret = kstrtoul(buf, 0, &val); -+ if (ret) -+ return ret; - if (val) - val = 1; - -diff -Nur linux-3.14.22.orig/arch/blackfin/include/asm/ftrace.h linux-3.14.22/arch/blackfin/include/asm/ftrace.h ---- linux-3.14.22.orig/arch/blackfin/include/asm/ftrace.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/blackfin/include/asm/ftrace.h 2014-10-22 14:55:51.070220001 -0500 -@@ -66,16 +66,7 @@ - - #endif /* CONFIG_FRAME_POINTER */ - --#define HAVE_ARCH_CALLER_ADDR -- --/* inline function or macro may lead to unexpected result */ --#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) --#define CALLER_ADDR1 ((unsigned long)return_address(1)) --#define CALLER_ADDR2 ((unsigned long)return_address(2)) --#define CALLER_ADDR3 ((unsigned long)return_address(3)) --#define CALLER_ADDR4 ((unsigned long)return_address(4)) --#define CALLER_ADDR5 ((unsigned long)return_address(5)) --#define CALLER_ADDR6 ((unsigned long)return_address(6)) -+#define ftrace_return_address(n) return_address(n) - - #endif /* __ASSEMBLY__ */ - -diff -Nur linux-3.14.22.orig/arch/hexagon/include/asm/elf.h linux-3.14.22/arch/hexagon/include/asm/elf.h ---- linux-3.14.22.orig/arch/hexagon/include/asm/elf.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/hexagon/include/asm/elf.h 2014-10-22 14:55:51.926220001 -0500 -@@ -1,7 +1,7 @@ - /* - * ELF definitions for the Hexagon architecture - * -- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. -+ * Copyright (c) 2010-2013, The Linux Foundation. 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 version 2 and -diff -Nur linux-3.14.22.orig/arch/parisc/include/asm/ftrace.h linux-3.14.22/arch/parisc/include/asm/ftrace.h ---- linux-3.14.22.orig/arch/parisc/include/asm/ftrace.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/parisc/include/asm/ftrace.h 2014-10-22 14:55:51.938220001 -0500 -@@ -24,15 +24,7 @@ - - extern unsigned long return_address(unsigned int); - --#define HAVE_ARCH_CALLER_ADDR -- --#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) --#define CALLER_ADDR1 return_address(1) --#define CALLER_ADDR2 return_address(2) --#define CALLER_ADDR3 return_address(3) --#define CALLER_ADDR4 return_address(4) --#define CALLER_ADDR5 return_address(5) --#define CALLER_ADDR6 return_address(6) -+#define ftrace_return_address(n) return_address(n) - - #endif /* __ASSEMBLY__ */ - -diff -Nur linux-3.14.22.orig/arch/s390/include/asm/cio.h linux-3.14.22/arch/s390/include/asm/cio.h ---- linux-3.14.22.orig/arch/s390/include/asm/cio.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/s390/include/asm/cio.h 2014-10-22 14:55:51.942220001 -0500 -@@ -199,7 +199,7 @@ - /** - * struct irb - interruption response block - * @scsw: subchannel status word -- * @esw: extened status word -+ * @esw: extended status word - * @ecw: extended control word - * - * The irb that is handed to the device driver when an interrupt occurs. For -diff -Nur linux-3.14.22.orig/arch/sh/include/asm/ftrace.h linux-3.14.22/arch/sh/include/asm/ftrace.h ---- linux-3.14.22.orig/arch/sh/include/asm/ftrace.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/sh/include/asm/ftrace.h 2014-10-22 14:55:51.942220001 -0500 -@@ -40,15 +40,7 @@ - /* arch/sh/kernel/return_address.c */ - extern void *return_address(unsigned int); - --#define HAVE_ARCH_CALLER_ADDR -- --#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) --#define CALLER_ADDR1 ((unsigned long)return_address(1)) --#define CALLER_ADDR2 ((unsigned long)return_address(2)) --#define CALLER_ADDR3 ((unsigned long)return_address(3)) --#define CALLER_ADDR4 ((unsigned long)return_address(4)) --#define CALLER_ADDR5 ((unsigned long)return_address(5)) --#define CALLER_ADDR6 ((unsigned long)return_address(6)) -+#define ftrace_return_address(n) return_address(n) - - #endif /* __ASSEMBLY__ */ - -diff -Nur linux-3.14.22.orig/arch/x86/kernel/setup.c linux-3.14.22/arch/x86/kernel/setup.c ---- linux-3.14.22.orig/arch/x86/kernel/setup.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/arch/x86/kernel/setup.c 2014-10-22 14:55:51.942220001 -0500 -@@ -1120,7 +1120,7 @@ - setup_real_mode(); - - memblock_set_current_limit(get_max_mapped()); -- dma_contiguous_reserve(0); -+ dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT); - - /* - * NOTE: On x86-32, only from this point on, fixmaps are ready for use. -diff -Nur linux-3.14.22.orig/block/bfq-cgroup.c linux-3.14.22/block/bfq-cgroup.c ---- linux-3.14.22.orig/block/bfq-cgroup.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/block/bfq-cgroup.c 2014-10-22 14:55:51.950220001 -0500 -@@ -0,0 +1,932 @@ -+/* -+ * BFQ: CGROUPS support. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ -+static DEFINE_MUTEX(bfqio_mutex); -+ -+static bool bfqio_is_removed(struct bfqio_cgroup *bgrp) -+{ -+ return bgrp ? !bgrp->online : false; -+} -+ -+static struct bfqio_cgroup bfqio_root_cgroup = { -+ .weight = BFQ_DEFAULT_GRP_WEIGHT, -+ .ioprio = BFQ_DEFAULT_GRP_IOPRIO, -+ .ioprio_class = BFQ_DEFAULT_GRP_CLASS, -+}; -+ -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static struct bfqio_cgroup *css_to_bfqio(struct cgroup_subsys_state *css) -+{ -+ return css ? container_of(css, struct bfqio_cgroup, css) : NULL; -+} -+ -+/* -+ * Search the bfq_group for bfqd into the hash table (by now only a list) -+ * of bgrp. Must be called under rcu_read_lock(). -+ */ -+static struct bfq_group *bfqio_lookup_group(struct bfqio_cgroup *bgrp, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_group *bfqg; -+ void *key; -+ -+ hlist_for_each_entry_rcu(bfqg, &bgrp->group_data, group_node) { -+ key = rcu_dereference(bfqg->bfqd); -+ if (key == bfqd) -+ return bfqg; -+ } -+ -+ return NULL; -+} -+ -+static inline void bfq_group_init_entity(struct bfqio_cgroup *bgrp, -+ struct bfq_group *bfqg) -+{ -+ struct bfq_entity *entity = &bfqg->entity; -+ -+ /* -+ * If the weight of the entity has never been set via the sysfs -+ * interface, then bgrp->weight == 0. In this case we initialize -+ * the weight from the current ioprio value. Otherwise, the group -+ * weight, if set, has priority over the ioprio value. -+ */ -+ if (bgrp->weight == 0) { -+ entity->new_weight = bfq_ioprio_to_weight(bgrp->ioprio); -+ entity->new_ioprio = bgrp->ioprio; -+ } else { -+ entity->new_weight = bgrp->weight; -+ entity->new_ioprio = bfq_weight_to_ioprio(bgrp->weight); -+ } -+ entity->orig_weight = entity->weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class = bgrp->ioprio_class; -+ entity->my_sched_data = &bfqg->sched_data; -+ bfqg->active_entities = 0; -+} -+ -+static inline void bfq_group_set_parent(struct bfq_group *bfqg, -+ struct bfq_group *parent) -+{ -+ struct bfq_entity *entity; -+ -+ BUG_ON(parent == NULL); -+ BUG_ON(bfqg == NULL); -+ -+ entity = &bfqg->entity; -+ entity->parent = parent->my_entity; -+ entity->sched_data = &parent->sched_data; -+} -+ -+/** -+ * bfq_group_chain_alloc - allocate a chain of groups. -+ * @bfqd: queue descriptor. -+ * @css: the leaf cgroup_subsys_state this chain starts from. -+ * -+ * Allocate a chain of groups starting from the one belonging to -+ * @cgroup up to the root cgroup. Stop if a cgroup on the chain -+ * to the root has already an allocated group on @bfqd. -+ */ -+static struct bfq_group *bfq_group_chain_alloc(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *prev = NULL, *leaf = NULL; -+ -+ for (; css != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) { -+ /* -+ * All the cgroups in the path from there to the -+ * root must have a bfq_group for bfqd, so we don't -+ * need any more allocations. -+ */ -+ break; -+ } -+ -+ bfqg = kzalloc(sizeof(*bfqg), GFP_ATOMIC); -+ if (bfqg == NULL) -+ goto cleanup; -+ -+ bfq_group_init_entity(bgrp, bfqg); -+ bfqg->my_entity = &bfqg->entity; -+ -+ if (leaf == NULL) { -+ leaf = bfqg; -+ prev = leaf; -+ } else { -+ bfq_group_set_parent(prev, bfqg); -+ /* -+ * Build a list of allocated nodes using the bfqd -+ * filed, that is still unused and will be -+ * initialized only after the node will be -+ * connected. -+ */ -+ prev->bfqd = bfqg; -+ prev = bfqg; -+ } -+ } -+ -+ return leaf; -+ -+cleanup: -+ while (leaf != NULL) { -+ prev = leaf; -+ leaf = leaf->bfqd; -+ kfree(prev); -+ } -+ -+ return NULL; -+} -+ -+/** -+ * bfq_group_chain_link - link an allocated group chain to a cgroup -+ * hierarchy. -+ * @bfqd: the queue descriptor. -+ * @css: the leaf cgroup_subsys_state to start from. -+ * @leaf: the leaf group (to be associated to @cgroup). -+ * -+ * Try to link a chain of groups to a cgroup hierarchy, connecting the -+ * nodes bottom-up, so we can be sure that when we find a cgroup in the -+ * hierarchy that already as a group associated to @bfqd all the nodes -+ * in the path to the root cgroup have one too. -+ * -+ * On locking: the queue lock protects the hierarchy (there is a hierarchy -+ * per device) while the bfqio_cgroup lock protects the list of groups -+ * belonging to the same cgroup. -+ */ -+static void bfq_group_chain_link(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css, -+ struct bfq_group *leaf) -+{ -+ struct bfqio_cgroup *bgrp; -+ struct bfq_group *bfqg, *next, *prev = NULL; -+ unsigned long flags; -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ -+ for (; css != NULL && leaf != NULL; css = css->parent) { -+ bgrp = css_to_bfqio(css); -+ next = leaf->bfqd; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ BUG_ON(bfqg != NULL); -+ -+ spin_lock_irqsave(&bgrp->lock, flags); -+ -+ rcu_assign_pointer(leaf->bfqd, bfqd); -+ hlist_add_head_rcu(&leaf->group_node, &bgrp->group_data); -+ hlist_add_head(&leaf->bfqd_node, &bfqd->group_list); -+ -+ spin_unlock_irqrestore(&bgrp->lock, flags); -+ -+ prev = leaf; -+ leaf = next; -+ } -+ -+ BUG_ON(css == NULL && leaf != NULL); -+ if (css != NULL && prev != NULL) { -+ bgrp = css_to_bfqio(css); -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ bfq_group_set_parent(prev, bfqg); -+ } -+} -+ -+/** -+ * bfq_find_alloc_group - return the group associated to @bfqd in @cgroup. -+ * @bfqd: queue descriptor. -+ * @cgroup: cgroup being searched for. -+ * -+ * Return a group associated to @bfqd in @cgroup, allocating one if -+ * necessary. When a group is returned all the cgroups in the path -+ * to the root have a group associated to @bfqd. -+ * -+ * If the allocation fails, return the root group: this breaks guarantees -+ * but is a safe fallback. If this loss becomes a problem it can be -+ * mitigated using the equivalent weight (given by the product of the -+ * weights of the groups in the path from @group to the root) in the -+ * root scheduler. -+ * -+ * We allocate all the missing nodes in the path from the leaf cgroup -+ * to the root and we connect the nodes only after all the allocations -+ * have been successful. -+ */ -+static struct bfq_group *bfq_find_alloc_group(struct bfq_data *bfqd, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct bfq_group *bfqg; -+ -+ bfqg = bfqio_lookup_group(bgrp, bfqd); -+ if (bfqg != NULL) -+ return bfqg; -+ -+ bfqg = bfq_group_chain_alloc(bfqd, css); -+ if (bfqg != NULL) -+ bfq_group_chain_link(bfqd, css, bfqg); -+ else -+ bfqg = bfqd->root_group; -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bfqq_move - migrate @bfqq to @bfqg. -+ * @bfqd: queue descriptor. -+ * @bfqq: the queue to move. -+ * @entity: @bfqq's entity. -+ * @bfqg: the group to move to. -+ * -+ * Move @bfqq to @bfqg, deactivating it from its old group and reactivating -+ * it on the new one. Avoid putting the entity on the old group idle tree. -+ * -+ * Must be called under the queue lock; the cgroup owning @bfqg must -+ * not disappear (by now this just means that we are called under -+ * rcu_read_lock()). -+ */ -+static void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct bfq_entity *entity, struct bfq_group *bfqg) -+{ -+ int busy, resume; -+ -+ busy = bfq_bfqq_busy(bfqq); -+ resume = !RB_EMPTY_ROOT(&bfqq->sort_list); -+ -+ BUG_ON(resume && !entity->on_st); -+ BUG_ON(busy && !resume && entity->on_st && -+ bfqq != bfqd->in_service_queue); -+ -+ if (busy) { -+ BUG_ON(atomic_read(&bfqq->ref) < 2); -+ -+ if (!resume) -+ bfq_del_bfqq_busy(bfqd, bfqq, 0); -+ else -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ } else if (entity->on_st) -+ bfq_put_idle_entity(bfq_entity_service_tree(entity), entity); -+ -+ /* -+ * Here we use a reference to bfqg. We don't need a refcounter -+ * as the cgroup reference will not be dropped, so that its -+ * destroy() callback will not be invoked. -+ */ -+ entity->parent = bfqg->my_entity; -+ entity->sched_data = &bfqg->sched_data; -+ -+ if (busy && resume) -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ if (bfqd->in_service_queue == NULL && !bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+} -+ -+/** -+ * __bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bfqd: the queue descriptor. -+ * @bic: the bic to move. -+ * @cgroup: the cgroup to move to. -+ * -+ * Move bic to cgroup, assuming that bfqd->queue is locked; the caller -+ * has to make sure that the reference to cgroup is valid across the call. -+ * -+ * NOTE: an alternative approach might have been to store the current -+ * cgroup in bfqq and getting a reference to it, reducing the lookup -+ * time here, at the price of slightly more complex code. -+ */ -+static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0); -+ struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1); -+ struct bfq_entity *entity; -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ -+ bgrp = css_to_bfqio(css); -+ -+ bfqg = bfq_find_alloc_group(bfqd, css); -+ if (async_bfqq != NULL) { -+ entity = &async_bfqq->entity; -+ -+ if (entity->sched_data != &bfqg->sched_data) { -+ bic_set_bfqq(bic, NULL, 0); -+ bfq_log_bfqq(bfqd, async_bfqq, -+ "bic_change_group: %p %d", -+ async_bfqq, atomic_read(&async_bfqq->ref)); -+ bfq_put_queue(async_bfqq); -+ } -+ } -+ -+ if (sync_bfqq != NULL) { -+ entity = &sync_bfqq->entity; -+ if (entity->sched_data != &bfqg->sched_data) -+ bfq_bfqq_move(bfqd, sync_bfqq, entity, bfqg); -+ } -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_bic_change_cgroup - move @bic to @cgroup. -+ * @bic: the bic being migrated. -+ * @cgroup: the destination cgroup. -+ * -+ * When the task owning @bic is moved to @cgroup, @bic is immediately -+ * moved into its new parent group. -+ */ -+static void bfq_bic_change_cgroup(struct bfq_io_cq *bic, -+ struct cgroup_subsys_state *css) -+{ -+ struct bfq_data *bfqd; -+ unsigned long uninitialized_var(flags); -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ if (bfqd != NULL) { -+ __bfq_bic_change_cgroup(bfqd, bic, css); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+} -+ -+/** -+ * bfq_bic_update_cgroup - update the cgroup of @bic. -+ * @bic: the @bic to update. -+ * -+ * Make sure that @bic is enqueued in the cgroup of the current task. -+ * We need this in addition to moving bics during the cgroup attach -+ * phase because the task owning @bic could be at its first disk -+ * access or we may end up in the root cgroup as the result of a -+ * memory allocation failure and here we try to move to the right -+ * group. -+ * -+ * Must be called under the queue lock. It is safe to use the returned -+ * value even after the rcu_read_unlock() as the migration/destruction -+ * paths act under the queue lock too. IOW it is impossible to race with -+ * group migration/destruction and end up with an invalid group as: -+ * a) here cgroup has not yet been destroyed, nor its destroy callback -+ * has started execution, as current holds a reference to it, -+ * b) if it is destroyed after rcu_read_unlock() [after current is -+ * migrated to a different cgroup] its attach() callback will have -+ * taken care of remove all the references to the old cgroup data. -+ */ -+static struct bfq_group *bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ struct bfq_group *bfqg; -+ struct cgroup_subsys_state *css; -+ -+ BUG_ON(bfqd == NULL); -+ -+ rcu_read_lock(); -+ css = task_css(current, bfqio_subsys_id); -+ bfqg = __bfq_bic_change_cgroup(bfqd, bic, css); -+ rcu_read_unlock(); -+ -+ return bfqg; -+} -+ -+/** -+ * bfq_flush_idle_tree - deactivate any entity on the idle tree of @st. -+ * @st: the service tree being flushed. -+ */ -+static inline void bfq_flush_idle_tree(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entity = st->first_idle; -+ -+ for (; entity != NULL; entity = st->first_idle) -+ __bfq_deactivate_entity(entity, 0); -+} -+ -+/** -+ * bfq_reparent_leaf_entity - move leaf entity to the root_group. -+ * @bfqd: the device data structure with the root group. -+ * @entity: the entity to move. -+ */ -+static inline void bfq_reparent_leaf_entity(struct bfq_data *bfqd, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(bfqq == NULL); -+ bfq_bfqq_move(bfqd, bfqq, entity, bfqd->root_group); -+ return; -+} -+ -+/** -+ * bfq_reparent_active_entities - move to the root group all active -+ * entities. -+ * @bfqd: the device data structure with the root group. -+ * @bfqg: the group to move from. -+ * @st: the service tree with the entities. -+ * -+ * Needs queue_lock to be taken and reference to be valid over the call. -+ */ -+static inline void bfq_reparent_active_entities(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ struct bfq_service_tree *st) -+{ -+ struct rb_root *active = &st->active; -+ struct bfq_entity *entity = NULL; -+ -+ if (!RB_EMPTY_ROOT(&st->active)) -+ entity = bfq_entity_of(rb_first(active)); -+ -+ for (; entity != NULL; entity = bfq_entity_of(rb_first(active))) -+ bfq_reparent_leaf_entity(bfqd, entity); -+ -+ if (bfqg->sched_data.in_service_entity != NULL) -+ bfq_reparent_leaf_entity(bfqd, -+ bfqg->sched_data.in_service_entity); -+ -+ return; -+} -+ -+/** -+ * bfq_destroy_group - destroy @bfqg. -+ * @bgrp: the bfqio_cgroup containing @bfqg. -+ * @bfqg: the group being destroyed. -+ * -+ * Destroy @bfqg, making sure that it is not referenced from its parent. -+ */ -+static void bfq_destroy_group(struct bfqio_cgroup *bgrp, struct bfq_group *bfqg) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_service_tree *st; -+ struct bfq_entity *entity = bfqg->my_entity; -+ unsigned long uninitialized_var(flags); -+ int i; -+ -+ hlist_del(&bfqg->group_node); -+ -+ /* -+ * Empty all service_trees belonging to this group before -+ * deactivating the group itself. -+ */ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) { -+ st = bfqg->sched_data.service_tree + i; -+ -+ /* -+ * The idle tree may still contain bfq_queues belonging -+ * to exited task because they never migrated to a different -+ * cgroup from the one being destroyed now. No one else -+ * can access them so it's safe to act without any lock. -+ */ -+ bfq_flush_idle_tree(st); -+ -+ /* -+ * It may happen that some queues are still active -+ * (busy) upon group destruction (if the corresponding -+ * processes have been forced to terminate). We move -+ * all the leaf entities corresponding to these queues -+ * to the root_group. -+ * Also, it may happen that the group has an entity -+ * in service, which is disconnected from the active -+ * tree: it must be moved, too. -+ * There is no need to put the sync queues, as the -+ * scheduler has taken no reference. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ bfq_reparent_active_entities(bfqd, bfqg, st); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(!RB_EMPTY_ROOT(&st->active)); -+ BUG_ON(!RB_EMPTY_ROOT(&st->idle)); -+ } -+ BUG_ON(bfqg->sched_data.next_in_service != NULL); -+ BUG_ON(bfqg->sched_data.in_service_entity != NULL); -+ -+ /* -+ * We may race with device destruction, take extra care when -+ * dereferencing bfqg->bfqd. -+ */ -+ bfqd = bfq_get_bfqd_locked(&bfqg->bfqd, &flags); -+ if (bfqd != NULL) { -+ hlist_del(&bfqg->bfqd_node); -+ __bfq_deactivate_entity(entity, 0); -+ bfq_put_async_queues(bfqd, bfqg); -+ bfq_put_bfqd_unlock(bfqd, &flags); -+ } -+ BUG_ON(entity->tree != NULL); -+ -+ /* -+ * No need to defer the kfree() to the end of the RCU grace -+ * period: we are called from the destroy() callback of our -+ * cgroup, so we can be sure that no one is a) still using -+ * this cgroup or b) doing lookups in it. -+ */ -+ kfree(bfqg); -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) -+ bfq_end_wr_async_queues(bfqd, bfqg); -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+/** -+ * bfq_disconnect_groups - disconnect @bfqd from all its groups. -+ * @bfqd: the device descriptor being exited. -+ * -+ * When the device exits we just make sure that no lookup can return -+ * the now unused group structures. They will be deallocated on cgroup -+ * destruction. -+ */ -+static void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ bfq_log(bfqd, "disconnect_groups beginning"); -+ hlist_for_each_entry_safe(bfqg, tmp, &bfqd->group_list, bfqd_node) { -+ hlist_del(&bfqg->bfqd_node); -+ -+ __bfq_deactivate_entity(bfqg->my_entity, 0); -+ -+ /* -+ * Don't remove from the group hash, just set an -+ * invalid key. No lookups can race with the -+ * assignment as bfqd is being destroyed; this -+ * implies also that new elements cannot be added -+ * to the list. -+ */ -+ rcu_assign_pointer(bfqg->bfqd, NULL); -+ -+ bfq_log(bfqd, "disconnect_groups: put async for group %p", -+ bfqg); -+ bfq_put_async_queues(bfqd, bfqg); -+ } -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ struct bfqio_cgroup *bgrp = &bfqio_root_cgroup; -+ struct bfq_group *bfqg = bfqd->root_group; -+ -+ bfq_put_async_queues(bfqd, bfqg); -+ -+ spin_lock_irq(&bgrp->lock); -+ hlist_del_rcu(&bfqg->group_node); -+ spin_unlock_irq(&bgrp->lock); -+ -+ /* -+ * No need to synchronize_rcu() here: since the device is gone -+ * there cannot be any read-side access to its root_group. -+ */ -+ kfree(bfqg); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ struct bfqio_cgroup *bgrp; -+ int i; -+ -+ bfqg = kzalloc_node(sizeof(*bfqg), GFP_KERNEL, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ bfqg->entity.parent = NULL; -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ bgrp = &bfqio_root_cgroup; -+ spin_lock_irq(&bgrp->lock); -+ rcu_assign_pointer(bfqg->bfqd, bfqd); -+ hlist_add_head_rcu(&bfqg->group_node, &bgrp->group_data); -+ spin_unlock_irq(&bgrp->lock); -+ -+ return bfqg; -+} -+ -+#define SHOW_FUNCTION(__VAR) \ -+static u64 bfqio_cgroup_##__VAR##_read(struct cgroup_subsys_state *css, \ -+ struct cftype *cftype) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ u64 ret = -ENODEV; \ -+ \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ ret = bgrp->__VAR; \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+SHOW_FUNCTION(weight); -+SHOW_FUNCTION(ioprio); -+SHOW_FUNCTION(ioprio_class); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__VAR, __MIN, __MAX) \ -+static int bfqio_cgroup_##__VAR##_write(struct cgroup_subsys_state *css,\ -+ struct cftype *cftype, \ -+ u64 val) \ -+{ \ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); \ -+ struct bfq_group *bfqg; \ -+ int ret = -EINVAL; \ -+ \ -+ if (val < (__MIN) || val > (__MAX)) \ -+ return ret; \ -+ \ -+ ret = -ENODEV; \ -+ mutex_lock(&bfqio_mutex); \ -+ if (bfqio_is_removed(bgrp)) \ -+ goto out_unlock; \ -+ ret = 0; \ -+ \ -+ spin_lock_irq(&bgrp->lock); \ -+ bgrp->__VAR = (unsigned short)val; \ -+ hlist_for_each_entry(bfqg, &bgrp->group_data, group_node) { \ -+ /* \ -+ * Setting the ioprio_changed flag of the entity \ -+ * to 1 with new_##__VAR == ##__VAR would re-set \ -+ * the value of the weight to its ioprio mapping. \ -+ * Set the flag only if necessary. \ -+ */ \ -+ if ((unsigned short)val != bfqg->entity.new_##__VAR) { \ -+ bfqg->entity.new_##__VAR = (unsigned short)val; \ -+ /* \ -+ * Make sure that the above new value has been \ -+ * stored in bfqg->entity.new_##__VAR before \ -+ * setting the ioprio_changed flag. In fact, \ -+ * this flag may be read asynchronously (in \ -+ * critical sections protected by a different \ -+ * lock than that held here), and finding this \ -+ * flag set may cause the execution of the code \ -+ * for updating parameters whose value may \ -+ * depend also on bfqg->entity.new_##__VAR (in \ -+ * __bfq_entity_update_weight_prio). \ -+ * This barrier makes sure that the new value \ -+ * of bfqg->entity.new_##__VAR is correctly \ -+ * seen in that code. \ -+ */ \ -+ smp_wmb(); \ -+ bfqg->entity.ioprio_changed = 1; \ -+ } \ -+ } \ -+ spin_unlock_irq(&bgrp->lock); \ -+ \ -+out_unlock: \ -+ mutex_unlock(&bfqio_mutex); \ -+ return ret; \ -+} -+ -+STORE_FUNCTION(weight, BFQ_MIN_WEIGHT, BFQ_MAX_WEIGHT); -+STORE_FUNCTION(ioprio, 0, IOPRIO_BE_NR - 1); -+STORE_FUNCTION(ioprio_class, IOPRIO_CLASS_RT, IOPRIO_CLASS_IDLE); -+#undef STORE_FUNCTION -+ -+static struct cftype bfqio_files[] = { -+ { -+ .name = "weight", -+ .read_u64 = bfqio_cgroup_weight_read, -+ .write_u64 = bfqio_cgroup_weight_write, -+ }, -+ { -+ .name = "ioprio", -+ .read_u64 = bfqio_cgroup_ioprio_read, -+ .write_u64 = bfqio_cgroup_ioprio_write, -+ }, -+ { -+ .name = "ioprio_class", -+ .read_u64 = bfqio_cgroup_ioprio_class_read, -+ .write_u64 = bfqio_cgroup_ioprio_class_write, -+ }, -+ { }, /* terminate */ -+}; -+ -+static struct cgroup_subsys_state *bfqio_create(struct cgroup_subsys_state -+ *parent_css) -+{ -+ struct bfqio_cgroup *bgrp; -+ -+ if (parent_css != NULL) { -+ bgrp = kzalloc(sizeof(*bgrp), GFP_KERNEL); -+ if (bgrp == NULL) -+ return ERR_PTR(-ENOMEM); -+ } else -+ bgrp = &bfqio_root_cgroup; -+ -+ spin_lock_init(&bgrp->lock); -+ INIT_HLIST_HEAD(&bgrp->group_data); -+ bgrp->ioprio = BFQ_DEFAULT_GRP_IOPRIO; -+ bgrp->ioprio_class = BFQ_DEFAULT_GRP_CLASS; -+ -+ return &bgrp->css; -+} -+ -+/* -+ * We cannot support shared io contexts, as we have no means to support -+ * two tasks with the same ioc in two different groups without major rework -+ * of the main bic/bfqq data structures. By now we allow a task to change -+ * its cgroup only if it's the only owner of its ioc; the drawback of this -+ * behavior is that a group containing a task that forked using CLONE_IO -+ * will not be destroyed until the tasks sharing the ioc die. -+ */ -+static int bfqio_can_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ int ret = 0; -+ -+ cgroup_taskset_for_each(task, css, tset) { -+ /* -+ * task_lock() is needed to avoid races with -+ * exit_io_context() -+ */ -+ task_lock(task); -+ ioc = task->io_context; -+ if (ioc != NULL && atomic_read(&ioc->nr_tasks) > 1) -+ /* -+ * ioc == NULL means that the task is either too -+ * young or exiting: if it has still no ioc the -+ * ioc can't be shared, if the task is exiting the -+ * attach will fail anyway, no matter what we -+ * return here. -+ */ -+ ret = -EINVAL; -+ task_unlock(task); -+ if (ret) -+ break; -+ } -+ -+ return ret; -+} -+ -+static void bfqio_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ struct io_context *ioc; -+ struct io_cq *icq; -+ -+ /* -+ * IMPORTANT NOTE: The move of more than one process at a time to a -+ * new group has not yet been tested. -+ */ -+ cgroup_taskset_for_each(task, css, tset) { -+ ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); -+ if (ioc) { -+ /* -+ * Handle cgroup change here. -+ */ -+ rcu_read_lock(); -+ hlist_for_each_entry_rcu(icq, &ioc->icq_list, ioc_node) -+ if (!strncmp( -+ icq->q->elevator->type->elevator_name, -+ "bfq", ELV_NAME_MAX)) -+ bfq_bic_change_cgroup(icq_to_bic(icq), -+ css); -+ rcu_read_unlock(); -+ put_io_context(ioc); -+ } -+ } -+} -+ -+static void bfqio_destroy(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ struct hlist_node *tmp; -+ struct bfq_group *bfqg; -+ -+ /* -+ * Since we are destroying the cgroup, there are no more tasks -+ * referencing it, and all the RCU grace periods that may have -+ * referenced it are ended (as the destruction of the parent -+ * cgroup is RCU-safe); bgrp->group_data will not be accessed by -+ * anything else and we don't need any synchronization. -+ */ -+ hlist_for_each_entry_safe(bfqg, tmp, &bgrp->group_data, group_node) -+ bfq_destroy_group(bgrp, bfqg); -+ -+ BUG_ON(!hlist_empty(&bgrp->group_data)); -+ -+ kfree(bgrp); -+} -+ -+static int bfqio_css_online(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = true; -+ mutex_unlock(&bfqio_mutex); -+ -+ return 0; -+} -+ -+static void bfqio_css_offline(struct cgroup_subsys_state *css) -+{ -+ struct bfqio_cgroup *bgrp = css_to_bfqio(css); -+ -+ mutex_lock(&bfqio_mutex); -+ bgrp->online = false; -+ mutex_unlock(&bfqio_mutex); -+} -+ -+struct cgroup_subsys bfqio_subsys = { -+ .name = "bfqio", -+ .css_alloc = bfqio_create, -+ .css_online = bfqio_css_online, -+ .css_offline = bfqio_css_offline, -+ .can_attach = bfqio_can_attach, -+ .attach = bfqio_attach, -+ .css_free = bfqio_destroy, -+ .subsys_id = bfqio_subsys_id, -+ .base_cftypes = bfqio_files, -+}; -+#else -+static inline void bfq_init_entity(struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+ entity->weight = entity->new_weight; -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = entity->new_ioprio; -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->sched_data = &bfqg->sched_data; -+} -+ -+static inline struct bfq_group * -+bfq_bic_update_cgroup(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ return bfqd->root_group; -+} -+ -+static inline void bfq_bfqq_move(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_entity *entity, -+ struct bfq_group *bfqg) -+{ -+} -+ -+static void bfq_end_wr_async(struct bfq_data *bfqd) -+{ -+ bfq_end_wr_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_disconnect_groups(struct bfq_data *bfqd) -+{ -+ bfq_put_async_queues(bfqd, bfqd->root_group); -+} -+ -+static inline void bfq_free_root_group(struct bfq_data *bfqd) -+{ -+ kfree(bfqd->root_group); -+} -+ -+static struct bfq_group *bfq_alloc_root_group(struct bfq_data *bfqd, int node) -+{ -+ struct bfq_group *bfqg; -+ int i; -+ -+ bfqg = kmalloc_node(sizeof(*bfqg), GFP_KERNEL | __GFP_ZERO, node); -+ if (bfqg == NULL) -+ return NULL; -+ -+ for (i = 0; i < BFQ_IOPRIO_CLASSES; i++) -+ bfqg->sched_data.service_tree[i] = BFQ_SERVICE_TREE_INIT; -+ -+ return bfqg; -+} -+#endif -diff -Nur linux-3.14.22.orig/block/bfq.h linux-3.14.22/block/bfq.h ---- linux-3.14.22.orig/block/bfq.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/block/bfq.h 2014-10-22 14:55:51.954220001 -0500 -@@ -0,0 +1,770 @@ -+/* -+ * BFQ-v7r5 for 3.14.0: data structures and common functions prototypes. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifndef _BFQ_H -+#define _BFQ_H -+ -+#include -+#include -+#include -+#include -+ -+#define BFQ_IOPRIO_CLASSES 3 -+#define BFQ_CL_IDLE_TIMEOUT (HZ/5) -+ -+#define BFQ_MIN_WEIGHT 1 -+#define BFQ_MAX_WEIGHT 1000 -+ -+#define BFQ_DEFAULT_GRP_WEIGHT 10 -+#define BFQ_DEFAULT_GRP_IOPRIO 0 -+#define BFQ_DEFAULT_GRP_CLASS IOPRIO_CLASS_BE -+ -+struct bfq_entity; -+ -+/** -+ * struct bfq_service_tree - per ioprio_class service tree. -+ * @active: tree for active entities (i.e., those backlogged). -+ * @idle: tree for idle entities (i.e., those not backlogged, with V <= F_i). -+ * @first_idle: idle entity with minimum F_i. -+ * @last_idle: idle entity with maximum F_i. -+ * @vtime: scheduler virtual time. -+ * @wsum: scheduler weight sum; active and idle entities contribute to it. -+ * -+ * Each service tree represents a B-WF2Q+ scheduler on its own. Each -+ * ioprio_class has its own independent scheduler, and so its own -+ * bfq_service_tree. All the fields are protected by the queue lock -+ * of the containing bfqd. -+ */ -+struct bfq_service_tree { -+ struct rb_root active; -+ struct rb_root idle; -+ -+ struct bfq_entity *first_idle; -+ struct bfq_entity *last_idle; -+ -+ u64 vtime; -+ unsigned long wsum; -+}; -+ -+/** -+ * struct bfq_sched_data - multi-class scheduler. -+ * @in_service_entity: entity in service. -+ * @next_in_service: head-of-the-line entity in the scheduler. -+ * @service_tree: array of service trees, one per ioprio_class. -+ * -+ * bfq_sched_data is the basic scheduler queue. It supports three -+ * ioprio_classes, and can be used either as a toplevel queue or as -+ * an intermediate queue on a hierarchical setup. -+ * @next_in_service points to the active entity of the sched_data -+ * service trees that will be scheduled next. -+ * -+ * The supported ioprio_classes are the same as in CFQ, in descending -+ * priority order, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE. -+ * Requests from higher priority queues are served before all the -+ * requests from lower priority queues; among requests of the same -+ * queue requests are served according to B-WF2Q+. -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_sched_data { -+ struct bfq_entity *in_service_entity; -+ struct bfq_entity *next_in_service; -+ struct bfq_service_tree service_tree[BFQ_IOPRIO_CLASSES]; -+}; -+ -+/** -+ * struct bfq_weight_counter - counter of the number of all active entities -+ * with a given weight. -+ * @weight: weight of the entities that this counter refers to. -+ * @num_active: number of active entities with this weight. -+ * @weights_node: weights tree member (see bfq_data's @queue_weights_tree -+ * and @group_weights_tree). -+ */ -+struct bfq_weight_counter { -+ short int weight; -+ unsigned int num_active; -+ struct rb_node weights_node; -+}; -+ -+/** -+ * struct bfq_entity - schedulable entity. -+ * @rb_node: service_tree member. -+ * @weight_counter: pointer to the weight counter associated with this entity. -+ * @on_st: flag, true if the entity is on a tree (either the active or -+ * the idle one of its service_tree). -+ * @finish: B-WF2Q+ finish timestamp (aka F_i). -+ * @start: B-WF2Q+ start timestamp (aka S_i). -+ * @tree: tree the entity is enqueued into; %NULL if not on a tree. -+ * @min_start: minimum start time of the (active) subtree rooted at -+ * this entity; used for O(log N) lookups into active trees. -+ * @service: service received during the last round of service. -+ * @budget: budget used to calculate F_i; F_i = S_i + @budget / @weight. -+ * @weight: weight of the queue -+ * @parent: parent entity, for hierarchical scheduling. -+ * @my_sched_data: for non-leaf nodes in the cgroup hierarchy, the -+ * associated scheduler queue, %NULL on leaf nodes. -+ * @sched_data: the scheduler queue this entity belongs to. -+ * @ioprio: the ioprio in use. -+ * @new_weight: when a weight change is requested, the new weight value. -+ * @orig_weight: original weight, used to implement weight boosting -+ * @new_ioprio: when an ioprio change is requested, the new ioprio value. -+ * @ioprio_class: the ioprio_class in use. -+ * @new_ioprio_class: when an ioprio_class change is requested, the new -+ * ioprio_class value. -+ * @ioprio_changed: flag, true when the user requested a weight, ioprio or -+ * ioprio_class change. -+ * -+ * A bfq_entity is used to represent either a bfq_queue (leaf node in the -+ * cgroup hierarchy) or a bfq_group into the upper level scheduler. Each -+ * entity belongs to the sched_data of the parent group in the cgroup -+ * hierarchy. Non-leaf entities have also their own sched_data, stored -+ * in @my_sched_data. -+ * -+ * Each entity stores independently its priority values; this would -+ * allow different weights on different devices, but this -+ * functionality is not exported to userspace by now. Priorities and -+ * weights are updated lazily, first storing the new values into the -+ * new_* fields, then setting the @ioprio_changed flag. As soon as -+ * there is a transition in the entity state that allows the priority -+ * update to take place the effective and the requested priority -+ * values are synchronized. -+ * -+ * Unless cgroups are used, the weight value is calculated from the -+ * ioprio to export the same interface as CFQ. When dealing with -+ * ``well-behaved'' queues (i.e., queues that do not spend too much -+ * time to consume their budget and have true sequential behavior, and -+ * when there are no external factors breaking anticipation) the -+ * relative weights at each level of the cgroups hierarchy should be -+ * guaranteed. All the fields are protected by the queue lock of the -+ * containing bfqd. -+ */ -+struct bfq_entity { -+ struct rb_node rb_node; -+ struct bfq_weight_counter *weight_counter; -+ -+ int on_st; -+ -+ u64 finish; -+ u64 start; -+ -+ struct rb_root *tree; -+ -+ u64 min_start; -+ -+ unsigned long service, budget; -+ unsigned short weight, new_weight; -+ unsigned short orig_weight; -+ -+ struct bfq_entity *parent; -+ -+ struct bfq_sched_data *my_sched_data; -+ struct bfq_sched_data *sched_data; -+ -+ unsigned short ioprio, new_ioprio; -+ unsigned short ioprio_class, new_ioprio_class; -+ -+ int ioprio_changed; -+}; -+ -+struct bfq_group; -+ -+/** -+ * struct bfq_queue - leaf schedulable entity. -+ * @ref: reference counter. -+ * @bfqd: parent bfq_data. -+ * @new_bfqq: shared bfq_queue if queue is cooperating with -+ * one or more other queues. -+ * @pos_node: request-position tree member (see bfq_data's @rq_pos_tree). -+ * @pos_root: request-position tree root (see bfq_data's @rq_pos_tree). -+ * @sort_list: sorted list of pending requests. -+ * @next_rq: if fifo isn't expired, next request to serve. -+ * @queued: nr of requests queued in @sort_list. -+ * @allocated: currently allocated requests. -+ * @meta_pending: pending metadata requests. -+ * @fifo: fifo list of requests in sort_list. -+ * @entity: entity representing this queue in the scheduler. -+ * @max_budget: maximum budget allowed from the feedback mechanism. -+ * @budget_timeout: budget expiration (in jiffies). -+ * @dispatched: number of requests on the dispatch list or inside driver. -+ * @flags: status flags. -+ * @bfqq_list: node for active/idle bfqq list inside our bfqd. -+ * @seek_samples: number of seeks sampled -+ * @seek_total: sum of the distances of the seeks sampled -+ * @seek_mean: mean seek distance -+ * @last_request_pos: position of the last request enqueued -+ * @requests_within_timer: number of consecutive pairs of request completion -+ * and arrival, such that the queue becomes idle -+ * after the completion, but the next request arrives -+ * within an idle time slice; used only if the queue's -+ * IO_bound has been cleared. -+ * @pid: pid of the process owning the queue, used for logging purposes. -+ * @last_wr_start_finish: start time of the current weight-raising period if -+ * the @bfq-queue is being weight-raised, otherwise -+ * finish time of the last weight-raising period -+ * @wr_cur_max_time: current max raising time for this queue -+ * @soft_rt_next_start: minimum time instant such that, only if a new -+ * request is enqueued after this time instant in an -+ * idle @bfq_queue with no outstanding requests, then -+ * the task associated with the queue it is deemed as -+ * soft real-time (see the comments to the function -+ * bfq_bfqq_softrt_next_start()) -+ * @last_idle_bklogged: time of the last transition of the @bfq_queue from -+ * idle to backlogged -+ * @service_from_backlogged: cumulative service received from the @bfq_queue -+ * since the last transition from idle to -+ * backlogged -+ * @bic: pointer to the bfq_io_cq owning the bfq_queue, set to %NULL if the -+ * queue is shared -+ * -+ * A bfq_queue is a leaf request queue; it can be associated with an -+ * io_context or more, if it is async or shared between cooperating -+ * processes. @cgroup holds a reference to the cgroup, to be sure that it -+ * does not disappear while a bfqq still references it (mostly to avoid -+ * races between request issuing and task migration followed by cgroup -+ * destruction). -+ * All the fields are protected by the queue lock of the containing bfqd. -+ */ -+struct bfq_queue { -+ atomic_t ref; -+ struct bfq_data *bfqd; -+ -+ /* fields for cooperating queues handling */ -+ struct bfq_queue *new_bfqq; -+ struct rb_node pos_node; -+ struct rb_root *pos_root; -+ -+ struct rb_root sort_list; -+ struct request *next_rq; -+ int queued[2]; -+ int allocated[2]; -+ int meta_pending; -+ struct list_head fifo; -+ -+ struct bfq_entity entity; -+ -+ unsigned long max_budget; -+ unsigned long budget_timeout; -+ -+ int dispatched; -+ -+ unsigned int flags; -+ -+ struct list_head bfqq_list; -+ -+ unsigned int seek_samples; -+ u64 seek_total; -+ sector_t seek_mean; -+ sector_t last_request_pos; -+ -+ unsigned int requests_within_timer; -+ -+ pid_t pid; -+ struct bfq_io_cq *bic; -+ -+ /* weight-raising fields */ -+ unsigned long wr_cur_max_time; -+ unsigned long soft_rt_next_start; -+ unsigned long last_wr_start_finish; -+ unsigned int wr_coeff; -+ unsigned long last_idle_bklogged; -+ unsigned long service_from_backlogged; -+}; -+ -+/** -+ * struct bfq_ttime - per process thinktime stats. -+ * @ttime_total: total process thinktime -+ * @ttime_samples: number of thinktime samples -+ * @ttime_mean: average process thinktime -+ */ -+struct bfq_ttime { -+ unsigned long last_end_request; -+ -+ unsigned long ttime_total; -+ unsigned long ttime_samples; -+ unsigned long ttime_mean; -+}; -+ -+/** -+ * struct bfq_io_cq - per (request_queue, io_context) structure. -+ * @icq: associated io_cq structure -+ * @bfqq: array of two process queues, the sync and the async -+ * @ttime: associated @bfq_ttime struct -+ * @wr_time_left: snapshot of the time left before weight raising ends -+ * for the sync queue associated to this process; this -+ * snapshot is taken to remember this value while the weight -+ * raising is suspended because the queue is merged with a -+ * shared queue, and is used to set @raising_cur_max_time -+ * when the queue is split from the shared queue and its -+ * weight is raised again -+ * @saved_idle_window: same purpose as the previous field for the idle -+ * window -+ * @saved_IO_bound: same purpose as the previous two fields for the I/O -+ * bound classification of a queue -+ * @cooperations: counter of consecutive successful queue merges underwent -+ * by any of the process' @bfq_queues -+ * @failed_cooperations: counter of consecutive failed queue merges of any -+ * of the process' @bfq_queues -+ */ -+struct bfq_io_cq { -+ struct io_cq icq; /* must be the first member */ -+ struct bfq_queue *bfqq[2]; -+ struct bfq_ttime ttime; -+ int ioprio; -+ -+ unsigned int wr_time_left; -+ unsigned int saved_idle_window; -+ unsigned int saved_IO_bound; -+ -+ unsigned int cooperations; -+ unsigned int failed_cooperations; -+}; -+ -+enum bfq_device_speed { -+ BFQ_BFQD_FAST, -+ BFQ_BFQD_SLOW, -+}; -+ -+/** -+ * struct bfq_data - per device data structure. -+ * @queue: request queue for the managed device. -+ * @root_group: root bfq_group for the device. -+ * @rq_pos_tree: rbtree sorted by next_request position, used when -+ * determining if two or more queues have interleaving -+ * requests (see bfq_close_cooperator()). -+ * @active_numerous_groups: number of bfq_groups containing more than one -+ * active @bfq_entity. -+ * @queue_weights_tree: rbtree of weight counters of @bfq_queues, sorted by -+ * weight. Used to keep track of whether all @bfq_queues -+ * have the same weight. The tree contains one counter -+ * for each distinct weight associated to some active -+ * and not weight-raised @bfq_queue (see the comments to -+ * the functions bfq_weights_tree_[add|remove] for -+ * further details). -+ * @group_weights_tree: rbtree of non-queue @bfq_entity weight counters, sorted -+ * by weight. Used to keep track of whether all -+ * @bfq_groups have the same weight. The tree contains -+ * one counter for each distinct weight associated to -+ * some active @bfq_group (see the comments to the -+ * functions bfq_weights_tree_[add|remove] for further -+ * details). -+ * @busy_queues: number of bfq_queues containing requests (including the -+ * queue in service, even if it is idling). -+ * @busy_in_flight_queues: number of @bfq_queues containing pending or -+ * in-flight requests, plus the @bfq_queue in -+ * service, even if idle but waiting for the -+ * possible arrival of its next sync request. This -+ * field is updated only if the device is rotational, -+ * but used only if the device is also NCQ-capable. -+ * The reason why the field is updated also for non- -+ * NCQ-capable rotational devices is related to the -+ * fact that the value of @hw_tag may be set also -+ * later than when busy_in_flight_queues may need to -+ * be incremented for the first time(s). Taking also -+ * this possibility into account, to avoid unbalanced -+ * increments/decrements, would imply more overhead -+ * than just updating busy_in_flight_queues -+ * regardless of the value of @hw_tag. -+ * @const_seeky_busy_in_flight_queues: number of constantly-seeky @bfq_queues -+ * (that is, seeky queues that expired -+ * for budget timeout at least once) -+ * containing pending or in-flight -+ * requests, including the in-service -+ * @bfq_queue if constantly seeky. This -+ * field is updated only if the device -+ * is rotational, but used only if the -+ * device is also NCQ-capable (see the -+ * comments to @busy_in_flight_queues). -+ * @wr_busy_queues: number of weight-raised busy @bfq_queues. -+ * @queued: number of queued requests. -+ * @rq_in_driver: number of requests dispatched and waiting for completion. -+ * @sync_flight: number of sync requests in the driver. -+ * @max_rq_in_driver: max number of reqs in driver in the last -+ * @hw_tag_samples completed requests. -+ * @hw_tag_samples: nr of samples used to calculate hw_tag. -+ * @hw_tag: flag set to one if the driver is showing a queueing behavior. -+ * @budgets_assigned: number of budgets assigned. -+ * @idle_slice_timer: timer set when idling for the next sequential request -+ * from the queue in service. -+ * @unplug_work: delayed work to restart dispatching on the request queue. -+ * @in_service_queue: bfq_queue in service. -+ * @in_service_bic: bfq_io_cq (bic) associated with the @in_service_queue. -+ * @last_position: on-disk position of the last served request. -+ * @last_budget_start: beginning of the last budget. -+ * @last_idling_start: beginning of the last idle slice. -+ * @peak_rate: peak transfer rate observed for a budget. -+ * @peak_rate_samples: number of samples used to calculate @peak_rate. -+ * @bfq_max_budget: maximum budget allotted to a bfq_queue before -+ * rescheduling. -+ * @group_list: list of all the bfq_groups active on the device. -+ * @active_list: list of all the bfq_queues active on the device. -+ * @idle_list: list of all the bfq_queues idle on the device. -+ * @bfq_quantum: max number of requests dispatched per dispatch round. -+ * @bfq_fifo_expire: timeout for async/sync requests; when it expires -+ * requests are served in fifo order. -+ * @bfq_back_penalty: weight of backward seeks wrt forward ones. -+ * @bfq_back_max: maximum allowed backward seek. -+ * @bfq_slice_idle: maximum idling time. -+ * @bfq_user_max_budget: user-configured max budget value -+ * (0 for auto-tuning). -+ * @bfq_max_budget_async_rq: maximum budget (in nr of requests) allotted to -+ * async queues. -+ * @bfq_timeout: timeout for bfq_queues to consume their budget; used to -+ * to prevent seeky queues to impose long latencies to well -+ * behaved ones (this also implies that seeky queues cannot -+ * receive guarantees in the service domain; after a timeout -+ * they are charged for the whole allocated budget, to try -+ * to preserve a behavior reasonably fair among them, but -+ * without service-domain guarantees). -+ * @bfq_coop_thresh: number of queue merges after which a @bfq_queue is -+ * no more granted any weight-raising. -+ * @bfq_failed_cooperations: number of consecutive failed cooperation -+ * chances after which weight-raising is restored -+ * to a queue subject to more than bfq_coop_thresh -+ * queue merges. -+ * @bfq_requests_within_timer: number of consecutive requests that must be -+ * issued within the idle time slice to set -+ * again idling to a queue which was marked as -+ * non-I/O-bound (see the definition of the -+ * IO_bound flag for further details). -+ * @bfq_wr_coeff: Maximum factor by which the weight of a weight-raised -+ * queue is multiplied -+ * @bfq_wr_max_time: maximum duration of a weight-raising period (jiffies) -+ * @bfq_wr_rt_max_time: maximum duration for soft real-time processes -+ * @bfq_wr_min_idle_time: minimum idle period after which weight-raising -+ * may be reactivated for a queue (in jiffies) -+ * @bfq_wr_min_inter_arr_async: minimum period between request arrivals -+ * after which weight-raising may be -+ * reactivated for an already busy queue -+ * (in jiffies) -+ * @bfq_wr_max_softrt_rate: max service-rate for a soft real-time queue, -+ * sectors per seconds -+ * @RT_prod: cached value of the product R*T used for computing the maximum -+ * duration of the weight raising automatically -+ * @device_speed: device-speed class for the low-latency heuristic -+ * @oom_bfqq: fallback dummy bfqq for extreme OOM conditions -+ * -+ * All the fields are protected by the @queue lock. -+ */ -+struct bfq_data { -+ struct request_queue *queue; -+ -+ struct bfq_group *root_group; -+ struct rb_root rq_pos_tree; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ int active_numerous_groups; -+#endif -+ -+ struct rb_root queue_weights_tree; -+ struct rb_root group_weights_tree; -+ -+ int busy_queues; -+ int busy_in_flight_queues; -+ int const_seeky_busy_in_flight_queues; -+ int wr_busy_queues; -+ int queued; -+ int rq_in_driver; -+ int sync_flight; -+ -+ int max_rq_in_driver; -+ int hw_tag_samples; -+ int hw_tag; -+ -+ int budgets_assigned; -+ -+ struct timer_list idle_slice_timer; -+ struct work_struct unplug_work; -+ -+ struct bfq_queue *in_service_queue; -+ struct bfq_io_cq *in_service_bic; -+ -+ sector_t last_position; -+ -+ ktime_t last_budget_start; -+ ktime_t last_idling_start; -+ int peak_rate_samples; -+ u64 peak_rate; -+ unsigned long bfq_max_budget; -+ -+ struct hlist_head group_list; -+ struct list_head active_list; -+ struct list_head idle_list; -+ -+ unsigned int bfq_quantum; -+ unsigned int bfq_fifo_expire[2]; -+ unsigned int bfq_back_penalty; -+ unsigned int bfq_back_max; -+ unsigned int bfq_slice_idle; -+ u64 bfq_class_idle_last_service; -+ -+ unsigned int bfq_user_max_budget; -+ unsigned int bfq_max_budget_async_rq; -+ unsigned int bfq_timeout[2]; -+ -+ unsigned int bfq_coop_thresh; -+ unsigned int bfq_failed_cooperations; -+ unsigned int bfq_requests_within_timer; -+ -+ bool low_latency; -+ -+ /* parameters of the low_latency heuristics */ -+ unsigned int bfq_wr_coeff; -+ unsigned int bfq_wr_max_time; -+ unsigned int bfq_wr_rt_max_time; -+ unsigned int bfq_wr_min_idle_time; -+ unsigned long bfq_wr_min_inter_arr_async; -+ unsigned int bfq_wr_max_softrt_rate; -+ u64 RT_prod; -+ enum bfq_device_speed device_speed; -+ -+ struct bfq_queue oom_bfqq; -+}; -+ -+enum bfqq_state_flags { -+ BFQ_BFQQ_FLAG_busy = 0, /* has requests or is in service */ -+ BFQ_BFQQ_FLAG_wait_request, /* waiting for a request */ -+ BFQ_BFQQ_FLAG_must_alloc, /* must be allowed rq alloc */ -+ BFQ_BFQQ_FLAG_fifo_expire, /* FIFO checked in this slice */ -+ BFQ_BFQQ_FLAG_idle_window, /* slice idling enabled */ -+ BFQ_BFQQ_FLAG_prio_changed, /* task priority has changed */ -+ BFQ_BFQQ_FLAG_sync, /* synchronous queue */ -+ BFQ_BFQQ_FLAG_budget_new, /* no completion with this budget */ -+ BFQ_BFQQ_FLAG_IO_bound, /* -+ * bfqq has timed-out at least once -+ * having consumed at most 2/10 of -+ * its budget -+ */ -+ BFQ_BFQQ_FLAG_constantly_seeky, /* -+ * bfqq has proved to be slow and -+ * seeky until budget timeout -+ */ -+ BFQ_BFQQ_FLAG_softrt_update, /* -+ * may need softrt-next-start -+ * update -+ */ -+ BFQ_BFQQ_FLAG_coop, /* bfqq is shared */ -+ BFQ_BFQQ_FLAG_split_coop, /* shared bfqq will be split */ -+ BFQ_BFQQ_FLAG_just_split, /* queue has just been split */ -+}; -+ -+#define BFQ_BFQQ_FNS(name) \ -+static inline void bfq_mark_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags |= (1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline void bfq_clear_bfqq_##name(struct bfq_queue *bfqq) \ -+{ \ -+ (bfqq)->flags &= ~(1 << BFQ_BFQQ_FLAG_##name); \ -+} \ -+static inline int bfq_bfqq_##name(const struct bfq_queue *bfqq) \ -+{ \ -+ return ((bfqq)->flags & (1 << BFQ_BFQQ_FLAG_##name)) != 0; \ -+} -+ -+BFQ_BFQQ_FNS(busy); -+BFQ_BFQQ_FNS(wait_request); -+BFQ_BFQQ_FNS(must_alloc); -+BFQ_BFQQ_FNS(fifo_expire); -+BFQ_BFQQ_FNS(idle_window); -+BFQ_BFQQ_FNS(prio_changed); -+BFQ_BFQQ_FNS(sync); -+BFQ_BFQQ_FNS(budget_new); -+BFQ_BFQQ_FNS(IO_bound); -+BFQ_BFQQ_FNS(constantly_seeky); -+BFQ_BFQQ_FNS(coop); -+BFQ_BFQQ_FNS(split_coop); -+BFQ_BFQQ_FNS(just_split); -+BFQ_BFQQ_FNS(softrt_update); -+#undef BFQ_BFQQ_FNS -+ -+/* Logging facilities. */ -+#define bfq_log_bfqq(bfqd, bfqq, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq%d " fmt, (bfqq)->pid, ##args) -+ -+#define bfq_log(bfqd, fmt, args...) \ -+ blk_add_trace_msg((bfqd)->queue, "bfq " fmt, ##args) -+ -+/* Expiration reasons. */ -+enum bfqq_expiration { -+ BFQ_BFQQ_TOO_IDLE = 0, /* -+ * queue has been idling for -+ * too long -+ */ -+ BFQ_BFQQ_BUDGET_TIMEOUT, /* budget took too long to be used */ -+ BFQ_BFQQ_BUDGET_EXHAUSTED, /* budget consumed */ -+ BFQ_BFQQ_NO_MORE_REQUESTS, /* the queue has no more requests */ -+}; -+ -+#ifdef CONFIG_CGROUP_BFQIO -+/** -+ * struct bfq_group - per (device, cgroup) data structure. -+ * @entity: schedulable entity to insert into the parent group sched_data. -+ * @sched_data: own sched_data, to contain child entities (they may be -+ * both bfq_queues and bfq_groups). -+ * @group_node: node to be inserted into the bfqio_cgroup->group_data -+ * list of the containing cgroup's bfqio_cgroup. -+ * @bfqd_node: node to be inserted into the @bfqd->group_list list -+ * of the groups active on the same device; used for cleanup. -+ * @bfqd: the bfq_data for the device this group acts upon. -+ * @async_bfqq: array of async queues for all the tasks belonging to -+ * the group, one queue per ioprio value per ioprio_class, -+ * except for the idle class that has only one queue. -+ * @async_idle_bfqq: async queue for the idle class (ioprio is ignored). -+ * @my_entity: pointer to @entity, %NULL for the toplevel group; used -+ * to avoid too many special cases during group creation/ -+ * migration. -+ * @active_entities: number of active entities belonging to the group; -+ * unused for the root group. Used to know whether there -+ * are groups with more than one active @bfq_entity -+ * (see the comments to the function -+ * bfq_bfqq_must_not_expire()). -+ * -+ * Each (device, cgroup) pair has its own bfq_group, i.e., for each cgroup -+ * there is a set of bfq_groups, each one collecting the lower-level -+ * entities belonging to the group that are acting on the same device. -+ * -+ * Locking works as follows: -+ * o @group_node is protected by the bfqio_cgroup lock, and is accessed -+ * via RCU from its readers. -+ * o @bfqd is protected by the queue lock, RCU is used to access it -+ * from the readers. -+ * o All the other fields are protected by the @bfqd queue lock. -+ */ -+struct bfq_group { -+ struct bfq_entity entity; -+ struct bfq_sched_data sched_data; -+ -+ struct hlist_node group_node; -+ struct hlist_node bfqd_node; -+ -+ void *bfqd; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+ -+ struct bfq_entity *my_entity; -+ -+ int active_entities; -+}; -+ -+/** -+ * struct bfqio_cgroup - bfq cgroup data structure. -+ * @css: subsystem state for bfq in the containing cgroup. -+ * @online: flag marked when the subsystem is inserted. -+ * @weight: cgroup weight. -+ * @ioprio: cgroup ioprio. -+ * @ioprio_class: cgroup ioprio_class. -+ * @lock: spinlock that protects @ioprio, @ioprio_class and @group_data. -+ * @group_data: list containing the bfq_group belonging to this cgroup. -+ * -+ * @group_data is accessed using RCU, with @lock protecting the updates, -+ * @ioprio and @ioprio_class are protected by @lock. -+ */ -+struct bfqio_cgroup { -+ struct cgroup_subsys_state css; -+ bool online; -+ -+ unsigned short weight, ioprio, ioprio_class; -+ -+ spinlock_t lock; -+ struct hlist_head group_data; -+}; -+#else -+struct bfq_group { -+ struct bfq_sched_data sched_data; -+ -+ struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR]; -+ struct bfq_queue *async_idle_bfqq; -+}; -+#endif -+ -+static inline struct bfq_service_tree * -+bfq_entity_service_tree(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sched_data = entity->sched_data; -+ unsigned int idx = entity->ioprio_class - 1; -+ -+ BUG_ON(idx >= BFQ_IOPRIO_CLASSES); -+ BUG_ON(sched_data == NULL); -+ -+ return sched_data->service_tree + idx; -+} -+ -+static inline struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, -+ int is_sync) -+{ -+ return bic->bfqq[!!is_sync]; -+} -+ -+static inline void bic_set_bfqq(struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq, int is_sync) -+{ -+ bic->bfqq[!!is_sync] = bfqq; -+} -+ -+static inline struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic) -+{ -+ return bic->icq.q->elevator->elevator_data; -+} -+ -+/** -+ * bfq_get_bfqd_locked - get a lock to a bfqd using a RCU protected pointer. -+ * @ptr: a pointer to a bfqd. -+ * @flags: storage for the flags to be saved. -+ * -+ * This function allows bfqg->bfqd to be protected by the -+ * queue lock of the bfqd they reference; the pointer is dereferenced -+ * under RCU, so the storage for bfqd is assured to be safe as long -+ * as the RCU read side critical section does not end. After the -+ * bfqd->queue->queue_lock is taken the pointer is rechecked, to be -+ * sure that no other writer accessed it. If we raced with a writer, -+ * the function returns NULL, with the queue unlocked, otherwise it -+ * returns the dereferenced pointer, with the queue locked. -+ */ -+static inline struct bfq_data *bfq_get_bfqd_locked(void **ptr, -+ unsigned long *flags) -+{ -+ struct bfq_data *bfqd; -+ -+ rcu_read_lock(); -+ bfqd = rcu_dereference(*(struct bfq_data **)ptr); -+ -+ if (bfqd != NULL) { -+ spin_lock_irqsave(bfqd->queue->queue_lock, *flags); -+ if (*ptr == bfqd) -+ goto out; -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+ } -+ -+ bfqd = NULL; -+out: -+ rcu_read_unlock(); -+ return bfqd; -+} -+ -+static inline void bfq_put_bfqd_unlock(struct bfq_data *bfqd, -+ unsigned long *flags) -+{ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, *flags); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic); -+static void bfq_put_queue(struct bfq_queue *bfqq); -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq); -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask); -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg); -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg); -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq); -+ -+#endif /* _BFQ_H */ -diff -Nur linux-3.14.22.orig/block/bfq-ioc.c linux-3.14.22/block/bfq-ioc.c ---- linux-3.14.22.orig/block/bfq-ioc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/block/bfq-ioc.c 2014-10-22 14:55:51.954220001 -0500 -@@ -0,0 +1,36 @@ -+/* -+ * BFQ: I/O context handling. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+/** -+ * icq_to_bic - convert iocontext queue structure to bfq_io_cq. -+ * @icq: the iocontext queue. -+ */ -+static inline struct bfq_io_cq *icq_to_bic(struct io_cq *icq) -+{ -+ /* bic->icq is the first member, %NULL will convert to %NULL */ -+ return container_of(icq, struct bfq_io_cq, icq); -+} -+ -+/** -+ * bfq_bic_lookup - search into @ioc a bic associated to @bfqd. -+ * @bfqd: the lookup key. -+ * @ioc: the io_context of the process doing I/O. -+ * -+ * Queue lock must be held. -+ */ -+static inline struct bfq_io_cq *bfq_bic_lookup(struct bfq_data *bfqd, -+ struct io_context *ioc) -+{ -+ if (ioc) -+ return icq_to_bic(ioc_lookup_icq(ioc, bfqd->queue)); -+ return NULL; -+} -diff -Nur linux-3.14.22.orig/block/bfq-iosched.c linux-3.14.22/block/bfq-iosched.c ---- linux-3.14.22.orig/block/bfq-iosched.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/block/bfq-iosched.c 2014-10-22 14:55:51.958220001 -0500 -@@ -0,0 +1,3919 @@ -+/* -+ * Budget Fair Queueing (BFQ) disk scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ * -+ * Licensed under the GPL-2 as detailed in the accompanying COPYING.BFQ -+ * file. -+ * -+ * BFQ is a proportional-share storage-I/O scheduling algorithm based on -+ * the slice-by-slice service scheme of CFQ. But BFQ assigns budgets, -+ * measured in number of sectors, to processes instead of time slices. The -+ * device is not granted to the in-service process for a given time slice, -+ * but until it has exhausted its assigned budget. This change from the time -+ * to the service domain allows BFQ to distribute the device throughput -+ * among processes as desired, without any distortion due to ZBR, workload -+ * fluctuations or other factors. BFQ uses an ad hoc internal scheduler, -+ * called B-WF2Q+, to schedule processes according to their budgets. More -+ * precisely, BFQ schedules queues associated to processes. Thanks to the -+ * accurate policy of B-WF2Q+, BFQ can afford to assign high budgets to -+ * I/O-bound processes issuing sequential requests (to boost the -+ * throughput), and yet guarantee a low latency to interactive and soft -+ * real-time applications. -+ * -+ * BFQ is described in [1], where also a reference to the initial, more -+ * theoretical paper on BFQ can be found. The interested reader can find -+ * in the latter paper full details on the main algorithm, as well as -+ * formulas of the guarantees and formal proofs of all the properties. -+ * With respect to the version of BFQ presented in these papers, this -+ * implementation adds a few more heuristics, such as the one that -+ * guarantees a low latency to soft real-time applications, and a -+ * hierarchical extension based on H-WF2Q+. -+ * -+ * B-WF2Q+ is based on WF2Q+, that is described in [2], together with -+ * H-WF2Q+, while the augmented tree used to implement B-WF2Q+ with O(log N) -+ * complexity derives from the one introduced with EEVDF in [3]. -+ * -+ * [1] P. Valente and M. Andreolini, ``Improving Application Responsiveness -+ * with the BFQ Disk I/O Scheduler'', -+ * Proceedings of the 5th Annual International Systems and Storage -+ * Conference (SYSTOR '12), June 2012. -+ * -+ * http://algogroup.unimo.it/people/paolo/disk_sched/bf1-v1-suite-results.pdf -+ * -+ * [2] Jon C.R. Bennett and H. Zhang, ``Hierarchical Packet Fair Queueing -+ * Algorithms,'' IEEE/ACM Transactions on Networking, 5(5):675-689, -+ * Oct 1997. -+ * -+ * http://www.cs.cmu.edu/~hzhang/papers/TON-97-Oct.ps.gz -+ * -+ * [3] I. Stoica and H. Abdel-Wahab, ``Earliest Eligible Virtual Deadline -+ * First: A Flexible and Accurate Mechanism for Proportional Share -+ * Resource Allocation,'' technical report. -+ * -+ * http://www.cs.berkeley.edu/~istoica/papers/eevdf-tr-95.pdf -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "bfq.h" -+#include "blk.h" -+ -+/* Max number of dispatches in one round of service. */ -+static const int bfq_quantum = 4; -+ -+/* Expiration time of sync (0) and async (1) requests, in jiffies. */ -+static const int bfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; -+ -+/* Maximum backwards seek, in KiB. */ -+static const int bfq_back_max = 16 * 1024; -+ -+/* Penalty of a backwards seek, in number of sectors. */ -+static const int bfq_back_penalty = 2; -+ -+/* Idling period duration, in jiffies. */ -+static int bfq_slice_idle = HZ / 125; -+ -+/* Default maximum budget values, in sectors and number of requests. */ -+static const int bfq_default_max_budget = 16 * 1024; -+static const int bfq_max_budget_async_rq = 4; -+ -+/* -+ * Async to sync throughput distribution is controlled as follows: -+ * when an async request is served, the entity is charged the number -+ * of sectors of the request, multiplied by the factor below -+ */ -+static const int bfq_async_charge_factor = 10; -+ -+/* Default timeout values, in jiffies, approximating CFQ defaults. */ -+static const int bfq_timeout_sync = HZ / 8; -+static int bfq_timeout_async = HZ / 25; -+ -+struct kmem_cache *bfq_pool; -+ -+/* Below this threshold (in ms), we consider thinktime immediate. */ -+#define BFQ_MIN_TT 2 -+ -+/* hw_tag detection: parallel requests threshold and min samples needed. */ -+#define BFQ_HW_QUEUE_THRESHOLD 4 -+#define BFQ_HW_QUEUE_SAMPLES 32 -+ -+#define BFQQ_SEEK_THR (sector_t)(8 * 1024) -+#define BFQQ_SEEKY(bfqq) ((bfqq)->seek_mean > BFQQ_SEEK_THR) -+ -+/* Min samples used for peak rate estimation (for autotuning). */ -+#define BFQ_PEAK_RATE_SAMPLES 32 -+ -+/* Shift used for peak rate fixed precision calculations. */ -+#define BFQ_RATE_SHIFT 16 -+ -+/* -+ * By default, BFQ computes the duration of the weight raising for -+ * interactive applications automatically, using the following formula: -+ * duration = (R / r) * T, where r is the peak rate of the device, and -+ * R and T are two reference parameters. -+ * In particular, R is the peak rate of the reference device (see below), -+ * and T is a reference time: given the systems that are likely to be -+ * installed on the reference device according to its speed class, T is -+ * about the maximum time needed, under BFQ and while reading two files in -+ * parallel, to load typical large applications on these systems. -+ * In practice, the slower/faster the device at hand is, the more/less it -+ * takes to load applications with respect to the reference device. -+ * Accordingly, the longer/shorter BFQ grants weight raising to interactive -+ * applications. -+ * -+ * BFQ uses four different reference pairs (R, T), depending on: -+ * . whether the device is rotational or non-rotational; -+ * . whether the device is slow, such as old or portable HDDs, as well as -+ * SD cards, or fast, such as newer HDDs and SSDs. -+ * -+ * The device's speed class is dynamically (re)detected in -+ * bfq_update_peak_rate() every time the estimated peak rate is updated. -+ * -+ * In the following definitions, R_slow[0]/R_fast[0] and T_slow[0]/T_fast[0] -+ * are the reference values for a slow/fast rotational device, whereas -+ * R_slow[1]/R_fast[1] and T_slow[1]/T_fast[1] are the reference values for -+ * a slow/fast non-rotational device. Finally, device_speed_thresh are the -+ * thresholds used to switch between speed classes. -+ * Both the reference peak rates and the thresholds are measured in -+ * sectors/usec, left-shifted by BFQ_RATE_SHIFT. -+ */ -+static int R_slow[2] = {1536, 10752}; -+static int R_fast[2] = {17415, 34791}; -+/* -+ * To improve readability, a conversion function is used to initialize the -+ * following arrays, which entails that they can be initialized only in a -+ * function. -+ */ -+static int T_slow[2]; -+static int T_fast[2]; -+static int device_speed_thresh[2]; -+ -+#define BFQ_SERVICE_TREE_INIT ((struct bfq_service_tree) \ -+ { RB_ROOT, RB_ROOT, NULL, NULL, 0, 0 }) -+ -+#define RQ_BIC(rq) ((struct bfq_io_cq *) (rq)->elv.priv[0]) -+#define RQ_BFQQ(rq) ((rq)->elv.priv[1]) -+ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd); -+ -+#include "bfq-ioc.c" -+#include "bfq-sched.c" -+#include "bfq-cgroup.c" -+ -+#define bfq_class_idle(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_IDLE) -+#define bfq_class_rt(bfqq) ((bfqq)->entity.ioprio_class ==\ -+ IOPRIO_CLASS_RT) -+ -+#define bfq_sample_valid(samples) ((samples) > 80) -+ -+/* -+ * We regard a request as SYNC, if either it's a read or has the SYNC bit -+ * set (in which case it could also be a direct WRITE). -+ */ -+static inline int bfq_bio_sync(struct bio *bio) -+{ -+ if (bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC)) -+ return 1; -+ -+ return 0; -+} -+ -+/* -+ * Scheduler run of queue, if there are requests pending and no one in the -+ * driver that will restart queueing. -+ */ -+static inline void bfq_schedule_dispatch(struct bfq_data *bfqd) -+{ -+ if (bfqd->queued != 0) { -+ bfq_log(bfqd, "schedule dispatch"); -+ kblockd_schedule_work(bfqd->queue, &bfqd->unplug_work); -+ } -+} -+ -+/* -+ * Lifted from AS - choose which of rq1 and rq2 that is best served now. -+ * We choose the request that is closesr to the head right now. Distance -+ * behind the head is penalized and only allowed to a certain extent. -+ */ -+static struct request *bfq_choose_req(struct bfq_data *bfqd, -+ struct request *rq1, -+ struct request *rq2, -+ sector_t last) -+{ -+ sector_t s1, s2, d1 = 0, d2 = 0; -+ unsigned long back_max; -+#define BFQ_RQ1_WRAP 0x01 /* request 1 wraps */ -+#define BFQ_RQ2_WRAP 0x02 /* request 2 wraps */ -+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */ -+ -+ if (rq1 == NULL || rq1 == rq2) -+ return rq2; -+ if (rq2 == NULL) -+ return rq1; -+ -+ if (rq_is_sync(rq1) && !rq_is_sync(rq2)) -+ return rq1; -+ else if (rq_is_sync(rq2) && !rq_is_sync(rq1)) -+ return rq2; -+ if ((rq1->cmd_flags & REQ_META) && !(rq2->cmd_flags & REQ_META)) -+ return rq1; -+ else if ((rq2->cmd_flags & REQ_META) && !(rq1->cmd_flags & REQ_META)) -+ return rq2; -+ -+ s1 = blk_rq_pos(rq1); -+ s2 = blk_rq_pos(rq2); -+ -+ /* -+ * By definition, 1KiB is 2 sectors. -+ */ -+ back_max = bfqd->bfq_back_max * 2; -+ -+ /* -+ * Strict one way elevator _except_ in the case where we allow -+ * short backward seeks which are biased as twice the cost of a -+ * similar forward seek. -+ */ -+ if (s1 >= last) -+ d1 = s1 - last; -+ else if (s1 + back_max >= last) -+ d1 = (last - s1) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ1_WRAP; -+ -+ if (s2 >= last) -+ d2 = s2 - last; -+ else if (s2 + back_max >= last) -+ d2 = (last - s2) * bfqd->bfq_back_penalty; -+ else -+ wrap |= BFQ_RQ2_WRAP; -+ -+ /* Found required data */ -+ -+ /* -+ * By doing switch() on the bit mask "wrap" we avoid having to -+ * check two variables for all permutations: --> faster! -+ */ -+ switch (wrap) { -+ case 0: /* common case for CFQ: rq1 and rq2 not wrapped */ -+ if (d1 < d2) -+ return rq1; -+ else if (d2 < d1) -+ return rq2; -+ else { -+ if (s1 >= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+ -+ case BFQ_RQ2_WRAP: -+ return rq1; -+ case BFQ_RQ1_WRAP: -+ return rq2; -+ case (BFQ_RQ1_WRAP|BFQ_RQ2_WRAP): /* both rqs wrapped */ -+ default: -+ /* -+ * Since both rqs are wrapped, -+ * start with the one that's further behind head -+ * (--> only *one* back seek required), -+ * since back seek takes more time than forward. -+ */ -+ if (s1 <= s2) -+ return rq1; -+ else -+ return rq2; -+ } -+} -+ -+static struct bfq_queue * -+bfq_rq_pos_tree_lookup(struct bfq_data *bfqd, struct rb_root *root, -+ sector_t sector, struct rb_node **ret_parent, -+ struct rb_node ***rb_link) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *bfqq = NULL; -+ -+ parent = NULL; -+ p = &root->rb_node; -+ while (*p) { -+ struct rb_node **n; -+ -+ parent = *p; -+ bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ -+ /* -+ * Sort strictly based on sector. Smallest to the left, -+ * largest to the right. -+ */ -+ if (sector > blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_right; -+ else if (sector < blk_rq_pos(bfqq->next_rq)) -+ n = &(*p)->rb_left; -+ else -+ break; -+ p = n; -+ bfqq = NULL; -+ } -+ -+ *ret_parent = parent; -+ if (rb_link) -+ *rb_link = p; -+ -+ bfq_log(bfqd, "rq_pos_tree_lookup %llu: returning %d", -+ (long long unsigned)sector, -+ bfqq != NULL ? bfqq->pid : 0); -+ -+ return bfqq; -+} -+ -+static void bfq_rq_pos_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct rb_node **p, *parent; -+ struct bfq_queue *__bfqq; -+ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ -+ if (bfq_class_idle(bfqq)) -+ return; -+ if (!bfqq->next_rq) -+ return; -+ -+ bfqq->pos_root = &bfqd->rq_pos_tree; -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, bfqq->pos_root, -+ blk_rq_pos(bfqq->next_rq), &parent, &p); -+ if (__bfqq == NULL) { -+ rb_link_node(&bfqq->pos_node, parent, p); -+ rb_insert_color(&bfqq->pos_node, bfqq->pos_root); -+ } else -+ bfqq->pos_root = NULL; -+} -+ -+/* -+ * Tell whether there are active queues or groups with differentiated weights. -+ */ -+static inline bool bfq_differentiated_weights(struct bfq_data *bfqd) -+{ -+ BUG_ON(!bfqd->hw_tag); -+ /* -+ * For weights to differ, at least one of the trees must contain -+ * at least two nodes. -+ */ -+ return (!RB_EMPTY_ROOT(&bfqd->queue_weights_tree) && -+ (bfqd->queue_weights_tree.rb_node->rb_left || -+ bfqd->queue_weights_tree.rb_node->rb_right) -+#ifdef CONFIG_CGROUP_BFQIO -+ ) || -+ (!RB_EMPTY_ROOT(&bfqd->group_weights_tree) && -+ (bfqd->group_weights_tree.rb_node->rb_left || -+ bfqd->group_weights_tree.rb_node->rb_right) -+#endif -+ ); -+} -+ -+/* -+ * If the weight-counter tree passed as input contains no counter for -+ * the weight of the input entity, then add that counter; otherwise just -+ * increment the existing counter. -+ * -+ * Note that weight-counter trees contain few nodes in mostly symmetric -+ * scenarios. For example, if all queues have the same weight, then the -+ * weight-counter tree for the queues may contain at most one node. -+ * This holds even if low_latency is on, because weight-raised queues -+ * are not inserted in the tree. -+ * In most scenarios, the rate at which nodes are created/destroyed -+ * should be low too. -+ */ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ struct rb_node **new = &(root->rb_node), *parent = NULL; -+ -+ /* -+ * Do not insert if: -+ * - the device does not support queueing; -+ * - the entity is already associated with a counter, which happens if: -+ * 1) the entity is associated with a queue, 2) a request arrival -+ * has caused the queue to become both non-weight-raised, and hence -+ * change its weight, and backlogged; in this respect, each -+ * of the two events causes an invocation of this function, -+ * 3) this is the invocation of this function caused by the second -+ * event. This second invocation is actually useless, and we handle -+ * this fact by exiting immediately. More efficient or clearer -+ * solutions might possibly be adopted. -+ */ -+ if (!bfqd->hw_tag || entity->weight_counter) -+ return; -+ -+ while (*new) { -+ struct bfq_weight_counter *__counter = container_of(*new, -+ struct bfq_weight_counter, -+ weights_node); -+ parent = *new; -+ -+ if (entity->weight == __counter->weight) { -+ entity->weight_counter = __counter; -+ goto inc_counter; -+ } -+ if (entity->weight < __counter->weight) -+ new = &((*new)->rb_left); -+ else -+ new = &((*new)->rb_right); -+ } -+ -+ entity->weight_counter = kzalloc(sizeof(struct bfq_weight_counter), -+ GFP_ATOMIC); -+ entity->weight_counter->weight = entity->weight; -+ rb_link_node(&entity->weight_counter->weights_node, parent, new); -+ rb_insert_color(&entity->weight_counter->weights_node, root); -+ -+inc_counter: -+ entity->weight_counter->num_active++; -+} -+ -+/* -+ * Decrement the weight counter associated with the entity, and, if the -+ * counter reaches 0, remove the counter from the tree. -+ * See the comments to the function bfq_weights_tree_add() for considerations -+ * about overhead. -+ */ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root) -+{ -+ /* -+ * Check whether the entity is actually associated with a counter. -+ * In fact, the device may not be considered NCQ-capable for a while, -+ * which implies that no insertion in the weight trees is performed, -+ * after which the device may start to be deemed NCQ-capable, and hence -+ * this function may start to be invoked. This may cause the function -+ * to be invoked for entities that are not associated with any counter. -+ */ -+ if (!entity->weight_counter) -+ return; -+ -+ BUG_ON(RB_EMPTY_ROOT(root)); -+ BUG_ON(entity->weight_counter->weight != entity->weight); -+ -+ BUG_ON(!entity->weight_counter->num_active); -+ entity->weight_counter->num_active--; -+ if (entity->weight_counter->num_active > 0) -+ goto reset_entity_pointer; -+ -+ rb_erase(&entity->weight_counter->weights_node, root); -+ kfree(entity->weight_counter); -+ -+reset_entity_pointer: -+ entity->weight_counter = NULL; -+} -+ -+static struct request *bfq_find_next_rq(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *last) -+{ -+ struct rb_node *rbnext = rb_next(&last->rb_node); -+ struct rb_node *rbprev = rb_prev(&last->rb_node); -+ struct request *next = NULL, *prev = NULL; -+ -+ BUG_ON(RB_EMPTY_NODE(&last->rb_node)); -+ -+ if (rbprev != NULL) -+ prev = rb_entry_rq(rbprev); -+ -+ if (rbnext != NULL) -+ next = rb_entry_rq(rbnext); -+ else { -+ rbnext = rb_first(&bfqq->sort_list); -+ if (rbnext && rbnext != &last->rb_node) -+ next = rb_entry_rq(rbnext); -+ } -+ -+ return bfq_choose_req(bfqd, next, prev, blk_rq_pos(last)); -+} -+ -+/* see the definition of bfq_async_charge_factor for details */ -+static inline unsigned long bfq_serv_to_charge(struct request *rq, -+ struct bfq_queue *bfqq) -+{ -+ return blk_rq_sectors(rq) * -+ (1 + ((!bfq_bfqq_sync(bfqq)) * (bfqq->wr_coeff == 1) * -+ bfq_async_charge_factor)); -+} -+ -+/** -+ * bfq_updated_next_req - update the queue after a new next_rq selection. -+ * @bfqd: the device data the queue belongs to. -+ * @bfqq: the queue to update. -+ * -+ * If the first request of a queue changes we make sure that the queue -+ * has enough budget to serve at least its first request (if the -+ * request has grown). We do this because if the queue has not enough -+ * budget for its first request, it has to go through two dispatch -+ * rounds to actually get it dispatched. -+ */ -+static void bfq_updated_next_req(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ struct request *next_rq = bfqq->next_rq; -+ unsigned long new_budget; -+ -+ if (next_rq == NULL) -+ return; -+ -+ if (bfqq == bfqd->in_service_queue) -+ /* -+ * In order not to break guarantees, budgets cannot be -+ * changed after an entity has been selected. -+ */ -+ return; -+ -+ BUG_ON(entity->tree != &st->active); -+ BUG_ON(entity == entity->sched_data->in_service_entity); -+ -+ new_budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ if (entity->budget != new_budget) { -+ entity->budget = new_budget; -+ bfq_log_bfqq(bfqd, bfqq, "updated next rq: new budget %lu", -+ new_budget); -+ bfq_activate_bfqq(bfqd, bfqq); -+ } -+} -+ -+static inline unsigned int bfq_wr_duration(struct bfq_data *bfqd) -+{ -+ u64 dur; -+ -+ if (bfqd->bfq_wr_max_time > 0) -+ return bfqd->bfq_wr_max_time; -+ -+ dur = bfqd->RT_prod; -+ do_div(dur, bfqd->peak_rate); -+ -+ return dur; -+} -+ -+static inline unsigned -+bfq_bfqq_cooperations(struct bfq_queue *bfqq) -+{ -+ return bfqq->bic ? bfqq->bic->cooperations : 0; -+} -+ -+static inline void -+bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_io_cq *bic) -+{ -+ if (bic->saved_idle_window) -+ bfq_mark_bfqq_idle_window(bfqq); -+ else -+ bfq_clear_bfqq_idle_window(bfqq); -+ if (bic->saved_IO_bound) -+ bfq_mark_bfqq_IO_bound(bfqq); -+ else -+ bfq_clear_bfqq_IO_bound(bfqq); -+ if (bic->wr_time_left && bfqq->bfqd->low_latency && -+ bic->cooperations < bfqq->bfqd->bfq_coop_thresh) { -+ /* -+ * Start a weight raising period with the duration given by -+ * the raising_time_left snapshot. -+ */ -+ if (bfq_bfqq_busy(bfqq)) -+ bfqq->bfqd->wr_busy_queues++; -+ bfqq->wr_coeff = bfqq->bfqd->bfq_wr_coeff; -+ bfqq->wr_cur_max_time = bic->wr_time_left; -+ bfqq->last_wr_start_finish = jiffies; -+ bfqq->entity.ioprio_changed = 1; -+ } -+ /* -+ * Clear wr_time_left to prevent bfq_bfqq_save_state() from -+ * getting confused about the queue's need of a weight-raising -+ * period. -+ */ -+ bic->wr_time_left = 0; -+} -+ -+/* -+ * Must be called with the queue_lock held. -+ */ -+static int bfqq_process_refs(struct bfq_queue *bfqq) -+{ -+ int process_refs, io_refs; -+ -+ io_refs = bfqq->allocated[READ] + bfqq->allocated[WRITE]; -+ process_refs = atomic_read(&bfqq->ref) - io_refs - bfqq->entity.on_st; -+ BUG_ON(process_refs < 0); -+ return process_refs; -+} -+ -+static void bfq_add_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *next_rq, *prev; -+ unsigned long old_wr_coeff = bfqq->wr_coeff; -+ int idle_for_long_time = 0; -+ -+ bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq)); -+ bfqq->queued[rq_is_sync(rq)]++; -+ bfqd->queued++; -+ -+ elv_rb_add(&bfqq->sort_list, rq); -+ -+ /* -+ * Check if this request is a better next-serve candidate. -+ */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, rq, bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ -+ /* -+ * Adjust priority tree position, if next_rq changes. -+ */ -+ if (prev != bfqq->next_rq) -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ -+ if (!bfq_bfqq_busy(bfqq)) { -+ int soft_rt = bfqd->bfq_wr_max_softrt_rate > 0 && -+ bfq_bfqq_cooperations(bfqq) < bfqd->bfq_coop_thresh && -+ time_is_before_jiffies(bfqq->soft_rt_next_start); -+ idle_for_long_time = bfq_bfqq_cooperations(bfqq) < -+ bfqd->bfq_coop_thresh && -+ time_is_before_jiffies( -+ bfqq->budget_timeout + -+ bfqd->bfq_wr_min_idle_time); -+ entity->budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ -+ if (!bfq_bfqq_IO_bound(bfqq)) { -+ if (time_before(jiffies, -+ RQ_BIC(rq)->ttime.last_end_request + -+ bfqd->bfq_slice_idle)) { -+ bfqq->requests_within_timer++; -+ if (bfqq->requests_within_timer >= -+ bfqd->bfq_requests_within_timer) -+ bfq_mark_bfqq_IO_bound(bfqq); -+ } else -+ bfqq->requests_within_timer = 0; -+ } -+ -+ if (!bfqd->low_latency) -+ goto add_bfqq_busy; -+ -+ if (bfq_bfqq_just_split(bfqq)) -+ goto set_ioprio_changed; -+ -+ /* -+ * If the queue: -+ * - is not being boosted, -+ * - has been idle for enough time, -+ * - is not a sync queue or is linked to a bfq_io_cq (it is -+ * shared "for its nature" or it is not shared and its -+ * requests have not been redirected to a shared queue) -+ * start a weight-raising period. -+ */ -+ if (old_wr_coeff == 1 && (idle_for_long_time || soft_rt) && -+ (!bfq_bfqq_sync(bfqq) || bfqq->bic != NULL)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ if (idle_for_long_time) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } else if (old_wr_coeff > 1) { -+ if (idle_for_long_time) -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ else if (bfq_bfqq_cooperations(bfqq) >= -+ bfqd->bfq_coop_thresh || -+ (bfqq->wr_cur_max_time == -+ bfqd->bfq_wr_rt_max_time && -+ !soft_rt)) { -+ bfqq->wr_coeff = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq-> -+ wr_cur_max_time)); -+ } else if (time_before( -+ bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time, -+ jiffies + -+ bfqd->bfq_wr_rt_max_time) && -+ soft_rt) { -+ /* -+ * -+ * The remaining weight-raising time is lower -+ * than bfqd->bfq_wr_rt_max_time, which means -+ * that the application is enjoying weight -+ * raising either because deemed soft-rt in -+ * the near past, or because deemed interactive -+ * a long ago. -+ * In both cases, resetting now the current -+ * remaining weight-raising time for the -+ * application to the weight-raising duration -+ * for soft rt applications would not cause any -+ * latency increase for the application (as the -+ * new duration would be higher than the -+ * remaining time). -+ * -+ * In addition, the application is now meeting -+ * the requirements for being deemed soft rt. -+ * In the end we can correctly and safely -+ * (re)charge the weight-raising duration for -+ * the application with the weight-raising -+ * duration for soft rt applications. -+ * -+ * In particular, doing this recharge now, i.e., -+ * before the weight-raising period for the -+ * application finishes, reduces the probability -+ * of the following negative scenario: -+ * 1) the weight of a soft rt application is -+ * raised at startup (as for any newly -+ * created application), -+ * 2) since the application is not interactive, -+ * at a certain time weight-raising is -+ * stopped for the application, -+ * 3) at that time the application happens to -+ * still have pending requests, and hence -+ * is destined to not have a chance to be -+ * deemed soft rt before these requests are -+ * completed (see the comments to the -+ * function bfq_bfqq_softrt_next_start() -+ * for details on soft rt detection), -+ * 4) these pending requests experience a high -+ * latency because the application is not -+ * weight-raised while they are pending. -+ */ -+ bfqq->last_wr_start_finish = jiffies; -+ bfqq->wr_cur_max_time = -+ bfqd->bfq_wr_rt_max_time; -+ } -+ } -+set_ioprio_changed: -+ if (old_wr_coeff != bfqq->wr_coeff) -+ entity->ioprio_changed = 1; -+add_bfqq_busy: -+ bfqq->last_idle_bklogged = jiffies; -+ bfqq->service_from_backlogged = 0; -+ bfq_clear_bfqq_softrt_update(bfqq); -+ bfq_add_bfqq_busy(bfqd, bfqq); -+ } else { -+ if (bfqd->low_latency && old_wr_coeff == 1 && !rq_is_sync(rq) && -+ time_is_before_jiffies( -+ bfqq->last_wr_start_finish + -+ bfqd->bfq_wr_min_inter_arr_async)) { -+ bfqq->wr_coeff = bfqd->bfq_wr_coeff; -+ bfqq->wr_cur_max_time = bfq_wr_duration(bfqd); -+ -+ bfqd->wr_busy_queues++; -+ entity->ioprio_changed = 1; -+ bfq_log_bfqq(bfqd, bfqq, -+ "non-idle wrais starting at %lu, rais_max_time %u", -+ jiffies, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ if (prev != bfqq->next_rq) -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ if (bfqd->low_latency && -+ (old_wr_coeff == 1 || bfqq->wr_coeff == 1 || -+ idle_for_long_time)) -+ bfqq->last_wr_start_finish = jiffies; -+} -+ -+static struct request *bfq_find_rq_fmerge(struct bfq_data *bfqd, -+ struct bio *bio) -+{ -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return NULL; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ if (bfqq != NULL) -+ return elv_rb_find(&bfqq->sort_list, bio_end_sector(bio)); -+ -+ return NULL; -+} -+ -+static void bfq_activate_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ bfqd->rq_in_driver++; -+ bfqd->last_position = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ bfq_log(bfqd, "activate_request: new bfqd->last_position %llu", -+ (long long unsigned)bfqd->last_position); -+} -+ -+static inline void bfq_deactivate_request(struct request_queue *q, -+ struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ -+ BUG_ON(bfqd->rq_in_driver == 0); -+ bfqd->rq_in_driver--; -+} -+ -+static void bfq_remove_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ const int sync = rq_is_sync(rq); -+ -+ if (bfqq->next_rq == rq) { -+ bfqq->next_rq = bfq_find_next_rq(bfqd, bfqq, rq); -+ bfq_updated_next_req(bfqd, bfqq); -+ } -+ -+ list_del_init(&rq->queuelist); -+ BUG_ON(bfqq->queued[sync] == 0); -+ bfqq->queued[sync]--; -+ bfqd->queued--; -+ elv_rb_del(&bfqq->sort_list, rq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ /* -+ * Remove queue from request-position tree as it is empty. -+ */ -+ if (bfqq->pos_root != NULL) { -+ rb_erase(&bfqq->pos_node, bfqq->pos_root); -+ bfqq->pos_root = NULL; -+ } -+ } -+ -+ if (rq->cmd_flags & REQ_META) { -+ BUG_ON(bfqq->meta_pending == 0); -+ bfqq->meta_pending--; -+ } -+} -+ -+static int bfq_merge(struct request_queue *q, struct request **req, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct request *__rq; -+ -+ __rq = bfq_find_rq_fmerge(bfqd, bio); -+ if (__rq != NULL && elv_rq_merge_ok(__rq, bio)) { -+ *req = __rq; -+ return ELEVATOR_FRONT_MERGE; -+ } -+ -+ return ELEVATOR_NO_MERGE; -+} -+ -+static void bfq_merged_request(struct request_queue *q, struct request *req, -+ int type) -+{ -+ if (type == ELEVATOR_FRONT_MERGE && -+ rb_prev(&req->rb_node) && -+ blk_rq_pos(req) < -+ blk_rq_pos(container_of(rb_prev(&req->rb_node), -+ struct request, rb_node))) { -+ struct bfq_queue *bfqq = RQ_BFQQ(req); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ struct request *prev, *next_rq; -+ -+ /* Reposition request in its sort_list */ -+ elv_rb_del(&bfqq->sort_list, req); -+ elv_rb_add(&bfqq->sort_list, req); -+ /* Choose next request to be served for bfqq */ -+ prev = bfqq->next_rq; -+ next_rq = bfq_choose_req(bfqd, bfqq->next_rq, req, -+ bfqd->last_position); -+ BUG_ON(next_rq == NULL); -+ bfqq->next_rq = next_rq; -+ /* -+ * If next_rq changes, update both the queue's budget to -+ * fit the new request and the queue's position in its -+ * rq_pos_tree. -+ */ -+ if (prev != bfqq->next_rq) { -+ bfq_updated_next_req(bfqd, bfqq); -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+ } -+} -+ -+static void bfq_merged_requests(struct request_queue *q, struct request *rq, -+ struct request *next) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * Reposition in fifo if next is older than rq. -+ */ -+ if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) && -+ time_before(rq_fifo_time(next), rq_fifo_time(rq))) { -+ list_move(&rq->queuelist, &next->queuelist); -+ rq_set_fifo_time(rq, rq_fifo_time(next)); -+ } -+ -+ if (bfqq->next_rq == next) -+ bfqq->next_rq = rq; -+ -+ bfq_remove_request(next); -+} -+ -+/* Must be called with bfqq != NULL */ -+static inline void bfq_bfqq_end_wr(struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq == NULL); -+ if (bfq_bfqq_busy(bfqq)) -+ bfqq->bfqd->wr_busy_queues--; -+ bfqq->wr_coeff = 1; -+ bfqq->wr_cur_max_time = 0; -+ /* Trigger a weight change on the next activation of the queue */ -+ bfqq->entity.ioprio_changed = 1; -+} -+ -+static void bfq_end_wr_async_queues(struct bfq_data *bfqd, -+ struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ if (bfqg->async_bfqq[i][j] != NULL) -+ bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]); -+ if (bfqg->async_idle_bfqq != NULL) -+ bfq_bfqq_end_wr(bfqg->async_idle_bfqq); -+} -+ -+static void bfq_end_wr(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq; -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) -+ bfq_bfqq_end_wr(bfqq); -+ bfq_end_wr_async(bfqd); -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+} -+ -+static inline sector_t bfq_io_struct_pos(void *io_struct, bool request) -+{ -+ if (request) -+ return blk_rq_pos(io_struct); -+ else -+ return ((struct bio *)io_struct)->bi_iter.bi_sector; -+} -+ -+static inline sector_t bfq_dist_from(sector_t pos1, -+ sector_t pos2) -+{ -+ if (pos1 >= pos2) -+ return pos1 - pos2; -+ else -+ return pos2 - pos1; -+} -+ -+static inline int bfq_rq_close_to_sector(void *io_struct, bool request, -+ sector_t sector) -+{ -+ return bfq_dist_from(bfq_io_struct_pos(io_struct, request), sector) <= -+ BFQQ_SEEK_THR; -+} -+ -+static struct bfq_queue *bfqq_close(struct bfq_data *bfqd, sector_t sector) -+{ -+ struct rb_root *root = &bfqd->rq_pos_tree; -+ struct rb_node *parent, *node; -+ struct bfq_queue *__bfqq; -+ -+ if (RB_EMPTY_ROOT(root)) -+ return NULL; -+ -+ /* -+ * First, if we find a request starting at the end of the last -+ * request, choose it. -+ */ -+ __bfqq = bfq_rq_pos_tree_lookup(bfqd, root, sector, &parent, NULL); -+ if (__bfqq != NULL) -+ return __bfqq; -+ -+ /* -+ * If the exact sector wasn't found, the parent of the NULL leaf -+ * will contain the closest sector (rq_pos_tree sorted by -+ * next_request position). -+ */ -+ __bfqq = rb_entry(parent, struct bfq_queue, pos_node); -+ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) -+ return __bfqq; -+ -+ if (blk_rq_pos(__bfqq->next_rq) < sector) -+ node = rb_next(&__bfqq->pos_node); -+ else -+ node = rb_prev(&__bfqq->pos_node); -+ if (node == NULL) -+ return NULL; -+ -+ __bfqq = rb_entry(node, struct bfq_queue, pos_node); -+ if (bfq_rq_close_to_sector(__bfqq->next_rq, true, sector)) -+ return __bfqq; -+ -+ return NULL; -+} -+ -+/* -+ * bfqd - obvious -+ * cur_bfqq - passed in so that we don't decide that the current queue -+ * is closely cooperating with itself -+ * sector - used as a reference point to search for a close queue -+ */ -+static struct bfq_queue *bfq_close_cooperator(struct bfq_data *bfqd, -+ struct bfq_queue *cur_bfqq, -+ sector_t sector) -+{ -+ struct bfq_queue *bfqq; -+ -+ if (bfq_class_idle(cur_bfqq)) -+ return NULL; -+ if (!bfq_bfqq_sync(cur_bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(cur_bfqq)) -+ return NULL; -+ -+ /* If device has only one backlogged bfq_queue, don't search. */ -+ if (bfqd->busy_queues == 1) -+ return NULL; -+ -+ /* -+ * We should notice if some of the queues are cooperating, e.g. -+ * working closely on the same area of the disk. In that case, -+ * we can group them together and don't waste time idling. -+ */ -+ bfqq = bfqq_close(bfqd, sector); -+ if (bfqq == NULL || bfqq == cur_bfqq) -+ return NULL; -+ -+ /* -+ * Do not merge queues from different bfq_groups. -+ */ -+ if (bfqq->entity.parent != cur_bfqq->entity.parent) -+ return NULL; -+ -+ /* -+ * It only makes sense to merge sync queues. -+ */ -+ if (!bfq_bfqq_sync(bfqq)) -+ return NULL; -+ if (BFQQ_SEEKY(bfqq)) -+ return NULL; -+ -+ /* -+ * Do not merge queues of different priority classes. -+ */ -+ if (bfq_class_rt(bfqq) != bfq_class_rt(cur_bfqq)) -+ return NULL; -+ -+ return bfqq; -+} -+ -+static struct bfq_queue * -+bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ int process_refs, new_process_refs; -+ struct bfq_queue *__bfqq; -+ -+ /* -+ * If there are no process references on the new_bfqq, then it is -+ * unsafe to follow the ->new_bfqq chain as other bfqq's in the chain -+ * may have dropped their last reference (not just their last process -+ * reference). -+ */ -+ if (!bfqq_process_refs(new_bfqq)) -+ return NULL; -+ -+ /* Avoid a circular list and skip interim queue merges. */ -+ while ((__bfqq = new_bfqq->new_bfqq)) { -+ if (__bfqq == bfqq) -+ return NULL; -+ new_bfqq = __bfqq; -+ } -+ -+ process_refs = bfqq_process_refs(bfqq); -+ new_process_refs = bfqq_process_refs(new_bfqq); -+ /* -+ * If the process for the bfqq has gone away, there is no -+ * sense in merging the queues. -+ */ -+ if (process_refs == 0 || new_process_refs == 0) -+ return NULL; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d", -+ new_bfqq->pid); -+ -+ /* -+ * Merging is just a redirection: the requests of the process -+ * owning one of the two queues are redirected to the other queue. -+ * The latter queue, in its turn, is set as shared if this is the -+ * first time that the requests of some process are redirected to -+ * it. -+ * -+ * We redirect bfqq to new_bfqq and not the opposite, because we -+ * are in the context of the process owning bfqq, hence we have -+ * the io_cq of this process. So we can immediately configure this -+ * io_cq to redirect the requests of the process to new_bfqq. -+ * -+ * NOTE, even if new_bfqq coincides with the in-service queue, the -+ * io_cq of new_bfqq is not available, because, if the in-service -+ * queue is shared, bfqd->in_service_bic may not point to the -+ * io_cq of the in-service queue. -+ * Redirecting the requests of the process owning bfqq to the -+ * currently in-service queue is in any case the best option, as -+ * we feed the in-service queue with new requests close to the -+ * last request served and, by doing so, hopefully increase the -+ * throughput. -+ */ -+ bfqq->new_bfqq = new_bfqq; -+ atomic_add(process_refs, &new_bfqq->ref); -+ return new_bfqq; -+} -+ -+/* -+ * Attempt to schedule a merge of bfqq with the currently in-service queue -+ * or with a close queue among the scheduled queues. -+ * Return NULL if no merge was scheduled, a pointer to the shared bfq_queue -+ * structure otherwise. -+ */ -+static struct bfq_queue * -+bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ void *io_struct, bool request) -+{ -+ struct bfq_queue *in_service_bfqq, *new_bfqq; -+ -+ if (bfqq->new_bfqq) -+ return bfqq->new_bfqq; -+ -+ if (!io_struct) -+ return NULL; -+ -+ in_service_bfqq = bfqd->in_service_queue; -+ -+ if (in_service_bfqq == NULL || in_service_bfqq == bfqq || -+ !bfqd->in_service_bic) -+ goto check_scheduled; -+ -+ if (bfq_class_idle(in_service_bfqq) || bfq_class_idle(bfqq)) -+ goto check_scheduled; -+ -+ if (bfq_class_rt(in_service_bfqq) != bfq_class_rt(bfqq)) -+ goto check_scheduled; -+ -+ if (in_service_bfqq->entity.parent != bfqq->entity.parent) -+ goto check_scheduled; -+ -+ if (bfq_rq_close_to_sector(io_struct, request, bfqd->last_position) && -+ bfq_bfqq_sync(in_service_bfqq) && bfq_bfqq_sync(bfqq)) { -+ new_bfqq = bfq_setup_merge(bfqq, in_service_bfqq); -+ if (new_bfqq != NULL) -+ return new_bfqq; /* Merge with in-service queue */ -+ } -+ -+ /* -+ * Check whether there is a cooperator among currently scheduled -+ * queues. The only thing we need is that the bio/request is not -+ * NULL, as we need it to establish whether a cooperator exists. -+ */ -+check_scheduled: -+ new_bfqq = bfq_close_cooperator(bfqd, bfqq, -+ bfq_io_struct_pos(io_struct, request)); -+ if (new_bfqq) -+ return bfq_setup_merge(bfqq, new_bfqq); -+ -+ return NULL; -+} -+ -+static inline void -+bfq_bfqq_save_state(struct bfq_queue *bfqq) -+{ -+ /* -+ * If bfqq->bic == NULL, the queue is already shared or its requests -+ * have already been redirected to a shared queue; both idle window -+ * and weight raising state have already been saved. Do nothing. -+ */ -+ if (bfqq->bic == NULL) -+ return; -+ if (bfqq->bic->wr_time_left) -+ /* -+ * This is the queue of a just-started process, and would -+ * deserve weight raising: we set wr_time_left to the full -+ * weight-raising duration to trigger weight-raising when -+ * and if the queue is split and the first request of the -+ * queue is enqueued. -+ */ -+ bfqq->bic->wr_time_left = bfq_wr_duration(bfqq->bfqd); -+ else if (bfqq->wr_coeff > 1) { -+ unsigned long wr_duration = -+ jiffies - bfqq->last_wr_start_finish; -+ /* -+ * It may happen that a queue's weight raising period lasts -+ * longer than its wr_cur_max_time, as weight raising is -+ * handled only when a request is enqueued or dispatched (it -+ * does not use any timer). If the weight raising period is -+ * about to end, don't save it. -+ */ -+ if (bfqq->wr_cur_max_time <= wr_duration) -+ bfqq->bic->wr_time_left = 0; -+ else -+ bfqq->bic->wr_time_left = -+ bfqq->wr_cur_max_time - wr_duration; -+ /* -+ * The bfq_queue is becoming shared or the requests of the -+ * process owning the queue are being redirected to a shared -+ * queue. Stop the weight raising period of the queue, as in -+ * both cases it should not be owned by an interactive or -+ * soft real-time application. -+ */ -+ bfq_bfqq_end_wr(bfqq); -+ } else -+ bfqq->bic->wr_time_left = 0; -+ bfqq->bic->saved_idle_window = bfq_bfqq_idle_window(bfqq); -+ bfqq->bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq); -+ bfqq->bic->cooperations++; -+ bfqq->bic->failed_cooperations = 0; -+} -+ -+static inline void -+bfq_get_bic_reference(struct bfq_queue *bfqq) -+{ -+ /* -+ * If bfqq->bic has a non-NULL value, the bic to which it belongs -+ * is about to begin using a shared bfq_queue. -+ */ -+ if (bfqq->bic) -+ atomic_long_inc(&bfqq->bic->icq.ioc->refcount); -+} -+ -+static void -+bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic, -+ struct bfq_queue *bfqq, struct bfq_queue *new_bfqq) -+{ -+ bfq_log_bfqq(bfqd, bfqq, "merging with queue %lu", -+ (long unsigned)new_bfqq->pid); -+ /* Save weight raising and idle window of the merged queues */ -+ bfq_bfqq_save_state(bfqq); -+ bfq_bfqq_save_state(new_bfqq); -+ if (bfq_bfqq_IO_bound(bfqq)) -+ bfq_mark_bfqq_IO_bound(new_bfqq); -+ bfq_clear_bfqq_IO_bound(bfqq); -+ /* -+ * Grab a reference to the bic, to prevent it from being destroyed -+ * before being possibly touched by a bfq_split_bfqq(). -+ */ -+ bfq_get_bic_reference(bfqq); -+ bfq_get_bic_reference(new_bfqq); -+ /* -+ * Merge queues (that is, let bic redirect its requests to new_bfqq) -+ */ -+ bic_set_bfqq(bic, new_bfqq, 1); -+ bfq_mark_bfqq_coop(new_bfqq); -+ /* -+ * new_bfqq now belongs to at least two bics (it is a shared queue): -+ * set new_bfqq->bic to NULL. bfqq either: -+ * - does not belong to any bic any more, and hence bfqq->bic must -+ * be set to NULL, or -+ * - is a queue whose owning bics have already been redirected to a -+ * different queue, hence the queue is destined to not belong to -+ * any bic soon and bfqq->bic is already NULL (therefore the next -+ * assignment causes no harm). -+ */ -+ new_bfqq->bic = NULL; -+ bfqq->bic = NULL; -+ bfq_put_queue(bfqq); -+} -+ -+static inline void bfq_bfqq_increase_failed_cooperations(struct bfq_queue *bfqq) -+{ -+ struct bfq_io_cq *bic = bfqq->bic; -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ if (bic && bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh) { -+ bic->failed_cooperations++; -+ if (bic->failed_cooperations >= bfqd->bfq_failed_cooperations) -+ bic->cooperations = 0; -+ } -+} -+ -+static int bfq_allow_merge(struct request_queue *q, struct request *rq, -+ struct bio *bio) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq, *new_bfqq; -+ -+ /* -+ * Disallow merge of a sync bio into an async request. -+ */ -+ if (bfq_bio_sync(bio) && !rq_is_sync(rq)) -+ return 0; -+ -+ /* -+ * Lookup the bfqq that this bio will be queued with. Allow -+ * merge only if rq is queued there. -+ * Queue lock is held here. -+ */ -+ bic = bfq_bic_lookup(bfqd, current->io_context); -+ if (bic == NULL) -+ return 0; -+ -+ bfqq = bic_to_bfqq(bic, bfq_bio_sync(bio)); -+ /* -+ * We take advantage of this function to perform an early merge -+ * of the queues of possible cooperating processes. -+ */ -+ if (bfqq != NULL) { -+ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, bio, false); -+ if (new_bfqq != NULL) { -+ bfq_merge_bfqqs(bfqd, bic, bfqq, new_bfqq); -+ /* -+ * If we get here, the bio will be queued in the -+ * shared queue, i.e., new_bfqq, so use new_bfqq -+ * to decide whether bio and rq can be merged. -+ */ -+ bfqq = new_bfqq; -+ } else -+ bfq_bfqq_increase_failed_cooperations(bfqq); -+ } -+ -+ return bfqq == RQ_BFQQ(rq); -+} -+ -+static void __bfq_set_in_service_queue(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ if (bfqq != NULL) { -+ bfq_mark_bfqq_must_alloc(bfqq); -+ bfq_mark_bfqq_budget_new(bfqq); -+ bfq_clear_bfqq_fifo_expire(bfqq); -+ -+ bfqd->budgets_assigned = (bfqd->budgets_assigned*7 + 256) / 8; -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "set_in_service_queue, cur-budget = %lu", -+ bfqq->entity.budget); -+ } -+ -+ bfqd->in_service_queue = bfqq; -+} -+ -+/* -+ * Get and set a new queue for service. -+ */ -+static struct bfq_queue *bfq_set_in_service_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfq_get_next_queue(bfqd); -+ -+ __bfq_set_in_service_queue(bfqd, bfqq); -+ return bfqq; -+} -+ -+/* -+ * If enough samples have been computed, return the current max budget -+ * stored in bfqd, which is dynamically updated according to the -+ * estimated disk peak rate; otherwise return the default max budget -+ */ -+static inline unsigned long bfq_max_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget; -+ else -+ return bfqd->bfq_max_budget; -+} -+ -+/* -+ * Return min budget, which is a fraction of the current or default -+ * max budget (trying with 1/32) -+ */ -+static inline unsigned long bfq_min_budget(struct bfq_data *bfqd) -+{ -+ if (bfqd->budgets_assigned < 194) -+ return bfq_default_max_budget / 32; -+ else -+ return bfqd->bfq_max_budget / 32; -+} -+ -+static void bfq_arm_slice_timer(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ struct bfq_io_cq *bic; -+ unsigned long sl; -+ -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Processes have exited, don't wait. */ -+ bic = bfqd->in_service_bic; -+ if (bic == NULL || atomic_read(&bic->icq.ioc->active_ref) == 0) -+ return; -+ -+ bfq_mark_bfqq_wait_request(bfqq); -+ -+ /* -+ * We don't want to idle for seeks, but we do want to allow -+ * fair distribution of slice time for a process doing back-to-back -+ * seeks. So allow a little bit of time for him to submit a new rq. -+ * -+ * To prevent processes with (partly) seeky workloads from -+ * being too ill-treated, grant them a small fraction of the -+ * assigned budget before reducing the waiting time to -+ * BFQ_MIN_TT. This happened to help reduce latency. -+ */ -+ sl = bfqd->bfq_slice_idle; -+ /* -+ * Unless the queue is being weight-raised, grant only minimum idle -+ * time if the queue either has been seeky for long enough or has -+ * already proved to be constantly seeky. -+ */ -+ if (bfq_sample_valid(bfqq->seek_samples) && -+ ((BFQQ_SEEKY(bfqq) && bfqq->entity.service > -+ bfq_max_budget(bfqq->bfqd) / 8) || -+ bfq_bfqq_constantly_seeky(bfqq)) && bfqq->wr_coeff == 1) -+ sl = min(sl, msecs_to_jiffies(BFQ_MIN_TT)); -+ else if (bfqq->wr_coeff > 1) -+ sl = sl * 3; -+ bfqd->last_idling_start = ktime_get(); -+ mod_timer(&bfqd->idle_slice_timer, jiffies + sl); -+ bfq_log(bfqd, "arm idle: %u/%u ms", -+ jiffies_to_msecs(sl), jiffies_to_msecs(bfqd->bfq_slice_idle)); -+} -+ -+/* -+ * Set the maximum time for the in-service queue to consume its -+ * budget. This prevents seeky processes from lowering the disk -+ * throughput (always guaranteed with a time slice scheme as in CFQ). -+ */ -+static void bfq_set_budget_timeout(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq = bfqd->in_service_queue; -+ unsigned int timeout_coeff; -+ if (bfqq->wr_cur_max_time == bfqd->bfq_wr_rt_max_time) -+ timeout_coeff = 1; -+ else -+ timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight; -+ -+ bfqd->last_budget_start = ktime_get(); -+ -+ bfq_clear_bfqq_budget_new(bfqq); -+ bfqq->budget_timeout = jiffies + -+ bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * timeout_coeff; -+ -+ bfq_log_bfqq(bfqd, bfqq, "set budget_timeout %u", -+ jiffies_to_msecs(bfqd->bfq_timeout[bfq_bfqq_sync(bfqq)] * -+ timeout_coeff)); -+} -+ -+/* -+ * Move request from internal lists to the request queue dispatch list. -+ */ -+static void bfq_dispatch_insert(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ /* -+ * For consistency, the next instruction should have been executed -+ * after removing the request from the queue and dispatching it. -+ * We execute instead this instruction before bfq_remove_request() -+ * (and hence introduce a temporary inconsistency), for efficiency. -+ * In fact, in a forced_dispatch, this prevents two counters related -+ * to bfqq->dispatched to risk to be uselessly decremented if bfqq -+ * is not in service, and then to be incremented again after -+ * incrementing bfqq->dispatched. -+ */ -+ bfqq->dispatched++; -+ bfq_remove_request(rq); -+ elv_dispatch_sort(q, rq); -+ -+ if (bfq_bfqq_sync(bfqq)) -+ bfqd->sync_flight++; -+} -+ -+/* -+ * Return expired entry, or NULL to just start from scratch in rbtree. -+ */ -+static struct request *bfq_check_fifo(struct bfq_queue *bfqq) -+{ -+ struct request *rq = NULL; -+ -+ if (bfq_bfqq_fifo_expire(bfqq)) -+ return NULL; -+ -+ bfq_mark_bfqq_fifo_expire(bfqq); -+ -+ if (list_empty(&bfqq->fifo)) -+ return NULL; -+ -+ rq = rq_entry_fifo(bfqq->fifo.next); -+ -+ if (time_before(jiffies, rq_fifo_time(rq))) -+ return NULL; -+ -+ return rq; -+} -+ -+static inline unsigned long bfq_bfqq_budget_left(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ return entity->budget - entity->service; -+} -+ -+static void __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ /* -+ * If this bfqq is shared between multiple processes, check -+ * to make sure that those processes are still issuing I/Os -+ * within the mean seek distance. If not, it may be time to -+ * break the queues apart again. -+ */ -+ if (bfq_bfqq_coop(bfqq) && BFQQ_SEEKY(bfqq)) -+ bfq_mark_bfqq_split_coop(bfqq); -+ -+ if (RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * Overloading budget_timeout field to store the time -+ * at which the queue remains with no backlog; used by -+ * the weight-raising mechanism. -+ */ -+ bfqq->budget_timeout = jiffies; -+ bfq_del_bfqq_busy(bfqd, bfqq, 1); -+ } else { -+ bfq_activate_bfqq(bfqd, bfqq); -+ /* -+ * Resort priority tree of potential close cooperators. -+ */ -+ bfq_rq_pos_tree_add(bfqd, bfqq); -+ } -+} -+ -+/** -+ * __bfq_bfqq_recalc_budget - try to adapt the budget to the @bfqq behavior. -+ * @bfqd: device data. -+ * @bfqq: queue to update. -+ * @reason: reason for expiration. -+ * -+ * Handle the feedback on @bfqq budget. See the body for detailed -+ * comments. -+ */ -+static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ enum bfqq_expiration reason) -+{ -+ struct request *next_rq; -+ unsigned long budget, min_budget; -+ -+ budget = bfqq->max_budget; -+ min_budget = bfq_min_budget(bfqd); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last budg %lu, budg left %lu", -+ bfqq->entity.budget, bfq_bfqq_budget_left(bfqq)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: last max_budg %lu, min budg %lu", -+ budget, bfq_min_budget(bfqd)); -+ bfq_log_bfqq(bfqd, bfqq, "recalc_budg: sync %d, seeky %d", -+ bfq_bfqq_sync(bfqq), BFQQ_SEEKY(bfqd->in_service_queue)); -+ -+ if (bfq_bfqq_sync(bfqq)) { -+ switch (reason) { -+ /* -+ * Caveat: in all the following cases we trade latency -+ * for throughput. -+ */ -+ case BFQ_BFQQ_TOO_IDLE: -+ /* -+ * This is the only case where we may reduce -+ * the budget: if there is no request of the -+ * process still waiting for completion, then -+ * we assume (tentatively) that the timer has -+ * expired because the batch of requests of -+ * the process could have been served with a -+ * smaller budget. Hence, betting that -+ * process will behave in the same way when it -+ * becomes backlogged again, we reduce its -+ * next budget. As long as we guess right, -+ * this budget cut reduces the latency -+ * experienced by the process. -+ * -+ * However, if there are still outstanding -+ * requests, then the process may have not yet -+ * issued its next request just because it is -+ * still waiting for the completion of some of -+ * the still outstanding ones. So in this -+ * subcase we do not reduce its budget, on the -+ * contrary we increase it to possibly boost -+ * the throughput, as discussed in the -+ * comments to the BUDGET_TIMEOUT case. -+ */ -+ if (bfqq->dispatched > 0) /* still outstanding reqs */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ else { -+ if (budget > 5 * min_budget) -+ budget -= 4 * min_budget; -+ else -+ budget = min_budget; -+ } -+ break; -+ case BFQ_BFQQ_BUDGET_TIMEOUT: -+ /* -+ * We double the budget here because: 1) it -+ * gives the chance to boost the throughput if -+ * this is not a seeky process (which may have -+ * bumped into this timeout because of, e.g., -+ * ZBR), 2) together with charge_full_budget -+ * it helps give seeky processes higher -+ * timestamps, and hence be served less -+ * frequently. -+ */ -+ budget = min(budget * 2, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_BUDGET_EXHAUSTED: -+ /* -+ * The process still has backlog, and did not -+ * let either the budget timeout or the disk -+ * idling timeout expire. Hence it is not -+ * seeky, has a short thinktime and may be -+ * happy with a higher budget too. So -+ * definitely increase the budget of this good -+ * candidate to boost the disk throughput. -+ */ -+ budget = min(budget * 4, bfqd->bfq_max_budget); -+ break; -+ case BFQ_BFQQ_NO_MORE_REQUESTS: -+ /* -+ * Leave the budget unchanged. -+ */ -+ default: -+ return; -+ } -+ } else /* async queue */ -+ /* async queues get always the maximum possible budget -+ * (their ability to dispatch is limited by -+ * @bfqd->bfq_max_budget_async_rq). -+ */ -+ budget = bfqd->bfq_max_budget; -+ -+ bfqq->max_budget = budget; -+ -+ if (bfqd->budgets_assigned >= 194 && bfqd->bfq_user_max_budget == 0 && -+ bfqq->max_budget > bfqd->bfq_max_budget) -+ bfqq->max_budget = bfqd->bfq_max_budget; -+ -+ /* -+ * Make sure that we have enough budget for the next request. -+ * Since the finish time of the bfqq must be kept in sync with -+ * the budget, be sure to call __bfq_bfqq_expire() after the -+ * update. -+ */ -+ next_rq = bfqq->next_rq; -+ if (next_rq != NULL) -+ bfqq->entity.budget = max_t(unsigned long, bfqq->max_budget, -+ bfq_serv_to_charge(next_rq, bfqq)); -+ else -+ bfqq->entity.budget = bfqq->max_budget; -+ -+ bfq_log_bfqq(bfqd, bfqq, "head sect: %u, new budget %lu", -+ next_rq != NULL ? blk_rq_sectors(next_rq) : 0, -+ bfqq->entity.budget); -+} -+ -+static unsigned long bfq_calc_max_budget(u64 peak_rate, u64 timeout) -+{ -+ unsigned long max_budget; -+ -+ /* -+ * The max_budget calculated when autotuning is equal to the -+ * amount of sectors transfered in timeout_sync at the -+ * estimated peak rate. -+ */ -+ max_budget = (unsigned long)(peak_rate * 1000 * -+ timeout >> BFQ_RATE_SHIFT); -+ -+ return max_budget; -+} -+ -+/* -+ * In addition to updating the peak rate, checks whether the process -+ * is "slow", and returns 1 if so. This slow flag is used, in addition -+ * to the budget timeout, to reduce the amount of service provided to -+ * seeky processes, and hence reduce their chances to lower the -+ * throughput. See the code for more details. -+ */ -+static int bfq_update_peak_rate(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int compensate, enum bfqq_expiration reason) -+{ -+ u64 bw, usecs, expected, timeout; -+ ktime_t delta; -+ int update = 0; -+ -+ if (!bfq_bfqq_sync(bfqq) || bfq_bfqq_budget_new(bfqq)) -+ return 0; -+ -+ if (compensate) -+ delta = bfqd->last_idling_start; -+ else -+ delta = ktime_get(); -+ delta = ktime_sub(delta, bfqd->last_budget_start); -+ usecs = ktime_to_us(delta); -+ -+ /* Don't trust short/unrealistic values. */ -+ if (usecs < 100 || usecs >= LONG_MAX) -+ return 0; -+ -+ /* -+ * Calculate the bandwidth for the last slice. We use a 64 bit -+ * value to store the peak rate, in sectors per usec in fixed -+ * point math. We do so to have enough precision in the estimate -+ * and to avoid overflows. -+ */ -+ bw = (u64)bfqq->entity.service << BFQ_RATE_SHIFT; -+ do_div(bw, (unsigned long)usecs); -+ -+ timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ /* -+ * Use only long (> 20ms) intervals to filter out spikes for -+ * the peak rate estimation. -+ */ -+ if (usecs > 20000) { -+ if (bw > bfqd->peak_rate || -+ (!BFQQ_SEEKY(bfqq) && -+ reason == BFQ_BFQQ_BUDGET_TIMEOUT)) { -+ bfq_log(bfqd, "measured bw =%llu", bw); -+ /* -+ * To smooth oscillations use a low-pass filter with -+ * alpha=7/8, i.e., -+ * new_rate = (7/8) * old_rate + (1/8) * bw -+ */ -+ do_div(bw, 8); -+ if (bw == 0) -+ return 0; -+ bfqd->peak_rate *= 7; -+ do_div(bfqd->peak_rate, 8); -+ bfqd->peak_rate += bw; -+ update = 1; -+ bfq_log(bfqd, "new peak_rate=%llu", bfqd->peak_rate); -+ } -+ -+ update |= bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES - 1; -+ -+ if (bfqd->peak_rate_samples < BFQ_PEAK_RATE_SAMPLES) -+ bfqd->peak_rate_samples++; -+ -+ if (bfqd->peak_rate_samples == BFQ_PEAK_RATE_SAMPLES && -+ update) { -+ int dev_type = blk_queue_nonrot(bfqd->queue); -+ if (bfqd->bfq_user_max_budget == 0) { -+ bfqd->bfq_max_budget = -+ bfq_calc_max_budget(bfqd->peak_rate, -+ timeout); -+ bfq_log(bfqd, "new max_budget=%lu", -+ bfqd->bfq_max_budget); -+ } -+ if (bfqd->device_speed == BFQ_BFQD_FAST && -+ bfqd->peak_rate < device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_SLOW; -+ bfqd->RT_prod = R_slow[dev_type] * -+ T_slow[dev_type]; -+ } else if (bfqd->device_speed == BFQ_BFQD_SLOW && -+ bfqd->peak_rate > device_speed_thresh[dev_type]) { -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ bfqd->RT_prod = R_fast[dev_type] * -+ T_fast[dev_type]; -+ } -+ } -+ } -+ -+ /* -+ * If the process has been served for a too short time -+ * interval to let its possible sequential accesses prevail on -+ * the initial seek time needed to move the disk head on the -+ * first sector it requested, then give the process a chance -+ * and for the moment return false. -+ */ -+ if (bfqq->entity.budget <= bfq_max_budget(bfqd) / 8) -+ return 0; -+ -+ /* -+ * A process is considered ``slow'' (i.e., seeky, so that we -+ * cannot treat it fairly in the service domain, as it would -+ * slow down too much the other processes) if, when a slice -+ * ends for whatever reason, it has received service at a -+ * rate that would not be high enough to complete the budget -+ * before the budget timeout expiration. -+ */ -+ expected = bw * 1000 * timeout >> BFQ_RATE_SHIFT; -+ -+ /* -+ * Caveat: processes doing IO in the slower disk zones will -+ * tend to be slow(er) even if not seeky. And the estimated -+ * peak rate will actually be an average over the disk -+ * surface. Hence, to not be too harsh with unlucky processes, -+ * we keep a budget/3 margin of safety before declaring a -+ * process slow. -+ */ -+ return expected > (4 * bfqq->entity.budget) / 3; -+} -+ -+/* -+ * To be deemed as soft real-time, an application must meet two -+ * requirements. First, the application must not require an average -+ * bandwidth higher than the approximate bandwidth required to playback or -+ * record a compressed high-definition video. -+ * The next function is invoked on the completion of the last request of a -+ * batch, to compute the next-start time instant, soft_rt_next_start, such -+ * that, if the next request of the application does not arrive before -+ * soft_rt_next_start, then the above requirement on the bandwidth is met. -+ * -+ * The second requirement is that the request pattern of the application is -+ * isochronous, i.e., that, after issuing a request or a batch of requests, -+ * the application stops issuing new requests until all its pending requests -+ * have been completed. After that, the application may issue a new batch, -+ * and so on. -+ * For this reason the next function is invoked to compute -+ * soft_rt_next_start only for applications that meet this requirement, -+ * whereas soft_rt_next_start is set to infinity for applications that do -+ * not. -+ * -+ * Unfortunately, even a greedy application may happen to behave in an -+ * isochronous way if the CPU load is high. In fact, the application may -+ * stop issuing requests while the CPUs are busy serving other processes, -+ * then restart, then stop again for a while, and so on. In addition, if -+ * the disk achieves a low enough throughput with the request pattern -+ * issued by the application (e.g., because the request pattern is random -+ * and/or the device is slow), then the application may meet the above -+ * bandwidth requirement too. To prevent such a greedy application to be -+ * deemed as soft real-time, a further rule is used in the computation of -+ * soft_rt_next_start: soft_rt_next_start must be higher than the current -+ * time plus the maximum time for which the arrival of a request is waited -+ * for when a sync queue becomes idle, namely bfqd->bfq_slice_idle. -+ * This filters out greedy applications, as the latter issue instead their -+ * next request as soon as possible after the last one has been completed -+ * (in contrast, when a batch of requests is completed, a soft real-time -+ * application spends some time processing data). -+ * -+ * Unfortunately, the last filter may easily generate false positives if -+ * only bfqd->bfq_slice_idle is used as a reference time interval and one -+ * or both the following cases occur: -+ * 1) HZ is so low that the duration of a jiffy is comparable to or higher -+ * than bfqd->bfq_slice_idle. This happens, e.g., on slow devices with -+ * HZ=100. -+ * 2) jiffies, instead of increasing at a constant rate, may stop increasing -+ * for a while, then suddenly 'jump' by several units to recover the lost -+ * increments. This seems to happen, e.g., inside virtual machines. -+ * To address this issue, we do not use as a reference time interval just -+ * bfqd->bfq_slice_idle, but bfqd->bfq_slice_idle plus a few jiffies. In -+ * particular we add the minimum number of jiffies for which the filter -+ * seems to be quite precise also in embedded systems and KVM/QEMU virtual -+ * machines. -+ */ -+static inline unsigned long bfq_bfqq_softrt_next_start(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ return max(bfqq->last_idle_bklogged + -+ HZ * bfqq->service_from_backlogged / -+ bfqd->bfq_wr_max_softrt_rate, -+ jiffies + bfqq->bfqd->bfq_slice_idle + 4); -+} -+ -+/* -+ * Return the largest-possible time instant such that, for as long as possible, -+ * the current time will be lower than this time instant according to the macro -+ * time_is_before_jiffies(). -+ */ -+static inline unsigned long bfq_infinity_from_now(unsigned long now) -+{ -+ return now + ULONG_MAX / 2; -+} -+ -+/** -+ * bfq_bfqq_expire - expire a queue. -+ * @bfqd: device owning the queue. -+ * @bfqq: the queue to expire. -+ * @compensate: if true, compensate for the time spent idling. -+ * @reason: the reason causing the expiration. -+ * -+ * -+ * If the process associated to the queue is slow (i.e., seeky), or in -+ * case of budget timeout, or, finally, if it is async, we -+ * artificially charge it an entire budget (independently of the -+ * actual service it received). As a consequence, the queue will get -+ * higher timestamps than the correct ones upon reactivation, and -+ * hence it will be rescheduled as if it had received more service -+ * than what it actually received. In the end, this class of processes -+ * will receive less service in proportion to how slowly they consume -+ * their budgets (and hence how seriously they tend to lower the -+ * throughput). -+ * -+ * In contrast, when a queue expires because it has been idling for -+ * too much or because it exhausted its budget, we do not touch the -+ * amount of service it has received. Hence when the queue will be -+ * reactivated and its timestamps updated, the latter will be in sync -+ * with the actual service received by the queue until expiration. -+ * -+ * Charging a full budget to the first type of queues and the exact -+ * service to the others has the effect of using the WF2Q+ policy to -+ * schedule the former on a timeslice basis, without violating the -+ * service domain guarantees of the latter. -+ */ -+static void bfq_bfqq_expire(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ int compensate, -+ enum bfqq_expiration reason) -+{ -+ int slow; -+ BUG_ON(bfqq != bfqd->in_service_queue); -+ -+ /* Update disk peak rate for autotuning and check whether the -+ * process is slow (see bfq_update_peak_rate). -+ */ -+ slow = bfq_update_peak_rate(bfqd, bfqq, compensate, reason); -+ -+ /* -+ * As above explained, 'punish' slow (i.e., seeky), timed-out -+ * and async queues, to favor sequential sync workloads. -+ * -+ * Processes doing I/O in the slower disk zones will tend to be -+ * slow(er) even if not seeky. Hence, since the estimated peak -+ * rate is actually an average over the disk surface, these -+ * processes may timeout just for bad luck. To avoid punishing -+ * them we do not charge a full budget to a process that -+ * succeeded in consuming at least 2/3 of its budget. -+ */ -+ if (slow || (reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3)) -+ bfq_bfqq_charge_full_budget(bfqq); -+ -+ bfqq->service_from_backlogged += bfqq->entity.service; -+ -+ if (BFQQ_SEEKY(bfqq) && reason == BFQ_BFQQ_BUDGET_TIMEOUT && -+ !bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_mark_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ -+ if (reason == BFQ_BFQQ_TOO_IDLE && -+ bfqq->entity.service <= 2 * bfqq->entity.budget / 10 ) -+ bfq_clear_bfqq_IO_bound(bfqq); -+ -+ if (bfqd->low_latency && bfqq->wr_coeff == 1) -+ bfqq->last_wr_start_finish = jiffies; -+ -+ if (bfqd->low_latency && bfqd->bfq_wr_max_softrt_rate > 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) { -+ /* -+ * If we get here, and there are no outstanding requests, -+ * then the request pattern is isochronous (see the comments -+ * to the function bfq_bfqq_softrt_next_start()). Hence we -+ * can compute soft_rt_next_start. If, instead, the queue -+ * still has outstanding requests, then we have to wait -+ * for the completion of all the outstanding requests to -+ * discover whether the request pattern is actually -+ * isochronous. -+ */ -+ if (bfqq->dispatched == 0) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ else { -+ /* -+ * The application is still waiting for the -+ * completion of one or more requests: -+ * prevent it from possibly being incorrectly -+ * deemed as soft real-time by setting its -+ * soft_rt_next_start to infinity. In fact, -+ * without this assignment, the application -+ * would be incorrectly deemed as soft -+ * real-time if: -+ * 1) it issued a new request before the -+ * completion of all its in-flight -+ * requests, and -+ * 2) at that time, its soft_rt_next_start -+ * happened to be in the past. -+ */ -+ bfqq->soft_rt_next_start = -+ bfq_infinity_from_now(jiffies); -+ /* -+ * Schedule an update of soft_rt_next_start to when -+ * the task may be discovered to be isochronous. -+ */ -+ bfq_mark_bfqq_softrt_update(bfqq); -+ } -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "expire (%d, slow %d, num_disp %d, idle_win %d)", reason, -+ slow, bfqq->dispatched, bfq_bfqq_idle_window(bfqq)); -+ -+ /* -+ * Increase, decrease or leave budget unchanged according to -+ * reason. -+ */ -+ __bfq_bfqq_recalc_budget(bfqd, bfqq, reason); -+ __bfq_bfqq_expire(bfqd, bfqq); -+} -+ -+/* -+ * Budget timeout is not implemented through a dedicated timer, but -+ * just checked on request arrivals and completions, as well as on -+ * idle timer expirations. -+ */ -+static int bfq_bfqq_budget_timeout(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_budget_new(bfqq) || -+ time_before(jiffies, bfqq->budget_timeout)) -+ return 0; -+ return 1; -+} -+ -+/* -+ * If we expire a queue that is waiting for the arrival of a new -+ * request, we may prevent the fictitious timestamp back-shifting that -+ * allows the guarantees of the queue to be preserved (see [1] for -+ * this tricky aspect). Hence we return true only if this condition -+ * does not hold, or if the queue is slow enough to deserve only to be -+ * kicked off for preserving a high throughput. -+*/ -+static inline int bfq_may_expire_for_budg_timeout(struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "may_budget_timeout: wait_request %d left %d timeout %d", -+ bfq_bfqq_wait_request(bfqq), -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3, -+ bfq_bfqq_budget_timeout(bfqq)); -+ -+ return (!bfq_bfqq_wait_request(bfqq) || -+ bfq_bfqq_budget_left(bfqq) >= bfqq->entity.budget / 3) -+ && -+ bfq_bfqq_budget_timeout(bfqq); -+} -+ -+/* -+ * Device idling is allowed only for the queues for which this function -+ * returns true. For this reason, the return value of this function plays a -+ * critical role for both throughput boosting and service guarantees. The -+ * return value is computed through a logical expression. In this rather -+ * long comment, we try to briefly describe all the details and motivations -+ * behind the components of this logical expression. -+ * -+ * First, the expression may be true only for sync queues. Besides, if -+ * bfqq is also being weight-raised, then the expression always evaluates -+ * to true, as device idling is instrumental for preserving low-latency -+ * guarantees (see [1]). Otherwise, the expression evaluates to true only -+ * if bfqq has a non-null idle window and at least one of the following -+ * two conditions holds. The first condition is that the device is not -+ * performing NCQ, because idling the device most certainly boosts the -+ * throughput if this condition holds and bfqq has been granted a non-null -+ * idle window. The second compound condition is made of the logical AND of -+ * two components. -+ * -+ * The first component is true only if there is no weight-raised busy -+ * queue. This guarantees that the device is not idled for a sync non- -+ * weight-raised queue when there are busy weight-raised queues. The former -+ * is then expired immediately if empty. Combined with the timestamping -+ * rules of BFQ (see [1] for details), this causes sync non-weight-raised -+ * queues to get a lower number of requests served, and hence to ask for a -+ * lower number of requests from the request pool, before the busy weight- -+ * raised queues get served again. -+ * -+ * This is beneficial for the processes associated with weight-raised -+ * queues, when the request pool is saturated (e.g., in the presence of -+ * write hogs). In fact, if the processes associated with the other queues -+ * ask for requests at a lower rate, then weight-raised processes have a -+ * higher probability to get a request from the pool immediately (or at -+ * least soon) when they need one. Hence they have a higher probability to -+ * actually get a fraction of the disk throughput proportional to their -+ * high weight. This is especially true with NCQ-capable drives, which -+ * enqueue several requests in advance and further reorder internally- -+ * queued requests. -+ * -+ * In the end, mistreating non-weight-raised queues when there are busy -+ * weight-raised queues seems to mitigate starvation problems in the -+ * presence of heavy write workloads and NCQ, and hence to guarantee a -+ * higher application and system responsiveness in these hostile scenarios. -+ * -+ * If the first component of the compound condition is instead true, i.e., -+ * there is no weight-raised busy queue, then the second component of the -+ * compound condition takes into account service-guarantee and throughput -+ * issues related to NCQ (recall that the compound condition is evaluated -+ * only if the device is detected as supporting NCQ). -+ * -+ * As for service guarantees, allowing the drive to enqueue more than one -+ * request at a time, and hence delegating de facto final scheduling -+ * decisions to the drive's internal scheduler, causes loss of control on -+ * the actual request service order. In this respect, when the drive is -+ * allowed to enqueue more than one request at a time, the service -+ * distribution enforced by the drive's internal scheduler is likely to -+ * coincide with the desired device-throughput distribution only in the -+ * following, perfectly symmetric, scenario: -+ * 1) all active queues have the same weight, -+ * 2) all active groups at the same level in the groups tree have the same -+ * weight, -+ * 3) all active groups at the same level in the groups tree have the same -+ * number of children. -+ * -+ * Even in such a scenario, sequential I/O may still receive a preferential -+ * treatment, but this is not likely to be a big issue with flash-based -+ * devices, because of their non-dramatic loss of throughput with random -+ * I/O. Things do differ with HDDs, for which additional care is taken, as -+ * explained after completing the discussion for flash-based devices. -+ * -+ * Unfortunately, keeping the necessary state for evaluating exactly the -+ * above symmetry conditions would be quite complex and time-consuming. -+ * Therefore BFQ evaluates instead the following stronger sub-conditions, -+ * for which it is much easier to maintain the needed state: -+ * 1) all active queues have the same weight, -+ * 2) all active groups have the same weight, -+ * 3) all active groups have at most one active child each. -+ * In particular, the last two conditions are always true if hierarchical -+ * support and the cgroups interface are not enabled, hence no state needs -+ * to be maintained in this case. -+ * -+ * According to the above considerations, the second component of the -+ * compound condition evaluates to true if any of the above symmetry -+ * sub-condition does not hold, or the device is not flash-based. Therefore, -+ * if also the first component is true, then idling is allowed for a sync -+ * queue. These are the only sub-conditions considered if the device is -+ * flash-based, as, for such a device, it is sensible to force idling only -+ * for service-guarantee issues. In fact, as for throughput, idling -+ * NCQ-capable flash-based devices would not boost the throughput even -+ * with sequential I/O; rather it would lower the throughput in proportion -+ * to how fast the device is. In the end, (only) if all the three -+ * sub-conditions hold and the device is flash-based, the compound -+ * condition evaluates to false and therefore no idling is performed. -+ * -+ * As already said, things change with a rotational device, where idling -+ * boosts the throughput with sequential I/O (even with NCQ). Hence, for -+ * such a device the second component of the compound condition evaluates -+ * to true also if the following additional sub-condition does not hold: -+ * the queue is constantly seeky. Unfortunately, this different behavior -+ * with respect to flash-based devices causes an additional asymmetry: if -+ * some sync queues enjoy idling and some other sync queues do not, then -+ * the latter get a low share of the device throughput, simply because the -+ * former get many requests served after being set as in service, whereas -+ * the latter do not. As a consequence, to guarantee the desired throughput -+ * distribution, on HDDs the compound expression evaluates to true (and -+ * hence device idling is performed) also if the following last symmetry -+ * condition does not hold: no other queue is benefiting from idling. Also -+ * this last condition is actually replaced with a simpler-to-maintain and -+ * stronger condition: there is no busy queue which is not constantly seeky -+ * (and hence may also benefit from idling). -+ * -+ * To sum up, when all the required symmetry and throughput-boosting -+ * sub-conditions hold, the second component of the compound condition -+ * evaluates to false, and hence no idling is performed. This helps to -+ * keep the drives' internal queues full on NCQ-capable devices, and hence -+ * to boost the throughput, without causing 'almost' any loss of service -+ * guarantees. The 'almost' follows from the fact that, if the internal -+ * queue of one such device is filled while all the sub-conditions hold, -+ * but at some point in time some sub-condition stops to hold, then it may -+ * become impossible to let requests be served in the new desired order -+ * until all the requests already queued in the device have been served. -+ */ -+static inline bool bfq_bfqq_must_not_expire(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+#define symmetric_scenario (!bfqd->active_numerous_groups && \ -+ !bfq_differentiated_weights(bfqd)) -+#else -+#define symmetric_scenario (!bfq_differentiated_weights(bfqd)) -+#endif -+#define cond_for_seeky_on_ncq_hdd (bfq_bfqq_constantly_seeky(bfqq) && \ -+ bfqd->busy_in_flight_queues == \ -+ bfqd->const_seeky_busy_in_flight_queues) -+/* -+ * Condition for expiring a non-weight-raised queue (and hence not idling -+ * the device). -+ */ -+#define cond_for_expiring_non_wr (bfqd->hw_tag && \ -+ (bfqd->wr_busy_queues > 0 || \ -+ (symmetric_scenario && \ -+ (blk_queue_nonrot(bfqd->queue) || \ -+ cond_for_seeky_on_ncq_hdd)))) -+ -+ return bfq_bfqq_sync(bfqq) && -+ (bfq_bfqq_IO_bound(bfqq) || bfqq->wr_coeff > 1) && -+ (bfqq->wr_coeff > 1 || -+ (bfq_bfqq_idle_window(bfqq) && -+ !cond_for_expiring_non_wr) -+ ); -+} -+ -+/* -+ * If the in-service queue is empty but sync, and the function -+ * bfq_bfqq_must_not_expire returns true, then: -+ * 1) the queue must remain in service and cannot be expired, and -+ * 2) the disk must be idled to wait for the possible arrival of a new -+ * request for the queue. -+ * See the comments to the function bfq_bfqq_must_not_expire for the reasons -+ * why performing device idling is the best choice to boost the throughput -+ * and preserve service guarantees when bfq_bfqq_must_not_expire itself -+ * returns true. -+ */ -+static inline bool bfq_bfqq_must_idle(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ return RB_EMPTY_ROOT(&bfqq->sort_list) && bfqd->bfq_slice_idle != 0 && -+ bfq_bfqq_must_not_expire(bfqq); -+} -+ -+/* -+ * Select a queue for service. If we have a current queue in service, -+ * check whether to continue servicing it, or retrieve and set a new one. -+ */ -+static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq; -+ struct request *next_rq; -+ enum bfqq_expiration reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq == NULL) -+ goto new_queue; -+ -+ bfq_log_bfqq(bfqd, bfqq, "select_queue: already in-service queue"); -+ -+ if (bfq_may_expire_for_budg_timeout(bfqq) && -+ !timer_pending(&bfqd->idle_slice_timer) && -+ !bfq_bfqq_must_idle(bfqq)) -+ goto expire; -+ -+ next_rq = bfqq->next_rq; -+ /* -+ * If bfqq has requests queued and it has enough budget left to -+ * serve them, keep the queue, otherwise expire it. -+ */ -+ if (next_rq != NULL) { -+ if (bfq_serv_to_charge(next_rq, bfqq) > -+ bfq_bfqq_budget_left(bfqq)) { -+ reason = BFQ_BFQQ_BUDGET_EXHAUSTED; -+ goto expire; -+ } else { -+ /* -+ * The idle timer may be pending because we may -+ * not disable disk idling even when a new request -+ * arrives. -+ */ -+ if (timer_pending(&bfqd->idle_slice_timer)) { -+ /* -+ * If we get here: 1) at least a new request -+ * has arrived but we have not disabled the -+ * timer because the request was too small, -+ * 2) then the block layer has unplugged -+ * the device, causing the dispatch to be -+ * invoked. -+ * -+ * Since the device is unplugged, now the -+ * requests are probably large enough to -+ * provide a reasonable throughput. -+ * So we disable idling. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ } -+ goto keep_queue; -+ } -+ } -+ -+ /* -+ * No requests pending. If the in-service queue still has requests -+ * in flight (possibly waiting for a completion) or is idling for a -+ * new request, then keep it. -+ */ -+ if (timer_pending(&bfqd->idle_slice_timer) || -+ (bfqq->dispatched != 0 && bfq_bfqq_must_not_expire(bfqq))) { -+ bfqq = NULL; -+ goto keep_queue; -+ } -+ -+ reason = BFQ_BFQQ_NO_MORE_REQUESTS; -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, reason); -+new_queue: -+ bfqq = bfq_set_in_service_queue(bfqd); -+ bfq_log(bfqd, "select_queue: new queue %d returned", -+ bfqq != NULL ? bfqq->pid : 0); -+keep_queue: -+ return bfqq; -+} -+ -+static void bfq_update_wr_data(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ if (bfqq->wr_coeff > 1) { /* queue is being weight-raised */ -+ bfq_log_bfqq(bfqd, bfqq, -+ "raising period dur %u/%u msec, old coeff %u, w %d(%d)", -+ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time), -+ bfqq->wr_coeff, -+ bfqq->entity.weight, bfqq->entity.orig_weight); -+ -+ BUG_ON(bfqq != bfqd->in_service_queue && entity->weight != -+ entity->orig_weight * bfqq->wr_coeff); -+ if (entity->ioprio_changed) -+ bfq_log_bfqq(bfqd, bfqq, "WARN: pending prio change"); -+ -+ /* -+ * If too much time has elapsed from the beginning -+ * of this weight-raising period, or the queue has -+ * exceeded the acceptable number of cooperations, -+ * stop it. -+ */ -+ if (bfq_bfqq_cooperations(bfqq) >= bfqd->bfq_coop_thresh || -+ time_is_before_jiffies(bfqq->last_wr_start_finish + -+ bfqq->wr_cur_max_time)) { -+ bfqq->last_wr_start_finish = jiffies; -+ bfq_log_bfqq(bfqd, bfqq, -+ "wrais ending at %lu, rais_max_time %u", -+ bfqq->last_wr_start_finish, -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ bfq_bfqq_end_wr(bfqq); -+ } -+ } -+ /* Update weight both if it must be raised and if it must be lowered */ -+ if ((entity->weight > entity->orig_weight) != (bfqq->wr_coeff > 1)) -+ __bfq_entity_update_weight_prio( -+ bfq_entity_service_tree(entity), -+ entity); -+} -+ -+/* -+ * Dispatch one request from bfqq, moving it to the request queue -+ * dispatch list. -+ */ -+static int bfq_dispatch_request(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ struct request *rq; -+ unsigned long service_to_charge; -+ -+ BUG_ON(RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ /* Follow expired path, else get first next available. */ -+ rq = bfq_check_fifo(bfqq); -+ if (rq == NULL) -+ rq = bfqq->next_rq; -+ service_to_charge = bfq_serv_to_charge(rq, bfqq); -+ -+ if (service_to_charge > bfq_bfqq_budget_left(bfqq)) { -+ /* -+ * This may happen if the next rq is chosen in fifo order -+ * instead of sector order. The budget is properly -+ * dimensioned to be always sufficient to serve the next -+ * request only if it is chosen in sector order. The reason -+ * is that it would be quite inefficient and little useful -+ * to always make sure that the budget is large enough to -+ * serve even the possible next rq in fifo order. -+ * In fact, requests are seldom served in fifo order. -+ * -+ * Expire the queue for budget exhaustion, and make sure -+ * that the next act_budget is enough to serve the next -+ * request, even if it comes from the fifo expired path. -+ */ -+ bfqq->next_rq = rq; -+ /* -+ * Since this dispatch is failed, make sure that -+ * a new one will be performed -+ */ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ goto expire; -+ } -+ -+ /* Finally, insert request into driver dispatch list. */ -+ bfq_bfqq_served(bfqq, service_to_charge); -+ bfq_dispatch_insert(bfqd->queue, rq); -+ -+ bfq_update_wr_data(bfqd, bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "dispatched %u sec req (%llu), budg left %lu", -+ blk_rq_sectors(rq), -+ (long long unsigned)blk_rq_pos(rq), -+ bfq_bfqq_budget_left(bfqq)); -+ -+ dispatched++; -+ -+ if (bfqd->in_service_bic == NULL) { -+ atomic_long_inc(&RQ_BIC(rq)->icq.ioc->refcount); -+ bfqd->in_service_bic = RQ_BIC(rq); -+ } -+ -+ if (bfqd->busy_queues > 1 && ((!bfq_bfqq_sync(bfqq) && -+ dispatched >= bfqd->bfq_max_budget_async_rq) || -+ bfq_class_idle(bfqq))) -+ goto expire; -+ -+ return dispatched; -+ -+expire: -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_EXHAUSTED); -+ return dispatched; -+} -+ -+static int __bfq_forced_dispatch_bfqq(struct bfq_queue *bfqq) -+{ -+ int dispatched = 0; -+ -+ while (bfqq->next_rq != NULL) { -+ bfq_dispatch_insert(bfqq->bfqd->queue, bfqq->next_rq); -+ dispatched++; -+ } -+ -+ BUG_ON(!list_empty(&bfqq->fifo)); -+ return dispatched; -+} -+ -+/* -+ * Drain our current requests. -+ * Used for barriers and when switching io schedulers on-the-fly. -+ */ -+static int bfq_forced_dispatch(struct bfq_data *bfqd) -+{ -+ struct bfq_queue *bfqq, *n; -+ struct bfq_service_tree *st; -+ int dispatched = 0; -+ -+ bfqq = bfqd->in_service_queue; -+ if (bfqq != NULL) -+ __bfq_bfqq_expire(bfqd, bfqq); -+ -+ /* -+ * Loop through classes, and be careful to leave the scheduler -+ * in a consistent state, as feedback mechanisms and vtime -+ * updates cannot be disabled during the process. -+ */ -+ list_for_each_entry_safe(bfqq, n, &bfqd->active_list, bfqq_list) { -+ st = bfq_entity_service_tree(&bfqq->entity); -+ -+ dispatched += __bfq_forced_dispatch_bfqq(bfqq); -+ bfqq->max_budget = bfq_max_budget(bfqd); -+ -+ bfq_forget_idle(st); -+ } -+ -+ BUG_ON(bfqd->busy_queues != 0); -+ -+ return dispatched; -+} -+ -+static int bfq_dispatch_requests(struct request_queue *q, int force) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq; -+ int max_dispatch; -+ -+ bfq_log(bfqd, "dispatch requests: %d busy queues", bfqd->busy_queues); -+ if (bfqd->busy_queues == 0) -+ return 0; -+ -+ if (unlikely(force)) -+ return bfq_forced_dispatch(bfqd); -+ -+ bfqq = bfq_select_queue(bfqd); -+ if (bfqq == NULL) -+ return 0; -+ -+ max_dispatch = bfqd->bfq_quantum; -+ if (bfq_class_idle(bfqq)) -+ max_dispatch = 1; -+ -+ if (!bfq_bfqq_sync(bfqq)) -+ max_dispatch = bfqd->bfq_max_budget_async_rq; -+ -+ if (bfqq->dispatched >= max_dispatch) { -+ if (bfqd->busy_queues > 1) -+ return 0; -+ if (bfqq->dispatched >= 4 * max_dispatch) -+ return 0; -+ } -+ -+ if (bfqd->sync_flight != 0 && !bfq_bfqq_sync(bfqq)) -+ return 0; -+ -+ bfq_clear_bfqq_wait_request(bfqq); -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ if (!bfq_dispatch_request(bfqd, bfqq)) -+ return 0; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dispatched one request of %d (max_disp %d)", -+ bfqq->pid, max_dispatch); -+ -+ return 1; -+} -+ -+/* -+ * Task holds one reference to the queue, dropped when task exits. Each rq -+ * in-flight on this queue also holds a reference, dropped when rq is freed. -+ * -+ * Queue lock must be held here. -+ */ -+static void bfq_put_queue(struct bfq_queue *bfqq) -+{ -+ struct bfq_data *bfqd = bfqq->bfqd; -+ -+ BUG_ON(atomic_read(&bfqq->ref) <= 0); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ if (!atomic_dec_and_test(&bfqq->ref)) -+ return; -+ -+ BUG_ON(rb_first(&bfqq->sort_list) != NULL); -+ BUG_ON(bfqq->allocated[READ] + bfqq->allocated[WRITE] != 0); -+ BUG_ON(bfqq->entity.tree != NULL); -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqd->in_service_queue == bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, "put_queue: %p freed", bfqq); -+ -+ kmem_cache_free(bfq_pool, bfqq); -+} -+ -+static void bfq_put_cooperator(struct bfq_queue *bfqq) -+{ -+ struct bfq_queue *__bfqq, *next; -+ -+ /* -+ * If this queue was scheduled to merge with another queue, be -+ * sure to drop the reference taken on that queue (and others in -+ * the merge chain). See bfq_setup_merge and bfq_merge_bfqqs. -+ */ -+ __bfqq = bfqq->new_bfqq; -+ while (__bfqq) { -+ if (__bfqq == bfqq) -+ break; -+ next = __bfqq->new_bfqq; -+ bfq_put_queue(__bfqq); -+ __bfqq = next; -+ } -+} -+ -+static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ if (bfqq == bfqd->in_service_queue) { -+ __bfq_bfqq_expire(bfqd, bfqq); -+ bfq_schedule_dispatch(bfqd); -+ } -+ -+ bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+} -+ -+static inline void bfq_init_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ -+ bic->ttime.last_end_request = jiffies; -+ /* -+ * A newly created bic indicates that the process has just -+ * started doing I/O, and is probably mapping into memory its -+ * executable and libraries: it definitely needs weight raising. -+ * There is however the possibility that the process performs, -+ * for a while, I/O close to some other process. EQM intercepts -+ * this behavior and may merge the queue corresponding to the -+ * process with some other queue, BEFORE the weight of the queue -+ * is raised. Merged queues are not weight-raised (they are assumed -+ * to belong to processes that benefit only from high throughput). -+ * If the merge is basically the consequence of an accident, then -+ * the queue will be split soon and will get back its old weight. -+ * It is then important to write down somewhere that this queue -+ * does need weight raising, even if it did not make it to get its -+ * weight raised before being merged. To this purpose, we overload -+ * the field raising_time_left and assign 1 to it, to mark the queue -+ * as needing weight raising. -+ */ -+ bic->wr_time_left = 1; -+} -+ -+static void bfq_exit_icq(struct io_cq *icq) -+{ -+ struct bfq_io_cq *bic = icq_to_bic(icq); -+ struct bfq_data *bfqd = bic_to_bfqd(bic); -+ -+ if (bic->bfqq[BLK_RW_ASYNC]) { -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_ASYNC]); -+ bic->bfqq[BLK_RW_ASYNC] = NULL; -+ } -+ -+ if (bic->bfqq[BLK_RW_SYNC]) { -+ /* -+ * If the bic is using a shared queue, put the reference -+ * taken on the io_context when the bic started using a -+ * shared bfq_queue. -+ */ -+ if (bfq_bfqq_coop(bic->bfqq[BLK_RW_SYNC])) -+ put_io_context(icq->ioc); -+ bfq_exit_bfqq(bfqd, bic->bfqq[BLK_RW_SYNC]); -+ bic->bfqq[BLK_RW_SYNC] = NULL; -+ } -+} -+ -+/* -+ * Update the entity prio values; note that the new values will not -+ * be used until the next (re)activation. -+ */ -+static void bfq_init_prio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) -+{ -+ struct task_struct *tsk = current; -+ int ioprio_class; -+ -+ if (!bfq_bfqq_prio_changed(bfqq)) -+ return; -+ -+ ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ switch (ioprio_class) { -+ default: -+ dev_err(bfqq->bfqd->queue->backing_dev_info.dev, -+ "bfq: bad prio %x\n", ioprio_class); -+ case IOPRIO_CLASS_NONE: -+ /* -+ * No prio set, inherit CPU scheduling settings. -+ */ -+ bfqq->entity.new_ioprio = task_nice_ioprio(tsk); -+ bfqq->entity.new_ioprio_class = task_nice_ioclass(tsk); -+ break; -+ case IOPRIO_CLASS_RT: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_RT; -+ break; -+ case IOPRIO_CLASS_BE: -+ bfqq->entity.new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_BE; -+ break; -+ case IOPRIO_CLASS_IDLE: -+ bfqq->entity.new_ioprio_class = IOPRIO_CLASS_IDLE; -+ bfqq->entity.new_ioprio = 7; -+ bfq_clear_bfqq_idle_window(bfqq); -+ break; -+ } -+ -+ bfqq->entity.ioprio_changed = 1; -+ -+ bfq_clear_bfqq_prio_changed(bfqq); -+} -+ -+static void bfq_changed_ioprio(struct bfq_io_cq *bic) -+{ -+ struct bfq_data *bfqd; -+ struct bfq_queue *bfqq, *new_bfqq; -+ struct bfq_group *bfqg; -+ unsigned long uninitialized_var(flags); -+ int ioprio = bic->icq.ioc->ioprio; -+ -+ bfqd = bfq_get_bfqd_locked(&(bic->icq.q->elevator->elevator_data), -+ &flags); -+ /* -+ * This condition may trigger on a newly created bic, be sure to -+ * drop the lock before returning. -+ */ -+ if (unlikely(bfqd == NULL) || likely(bic->ioprio == ioprio)) -+ goto out; -+ -+ bfqq = bic->bfqq[BLK_RW_ASYNC]; -+ if (bfqq != NULL) { -+ bfqg = container_of(bfqq->entity.sched_data, struct bfq_group, -+ sched_data); -+ new_bfqq = bfq_get_queue(bfqd, bfqg, BLK_RW_ASYNC, bic, -+ GFP_ATOMIC); -+ if (new_bfqq != NULL) { -+ bic->bfqq[BLK_RW_ASYNC] = new_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, -+ "changed_ioprio: bfqq %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+ } -+ -+ bfqq = bic->bfqq[BLK_RW_SYNC]; -+ if (bfqq != NULL) -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ bic->ioprio = ioprio; -+ -+out: -+ bfq_put_bfqd_unlock(bfqd, &flags); -+} -+ -+static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ pid_t pid, int is_sync) -+{ -+ RB_CLEAR_NODE(&bfqq->entity.rb_node); -+ INIT_LIST_HEAD(&bfqq->fifo); -+ -+ atomic_set(&bfqq->ref, 0); -+ bfqq->bfqd = bfqd; -+ -+ bfq_mark_bfqq_prio_changed(bfqq); -+ -+ if (is_sync) { -+ if (!bfq_class_idle(bfqq)) -+ bfq_mark_bfqq_idle_window(bfqq); -+ bfq_mark_bfqq_sync(bfqq); -+ } -+ bfq_mark_bfqq_IO_bound(bfqq); -+ -+ /* Tentative initial value to trade off between thr and lat */ -+ bfqq->max_budget = (2 * bfq_max_budget(bfqd)) / 3; -+ bfqq->pid = pid; -+ -+ bfqq->wr_coeff = 1; -+ bfqq->last_wr_start_finish = 0; -+ /* -+ * Set to the value for which bfqq will not be deemed as -+ * soft rt when it becomes backlogged. -+ */ -+ bfqq->soft_rt_next_start = bfq_infinity_from_now(jiffies); -+} -+ -+static struct bfq_queue *bfq_find_alloc_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int is_sync, -+ struct bfq_io_cq *bic, -+ gfp_t gfp_mask) -+{ -+ struct bfq_queue *bfqq, *new_bfqq = NULL; -+ -+retry: -+ /* bic always exists here */ -+ bfqq = bic_to_bfqq(bic, is_sync); -+ -+ /* -+ * Always try a new alloc if we fall back to the OOM bfqq -+ * originally, since it should just be a temporary situation. -+ */ -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = NULL; -+ if (new_bfqq != NULL) { -+ bfqq = new_bfqq; -+ new_bfqq = NULL; -+ } else if (gfp_mask & __GFP_WAIT) { -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ new_bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ spin_lock_irq(bfqd->queue->queue_lock); -+ if (new_bfqq != NULL) -+ goto retry; -+ } else { -+ bfqq = kmem_cache_alloc_node(bfq_pool, -+ gfp_mask | __GFP_ZERO, -+ bfqd->queue->node); -+ } -+ -+ if (bfqq != NULL) { -+ bfq_init_bfqq(bfqd, bfqq, current->pid, is_sync); -+ bfq_log_bfqq(bfqd, bfqq, "allocated"); -+ } else { -+ bfqq = &bfqd->oom_bfqq; -+ bfq_log_bfqq(bfqd, bfqq, "using oom bfqq"); -+ } -+ -+ bfq_init_prio_data(bfqq, bic); -+ bfq_init_entity(&bfqq->entity, bfqg); -+ } -+ -+ if (new_bfqq != NULL) -+ kmem_cache_free(bfq_pool, new_bfqq); -+ -+ return bfqq; -+} -+ -+static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, -+ int ioprio_class, int ioprio) -+{ -+ switch (ioprio_class) { -+ case IOPRIO_CLASS_RT: -+ return &bfqg->async_bfqq[0][ioprio]; -+ case IOPRIO_CLASS_NONE: -+ ioprio = IOPRIO_NORM; -+ /* fall through */ -+ case IOPRIO_CLASS_BE: -+ return &bfqg->async_bfqq[1][ioprio]; -+ case IOPRIO_CLASS_IDLE: -+ return &bfqg->async_idle_bfqq; -+ default: -+ BUG(); -+ } -+} -+ -+static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, -+ struct bfq_group *bfqg, int is_sync, -+ struct bfq_io_cq *bic, gfp_t gfp_mask) -+{ -+ const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio); -+ const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio); -+ struct bfq_queue **async_bfqq = NULL; -+ struct bfq_queue *bfqq = NULL; -+ -+ if (!is_sync) { -+ async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class, -+ ioprio); -+ bfqq = *async_bfqq; -+ } -+ -+ if (bfqq == NULL) -+ bfqq = bfq_find_alloc_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ -+ /* -+ * Pin the queue now that it's allocated, scheduler exit will -+ * prune it. -+ */ -+ if (!is_sync && *async_bfqq == NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, bfqq not in async: %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ *async_bfqq = bfqq; -+ } -+ -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ return bfqq; -+} -+ -+static void bfq_update_io_thinktime(struct bfq_data *bfqd, -+ struct bfq_io_cq *bic) -+{ -+ unsigned long elapsed = jiffies - bic->ttime.last_end_request; -+ unsigned long ttime = min(elapsed, 2UL * bfqd->bfq_slice_idle); -+ -+ bic->ttime.ttime_samples = (7*bic->ttime.ttime_samples + 256) / 8; -+ bic->ttime.ttime_total = (7*bic->ttime.ttime_total + 256*ttime) / 8; -+ bic->ttime.ttime_mean = (bic->ttime.ttime_total + 128) / -+ bic->ttime.ttime_samples; -+} -+ -+static void bfq_update_io_seektime(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ sector_t sdist; -+ u64 total; -+ -+ if (bfqq->last_request_pos < blk_rq_pos(rq)) -+ sdist = blk_rq_pos(rq) - bfqq->last_request_pos; -+ else -+ sdist = bfqq->last_request_pos - blk_rq_pos(rq); -+ -+ /* -+ * Don't allow the seek distance to get too large from the -+ * odd fragment, pagein, etc. -+ */ -+ if (bfqq->seek_samples == 0) /* first request, not really a seek */ -+ sdist = 0; -+ else if (bfqq->seek_samples <= 60) /* second & third seek */ -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*1024); -+ else -+ sdist = min(sdist, (bfqq->seek_mean * 4) + 2*1024*64); -+ -+ bfqq->seek_samples = (7*bfqq->seek_samples + 256) / 8; -+ bfqq->seek_total = (7*bfqq->seek_total + (u64)256*sdist) / 8; -+ total = bfqq->seek_total + (bfqq->seek_samples/2); -+ do_div(total, bfqq->seek_samples); -+ bfqq->seek_mean = (sector_t)total; -+ -+ bfq_log_bfqq(bfqd, bfqq, "dist=%llu mean=%llu", (u64)sdist, -+ (u64)bfqq->seek_mean); -+} -+ -+/* -+ * Disable idle window if the process thinks too long or seeks so much that -+ * it doesn't matter. -+ */ -+static void bfq_update_idle_window(struct bfq_data *bfqd, -+ struct bfq_queue *bfqq, -+ struct bfq_io_cq *bic) -+{ -+ int enable_idle; -+ -+ /* Don't idle for async or idle io prio class. */ -+ if (!bfq_bfqq_sync(bfqq) || bfq_class_idle(bfqq)) -+ return; -+ -+ /* Idle window just restored, statistics are meaningless. */ -+ if (bfq_bfqq_just_split(bfqq)) -+ return; -+ -+ enable_idle = bfq_bfqq_idle_window(bfqq); -+ -+ if (atomic_read(&bic->icq.ioc->active_ref) == 0 || -+ bfqd->bfq_slice_idle == 0 || -+ (bfqd->hw_tag && BFQQ_SEEKY(bfqq) && -+ bfqq->wr_coeff == 1)) -+ enable_idle = 0; -+ else if (bfq_sample_valid(bic->ttime.ttime_samples)) { -+ if (bic->ttime.ttime_mean > bfqd->bfq_slice_idle && -+ bfqq->wr_coeff == 1) -+ enable_idle = 0; -+ else -+ enable_idle = 1; -+ } -+ bfq_log_bfqq(bfqd, bfqq, "update_idle_window: enable_idle %d", -+ enable_idle); -+ -+ if (enable_idle) -+ bfq_mark_bfqq_idle_window(bfqq); -+ else -+ bfq_clear_bfqq_idle_window(bfqq); -+} -+ -+/* -+ * Called when a new fs request (rq) is added to bfqq. Check if there's -+ * something we should do about it. -+ */ -+static void bfq_rq_enqueued(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ struct request *rq) -+{ -+ struct bfq_io_cq *bic = RQ_BIC(rq); -+ -+ if (rq->cmd_flags & REQ_META) -+ bfqq->meta_pending++; -+ -+ bfq_update_io_thinktime(bfqd, bic); -+ bfq_update_io_seektime(bfqd, bfqq, rq); -+ if (!BFQQ_SEEKY(bfqq) && bfq_bfqq_constantly_seeky(bfqq)) { -+ bfq_clear_bfqq_constantly_seeky(bfqq); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ if (bfqq->entity.service > bfq_max_budget(bfqd) / 8 || -+ !BFQQ_SEEKY(bfqq)) -+ bfq_update_idle_window(bfqd, bfqq, bic); -+ bfq_clear_bfqq_just_split(bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, -+ "rq_enqueued: idle_window=%d (seeky %d, mean %llu)", -+ bfq_bfqq_idle_window(bfqq), BFQQ_SEEKY(bfqq), -+ (long long unsigned)bfqq->seek_mean); -+ -+ bfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); -+ -+ if (bfqq == bfqd->in_service_queue && bfq_bfqq_wait_request(bfqq)) { -+ int small_req = bfqq->queued[rq_is_sync(rq)] == 1 && -+ blk_rq_sectors(rq) < 32; -+ int budget_timeout = bfq_bfqq_budget_timeout(bfqq); -+ -+ /* -+ * There is just this request queued: if the request -+ * is small and the queue is not to be expired, then -+ * just exit. -+ * -+ * In this way, if the disk is being idled to wait for -+ * a new request from the in-service queue, we avoid -+ * unplugging the device and committing the disk to serve -+ * just a small request. On the contrary, we wait for -+ * the block layer to decide when to unplug the device: -+ * hopefully, new requests will be merged to this one -+ * quickly, then the device will be unplugged and -+ * larger requests will be dispatched. -+ */ -+ if (small_req && !budget_timeout) -+ return; -+ -+ /* -+ * A large enough request arrived, or the queue is to -+ * be expired: in both cases disk idling is to be -+ * stopped, so clear wait_request flag and reset -+ * timer. -+ */ -+ bfq_clear_bfqq_wait_request(bfqq); -+ del_timer(&bfqd->idle_slice_timer); -+ -+ /* -+ * The queue is not empty, because a new request just -+ * arrived. Hence we can safely expire the queue, in -+ * case of budget timeout, without risking that the -+ * timestamps of the queue are not updated correctly. -+ * See [1] for more details. -+ */ -+ if (budget_timeout) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ -+ /* -+ * Let the request rip immediately, or let a new queue be -+ * selected if bfqq has just been expired. -+ */ -+ __blk_run_queue(bfqd->queue); -+ } -+} -+ -+static void bfq_insert_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_queue *bfqq = RQ_BFQQ(rq), *new_bfqq; -+ -+ assert_spin_locked(bfqd->queue->queue_lock); -+ -+ /* -+ * An unplug may trigger a requeue of a request from the device -+ * driver: make sure we are in process context while trying to -+ * merge two bfq_queues. -+ */ -+ if (!in_interrupt()) { -+ new_bfqq = bfq_setup_cooperator(bfqd, bfqq, rq, true); -+ if (new_bfqq != NULL) { -+ if (bic_to_bfqq(RQ_BIC(rq), 1) != bfqq) -+ new_bfqq = bic_to_bfqq(RQ_BIC(rq), 1); -+ /* -+ * Release the request's reference to the old bfqq -+ * and make sure one is taken to the shared queue. -+ */ -+ new_bfqq->allocated[rq_data_dir(rq)]++; -+ bfqq->allocated[rq_data_dir(rq)]--; -+ atomic_inc(&new_bfqq->ref); -+ bfq_put_queue(bfqq); -+ if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) -+ bfq_merge_bfqqs(bfqd, RQ_BIC(rq), -+ bfqq, new_bfqq); -+ rq->elv.priv[1] = new_bfqq; -+ bfqq = new_bfqq; -+ } else -+ bfq_bfqq_increase_failed_cooperations(bfqq); -+ } -+ -+ bfq_init_prio_data(bfqq, RQ_BIC(rq)); -+ -+ bfq_add_request(rq); -+ -+ /* -+ * Here a newly-created bfq_queue has already started a weight-raising -+ * period: clear raising_time_left to prevent bfq_bfqq_save_state() -+ * from assigning it a full weight-raising period. See the detailed -+ * comments about this field in bfq_init_icq(). -+ */ -+ if (bfqq->bic != NULL) -+ bfqq->bic->wr_time_left = 0; -+ rq_set_fifo_time(rq, jiffies + bfqd->bfq_fifo_expire[rq_is_sync(rq)]); -+ list_add_tail(&rq->queuelist, &bfqq->fifo); -+ -+ bfq_rq_enqueued(bfqd, bfqq, rq); -+} -+ -+static void bfq_update_hw_tag(struct bfq_data *bfqd) -+{ -+ bfqd->max_rq_in_driver = max(bfqd->max_rq_in_driver, -+ bfqd->rq_in_driver); -+ -+ if (bfqd->hw_tag == 1) -+ return; -+ -+ /* -+ * This sample is valid if the number of outstanding requests -+ * is large enough to allow a queueing behavior. Note that the -+ * sum is not exact, as it's not taking into account deactivated -+ * requests. -+ */ -+ if (bfqd->rq_in_driver + bfqd->queued < BFQ_HW_QUEUE_THRESHOLD) -+ return; -+ -+ if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES) -+ return; -+ -+ bfqd->hw_tag = bfqd->max_rq_in_driver > BFQ_HW_QUEUE_THRESHOLD; -+ bfqd->max_rq_in_driver = 0; -+ bfqd->hw_tag_samples = 0; -+} -+ -+static void bfq_completed_request(struct request_queue *q, struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ struct bfq_data *bfqd = bfqq->bfqd; -+ bool sync = bfq_bfqq_sync(bfqq); -+ -+ bfq_log_bfqq(bfqd, bfqq, "completed one req with %u sects left (%d)", -+ blk_rq_sectors(rq), sync); -+ -+ bfq_update_hw_tag(bfqd); -+ -+ BUG_ON(!bfqd->rq_in_driver); -+ BUG_ON(!bfqq->dispatched); -+ bfqd->rq_in_driver--; -+ bfqq->dispatched--; -+ -+ if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ -+ if (sync) { -+ bfqd->sync_flight--; -+ RQ_BIC(rq)->ttime.last_end_request = jiffies; -+ } -+ -+ /* -+ * If we are waiting to discover whether the request pattern of the -+ * task associated with the queue is actually isochronous, and -+ * both requisites for this condition to hold are satisfied, then -+ * compute soft_rt_next_start (see the comments to the function -+ * bfq_bfqq_softrt_next_start()). -+ */ -+ if (bfq_bfqq_softrt_update(bfqq) && bfqq->dispatched == 0 && -+ RB_EMPTY_ROOT(&bfqq->sort_list)) -+ bfqq->soft_rt_next_start = -+ bfq_bfqq_softrt_next_start(bfqd, bfqq); -+ -+ /* -+ * If this is the in-service queue, check if it needs to be expired, -+ * or if we want to idle in case it has no pending requests. -+ */ -+ if (bfqd->in_service_queue == bfqq) { -+ if (bfq_bfqq_budget_new(bfqq)) -+ bfq_set_budget_timeout(bfqd); -+ -+ if (bfq_bfqq_must_idle(bfqq)) { -+ bfq_arm_slice_timer(bfqd); -+ goto out; -+ } else if (bfq_may_expire_for_budg_timeout(bfqq)) -+ bfq_bfqq_expire(bfqd, bfqq, 0, BFQ_BFQQ_BUDGET_TIMEOUT); -+ else if (RB_EMPTY_ROOT(&bfqq->sort_list) && -+ (bfqq->dispatched == 0 || -+ !bfq_bfqq_must_not_expire(bfqq))) -+ bfq_bfqq_expire(bfqd, bfqq, 0, -+ BFQ_BFQQ_NO_MORE_REQUESTS); -+ } -+ -+ if (!bfqd->rq_in_driver) -+ bfq_schedule_dispatch(bfqd); -+ -+out: -+ return; -+} -+ -+static inline int __bfq_may_queue(struct bfq_queue *bfqq) -+{ -+ if (bfq_bfqq_wait_request(bfqq) && bfq_bfqq_must_alloc(bfqq)) { -+ bfq_clear_bfqq_must_alloc(bfqq); -+ return ELV_MQUEUE_MUST; -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+static int bfq_may_queue(struct request_queue *q, int rw) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct task_struct *tsk = current; -+ struct bfq_io_cq *bic; -+ struct bfq_queue *bfqq; -+ -+ /* -+ * Don't force setup of a queue from here, as a call to may_queue -+ * does not necessarily imply that a request actually will be -+ * queued. So just lookup a possibly existing queue, or return -+ * 'may queue' if that fails. -+ */ -+ bic = bfq_bic_lookup(bfqd, tsk->io_context); -+ if (bic == NULL) -+ return ELV_MQUEUE_MAY; -+ -+ bfqq = bic_to_bfqq(bic, rw_is_sync(rw)); -+ if (bfqq != NULL) { -+ bfq_init_prio_data(bfqq, bic); -+ -+ return __bfq_may_queue(bfqq); -+ } -+ -+ return ELV_MQUEUE_MAY; -+} -+ -+/* -+ * Queue lock held here. -+ */ -+static void bfq_put_request(struct request *rq) -+{ -+ struct bfq_queue *bfqq = RQ_BFQQ(rq); -+ -+ if (bfqq != NULL) { -+ const int rw = rq_data_dir(rq); -+ -+ BUG_ON(!bfqq->allocated[rw]); -+ bfqq->allocated[rw]--; -+ -+ rq->elv.priv[0] = NULL; -+ rq->elv.priv[1] = NULL; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "put_request %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+/* -+ * Returns NULL if a new bfqq should be allocated, or the old bfqq if this -+ * was the last process referring to said bfqq. -+ */ -+static struct bfq_queue * -+bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq) -+{ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue"); -+ -+ put_io_context(bic->icq.ioc); -+ -+ if (bfqq_process_refs(bfqq) == 1) { -+ bfqq->pid = current->pid; -+ bfq_clear_bfqq_coop(bfqq); -+ bfq_clear_bfqq_split_coop(bfqq); -+ return bfqq; -+ } -+ -+ bic_set_bfqq(bic, NULL, 1); -+ -+ bfq_put_cooperator(bfqq); -+ -+ bfq_put_queue(bfqq); -+ return NULL; -+} -+ -+/* -+ * Allocate bfq data structures associated with this request. -+ */ -+static int bfq_set_request(struct request_queue *q, struct request *rq, -+ struct bio *bio, gfp_t gfp_mask) -+{ -+ struct bfq_data *bfqd = q->elevator->elevator_data; -+ struct bfq_io_cq *bic = icq_to_bic(rq->elv.icq); -+ const int rw = rq_data_dir(rq); -+ const int is_sync = rq_is_sync(rq); -+ struct bfq_queue *bfqq; -+ struct bfq_group *bfqg; -+ unsigned long flags; -+ bool split = false; -+ -+ might_sleep_if(gfp_mask & __GFP_WAIT); -+ -+ bfq_changed_ioprio(bic); -+ -+ spin_lock_irqsave(q->queue_lock, flags); -+ -+ if (bic == NULL) -+ goto queue_fail; -+ -+ bfqg = bfq_bic_update_cgroup(bic); -+ -+new_queue: -+ bfqq = bic_to_bfqq(bic, is_sync); -+ if (bfqq == NULL || bfqq == &bfqd->oom_bfqq) { -+ bfqq = bfq_get_queue(bfqd, bfqg, is_sync, bic, gfp_mask); -+ bic_set_bfqq(bic, bfqq, is_sync); -+ } else { -+ /* If the queue was seeky for too long, break it apart. */ -+ if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq)) { -+ bfq_log_bfqq(bfqd, bfqq, "breaking apart bfqq"); -+ bfqq = bfq_split_bfqq(bic, bfqq); -+ split = true; -+ if (!bfqq) -+ goto new_queue; -+ } -+ } -+ -+ bfqq->allocated[rw]++; -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqd, bfqq, "set_request: bfqq %p, %d", bfqq, -+ atomic_read(&bfqq->ref)); -+ -+ rq->elv.priv[0] = bic; -+ rq->elv.priv[1] = bfqq; -+ -+ /* -+ * If a bfq_queue has only one process reference, it is owned -+ * by only one bfq_io_cq: we can set the bic field of the -+ * bfq_queue to the address of that structure. Also, if the -+ * queue has just been split, mark a flag so that the -+ * information is available to the other scheduler hooks. -+ */ -+ if (bfqq_process_refs(bfqq) == 1) { -+ bfqq->bic = bic; -+ if (split) { -+ bfq_mark_bfqq_just_split(bfqq); -+ /* -+ * If the queue has just been split from a shared -+ * queue, restore the idle window and the possible -+ * weight raising period. -+ */ -+ bfq_bfqq_resume_state(bfqq, bic); -+ } -+ } -+ -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 0; -+ -+queue_fail: -+ bfq_schedule_dispatch(bfqd); -+ spin_unlock_irqrestore(q->queue_lock, flags); -+ -+ return 1; -+} -+ -+static void bfq_kick_queue(struct work_struct *work) -+{ -+ struct bfq_data *bfqd = -+ container_of(work, struct bfq_data, unplug_work); -+ struct request_queue *q = bfqd->queue; -+ -+ spin_lock_irq(q->queue_lock); -+ __blk_run_queue(q); -+ spin_unlock_irq(q->queue_lock); -+} -+ -+/* -+ * Handler of the expiration of the timer running if the in-service queue -+ * is idling inside its time slice. -+ */ -+static void bfq_idle_slice_timer(unsigned long data) -+{ -+ struct bfq_data *bfqd = (struct bfq_data *)data; -+ struct bfq_queue *bfqq; -+ unsigned long flags; -+ enum bfqq_expiration reason; -+ -+ spin_lock_irqsave(bfqd->queue->queue_lock, flags); -+ -+ bfqq = bfqd->in_service_queue; -+ /* -+ * Theoretical race here: the in-service queue can be NULL or -+ * different from the queue that was idling if the timer handler -+ * spins on the queue_lock and a new request arrives for the -+ * current queue and there is a full dispatch cycle that changes -+ * the in-service queue. This can hardly happen, but in the worst -+ * case we just expire a queue too early. -+ */ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqd, bfqq, "slice_timer expired"); -+ if (bfq_bfqq_budget_timeout(bfqq)) -+ /* -+ * Also here the queue can be safely expired -+ * for budget timeout without wasting -+ * guarantees -+ */ -+ reason = BFQ_BFQQ_BUDGET_TIMEOUT; -+ else if (bfqq->queued[0] == 0 && bfqq->queued[1] == 0) -+ /* -+ * The queue may not be empty upon timer expiration, -+ * because we may not disable the timer when the -+ * first request of the in-service queue arrives -+ * during disk idling. -+ */ -+ reason = BFQ_BFQQ_TOO_IDLE; -+ else -+ goto schedule_dispatch; -+ -+ bfq_bfqq_expire(bfqd, bfqq, 1, reason); -+ } -+ -+schedule_dispatch: -+ bfq_schedule_dispatch(bfqd); -+ -+ spin_unlock_irqrestore(bfqd->queue->queue_lock, flags); -+} -+ -+static void bfq_shutdown_timer_wq(struct bfq_data *bfqd) -+{ -+ del_timer_sync(&bfqd->idle_slice_timer); -+ cancel_work_sync(&bfqd->unplug_work); -+} -+ -+static inline void __bfq_put_async_bfqq(struct bfq_data *bfqd, -+ struct bfq_queue **bfqq_ptr) -+{ -+ struct bfq_group *root_group = bfqd->root_group; -+ struct bfq_queue *bfqq = *bfqq_ptr; -+ -+ bfq_log(bfqd, "put_async_bfqq: %p", bfqq); -+ if (bfqq != NULL) { -+ bfq_bfqq_move(bfqd, bfqq, &bfqq->entity, root_group); -+ bfq_log_bfqq(bfqd, bfqq, "put_async_bfqq: putting %p, %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ *bfqq_ptr = NULL; -+ } -+} -+ -+/* -+ * Release all the bfqg references to its async queues. If we are -+ * deallocating the group these queues may still contain requests, so -+ * we reparent them to the root cgroup (i.e., the only one that will -+ * exist for sure until all the requests on a device are gone). -+ */ -+static void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg) -+{ -+ int i, j; -+ -+ for (i = 0; i < 2; i++) -+ for (j = 0; j < IOPRIO_BE_NR; j++) -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]); -+ -+ __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq); -+} -+ -+static void bfq_exit_queue(struct elevator_queue *e) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ struct request_queue *q = bfqd->queue; -+ struct bfq_queue *bfqq, *n; -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ spin_lock_irq(q->queue_lock); -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ list_for_each_entry_safe(bfqq, n, &bfqd->idle_list, bfqq_list) -+ bfq_deactivate_bfqq(bfqd, bfqq, 0); -+ -+ bfq_disconnect_groups(bfqd); -+ spin_unlock_irq(q->queue_lock); -+ -+ bfq_shutdown_timer_wq(bfqd); -+ -+ synchronize_rcu(); -+ -+ BUG_ON(timer_pending(&bfqd->idle_slice_timer)); -+ -+ bfq_free_root_group(bfqd); -+ kfree(bfqd); -+} -+ -+static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) -+{ -+ struct bfq_group *bfqg; -+ struct bfq_data *bfqd; -+ struct elevator_queue *eq; -+ -+ eq = elevator_alloc(q, e); -+ if (eq == NULL) -+ return -ENOMEM; -+ -+ bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); -+ if (bfqd == NULL) { -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ eq->elevator_data = bfqd; -+ -+ /* -+ * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues. -+ * Grab a permanent reference to it, so that the normal code flow -+ * will not attempt to free it. -+ */ -+ bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, 1, 0); -+ atomic_inc(&bfqd->oom_bfqq.ref); -+ -+ bfqd->queue = q; -+ -+ spin_lock_irq(q->queue_lock); -+ q->elevator = eq; -+ spin_unlock_irq(q->queue_lock); -+ -+ bfqg = bfq_alloc_root_group(bfqd, q->node); -+ if (bfqg == NULL) { -+ kfree(bfqd); -+ kobject_put(&eq->kobj); -+ return -ENOMEM; -+ } -+ -+ bfqd->root_group = bfqg; -+#ifdef CONFIG_CGROUP_BFQIO -+ bfqd->active_numerous_groups = 0; -+#endif -+ -+ init_timer(&bfqd->idle_slice_timer); -+ bfqd->idle_slice_timer.function = bfq_idle_slice_timer; -+ bfqd->idle_slice_timer.data = (unsigned long)bfqd; -+ -+ bfqd->rq_pos_tree = RB_ROOT; -+ bfqd->queue_weights_tree = RB_ROOT; -+ bfqd->group_weights_tree = RB_ROOT; -+ -+ INIT_WORK(&bfqd->unplug_work, bfq_kick_queue); -+ -+ INIT_LIST_HEAD(&bfqd->active_list); -+ INIT_LIST_HEAD(&bfqd->idle_list); -+ -+ bfqd->hw_tag = -1; -+ -+ bfqd->bfq_max_budget = bfq_default_max_budget; -+ -+ bfqd->bfq_quantum = bfq_quantum; -+ bfqd->bfq_fifo_expire[0] = bfq_fifo_expire[0]; -+ bfqd->bfq_fifo_expire[1] = bfq_fifo_expire[1]; -+ bfqd->bfq_back_max = bfq_back_max; -+ bfqd->bfq_back_penalty = bfq_back_penalty; -+ bfqd->bfq_slice_idle = bfq_slice_idle; -+ bfqd->bfq_class_idle_last_service = 0; -+ bfqd->bfq_max_budget_async_rq = bfq_max_budget_async_rq; -+ bfqd->bfq_timeout[BLK_RW_ASYNC] = bfq_timeout_async; -+ bfqd->bfq_timeout[BLK_RW_SYNC] = bfq_timeout_sync; -+ -+ bfqd->bfq_coop_thresh = 2; -+ bfqd->bfq_failed_cooperations = 7000; -+ bfqd->bfq_requests_within_timer = 120; -+ -+ bfqd->low_latency = true; -+ -+ bfqd->bfq_wr_coeff = 20; -+ bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300); -+ bfqd->bfq_wr_max_time = 0; -+ bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000); -+ bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500); -+ bfqd->bfq_wr_max_softrt_rate = 7000; /* -+ * Approximate rate required -+ * to playback or record a -+ * high-definition compressed -+ * video. -+ */ -+ bfqd->wr_busy_queues = 0; -+ bfqd->busy_in_flight_queues = 0; -+ bfqd->const_seeky_busy_in_flight_queues = 0; -+ -+ /* -+ * Begin by assuming, optimistically, that the device peak rate is -+ * equal to the highest reference rate. -+ */ -+ bfqd->RT_prod = R_fast[blk_queue_nonrot(bfqd->queue)] * -+ T_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->peak_rate = R_fast[blk_queue_nonrot(bfqd->queue)]; -+ bfqd->device_speed = BFQ_BFQD_FAST; -+ -+ return 0; -+} -+ -+static void bfq_slab_kill(void) -+{ -+ if (bfq_pool != NULL) -+ kmem_cache_destroy(bfq_pool); -+} -+ -+static int __init bfq_slab_setup(void) -+{ -+ bfq_pool = KMEM_CACHE(bfq_queue, 0); -+ if (bfq_pool == NULL) -+ return -ENOMEM; -+ return 0; -+} -+ -+static ssize_t bfq_var_show(unsigned int var, char *page) -+{ -+ return sprintf(page, "%d\n", var); -+} -+ -+static ssize_t bfq_var_store(unsigned long *var, const char *page, -+ size_t count) -+{ -+ unsigned long new_val; -+ int ret = kstrtoul(page, 10, &new_val); -+ -+ if (ret == 0) -+ *var = new_val; -+ -+ return count; -+} -+ -+static ssize_t bfq_wr_max_time_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ return sprintf(page, "%d\n", bfqd->bfq_wr_max_time > 0 ? -+ jiffies_to_msecs(bfqd->bfq_wr_max_time) : -+ jiffies_to_msecs(bfq_wr_duration(bfqd))); -+} -+ -+static ssize_t bfq_weights_show(struct elevator_queue *e, char *page) -+{ -+ struct bfq_queue *bfqq; -+ struct bfq_data *bfqd = e->elevator_data; -+ ssize_t num_char = 0; -+ -+ num_char += sprintf(page + num_char, "Tot reqs queued %d\n\n", -+ bfqd->queued); -+ -+ spin_lock_irq(bfqd->queue->queue_lock); -+ -+ num_char += sprintf(page + num_char, "Active:\n"); -+ list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, nr_queued %d %d, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ bfqq->queued[0], -+ bfqq->queued[1], -+ jiffies_to_msecs(jiffies - bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ num_char += sprintf(page + num_char, "Idle:\n"); -+ list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list) { -+ num_char += sprintf(page + num_char, -+ "pid%d: weight %hu, dur %d/%u\n", -+ bfqq->pid, -+ bfqq->entity.weight, -+ jiffies_to_msecs(jiffies - -+ bfqq->last_wr_start_finish), -+ jiffies_to_msecs(bfqq->wr_cur_max_time)); -+ } -+ -+ spin_unlock_irq(bfqd->queue->queue_lock); -+ -+ return num_char; -+} -+ -+#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ -+static ssize_t __FUNC(struct elevator_queue *e, char *page) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned int __data = __VAR; \ -+ if (__CONV) \ -+ __data = jiffies_to_msecs(__data); \ -+ return bfq_var_show(__data, (page)); \ -+} -+SHOW_FUNCTION(bfq_quantum_show, bfqd->bfq_quantum, 0); -+SHOW_FUNCTION(bfq_fifo_expire_sync_show, bfqd->bfq_fifo_expire[1], 1); -+SHOW_FUNCTION(bfq_fifo_expire_async_show, bfqd->bfq_fifo_expire[0], 1); -+SHOW_FUNCTION(bfq_back_seek_max_show, bfqd->bfq_back_max, 0); -+SHOW_FUNCTION(bfq_back_seek_penalty_show, bfqd->bfq_back_penalty, 0); -+SHOW_FUNCTION(bfq_slice_idle_show, bfqd->bfq_slice_idle, 1); -+SHOW_FUNCTION(bfq_max_budget_show, bfqd->bfq_user_max_budget, 0); -+SHOW_FUNCTION(bfq_max_budget_async_rq_show, -+ bfqd->bfq_max_budget_async_rq, 0); -+SHOW_FUNCTION(bfq_timeout_sync_show, bfqd->bfq_timeout[BLK_RW_SYNC], 1); -+SHOW_FUNCTION(bfq_timeout_async_show, bfqd->bfq_timeout[BLK_RW_ASYNC], 1); -+SHOW_FUNCTION(bfq_low_latency_show, bfqd->low_latency, 0); -+SHOW_FUNCTION(bfq_wr_coeff_show, bfqd->bfq_wr_coeff, 0); -+SHOW_FUNCTION(bfq_wr_rt_max_time_show, bfqd->bfq_wr_rt_max_time, 1); -+SHOW_FUNCTION(bfq_wr_min_idle_time_show, bfqd->bfq_wr_min_idle_time, 1); -+SHOW_FUNCTION(bfq_wr_min_inter_arr_async_show, bfqd->bfq_wr_min_inter_arr_async, -+ 1); -+SHOW_FUNCTION(bfq_wr_max_softrt_rate_show, bfqd->bfq_wr_max_softrt_rate, 0); -+#undef SHOW_FUNCTION -+ -+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ -+static ssize_t \ -+__FUNC(struct elevator_queue *e, const char *page, size_t count) \ -+{ \ -+ struct bfq_data *bfqd = e->elevator_data; \ -+ unsigned long uninitialized_var(__data); \ -+ int ret = bfq_var_store(&__data, (page), count); \ -+ if (__data < (MIN)) \ -+ __data = (MIN); \ -+ else if (__data > (MAX)) \ -+ __data = (MAX); \ -+ if (__CONV) \ -+ *(__PTR) = msecs_to_jiffies(__data); \ -+ else \ -+ *(__PTR) = __data; \ -+ return ret; \ -+} -+STORE_FUNCTION(bfq_quantum_store, &bfqd->bfq_quantum, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_fifo_expire_sync_store, &bfqd->bfq_fifo_expire[1], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_fifo_expire_async_store, &bfqd->bfq_fifo_expire[0], 1, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_back_seek_max_store, &bfqd->bfq_back_max, 0, INT_MAX, 0); -+STORE_FUNCTION(bfq_back_seek_penalty_store, &bfqd->bfq_back_penalty, 1, -+ INT_MAX, 0); -+STORE_FUNCTION(bfq_slice_idle_store, &bfqd->bfq_slice_idle, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_max_budget_async_rq_store, &bfqd->bfq_max_budget_async_rq, -+ 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_timeout_async_store, &bfqd->bfq_timeout[BLK_RW_ASYNC], 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_coeff_store, &bfqd->bfq_wr_coeff, 1, INT_MAX, 0); -+STORE_FUNCTION(bfq_wr_max_time_store, &bfqd->bfq_wr_max_time, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_rt_max_time_store, &bfqd->bfq_wr_rt_max_time, 0, INT_MAX, -+ 1); -+STORE_FUNCTION(bfq_wr_min_idle_time_store, &bfqd->bfq_wr_min_idle_time, 0, -+ INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_min_inter_arr_async_store, -+ &bfqd->bfq_wr_min_inter_arr_async, 0, INT_MAX, 1); -+STORE_FUNCTION(bfq_wr_max_softrt_rate_store, &bfqd->bfq_wr_max_softrt_rate, 0, -+ INT_MAX, 0); -+#undef STORE_FUNCTION -+ -+/* do nothing for the moment */ -+static ssize_t bfq_weights_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ return count; -+} -+ -+static inline unsigned long bfq_estimated_max_budget(struct bfq_data *bfqd) -+{ -+ u64 timeout = jiffies_to_msecs(bfqd->bfq_timeout[BLK_RW_SYNC]); -+ -+ if (bfqd->peak_rate_samples >= BFQ_PEAK_RATE_SAMPLES) -+ return bfq_calc_max_budget(bfqd->peak_rate, timeout); -+ else -+ return bfq_default_max_budget; -+} -+ -+static ssize_t bfq_max_budget_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ else { -+ if (__data > INT_MAX) -+ __data = INT_MAX; -+ bfqd->bfq_max_budget = __data; -+ } -+ -+ bfqd->bfq_user_max_budget = __data; -+ -+ return ret; -+} -+ -+static ssize_t bfq_timeout_sync_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data < 1) -+ __data = 1; -+ else if (__data > INT_MAX) -+ __data = INT_MAX; -+ -+ bfqd->bfq_timeout[BLK_RW_SYNC] = msecs_to_jiffies(__data); -+ if (bfqd->bfq_user_max_budget == 0) -+ bfqd->bfq_max_budget = bfq_estimated_max_budget(bfqd); -+ -+ return ret; -+} -+ -+static ssize_t bfq_low_latency_store(struct elevator_queue *e, -+ const char *page, size_t count) -+{ -+ struct bfq_data *bfqd = e->elevator_data; -+ unsigned long uninitialized_var(__data); -+ int ret = bfq_var_store(&__data, (page), count); -+ -+ if (__data > 1) -+ __data = 1; -+ if (__data == 0 && bfqd->low_latency != 0) -+ bfq_end_wr(bfqd); -+ bfqd->low_latency = __data; -+ -+ return ret; -+} -+ -+#define BFQ_ATTR(name) \ -+ __ATTR(name, S_IRUGO|S_IWUSR, bfq_##name##_show, bfq_##name##_store) -+ -+static struct elv_fs_entry bfq_attrs[] = { -+ BFQ_ATTR(quantum), -+ BFQ_ATTR(fifo_expire_sync), -+ BFQ_ATTR(fifo_expire_async), -+ BFQ_ATTR(back_seek_max), -+ BFQ_ATTR(back_seek_penalty), -+ BFQ_ATTR(slice_idle), -+ BFQ_ATTR(max_budget), -+ BFQ_ATTR(max_budget_async_rq), -+ BFQ_ATTR(timeout_sync), -+ BFQ_ATTR(timeout_async), -+ BFQ_ATTR(low_latency), -+ BFQ_ATTR(wr_coeff), -+ BFQ_ATTR(wr_max_time), -+ BFQ_ATTR(wr_rt_max_time), -+ BFQ_ATTR(wr_min_idle_time), -+ BFQ_ATTR(wr_min_inter_arr_async), -+ BFQ_ATTR(wr_max_softrt_rate), -+ BFQ_ATTR(weights), -+ __ATTR_NULL -+}; -+ -+static struct elevator_type iosched_bfq = { -+ .ops = { -+ .elevator_merge_fn = bfq_merge, -+ .elevator_merged_fn = bfq_merged_request, -+ .elevator_merge_req_fn = bfq_merged_requests, -+ .elevator_allow_merge_fn = bfq_allow_merge, -+ .elevator_dispatch_fn = bfq_dispatch_requests, -+ .elevator_add_req_fn = bfq_insert_request, -+ .elevator_activate_req_fn = bfq_activate_request, -+ .elevator_deactivate_req_fn = bfq_deactivate_request, -+ .elevator_completed_req_fn = bfq_completed_request, -+ .elevator_former_req_fn = elv_rb_former_request, -+ .elevator_latter_req_fn = elv_rb_latter_request, -+ .elevator_init_icq_fn = bfq_init_icq, -+ .elevator_exit_icq_fn = bfq_exit_icq, -+ .elevator_set_req_fn = bfq_set_request, -+ .elevator_put_req_fn = bfq_put_request, -+ .elevator_may_queue_fn = bfq_may_queue, -+ .elevator_init_fn = bfq_init_queue, -+ .elevator_exit_fn = bfq_exit_queue, -+ }, -+ .icq_size = sizeof(struct bfq_io_cq), -+ .icq_align = __alignof__(struct bfq_io_cq), -+ .elevator_attrs = bfq_attrs, -+ .elevator_name = "bfq", -+ .elevator_owner = THIS_MODULE, -+}; -+ -+static int __init bfq_init(void) -+{ -+ /* -+ * Can be 0 on HZ < 1000 setups. -+ */ -+ if (bfq_slice_idle == 0) -+ bfq_slice_idle = 1; -+ -+ if (bfq_timeout_async == 0) -+ bfq_timeout_async = 1; -+ -+ if (bfq_slab_setup()) -+ return -ENOMEM; -+ -+ /* -+ * Times to load large popular applications for the typical systems -+ * installed on the reference devices (see the comments before the -+ * definitions of the two arrays). -+ */ -+ T_slow[0] = msecs_to_jiffies(2600); -+ T_slow[1] = msecs_to_jiffies(1000); -+ T_fast[0] = msecs_to_jiffies(5500); -+ T_fast[1] = msecs_to_jiffies(2000); -+ -+ /* -+ * Thresholds that determine the switch between speed classes (see -+ * the comments before the definition of the array). -+ */ -+ device_speed_thresh[0] = (R_fast[0] + R_slow[0]) / 2; -+ device_speed_thresh[1] = (R_fast[1] + R_slow[1]) / 2; -+ -+ elv_register(&iosched_bfq); -+ pr_info("BFQ I/O-scheduler version: v7r5"); -+ -+ return 0; -+} -+ -+static void __exit bfq_exit(void) -+{ -+ elv_unregister(&iosched_bfq); -+ bfq_slab_kill(); -+} -+ -+module_init(bfq_init); -+module_exit(bfq_exit); -+ -+MODULE_AUTHOR("Fabio Checconi, Paolo Valente"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/block/bfq-sched.c linux-3.14.22/block/bfq-sched.c ---- linux-3.14.22.orig/block/bfq-sched.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/block/bfq-sched.c 2014-10-22 14:55:51.958220001 -0500 -@@ -0,0 +1,1179 @@ -+/* -+ * BFQ: Hierarchical B-WF2Q+ scheduler. -+ * -+ * Based on ideas and code from CFQ: -+ * Copyright (C) 2003 Jens Axboe -+ * -+ * Copyright (C) 2008 Fabio Checconi -+ * Paolo Valente -+ * -+ * Copyright (C) 2010 Paolo Valente -+ */ -+ -+#ifdef CONFIG_CGROUP_BFQIO -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = entity->parent) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (; entity && ({ parent = entity->parent; 1; }); entity = parent) -+ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd); -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+ struct bfq_entity *bfqg_entity; -+ struct bfq_group *bfqg; -+ struct bfq_sched_data *group_sd; -+ -+ BUG_ON(next_in_service == NULL); -+ -+ group_sd = next_in_service->sched_data; -+ -+ bfqg = container_of(group_sd, struct bfq_group, sched_data); -+ /* -+ * bfq_group's my_entity field is not NULL only if the group -+ * is not the root group. We must not touch the root entity -+ * as it must never become an in-service entity. -+ */ -+ bfqg_entity = bfqg->my_entity; -+ if (bfqg_entity != NULL) -+ bfqg_entity->budget = next_in_service->budget; -+} -+ -+static int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ struct bfq_entity *next_in_service; -+ -+ if (sd->in_service_entity != NULL) -+ /* will update/requeue at the end of service */ -+ return 0; -+ -+ /* -+ * NOTE: this can be improved in many ways, such as returning -+ * 1 (and thus propagating upwards the update) only when the -+ * budget changes, or caching the bfqq that will be scheduled -+ * next from this subtree. By now we worry more about -+ * correctness than about performance... -+ */ -+ next_in_service = bfq_lookup_next_entity(sd, 0, NULL); -+ sd->next_in_service = next_in_service; -+ -+ if (next_in_service != NULL) -+ bfq_update_budget(next_in_service); -+ -+ return 1; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(sd->next_in_service != entity); -+} -+#else -+#define for_each_entity(entity) \ -+ for (; entity != NULL; entity = NULL) -+ -+#define for_each_entity_safe(entity, parent) \ -+ for (parent = NULL; entity != NULL; entity = parent) -+ -+static inline int bfq_update_next_in_service(struct bfq_sched_data *sd) -+{ -+ return 0; -+} -+ -+static inline void bfq_check_next_in_service(struct bfq_sched_data *sd, -+ struct bfq_entity *entity) -+{ -+} -+ -+static inline void bfq_update_budget(struct bfq_entity *next_in_service) -+{ -+} -+#endif -+ -+/* -+ * Shift for timestamp calculations. This actually limits the maximum -+ * service allowed in one timestamp delta (small shift values increase it), -+ * the maximum total weight that can be used for the queues in the system -+ * (big shift values increase it), and the period of virtual time -+ * wraparounds. -+ */ -+#define WFQ_SERVICE_SHIFT 22 -+ -+/** -+ * bfq_gt - compare two timestamps. -+ * @a: first ts. -+ * @b: second ts. -+ * -+ * Return @a > @b, dealing with wrapping correctly. -+ */ -+static inline int bfq_gt(u64 a, u64 b) -+{ -+ return (s64)(a - b) > 0; -+} -+ -+static inline struct bfq_queue *bfq_entity_to_bfqq(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = NULL; -+ -+ BUG_ON(entity == NULL); -+ -+ if (entity->my_sched_data == NULL) -+ bfqq = container_of(entity, struct bfq_queue, entity); -+ -+ return bfqq; -+} -+ -+ -+/** -+ * bfq_delta - map service into the virtual time domain. -+ * @service: amount of service. -+ * @weight: scale factor (weight of an entity or weight sum). -+ */ -+static inline u64 bfq_delta(unsigned long service, -+ unsigned long weight) -+{ -+ u64 d = (u64)service << WFQ_SERVICE_SHIFT; -+ -+ do_div(d, weight); -+ return d; -+} -+ -+/** -+ * bfq_calc_finish - assign the finish time to an entity. -+ * @entity: the entity to act upon. -+ * @service: the service to be charged to the entity. -+ */ -+static inline void bfq_calc_finish(struct bfq_entity *entity, -+ unsigned long service) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ BUG_ON(entity->weight == 0); -+ -+ entity->finish = entity->start + -+ bfq_delta(service, entity->weight); -+ -+ if (bfqq != NULL) { -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: serv %lu, w %d", -+ service, entity->weight); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, -+ "calc_finish: start %llu, finish %llu, delta %llu", -+ entity->start, entity->finish, -+ bfq_delta(service, entity->weight)); -+ } -+} -+ -+/** -+ * bfq_entity_of - get an entity from a node. -+ * @node: the node field of the entity. -+ * -+ * Convert a node pointer to the relative entity. This is used only -+ * to simplify the logic of some functions and not as the generic -+ * conversion mechanism because, e.g., in the tree walking functions, -+ * the check for a %NULL value would be redundant. -+ */ -+static inline struct bfq_entity *bfq_entity_of(struct rb_node *node) -+{ -+ struct bfq_entity *entity = NULL; -+ -+ if (node != NULL) -+ entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ return entity; -+} -+ -+/** -+ * bfq_extract - remove an entity from a tree. -+ * @root: the tree root. -+ * @entity: the entity to remove. -+ */ -+static inline void bfq_extract(struct rb_root *root, -+ struct bfq_entity *entity) -+{ -+ BUG_ON(entity->tree != root); -+ -+ entity->tree = NULL; -+ rb_erase(&entity->rb_node, root); -+} -+ -+/** -+ * bfq_idle_extract - extract an entity from the idle tree. -+ * @st: the service tree of the owning @entity. -+ * @entity: the entity being removed. -+ */ -+static void bfq_idle_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *next; -+ -+ BUG_ON(entity->tree != &st->idle); -+ -+ if (entity == st->first_idle) { -+ next = rb_next(&entity->rb_node); -+ st->first_idle = bfq_entity_of(next); -+ } -+ -+ if (entity == st->last_idle) { -+ next = rb_prev(&entity->rb_node); -+ st->last_idle = bfq_entity_of(next); -+ } -+ -+ bfq_extract(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+} -+ -+/** -+ * bfq_insert - generic tree insertion. -+ * @root: tree root. -+ * @entity: entity to insert. -+ * -+ * This is used for the idle and the active tree, since they are both -+ * ordered by finish time. -+ */ -+static void bfq_insert(struct rb_root *root, struct bfq_entity *entity) -+{ -+ struct bfq_entity *entry; -+ struct rb_node **node = &root->rb_node; -+ struct rb_node *parent = NULL; -+ -+ BUG_ON(entity->tree != NULL); -+ -+ while (*node != NULL) { -+ parent = *node; -+ entry = rb_entry(parent, struct bfq_entity, rb_node); -+ -+ if (bfq_gt(entry->finish, entity->finish)) -+ node = &parent->rb_left; -+ else -+ node = &parent->rb_right; -+ } -+ -+ rb_link_node(&entity->rb_node, parent, node); -+ rb_insert_color(&entity->rb_node, root); -+ -+ entity->tree = root; -+} -+ -+/** -+ * bfq_update_min - update the min_start field of a entity. -+ * @entity: the entity to update. -+ * @node: one of its children. -+ * -+ * This function is called when @entity may store an invalid value for -+ * min_start due to updates to the active tree. The function assumes -+ * that the subtree rooted at @node (which may be its left or its right -+ * child) has a valid min_start value. -+ */ -+static inline void bfq_update_min(struct bfq_entity *entity, -+ struct rb_node *node) -+{ -+ struct bfq_entity *child; -+ -+ if (node != NULL) { -+ child = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entity->min_start, child->min_start)) -+ entity->min_start = child->min_start; -+ } -+} -+ -+/** -+ * bfq_update_active_node - recalculate min_start. -+ * @node: the node to update. -+ * -+ * @node may have changed position or one of its children may have moved, -+ * this function updates its min_start value. The left and right subtrees -+ * are assumed to hold a correct min_start value. -+ */ -+static inline void bfq_update_active_node(struct rb_node *node) -+{ -+ struct bfq_entity *entity = rb_entry(node, struct bfq_entity, rb_node); -+ -+ entity->min_start = entity->start; -+ bfq_update_min(entity, node->rb_right); -+ bfq_update_min(entity, node->rb_left); -+} -+ -+/** -+ * bfq_update_active_tree - update min_start for the whole active tree. -+ * @node: the starting node. -+ * -+ * @node must be the deepest modified node after an update. This function -+ * updates its min_start using the values held by its children, assuming -+ * that they did not change, and then updates all the nodes that may have -+ * changed in the path to the root. The only nodes that may have changed -+ * are the ones in the path or their siblings. -+ */ -+static void bfq_update_active_tree(struct rb_node *node) -+{ -+ struct rb_node *parent; -+ -+up: -+ bfq_update_active_node(node); -+ -+ parent = rb_parent(node); -+ if (parent == NULL) -+ return; -+ -+ if (node == parent->rb_left && parent->rb_right != NULL) -+ bfq_update_active_node(parent->rb_right); -+ else if (parent->rb_left != NULL) -+ bfq_update_active_node(parent->rb_left); -+ -+ node = parent; -+ goto up; -+} -+ -+static void bfq_weights_tree_add(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+static void bfq_weights_tree_remove(struct bfq_data *bfqd, -+ struct bfq_entity *entity, -+ struct rb_root *root); -+ -+ -+/** -+ * bfq_active_insert - insert an entity in the active tree of its -+ * group/device. -+ * @st: the service tree of the entity. -+ * @entity: the entity being inserted. -+ * -+ * The active tree is ordered by finish time, but an extra key is kept -+ * per each node, containing the minimum value for the start times of -+ * its children (and the node itself), so it's possible to search for -+ * the eligible node with the lowest finish time in logarithmic time. -+ */ -+static void bfq_active_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node = &entity->rb_node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ bfq_insert(&st->active, entity); -+ -+ if (node->rb_left != NULL) -+ node = node->rb_left; -+ else if (node->rb_right != NULL) -+ node = node->rb_right; -+ -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_add(bfqd, entity, &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ bfqg->active_entities++; -+ if (bfqg->active_entities == 2) -+ bfqd->active_numerous_groups++; -+ } -+#endif -+} -+ -+/** -+ * bfq_ioprio_to_weight - calc a weight from an ioprio. -+ * @ioprio: the ioprio value to convert. -+ */ -+static inline unsigned short bfq_ioprio_to_weight(int ioprio) -+{ -+ BUG_ON(ioprio < 0 || ioprio >= IOPRIO_BE_NR); -+ return IOPRIO_BE_NR - ioprio; -+} -+ -+/** -+ * bfq_weight_to_ioprio - calc an ioprio from a weight. -+ * @weight: the weight value to convert. -+ * -+ * To preserve as mush as possible the old only-ioprio user interface, -+ * 0 is used as an escape ioprio value for weights (numerically) equal or -+ * larger than IOPRIO_BE_NR -+ */ -+static inline unsigned short bfq_weight_to_ioprio(int weight) -+{ -+ BUG_ON(weight < BFQ_MIN_WEIGHT || weight > BFQ_MAX_WEIGHT); -+ return IOPRIO_BE_NR - weight < 0 ? 0 : IOPRIO_BE_NR - weight; -+} -+ -+static inline void bfq_get_entity(struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ -+ if (bfqq != NULL) { -+ atomic_inc(&bfqq->ref); -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ } -+} -+ -+/** -+ * bfq_find_deepest - find the deepest node that an extraction can modify. -+ * @node: the node being removed. -+ * -+ * Do the first step of an extraction in an rb tree, looking for the -+ * node that will replace @node, and returning the deepest node that -+ * the following modifications to the tree can touch. If @node is the -+ * last node in the tree return %NULL. -+ */ -+static struct rb_node *bfq_find_deepest(struct rb_node *node) -+{ -+ struct rb_node *deepest; -+ -+ if (node->rb_right == NULL && node->rb_left == NULL) -+ deepest = rb_parent(node); -+ else if (node->rb_right == NULL) -+ deepest = node->rb_left; -+ else if (node->rb_left == NULL) -+ deepest = node->rb_right; -+ else { -+ deepest = rb_next(node); -+ if (deepest->rb_right != NULL) -+ deepest = deepest->rb_right; -+ else if (rb_parent(deepest) != node) -+ deepest = rb_parent(deepest); -+ } -+ -+ return deepest; -+} -+ -+/** -+ * bfq_active_extract - remove an entity from the active tree. -+ * @st: the service_tree containing the tree. -+ * @entity: the entity being removed. -+ */ -+static void bfq_active_extract(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct rb_node *node; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd = NULL; -+ struct bfq_group *bfqg = NULL; -+ struct bfq_data *bfqd = NULL; -+#endif -+ -+ node = bfq_find_deepest(&entity->rb_node); -+ bfq_extract(&st->active, entity); -+ -+ if (node != NULL) -+ bfq_update_active_tree(node); -+ -+#ifdef CONFIG_CGROUP_BFQIO -+ sd = entity->sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+#endif -+ if (bfqq != NULL) -+ list_del(&bfqq->bfqq_list); -+#ifdef CONFIG_CGROUP_BFQIO -+ else { /* bfq_group */ -+ BUG_ON(!bfqd); -+ bfq_weights_tree_remove(bfqd, entity, -+ &bfqd->group_weights_tree); -+ } -+ if (bfqg != bfqd->root_group) { -+ BUG_ON(!bfqg); -+ BUG_ON(!bfqd); -+ BUG_ON(!bfqg->active_entities); -+ bfqg->active_entities--; -+ if (bfqg->active_entities == 1) { -+ BUG_ON(!bfqd->active_numerous_groups); -+ bfqd->active_numerous_groups--; -+ } -+ } -+#endif -+} -+ -+/** -+ * bfq_idle_insert - insert an entity into the idle tree. -+ * @st: the service tree containing the tree. -+ * @entity: the entity to insert. -+ */ -+static void bfq_idle_insert(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (first_idle == NULL || bfq_gt(first_idle->finish, entity->finish)) -+ st->first_idle = entity; -+ if (last_idle == NULL || bfq_gt(entity->finish, last_idle->finish)) -+ st->last_idle = entity; -+ -+ bfq_insert(&st->idle, entity); -+ -+ if (bfqq != NULL) -+ list_add(&bfqq->bfqq_list, &bfqq->bfqd->idle_list); -+} -+ -+/** -+ * bfq_forget_entity - remove an entity from the wfq trees. -+ * @st: the service tree. -+ * @entity: the entity being removed. -+ * -+ * Update the device status and forget everything about @entity, putting -+ * the device reference to it, if it is a queue. Entities belonging to -+ * groups are not refcounted. -+ */ -+static void bfq_forget_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ struct bfq_sched_data *sd; -+ -+ BUG_ON(!entity->on_st); -+ -+ entity->on_st = 0; -+ st->wsum -= entity->weight; -+ if (bfqq != NULL) { -+ sd = entity->sched_data; -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "forget_entity: %p %d", -+ bfqq, atomic_read(&bfqq->ref)); -+ bfq_put_queue(bfqq); -+ } -+} -+ -+/** -+ * bfq_put_idle_entity - release the idle tree ref of an entity. -+ * @st: service tree for the entity. -+ * @entity: the entity being released. -+ */ -+static void bfq_put_idle_entity(struct bfq_service_tree *st, -+ struct bfq_entity *entity) -+{ -+ bfq_idle_extract(st, entity); -+ bfq_forget_entity(st, entity); -+} -+ -+/** -+ * bfq_forget_idle - update the idle tree if necessary. -+ * @st: the service tree to act upon. -+ * -+ * To preserve the global O(log N) complexity we only remove one entry here; -+ * as the idle tree will not grow indefinitely this can be done safely. -+ */ -+static void bfq_forget_idle(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *first_idle = st->first_idle; -+ struct bfq_entity *last_idle = st->last_idle; -+ -+ if (RB_EMPTY_ROOT(&st->active) && last_idle != NULL && -+ !bfq_gt(last_idle->finish, st->vtime)) { -+ /* -+ * Forget the whole idle tree, increasing the vtime past -+ * the last finish time of idle entities. -+ */ -+ st->vtime = last_idle->finish; -+ } -+ -+ if (first_idle != NULL && !bfq_gt(first_idle->finish, st->vtime)) -+ bfq_put_idle_entity(st, first_idle); -+} -+ -+static struct bfq_service_tree * -+__bfq_entity_update_weight_prio(struct bfq_service_tree *old_st, -+ struct bfq_entity *entity) -+{ -+ struct bfq_service_tree *new_st = old_st; -+ -+ if (entity->ioprio_changed) { -+ struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity); -+ unsigned short prev_weight, new_weight; -+ struct bfq_data *bfqd = NULL; -+ struct rb_root *root; -+#ifdef CONFIG_CGROUP_BFQIO -+ struct bfq_sched_data *sd; -+ struct bfq_group *bfqg; -+#endif -+ -+ if (bfqq != NULL) -+ bfqd = bfqq->bfqd; -+#ifdef CONFIG_CGROUP_BFQIO -+ else { -+ sd = entity->my_sched_data; -+ bfqg = container_of(sd, struct bfq_group, sched_data); -+ BUG_ON(!bfqg); -+ bfqd = (struct bfq_data *)bfqg->bfqd; -+ BUG_ON(!bfqd); -+ } -+#endif -+ -+ BUG_ON(old_st->wsum < entity->weight); -+ old_st->wsum -= entity->weight; -+ -+ if (entity->new_weight != entity->orig_weight) { -+ entity->orig_weight = entity->new_weight; -+ entity->ioprio = -+ bfq_weight_to_ioprio(entity->orig_weight); -+ } else if (entity->new_ioprio != entity->ioprio) { -+ entity->ioprio = entity->new_ioprio; -+ entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ } else -+ entity->new_weight = entity->orig_weight = -+ bfq_ioprio_to_weight(entity->ioprio); -+ -+ entity->ioprio_class = entity->new_ioprio_class; -+ entity->ioprio_changed = 0; -+ -+ /* -+ * NOTE: here we may be changing the weight too early, -+ * this will cause unfairness. The correct approach -+ * would have required additional complexity to defer -+ * weight changes to the proper time instants (i.e., -+ * when entity->finish <= old_st->vtime). -+ */ -+ new_st = bfq_entity_service_tree(entity); -+ -+ prev_weight = entity->weight; -+ new_weight = entity->orig_weight * -+ (bfqq != NULL ? bfqq->wr_coeff : 1); -+ /* -+ * If the weight of the entity changes, remove the entity -+ * from its old weight counter (if there is a counter -+ * associated with the entity), and add it to the counter -+ * associated with its new weight. -+ */ -+ if (prev_weight != new_weight) { -+ root = bfqq ? &bfqd->queue_weights_tree : -+ &bfqd->group_weights_tree; -+ bfq_weights_tree_remove(bfqd, entity, root); -+ } -+ entity->weight = new_weight; -+ /* -+ * Add the entity to its weights tree only if it is -+ * not associated with a weight-raised queue. -+ */ -+ if (prev_weight != new_weight && -+ (bfqq ? bfqq->wr_coeff == 1 : 1)) -+ /* If we get here, root has been initialized. */ -+ bfq_weights_tree_add(bfqd, entity, root); -+ -+ new_st->wsum += entity->weight; -+ -+ if (new_st != old_st) -+ entity->start = new_st->vtime; -+ } -+ -+ return new_st; -+} -+ -+/** -+ * bfq_bfqq_served - update the scheduler status after selection for -+ * service. -+ * @bfqq: the queue being served. -+ * @served: bytes to transfer. -+ * -+ * NOTE: this can be optimized, as the timestamps of upper level entities -+ * are synchronized every time a new bfqq is selected for service. By now, -+ * we keep it to better check consistency. -+ */ -+static void bfq_bfqq_served(struct bfq_queue *bfqq, unsigned long served) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ struct bfq_service_tree *st; -+ -+ for_each_entity(entity) { -+ st = bfq_entity_service_tree(entity); -+ -+ entity->service += served; -+ BUG_ON(entity->service > entity->budget); -+ BUG_ON(st->wsum == 0); -+ -+ st->vtime += bfq_delta(served, st->wsum); -+ bfq_forget_idle(st); -+ } -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "bfqq_served %lu secs", served); -+} -+ -+/** -+ * bfq_bfqq_charge_full_budget - set the service to the entity budget. -+ * @bfqq: the queue that needs a service update. -+ * -+ * When it's not possible to be fair in the service domain, because -+ * a queue is not consuming its budget fast enough (the meaning of -+ * fast depends on the timeout parameter), we charge it a full -+ * budget. In this way we should obtain a sort of time-domain -+ * fairness among all the seeky/slow queues. -+ */ -+static inline void bfq_bfqq_charge_full_budget(struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_log_bfqq(bfqq->bfqd, bfqq, "charge_full_budget"); -+ -+ bfq_bfqq_served(bfqq, entity->budget - entity->service); -+} -+ -+/** -+ * __bfq_activate_entity - activate an entity. -+ * @entity: the entity being activated. -+ * -+ * Called whenever an entity is activated, i.e., it is not active and one -+ * of its children receives a new request, or has to be reactivated due to -+ * budget exhaustion. It uses the current budget of the entity (and the -+ * service received if @entity is active) of the queue to calculate its -+ * timestamps. -+ */ -+static void __bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ -+ if (entity == sd->in_service_entity) { -+ BUG_ON(entity->tree != NULL); -+ /* -+ * If we are requeueing the current entity we have -+ * to take care of not charging to it service it has -+ * not received. -+ */ -+ bfq_calc_finish(entity, entity->service); -+ entity->start = entity->finish; -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) { -+ /* -+ * Requeueing an entity due to a change of some -+ * next_in_service entity below it. We reuse the -+ * old start time. -+ */ -+ bfq_active_extract(st, entity); -+ } else if (entity->tree == &st->idle) { -+ /* -+ * Must be on the idle tree, bfq_idle_extract() will -+ * check for that. -+ */ -+ bfq_idle_extract(st, entity); -+ entity->start = bfq_gt(st->vtime, entity->finish) ? -+ st->vtime : entity->finish; -+ } else { -+ /* -+ * The finish time of the entity may be invalid, and -+ * it is in the past for sure, otherwise the queue -+ * would have been on the idle tree. -+ */ -+ entity->start = st->vtime; -+ st->wsum += entity->weight; -+ bfq_get_entity(entity); -+ -+ BUG_ON(entity->on_st); -+ entity->on_st = 1; -+ } -+ -+ st = __bfq_entity_update_weight_prio(st, entity); -+ bfq_calc_finish(entity, entity->budget); -+ bfq_active_insert(st, entity); -+} -+ -+/** -+ * bfq_activate_entity - activate an entity and its ancestors if necessary. -+ * @entity: the entity to activate. -+ * -+ * Activate @entity and all the entities on the path from it to the root. -+ */ -+static void bfq_activate_entity(struct bfq_entity *entity) -+{ -+ struct bfq_sched_data *sd; -+ -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ /* -+ * No need to propagate the activation to the -+ * upper entities, as they will be updated when -+ * the in-service entity is rescheduled. -+ */ -+ break; -+ } -+} -+ -+/** -+ * __bfq_deactivate_entity - deactivate an entity from its service tree. -+ * @entity: the entity to deactivate. -+ * @requeue: if false, the entity will not be put into the idle tree. -+ * -+ * Deactivate an entity, independently from its previous state. If the -+ * entity was not on a service tree just return, otherwise if it is on -+ * any scheduler tree, extract it from that tree, and if necessary -+ * and if the caller did not specify @requeue, put it on the idle tree. -+ * -+ * Return %1 if the caller should update the entity hierarchy, i.e., -+ * if the entity was in service or if it was the next_in_service for -+ * its sched_data; return %0 otherwise. -+ */ -+static int __bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd = entity->sched_data; -+ struct bfq_service_tree *st = bfq_entity_service_tree(entity); -+ int was_in_service = entity == sd->in_service_entity; -+ int ret = 0; -+ -+ if (!entity->on_st) -+ return 0; -+ -+ BUG_ON(was_in_service && entity->tree != NULL); -+ -+ if (was_in_service) { -+ bfq_calc_finish(entity, entity->service); -+ sd->in_service_entity = NULL; -+ } else if (entity->tree == &st->active) -+ bfq_active_extract(st, entity); -+ else if (entity->tree == &st->idle) -+ bfq_idle_extract(st, entity); -+ else if (entity->tree != NULL) -+ BUG(); -+ -+ if (was_in_service || sd->next_in_service == entity) -+ ret = bfq_update_next_in_service(sd); -+ -+ if (!requeue || !bfq_gt(entity->finish, st->vtime)) -+ bfq_forget_entity(st, entity); -+ else -+ bfq_idle_insert(st, entity); -+ -+ BUG_ON(sd->in_service_entity == entity); -+ BUG_ON(sd->next_in_service == entity); -+ -+ return ret; -+} -+ -+/** -+ * bfq_deactivate_entity - deactivate an entity. -+ * @entity: the entity to deactivate. -+ * @requeue: true if the entity can be put on the idle tree -+ */ -+static void bfq_deactivate_entity(struct bfq_entity *entity, int requeue) -+{ -+ struct bfq_sched_data *sd; -+ struct bfq_entity *parent; -+ -+ for_each_entity_safe(entity, parent) { -+ sd = entity->sched_data; -+ -+ if (!__bfq_deactivate_entity(entity, requeue)) -+ /* -+ * The parent entity is still backlogged, and -+ * we don't need to update it as it is still -+ * in service. -+ */ -+ break; -+ -+ if (sd->next_in_service != NULL) -+ /* -+ * The parent entity is still backlogged and -+ * the budgets on the path towards the root -+ * need to be updated. -+ */ -+ goto update; -+ -+ /* -+ * If we reach there the parent is no more backlogged and -+ * we want to propagate the dequeue upwards. -+ */ -+ requeue = 1; -+ } -+ -+ return; -+ -+update: -+ entity = parent; -+ for_each_entity(entity) { -+ __bfq_activate_entity(entity); -+ -+ sd = entity->sched_data; -+ if (!bfq_update_next_in_service(sd)) -+ break; -+ } -+} -+ -+/** -+ * bfq_update_vtime - update vtime if necessary. -+ * @st: the service tree to act upon. -+ * -+ * If necessary update the service tree vtime to have at least one -+ * eligible entity, skipping to its start time. Assumes that the -+ * active tree of the device is not empty. -+ * -+ * NOTE: this hierarchical implementation updates vtimes quite often, -+ * we may end up with reactivated processes getting timestamps after a -+ * vtime skip done because we needed a ->first_active entity on some -+ * intermediate node. -+ */ -+static void bfq_update_vtime(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry; -+ struct rb_node *node = st->active.rb_node; -+ -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+ if (bfq_gt(entry->min_start, st->vtime)) { -+ st->vtime = entry->min_start; -+ bfq_forget_idle(st); -+ } -+} -+ -+/** -+ * bfq_first_active_entity - find the eligible entity with -+ * the smallest finish time -+ * @st: the service tree to select from. -+ * -+ * This function searches the first schedulable entity, starting from the -+ * root of the tree and going on the left every time on this side there is -+ * a subtree with at least one eligible (start >= vtime) entity. The path on -+ * the right is followed only if a) the left subtree contains no eligible -+ * entities and b) no eligible entity has been found yet. -+ */ -+static struct bfq_entity *bfq_first_active_entity(struct bfq_service_tree *st) -+{ -+ struct bfq_entity *entry, *first = NULL; -+ struct rb_node *node = st->active.rb_node; -+ -+ while (node != NULL) { -+ entry = rb_entry(node, struct bfq_entity, rb_node); -+left: -+ if (!bfq_gt(entry->start, st->vtime)) -+ first = entry; -+ -+ BUG_ON(bfq_gt(entry->min_start, st->vtime)); -+ -+ if (node->rb_left != NULL) { -+ entry = rb_entry(node->rb_left, -+ struct bfq_entity, rb_node); -+ if (!bfq_gt(entry->min_start, st->vtime)) { -+ node = node->rb_left; -+ goto left; -+ } -+ } -+ if (first != NULL) -+ break; -+ node = node->rb_right; -+ } -+ -+ BUG_ON(first == NULL && !RB_EMPTY_ROOT(&st->active)); -+ return first; -+} -+ -+/** -+ * __bfq_lookup_next_entity - return the first eligible entity in @st. -+ * @st: the service tree. -+ * -+ * Update the virtual time in @st and return the first eligible entity -+ * it contains. -+ */ -+static struct bfq_entity *__bfq_lookup_next_entity(struct bfq_service_tree *st, -+ bool force) -+{ -+ struct bfq_entity *entity, *new_next_in_service = NULL; -+ -+ if (RB_EMPTY_ROOT(&st->active)) -+ return NULL; -+ -+ bfq_update_vtime(st); -+ entity = bfq_first_active_entity(st); -+ BUG_ON(bfq_gt(entity->start, st->vtime)); -+ -+ /* -+ * If the chosen entity does not match with the sched_data's -+ * next_in_service and we are forcedly serving the IDLE priority -+ * class tree, bubble up budget update. -+ */ -+ if (unlikely(force && entity != entity->sched_data->next_in_service)) { -+ new_next_in_service = entity; -+ for_each_entity(new_next_in_service) -+ bfq_update_budget(new_next_in_service); -+ } -+ -+ return entity; -+} -+ -+/** -+ * bfq_lookup_next_entity - return the first eligible entity in @sd. -+ * @sd: the sched_data. -+ * @extract: if true the returned entity will be also extracted from @sd. -+ * -+ * NOTE: since we cache the next_in_service entity at each level of the -+ * hierarchy, the complexity of the lookup can be decreased with -+ * absolutely no effort just returning the cached next_in_service value; -+ * we prefer to do full lookups to test the consistency of * the data -+ * structures. -+ */ -+static struct bfq_entity *bfq_lookup_next_entity(struct bfq_sched_data *sd, -+ int extract, -+ struct bfq_data *bfqd) -+{ -+ struct bfq_service_tree *st = sd->service_tree; -+ struct bfq_entity *entity; -+ int i = 0; -+ -+ BUG_ON(sd->in_service_entity != NULL); -+ -+ if (bfqd != NULL && -+ jiffies - bfqd->bfq_class_idle_last_service > BFQ_CL_IDLE_TIMEOUT) { -+ entity = __bfq_lookup_next_entity(st + BFQ_IOPRIO_CLASSES - 1, -+ true); -+ if (entity != NULL) { -+ i = BFQ_IOPRIO_CLASSES - 1; -+ bfqd->bfq_class_idle_last_service = jiffies; -+ sd->next_in_service = entity; -+ } -+ } -+ for (; i < BFQ_IOPRIO_CLASSES; i++) { -+ entity = __bfq_lookup_next_entity(st + i, false); -+ if (entity != NULL) { -+ if (extract) { -+ bfq_check_next_in_service(sd, entity); -+ bfq_active_extract(st + i, entity); -+ sd->in_service_entity = entity; -+ sd->next_in_service = NULL; -+ } -+ break; -+ } -+ } -+ -+ return entity; -+} -+ -+/* -+ * Get next queue for service. -+ */ -+static struct bfq_queue *bfq_get_next_queue(struct bfq_data *bfqd) -+{ -+ struct bfq_entity *entity = NULL; -+ struct bfq_sched_data *sd; -+ struct bfq_queue *bfqq; -+ -+ BUG_ON(bfqd->in_service_queue != NULL); -+ -+ if (bfqd->busy_queues == 0) -+ return NULL; -+ -+ sd = &bfqd->root_group->sched_data; -+ for (; sd != NULL; sd = entity->my_sched_data) { -+ entity = bfq_lookup_next_entity(sd, 1, bfqd); -+ BUG_ON(entity == NULL); -+ entity->service = 0; -+ } -+ -+ bfqq = bfq_entity_to_bfqq(entity); -+ BUG_ON(bfqq == NULL); -+ -+ return bfqq; -+} -+ -+static void __bfq_bfqd_reset_in_service(struct bfq_data *bfqd) -+{ -+ if (bfqd->in_service_bic != NULL) { -+ put_io_context(bfqd->in_service_bic->icq.ioc); -+ bfqd->in_service_bic = NULL; -+ } -+ -+ bfqd->in_service_queue = NULL; -+ del_timer(&bfqd->idle_slice_timer); -+} -+ -+static void bfq_deactivate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ if (bfqq == bfqd->in_service_queue) -+ __bfq_bfqd_reset_in_service(bfqd); -+ -+ bfq_deactivate_entity(entity, requeue); -+} -+ -+static void bfq_activate_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ struct bfq_entity *entity = &bfqq->entity; -+ -+ bfq_activate_entity(entity); -+} -+ -+/* -+ * Called when the bfqq no longer has requests pending, remove it from -+ * the service tree. -+ */ -+static void bfq_del_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq, -+ int requeue) -+{ -+ BUG_ON(!bfq_bfqq_busy(bfqq)); -+ BUG_ON(!RB_EMPTY_ROOT(&bfqq->sort_list)); -+ -+ bfq_log_bfqq(bfqd, bfqq, "del from busy"); -+ -+ bfq_clear_bfqq_busy(bfqq); -+ -+ BUG_ON(bfqd->busy_queues == 0); -+ bfqd->busy_queues--; -+ -+ if (!bfqq->dispatched) { -+ bfq_weights_tree_remove(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ BUG_ON(!bfqd->busy_in_flight_queues); -+ bfqd->busy_in_flight_queues--; -+ if (bfq_bfqq_constantly_seeky(bfqq)) { -+ BUG_ON(!bfqd-> -+ const_seeky_busy_in_flight_queues); -+ bfqd->const_seeky_busy_in_flight_queues--; -+ } -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues--; -+ -+ bfq_deactivate_bfqq(bfqd, bfqq, requeue); -+} -+ -+/* -+ * Called when an inactive queue receives a new request. -+ */ -+static void bfq_add_bfqq_busy(struct bfq_data *bfqd, struct bfq_queue *bfqq) -+{ -+ BUG_ON(bfq_bfqq_busy(bfqq)); -+ BUG_ON(bfqq == bfqd->in_service_queue); -+ -+ bfq_log_bfqq(bfqd, bfqq, "add to busy"); -+ -+ bfq_activate_bfqq(bfqd, bfqq); -+ -+ bfq_mark_bfqq_busy(bfqq); -+ bfqd->busy_queues++; -+ -+ if (!bfqq->dispatched) { -+ if (bfqq->wr_coeff == 1) -+ bfq_weights_tree_add(bfqd, &bfqq->entity, -+ &bfqd->queue_weights_tree); -+ if (!blk_queue_nonrot(bfqd->queue)) { -+ bfqd->busy_in_flight_queues++; -+ if (bfq_bfqq_constantly_seeky(bfqq)) -+ bfqd->const_seeky_busy_in_flight_queues++; -+ } -+ } -+ if (bfqq->wr_coeff > 1) -+ bfqd->wr_busy_queues++; -+} -diff -Nur linux-3.14.22.orig/block/blk-core.c linux-3.14.22/block/blk-core.c ---- linux-3.14.22.orig/block/blk-core.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/block/blk-core.c 2014-10-22 14:55:51.958220001 -0500 -@@ -1928,7 +1928,7 @@ - * in some cases below, so export this function. - * Request stacking drivers like request-based dm may change the queue - * limits while requests are in the queue (e.g. dm's table swapping). -- * Such request stacking drivers should check those requests agaist -+ * Such request stacking drivers should check those requests against - * the new queue limits again when they dispatch those requests, - * although such checkings are also done against the old queue limits - * when submitting requests. -diff -Nur linux-3.14.22.orig/block/blk-map.c linux-3.14.22/block/blk-map.c ---- linux-3.14.22.orig/block/blk-map.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/block/blk-map.c 2014-10-22 14:55:51.962220001 -0500 -@@ -285,7 +285,7 @@ - * - * Description: - * Data will be mapped directly if possible. Otherwise a bounce -- * buffer is used. Can be called multple times to append multple -+ * buffer is used. Can be called multiple times to append multiple - * buffers. - */ - int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, -diff -Nur linux-3.14.22.orig/block/Kconfig.iosched linux-3.14.22/block/Kconfig.iosched ---- linux-3.14.22.orig/block/Kconfig.iosched 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/block/Kconfig.iosched 2014-10-22 14:55:51.962220001 -0500 -@@ -39,6 +39,27 @@ - ---help--- - Enable group IO scheduling in CFQ. - -+config IOSCHED_BFQ -+ tristate "BFQ I/O scheduler" -+ default n -+ ---help--- -+ The BFQ I/O scheduler tries to distribute bandwidth among -+ all processes according to their weights. -+ It aims at distributing the bandwidth as desired, independently of -+ the disk parameters and with any workload. It also tries to -+ guarantee low latency to interactive and soft real-time -+ applications. If compiled built-in (saying Y here), BFQ can -+ be configured to support hierarchical scheduling. -+ -+config CGROUP_BFQIO -+ bool "BFQ hierarchical scheduling support" -+ depends on CGROUPS && IOSCHED_BFQ=y -+ default n -+ ---help--- -+ Enable hierarchical scheduling in BFQ, using the cgroups -+ filesystem interface. The name of the subsystem will be -+ bfqio. -+ - choice - prompt "Default I/O scheduler" - default DEFAULT_CFQ -@@ -52,6 +73,16 @@ - config DEFAULT_CFQ - bool "CFQ" if IOSCHED_CFQ=y - -+ config DEFAULT_BFQ -+ bool "BFQ" if IOSCHED_BFQ=y -+ help -+ Selects BFQ as the default I/O scheduler which will be -+ used by default for all block devices. -+ The BFQ I/O scheduler aims at distributing the bandwidth -+ as desired, independently of the disk parameters and with -+ any workload. It also tries to guarantee low latency to -+ interactive and soft real-time applications. -+ - config DEFAULT_NOOP - bool "No-op" - -@@ -61,6 +92,7 @@ - string - default "deadline" if DEFAULT_DEADLINE - default "cfq" if DEFAULT_CFQ -+ default "bfq" if DEFAULT_BFQ - default "noop" if DEFAULT_NOOP - - endmenu -diff -Nur linux-3.14.22.orig/block/Makefile linux-3.14.22/block/Makefile ---- linux-3.14.22.orig/block/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/block/Makefile 2014-10-22 14:55:51.962220001 -0500 -@@ -16,6 +16,7 @@ - obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o - obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o - obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o -+obj-$(CONFIG_IOSCHED_BFQ) += bfq-iosched.o - - obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o - obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o -diff -Nur linux-3.14.22.orig/crypto/blkcipher.c linux-3.14.22/crypto/blkcipher.c ---- linux-3.14.22.orig/crypto/blkcipher.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/crypto/blkcipher.c 2014-10-22 14:55:51.962220001 -0500 -@@ -70,14 +70,12 @@ - return max(start, end_page); - } - --static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm, -- struct blkcipher_walk *walk, -+static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk, - unsigned int bsize) - { - u8 *addr; -- unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - -- addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); -+ addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1); - addr = blkcipher_get_spot(addr, bsize); - scatterwalk_copychunks(addr, &walk->out, bsize, 1); - return bsize; -@@ -105,7 +103,6 @@ - int blkcipher_walk_done(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, int err) - { -- struct crypto_blkcipher *tfm = desc->tfm; - unsigned int nbytes = 0; - - if (likely(err >= 0)) { -@@ -117,7 +114,7 @@ - err = -EINVAL; - goto err; - } else -- n = blkcipher_done_slow(tfm, walk, n); -+ n = blkcipher_done_slow(walk, n); - - nbytes = walk->total - n; - err = 0; -@@ -136,7 +133,7 @@ - } - - if (walk->iv != desc->info) -- memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm)); -+ memcpy(desc->info, walk->iv, walk->ivsize); - if (walk->buffer != walk->page) - kfree(walk->buffer); - if (walk->page) -@@ -226,22 +223,20 @@ - static int blkcipher_walk_next(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) - { -- struct crypto_blkcipher *tfm = desc->tfm; -- unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - unsigned int bsize; - unsigned int n; - int err; - - n = walk->total; -- if (unlikely(n < crypto_blkcipher_blocksize(tfm))) { -+ if (unlikely(n < walk->cipher_blocksize)) { - desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; - return blkcipher_walk_done(desc, walk, -EINVAL); - } - - walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY | - BLKCIPHER_WALK_DIFF); -- if (!scatterwalk_aligned(&walk->in, alignmask) || -- !scatterwalk_aligned(&walk->out, alignmask)) { -+ if (!scatterwalk_aligned(&walk->in, walk->alignmask) || -+ !scatterwalk_aligned(&walk->out, walk->alignmask)) { - walk->flags |= BLKCIPHER_WALK_COPY; - if (!walk->page) { - walk->page = (void *)__get_free_page(GFP_ATOMIC); -@@ -250,12 +245,12 @@ - } - } - -- bsize = min(walk->blocksize, n); -+ bsize = min(walk->walk_blocksize, n); - n = scatterwalk_clamp(&walk->in, n); - n = scatterwalk_clamp(&walk->out, n); - - if (unlikely(n < bsize)) { -- err = blkcipher_next_slow(desc, walk, bsize, alignmask); -+ err = blkcipher_next_slow(desc, walk, bsize, walk->alignmask); - goto set_phys_lowmem; - } - -@@ -277,28 +272,26 @@ - return err; - } - --static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, -- struct crypto_blkcipher *tfm, -- unsigned int alignmask) --{ -- unsigned bs = walk->blocksize; -- unsigned int ivsize = crypto_blkcipher_ivsize(tfm); -- unsigned aligned_bs = ALIGN(bs, alignmask + 1); -- unsigned int size = aligned_bs * 2 + ivsize + max(aligned_bs, ivsize) - -- (alignmask + 1); -+static inline int blkcipher_copy_iv(struct blkcipher_walk *walk) -+{ -+ unsigned bs = walk->walk_blocksize; -+ unsigned aligned_bs = ALIGN(bs, walk->alignmask + 1); -+ unsigned int size = aligned_bs * 2 + -+ walk->ivsize + max(aligned_bs, walk->ivsize) - -+ (walk->alignmask + 1); - u8 *iv; - -- size += alignmask & ~(crypto_tfm_ctx_alignment() - 1); -+ size += walk->alignmask & ~(crypto_tfm_ctx_alignment() - 1); - walk->buffer = kmalloc(size, GFP_ATOMIC); - if (!walk->buffer) - return -ENOMEM; - -- iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); -+ iv = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1); - iv = blkcipher_get_spot(iv, bs) + aligned_bs; - iv = blkcipher_get_spot(iv, bs) + aligned_bs; -- iv = blkcipher_get_spot(iv, ivsize); -+ iv = blkcipher_get_spot(iv, walk->ivsize); - -- walk->iv = memcpy(iv, walk->iv, ivsize); -+ walk->iv = memcpy(iv, walk->iv, walk->ivsize); - return 0; - } - -@@ -306,7 +299,10 @@ - struct blkcipher_walk *walk) - { - walk->flags &= ~BLKCIPHER_WALK_PHYS; -- walk->blocksize = crypto_blkcipher_blocksize(desc->tfm); -+ walk->walk_blocksize = crypto_blkcipher_blocksize(desc->tfm); -+ walk->cipher_blocksize = walk->walk_blocksize; -+ walk->ivsize = crypto_blkcipher_ivsize(desc->tfm); -+ walk->alignmask = crypto_blkcipher_alignmask(desc->tfm); - return blkcipher_walk_first(desc, walk); - } - EXPORT_SYMBOL_GPL(blkcipher_walk_virt); -@@ -315,7 +311,10 @@ - struct blkcipher_walk *walk) - { - walk->flags |= BLKCIPHER_WALK_PHYS; -- walk->blocksize = crypto_blkcipher_blocksize(desc->tfm); -+ walk->walk_blocksize = crypto_blkcipher_blocksize(desc->tfm); -+ walk->cipher_blocksize = walk->walk_blocksize; -+ walk->ivsize = crypto_blkcipher_ivsize(desc->tfm); -+ walk->alignmask = crypto_blkcipher_alignmask(desc->tfm); - return blkcipher_walk_first(desc, walk); - } - EXPORT_SYMBOL_GPL(blkcipher_walk_phys); -@@ -323,9 +322,6 @@ - static int blkcipher_walk_first(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) - { -- struct crypto_blkcipher *tfm = desc->tfm; -- unsigned int alignmask = crypto_blkcipher_alignmask(tfm); -- - if (WARN_ON_ONCE(in_irq())) - return -EDEADLK; - -@@ -335,8 +331,8 @@ - - walk->buffer = NULL; - walk->iv = desc->info; -- if (unlikely(((unsigned long)walk->iv & alignmask))) { -- int err = blkcipher_copy_iv(walk, tfm, alignmask); -+ if (unlikely(((unsigned long)walk->iv & walk->alignmask))) { -+ int err = blkcipher_copy_iv(walk); - if (err) - return err; - } -@@ -353,11 +349,28 @@ - unsigned int blocksize) - { - walk->flags &= ~BLKCIPHER_WALK_PHYS; -- walk->blocksize = blocksize; -+ walk->walk_blocksize = blocksize; -+ walk->cipher_blocksize = crypto_blkcipher_blocksize(desc->tfm); -+ walk->ivsize = crypto_blkcipher_ivsize(desc->tfm); -+ walk->alignmask = crypto_blkcipher_alignmask(desc->tfm); - return blkcipher_walk_first(desc, walk); - } - EXPORT_SYMBOL_GPL(blkcipher_walk_virt_block); - -+int blkcipher_aead_walk_virt_block(struct blkcipher_desc *desc, -+ struct blkcipher_walk *walk, -+ struct crypto_aead *tfm, -+ unsigned int blocksize) -+{ -+ walk->flags &= ~BLKCIPHER_WALK_PHYS; -+ walk->walk_blocksize = blocksize; -+ walk->cipher_blocksize = crypto_aead_blocksize(tfm); -+ walk->ivsize = crypto_aead_ivsize(tfm); -+ walk->alignmask = crypto_aead_alignmask(tfm); -+ return blkcipher_walk_first(desc, walk); -+} -+EXPORT_SYMBOL_GPL(blkcipher_aead_walk_virt_block); -+ - static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) - { -diff -Nur linux-3.14.22.orig/crypto/tcrypt.c linux-3.14.22/crypto/tcrypt.c ---- linux-3.14.22.orig/crypto/tcrypt.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/crypto/tcrypt.c 2014-10-22 14:55:51.962220001 -0500 -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include "tcrypt.h" - #include "internal.h" - -@@ -447,6 +448,7 @@ - goto out; - } - -+ schedule(); - printk("test %u (%d bit key, %d byte blocks): ", i, - *keysize * 8, *b_size); - -@@ -713,6 +715,7 @@ - if (speed[i].klen) - crypto_hash_setkey(tfm, tvmem[0], speed[i].klen); - -+ schedule(); - printk(KERN_INFO "test%3u " - "(%5u byte blocks,%5u bytes per update,%4u updates): ", - i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); -@@ -953,6 +956,7 @@ - break; - } - -+ schedule(); - pr_info("test%3u " - "(%5u byte blocks,%5u bytes per update,%4u updates): ", - i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); -@@ -1118,6 +1122,7 @@ - goto out_free_req; - } - -+ schedule(); - pr_info("test %u (%d bit key, %d byte blocks): ", i, - *keysize * 8, *b_size); - -@@ -1199,6 +1204,7 @@ - printk("alg %s ", *name); - printk(crypto_has_alg(*name, 0, 0) ? - "found\n" : "not found\n"); -+ schedule(); - name++; - } - } -diff -Nur linux-3.14.22.orig/Documentation/ABI/testing/sysfs-class-net-statistics linux-3.14.22/Documentation/ABI/testing/sysfs-class-net-statistics ---- linux-3.14.22.orig/Documentation/ABI/testing/sysfs-class-net-statistics 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/ABI/testing/sysfs-class-net-statistics 2014-10-22 14:55:51.962220001 -0500 -@@ -0,0 +1,201 @@ -+What: /sys/class//statistics/collisions -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of collisions seen by this network device. -+ This value might not be relevant with all MAC layers. -+ -+What: /sys/class//statistics/multicast -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of multicast packets received by this -+ network device. -+ -+What: /sys/class//statistics/rx_bytes -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of bytes received by this network device. -+ See the network driver for the exact meaning of when this -+ value is incremented. -+ -+What: /sys/class//statistics/rx_compressed -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of compressed packets received by this -+ network device. This value might only be relevant for interfaces -+ that support packet compression (e.g: PPP). -+ -+What: /sys/class//statistics/rx_crc_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets received with a CRC (FCS) error -+ by this network device. Note that the specific meaning might -+ depend on the MAC layer used by the interface. -+ -+What: /sys/class//statistics/rx_dropped -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets received by the network device -+ but dropped, that are not forwarded to the upper layers for -+ packet processing. See the network driver for the exact -+ meaning of this value. -+ -+What: /sys/class//statistics/rx_fifo_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of receive FIFO errors seen by this -+ network device. See the network driver for the exact -+ meaning of this value. -+ -+What: /sys/class//statistics/rx_frame_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of received frames with error, such as -+ alignment errors. Note that the specific meaning depends on -+ on the MAC layer protocol used. See the network driver for -+ the exact meaning of this value. -+ -+What: /sys/class//statistics/rx_length_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of received error packet with a length -+ error, oversized or undersized. See the network driver for the -+ exact meaning of this value. -+ -+What: /sys/class//statistics/rx_missed_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of received packets that have been missed -+ due to lack of capacity in the receive side. See the network -+ driver for the exact meaning of this value. -+ -+What: /sys/class//statistics/rx_over_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of received packets that are oversized -+ compared to what the network device is configured to accept -+ (e.g: larger than MTU). See the network driver for the exact -+ meaning of this value. -+ -+What: /sys/class//statistics/rx_packets -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the total number of good packets received by this -+ network device. -+ -+What: /sys/class//statistics/tx_aborted_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets that have been aborted -+ during transmission by a network device (e.g: because of -+ a medium collision). See the network driver for the exact -+ meaning of this value. -+ -+What: /sys/class//statistics/tx_bytes -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of bytes transmitted by a network -+ device. See the network driver for the exact meaning of this -+ value, in particular whether this accounts for all successfully -+ transmitted packets or all packets that have been queued for -+ transmission. -+ -+What: /sys/class//statistics/tx_carrier_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets that could not be transmitted -+ because of carrier errors (e.g: physical link down). See the -+ network driver for the exact meaning of this value. -+ -+What: /sys/class//statistics/tx_compressed -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of transmitted compressed packets. Note -+ this might only be relevant for devices that support -+ compression (e.g: PPP). -+ -+What: /sys/class//statistics/tx_dropped -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets dropped during transmission. -+ See the driver for the exact reasons as to why the packets were -+ dropped. -+ -+What: /sys/class//statistics/tx_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets in error during transmission by -+ a network device. See the driver for the exact reasons as to -+ why the packets were dropped. -+ -+What: /sys/class//statistics/tx_fifo_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets having caused a transmit -+ FIFO error. See the driver for the exact reasons as to why the -+ packets were dropped. -+ -+What: /sys/class//statistics/tx_heartbeat_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets transmitted that have been -+ reported as heartbeat errors. See the driver for the exact -+ reasons as to why the packets were dropped. -+ -+What: /sys/class//statistics/tx_packets -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets transmitted by a network -+ device. See the driver for whether this reports the number of all -+ attempted or successful transmissions. -+ -+What: /sys/class//statistics/tx_window_errors -+Date: April 2005 -+KernelVersion: 2.6.12 -+Contact: netdev@vger.kernel.org -+Description: -+ Indicates the number of packets not successfully transmitted -+ due to a window collision. The specific meaning depends on the -+ MAC layer used. On Ethernet this is usually used to report -+ late collisions errors. -diff -Nur linux-3.14.22.orig/Documentation/arm64/booting.txt linux-3.14.22/Documentation/arm64/booting.txt ---- linux-3.14.22.orig/Documentation/arm64/booting.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/arm64/booting.txt 2014-10-22 14:55:51.962220001 -0500 -@@ -111,8 +111,14 @@ - - Caches, MMUs - The MMU must be off. - Instruction cache may be on or off. -- Data cache must be off and invalidated. -- External caches (if present) must be configured and disabled. -+ The address range corresponding to the loaded kernel image must be -+ cleaned to the PoC. In the presence of a system cache or other -+ coherent masters with caches enabled, this will typically require -+ cache maintenance by VA rather than set/way operations. -+ System caches which respect the architected cache maintenance by VA -+ operations must be configured and may be enabled. -+ System caches which do not respect architected cache maintenance by VA -+ operations (not recommended) must be configured and disabled. - - - Architected timers - CNTFRQ must be programmed with the timer frequency and CNTVOFF must -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt linux-3.14.22/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/arm/imx/busfreq-imx6.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -0,0 +1,64 @@ -+Freescale Busfreq driver -+ -+It is a generic driver that manages the frequency of the DDR, AHB and AXI buses in the iMX6x architecture. -+It works for both SMP and UP systems and for both DDR3 and LPDDR2 memory types. -+ -+Required properties are listed below: -+- compatible: should be "fsl,imx6_busfreq" -+- clocks: Lists the various clocks used by the busfreq driver -+- interrupts - Lists the interrupts used by the busfreq driver. This is needed only for SMP architecutre. -+- fsl,max_ddr_freq - The max ddr freq for this chip -+ -+Examples: -+For SOC imx6q.dtsi: -+ busfreq { /* BUSFREQ */ -+ compatible = "fsl,imx6_busfreq"; -+ clocks = <&clks 171>, <&clks 6>, <&clks 11>, <&clks 104>, <&clks 172>, <&clks 58>, -+ <&clks 18>, <&clks 60>, <&clks 20>, <&clks 3>; -+ clock-names = "pll2_bus", "pll2_pfd2_396m", "pll2_198m", "arm", "pll3_usb_otg", "periph", -+ "periph_pre", "periph_clk2", "periph_clk2_sel", "osc"; -+ interrupts = <0 107 0x04>, <0 112 0x4>, <0 113 0x4>, <0 114 0x4>; -+ interrupt-names = "irq_busfreq_0", "irq_busfreq_1", "irq_busfreq_2", "irq_busfreq_3"; -+ fsl,max_ddr_freq = <528000000>; -+ }; -+ -+The Freescale Busfreq driver supports the following setpoints for the DDR freq: -+enum bus_freq_mode { -+ BUS_FREQ_HIGH, -> The max freq the SOC supports -+ BUS_FREQ_MED, -> Medium setpoint (ex 400MHz for DDR3 when the max is 528MHz) -+ BUS_FREQ_AUDIO, -> Audio playback freq (50MHz) -+ BUS_FREQ_LOW, -> Low power IDLE freq (24MHz) -+}; -+ -+Currently the Freescale Busfreq driver implementation requires drivers to call the following APIs: -+1. request_bus_freq(enum bus_freq_mode): -+ The driver is requesting the system and ddr freq to be set to the requested value. The driver should call this -+ API before it even enables its clocks. -+ -+2. release_bus_freq(enum bus_freq_mode): -+ The driver no longer needs the system and ddr freq at the required value. The driver should call this API after -+ its work is done and it has disabled its clocks. -+ -+Examples: -+In the IPU driver, the requesting and releasing of the required bus frequency is tied into the runtime PM implementation: -+ -+int ipu_runtime_suspend(struct device *dev) -+{ -+ release_bus_freq(BUS_FREQ_HIGH); -+ dev_dbg(dev, "ipu busfreq high release.\n"); -+ -+ return 0; -+} -+ -+int ipu_runtime_resume(struct device *dev) -+{ -+ request_bus_freq(BUS_FREQ_HIGH); -+ dev_dbg(dev, "ipu busfreq high requst.\n"); -+ -+ return 0; -+} -+ -+static const struct dev_pm_ops ipu_pm_ops = { -+ SET_RUNTIME_PM_OPS(ipu_runtime_suspend, ipu_runtime_resume, NULL) -+ SET_SYSTEM_SLEEP_PM_OPS(ipu_suspend, ipu_resume) -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/arm/imx/gpc.txt linux-3.14.22/Documentation/devicetree/bindings/arm/imx/gpc.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/arm/imx/gpc.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/arm/imx/gpc.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -0,0 +1,20 @@ -+Freescale imx GPC bindings -+ -+Optional properties: -+- fsl,cpu_pupscr_sw2iso: for powering up CPU, number of 32K clock cycle PGC will wait before negating isolation signal. -+- fsl,cpu_pupscr_sw: for powering up CPU, number of 32K clock cycle PGC will wait before asserting isolation signal. -+- fsl,cpu_pdnscr_iso2sw: for powering down CPU, number of ipg clock cycle PGC will wait before negating isolation signal. -+- fsl,cpu_pdnscr_iso: for powering down CPU, number of ipg clock cycle PGC will wait before asserting isolation signal. -+ -+These properties are for adjusting the GPC PGC CPU power up/down setting, if there is no such property in dts, then default -+value in GPC PGC registers will be used. -+ -+ -+Example: -+ -+ &gpc { -+ fsl,cpu_pupscr_sw2iso = <0xf>; -+ fsl,cpu_pupscr_sw = <0xf>; -+ fsl,cpu_pdnscr_iso2sw = <0x1>; -+ fsl,cpu_pdnscr_iso = <0x1>; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/arm/pmu.txt linux-3.14.22/Documentation/devicetree/bindings/arm/pmu.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/arm/pmu.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/arm/pmu.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -17,6 +17,9 @@ - "arm,arm1176-pmu" - "arm,arm1136-pmu" - - interrupts : 1 combined interrupt or 1 per core. -+- cluster : a phandle to the cluster to which it belongs -+ If there are more than one cluster with same CPU type -+ then there should be separate PMU nodes per cluster. - - Example: - -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt linux-3.14.22/Documentation/devicetree/bindings/ata/ahci-platform.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/ata/ahci-platform.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/ata/ahci-platform.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -4,12 +4,19 @@ - Each SATA controller should have its own node. - - Required properties: --- compatible : compatible list, contains "snps,spear-ahci" -+- compatible : compatible list, contains "snps,spear-ahci", -+ "fsl,imx53-ahci" or "fsl,imx6q-ahci" - - interrupts : - - reg : - - Optional properties: - - dma-coherent : Present if dma operations are coherent -+- clocks : a list of phandle + clock specifier pairs -+- target-supply : regulator for SATA target power -+ -+"fsl,imx53-ahci", "fsl,imx6q-ahci" required properties: -+- clocks : must contain the sata, sata_ref and ahb clocks -+- clock-names : must contain "ahb" for the ahb clock - - Example: - sata@ffe08000 { -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/clock/imx6q-clock.txt linux-3.14.22/Documentation/devicetree/bindings/clock/imx6q-clock.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/clock/imx6q-clock.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/clock/imx6q-clock.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -89,8 +89,6 @@ - gpu3d_shader 74 - ipu1_podf 75 - ipu2_podf 76 -- ldb_di0_podf 77 -- ldb_di1_podf 78 - ipu1_di0_pre 79 - ipu1_di1_pre 80 - ipu2_di0_pre 81 -@@ -220,6 +218,20 @@ - lvds2_sel 205 - lvds1_gate 206 - lvds2_gate 207 -+ gpt_3m 208 -+ video_27m 209 -+ ldb_di0_div_7 210 -+ ldb_di1_div_7 211 -+ ldb_di0_div_sel 212 -+ ldb_di1_div_sel 213 -+ caam_mem 214 -+ caam_aclk 215 -+ caam_ipg 216 -+ epit1 217 -+ epit2 218 -+ tzasc2 219 -+ lvds1_in 220 -+ lvds1_out 221 - - Examples: - -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt linux-3.14.22/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt 2014-10-22 14:55:51.982220001 -0500 -@@ -47,6 +47,7 @@ - 20 ASRC - 21 ESAI - 22 SSI Dual FIFO (needs firmware ver >= 2) -+ 23 HDMI Audio - - The third cell specifies the transfer priority as below. - -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt linux-3.14.22/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt 2014-10-22 14:55:51.986220001 -0500 -@@ -0,0 +1,146 @@ -+* FSL IPUv3 Display/FB -+ -+The FSL IPUv3 is Image Processing Unit version 3, a part of video and graphics -+subsystem in an application processor. The goal of the IPU is to provide -+comprehensive support for the flow of data from an image sensor or/and to a -+display device. -+ -+Two IPU units are on the imx6q SOC while only one IPU unit on the imx6dl SOC. -+Each IPU unit has two display interfaces. -+ -+For LDB/LVDS panel, there are two LVDS channels(LVDS0 and LVDS1) which can -+transfer video data, these two channels can be used as -+split/dual/single/separate mode. -+-split mode means display data from DI0 or DI1 will send to both channels -+ LVDS0+LVDS1. -+-dual mode means display data from DI0 or DI1 will be duplicated on LVDS0 -+ and LVDS1, it said, LVDS0 and LVDS1 has the same content. -+-single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1. -+-separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work -+ at the same time. -+ "ldb=spl0/1" -- split mode on DI0/1 -+ "ldb=dul0/1" -- dual mode on DI0/1 -+ "ldb=sin0/1" -- single mode on LVDS0/1 -+ "ldb=sep0/1" -- separate mode begin from LVDS0/1 -+ -+Required properties for IPU: -+- bypass_reset :Bypass reset to avoid display channel being. -+ stopped by probe since it may start to work in bootloader: 0 or 1. -+- compatible : should be "fsl,imx6q-ipu". -+- reg : the register address range. -+- interrupts : the error and sync interrupts request. -+- clocks : the clock sources that it depends on. -+- clock-names: the related clock names. -+- resets : IPU reset specifier. See reset.txt and fsl,imx-src.txt in -+ Documentation/devicetree/bindings/reset/ for details. -+ -+Required properties for fb: -+- compatible : should be "fsl,mxc_sdc_fb". -+- disp_dev : display device: "ldb", "lcd", "hdmi", "mipi_dsi". -+- mode_str : video mode string: "LDB-XGA" or "LDB-1080P60" for ldb, -+ "CLAA-WVGA" for lcd, "TRULY-WVGA" for TRULY mipi_dsi lcd panel, -+ "1920x1080M@60" for hdmi. -+- default_bpp : default bits per pixel: 8/16/24/32 -+- int_clk : use internal clock as pixel clock: 0 or 1 -+- late_init : to avoid display channel being re-initialized -+ as we've probably setup the channel in bootloader: 0 or 1 -+- interface_pix_fmt : display interface pixel format as below: -+ RGB666 IPU_PIX_FMT_RGB666 -+ RGB565 IPU_PIX_FMT_RGB565 -+ RGB24 IPU_PIX_FMT_RGB24 -+ BGR24 IPU_PIX_FMT_BGR24 -+ GBR24 IPU_PIX_FMT_GBR24 -+ YUV444 IPU_PIX_FMT_YUV444 -+ LVDS666 IPU_PIX_FMT_LVDS666 -+ YUYV IPU_PIX_FMT_YUYV -+ UYVY IPU_PIX_FMT_UYVY -+ YVYV IPU_PIX_FMT_YVYU -+ VYUY IPU_PIX_FMT_VYUY -+ -+Required properties for display: -+- compatible : should be "fsl,lcd" for lcd panel, "fsl,imx6q-ldb" for ldb -+- reg : the register address range if necessary to have. -+- interrupts : the error and sync interrupts if necessary to have. -+- clocks : the clock sources that it depends on if necessary to have. -+- clock-names: the related clock names if necessary to have. -+- ipu_id : ipu id for the first display device: 0 or 1 -+- disp_id : display interface id for the first display interface: 0 or 1 -+- default_ifmt : save as above display interface pixel format for lcd -+- pinctrl-names : should be "default" -+- pinctrl-0 : should be pinctrl_ipu1_1 or pinctrl_ipu2_1, which depends on the -+ IPU connected. -+- sec_ipu_id : secondary ipu id for the second display device(ldb only): 0 or 1 -+- sec_disp_id : secondary display interface id for the second display -+ device(ldb only): 0 or 1 -+- ext_ref : reference resistor select for ldb only: 0 or 1 -+- mode : ldb mode as below: -+ spl0 LDB_SPL_DI0 -+ spl1 LDB_SPL_DI1 -+ dul0 LDB_DUL_DI0 -+ dul1 LDB_DUL_DI1 -+ sin0 LDB_SIN0 -+ sin1 LDB_SIN1 -+ sep0 LDB_SEP0 -+ sep1 LDB_SEP1 -+- gpr : the mux controller for the display engine's display interfaces and the display encoder -+ (only valid for mipi dsi now). -+- disp-power-on-supply : the regulator to control display panel's power. -+ (only valid for mipi dsi now). -+- resets : the gpio pin to reset the display device(only valid for mipi display panel now). -+- lcd_panel : the video mode name for the display device(only valid for mipi display panel now). -+- dev_id : the display engine's identity within the system, which intends to replace ipu_id -+ (only valid for mipi dsi now). -+ -+Example for IPU: -+ ipu1: ipu@02400000 { -+ compatible = "fsl,imx6q-ipu"; -+ reg = <0x02400000 0x400000>; -+ interrupts = <0 6 0x4 0 5 0x4>; -+ clocks = <&clks 130>, <&clks 131>, <&clks 132>, -+ <&clks 39>, <&clks 40>, -+ <&clks 135>, <&clks 136>; -+ clock-names = "bus", "di0", "di1", -+ "di0_sel", "di1_sel", -+ "ldb_di0", "ldb_di1"; -+ resets = <&src 2>; -+ bypass_reset = <0>; -+ }; -+ -+Example for fb: -+ fb0 { -+ compatible = "fsl,mxc_sdc_fb"; -+ disp_dev = "ldb"; -+ interface_pix_fmt = "RGB666"; -+ mode_str ="LDB-XGA"; -+ default_bpp = <16>; -+ int_clk = <0>; -+ late_init = <0>; -+ status = "okay"; -+ }; -+ -+Example for ldb display: -+ ldb@020e0000 { -+ ipu_id = <1>; -+ disp_id = <0>; -+ ext_ref = <1>; -+ mode = "sep0"; -+ sec_ipu_id = <1>; -+ sec_disp_id = <1>; -+ status = "okay"; -+ }; -+ -+Example for mipi dsi display: -+ mipi_dsi: mipi@021e0000 { -+ compatible = "fsl,imx6q-mipi-dsi"; -+ reg = <0x021e0000 0x4000>; -+ interrupts = <0 102 0x04>; -+ gpr = <&gpr>; -+ clocks = <&clks 138>, <&clks 204>; -+ clock-names = "mipi_pllref_clk", "mipi_cfg_clk"; -+ dev_id = <0>; -+ disp_id = <0>; -+ lcd_panel = "TRULY-WVGA"; -+ disp-power-on-supply = <®_mipi_dsi_pwr_on> -+ resets = <&mipi_dsi_reset>; -+ status = "okay"; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt linux-3.14.22/Documentation/devicetree/bindings/leds/leds-pwm.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/leds/leds-pwm.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/leds/leds-pwm.txt 2014-10-22 14:55:51.986220001 -0500 -@@ -13,6 +13,8 @@ - For the pwms and pwm-names property please refer to: - Documentation/devicetree/bindings/pwm/pwm.txt - - max-brightness : Maximum brightness possible for the LED -+- active-low : (optional) For PWMs where the LED is wired to supply -+ rather than ground. - - label : (optional) - see Documentation/devicetree/bindings/leds/common.txt - - linux,default-trigger : (optional) -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/mailbox/mailbox.txt linux-3.14.22/Documentation/devicetree/bindings/mailbox/mailbox.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/mailbox/mailbox.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/mailbox/mailbox.txt 2014-10-22 14:55:51.986220001 -0500 -@@ -0,0 +1,33 @@ -+* Generic Mailbox Controller and client driver bindings -+ -+Generic binding to provide a way for Mailbox controller drivers to -+assign appropriate mailbox channel to client drivers. -+ -+* Mailbox Controller -+ -+Required property: -+- #mbox-cells: Must be at least 1. Number of cells in a mailbox -+ specifier. -+ -+Example: -+ mailbox: mailbox { -+ ... -+ #mbox-cells = <1>; -+ }; -+ -+ -+* Mailbox Client -+ -+Required property: -+- mbox: List of phandle and mailbox channel specifier. -+ -+- mbox-names: List of identifier strings for each mailbox channel -+ required by the client. -+ -+Example: -+ pwr_cntrl: power { -+ ... -+ mbox-names = "pwr-ctrl", "rpc"; -+ mbox = <&mailbox 0 -+ &mailbox 1>; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/mlb/mlb150.txt linux-3.14.22/Documentation/devicetree/bindings/mlb/mlb150.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/mlb/mlb150.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/mlb/mlb150.txt 2014-10-22 14:55:51.990220001 -0500 -@@ -0,0 +1,22 @@ -+* Freescale Media Local Bus Host Controller (MLB) for i.MX6Q/DL -+ -+The Media Local Bus Host Controller on Freescale i.MX family -+provides an interface for MOST network. -+ -+Required properties: -+- compatible : Should be "fsl,-mlb150" -+- reg : Should contain mlb registers location and length -+- interrupts : Should contain mlb interrupt -+- clocks: Should contain the mlb clock sources -+- clock-names: Should be the names of mlb clock sources -+- iram : phandle pointing to the SRAM device node -+ -+Examples: -+mlb@0218c000 { -+ compatible = "fsl,imx6q-mlb150"; -+ reg = <0x0218c000 0x4000>; -+ interrupts = <0 53 0x04 0 117 0x04 0 126 0x04>; -+ clocks = <&clks 139>, <&clks 175>; -+ clock-names = "mlb", "pll8_mlb"; -+ iram = <&ocram>; -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/mmc/mmc.txt linux-3.14.22/Documentation/devicetree/bindings/mmc/mmc.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/mmc/mmc.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/mmc/mmc.txt 2014-10-22 14:55:51.990220001 -0500 -@@ -5,6 +5,8 @@ - Interpreted by the OF core: - - reg: Registers location and length. - - interrupts: Interrupts used by the MMC controller. -+- clocks: Clocks needed for the host controller, if any. -+- clock-names: Goes with clocks above. - - Card detection: - If no property below is supplied, host native card detect is used. -@@ -30,6 +32,15 @@ - - cap-sdio-irq: enable SDIO IRQ signalling on this interface - - full-pwr-cycle: full power cycle of the card is supported - -+Card power and reset control: -+The following properties can be specified for cases where the MMC -+peripheral needs additional reset, regulator and clock lines. It is for -+example common for WiFi/BT adapters to have these separate from the main -+MMC bus: -+ - card-reset-gpios: Specify GPIOs for card reset (reset active low) -+ - card-external-vcc-supply: Regulator to drive (independent) card VCC -+ - clock with name "card_ext_clock": External clock provided to the card -+ - *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line - polarity properties, we have to fix the meaning of the "normal" and "inverted" - line levels. We choose to follow the SDHCI standard, which specifies both those -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt linux-3.14.22/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt 2014-10-22 14:55:51.990220001 -0500 -@@ -71,6 +71,13 @@ - name for integer state ID 0, list entry 1 for state ID 1, and - so on. - -+pinctrl-assert-gpios: -+ List of phandles, each pointing at a GPIO which is used by some -+ board design to steer pins between two peripherals on the board. -+ It plays like a board level pin multiplexer to choose different -+ functions for given pins by pulling up/down the GPIOs. See -+ bindings/gpio/gpio.txt for details of how to specify GPIO. -+ - For example: - - /* For a client device requiring named states */ -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/reset/gpio-reset.txt linux-3.14.22/Documentation/devicetree/bindings/reset/gpio-reset.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/reset/gpio-reset.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/reset/gpio-reset.txt 2014-10-22 14:55:51.990220001 -0500 -@@ -0,0 +1,35 @@ -+GPIO reset controller -+===================== -+ -+A GPIO reset controller controls a single GPIO that is connected to the reset -+pin of a peripheral IC. Please also refer to reset.txt in this directory for -+common reset controller binding usage. -+ -+Required properties: -+- compatible: Should be "gpio-reset" -+- reset-gpios: A gpio used as reset line. The gpio specifier for this property -+ depends on the gpio controller that provides the gpio. -+- #reset-cells: 0, see below -+ -+Optional properties: -+- reset-delay-us: delay in microseconds. The gpio reset line will be asserted for -+ this duration to reset. -+- initially-in-reset: boolean. If not set, the initial state should be a -+ deasserted reset line. If this property exists, the -+ reset line should be kept in reset. -+ -+example: -+ -+sii902x_reset: gpio-reset { -+ compatible = "gpio-reset"; -+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; -+ reset-delay-us = <10000>; -+ initially-in-reset; -+ #reset-cells = <0>; -+}; -+ -+/* Device with nRESET pin connected to GPIO5_0 */ -+sii902x@39 { -+ /* ... */ -+ resets = <&sii902x_reset>; /* active-low GPIO5_0, 10 ms delay */ -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/sound/cs42888.txt linux-3.14.22/Documentation/devicetree/bindings/sound/cs42888.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/sound/cs42888.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/sound/cs42888.txt 2014-10-22 14:55:51.990220001 -0500 -@@ -0,0 +1,29 @@ -+CS42888 audio CODEC -+ -+This device supports I2C only. -+ -+Required properties: -+ -+ - compatible: "cirrus,cs42888" -+ - reg: the I2C address of the device. -+ - clocks: Phandle to the clock node. -+ - clock-names: Contains name for each entry in clocks. -+ "codec_osc" : the external oscillator. -+ "esai" : the hckt clock from esai. -+ - -supply: Phandle to the regulator . -+ -+Note: cs42888 needs a regulators node and a clocks node. -+ -+Example: -+In this case, the clock is external oscillator. -+ -+codec: cs42888@48 { -+ compatible = "cirrus,cs42888"; -+ reg = <0x048>; -+ clocks = <&codec_osc 0>; -+ clock-names = "codec_osc"; -+ VA-supply = <®_audio>; -+ VD-supply = <®_audio>; -+ VLS-supply = <®_audio>; -+ VLC-supply = <®_audio>; -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt linux-3.14.22/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/sound/fsl-asrc-p2p.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,23 @@ -+* Freescale Asynchronous Sample Rate Converter (ASRC) -+ -+This document is for asrc p2p node. p2p is one of asrc mode. asrc p2p depend on -+MXC_ASRC. -+ -+Required properties: -+ - compatible: Should be "fsl,-asrc-p2p". -+ - fsl,output-rate: the output rate of asrc p2p. which can be <32000> to <192000>, -+ - fsl,output-width: the output width of asrc p2p. which can be <16>, <24>. -+ - fsl,asrc-dma-rx-events: The rx dma event of the asrc, corresponding -+ to 3 pair of asrc. -+ - fsl,asrc-dma-tx-events: The tx dma event of the esai, corresponding -+ to 3 pair of asrc. -+ -+Example: -+asrc_p2p: asrc_p2p { -+ compatible = "fsl,imx6q-asrc-p2p"; -+ fsl,output-rate = <48000>; -+ fsl,output-width = <16>; -+ fsl,asrc-dma-rx-events = <17 18 19>; -+ fsl,asrc-dma-tx-events = <20 21 22>; -+ status = "okay"; -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt linux-3.14.22/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,25 @@ -+Freescale i.MX audio complex with CS42888 codec -+ -+Required properties: -+- compatible : "fsl,imx-audio-cs42888" -+- model : The user-visible name of this sound complex -+- esai-controller : The phandle of the i.MX SSI controller -+- audio-codec : The phandle of the CS42888 audio codec -+ -+Optional properties: -+- asrc-controller : The phandle of the i.MX ASRC controller -+- audio-routing : A list of the connections between audio components. -+ Each entry is a pair of strings, the first being the connection's sink, -+ the second being the connection's source. Valid names could be power -+ supplies, CS42888 pins, and the jacks on the board: -+ -+Example: -+ -+sound { -+ compatible = "fsl,imx6q-sabresd-wm8962", -+ "fsl,imx-audio-wm8962"; -+ model = "cs42888-audio"; -+ esai-controller = <&esai>; -+ asrc-controller = <&asrc_p2p>; -+ audio-codec = <&codec>; -+}; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt linux-3.14.22/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -24,6 +24,12 @@ - Note: The AUDMUX port numbering should start at 1, which is consistent with - hardware manual. - -+Optional properties: -+- hp-det-gpios : The gpio pin to detect plug in/out event that happens to -+ Headphone jack. -+- mic-det-gpios: The gpio pin to detect plug in/out event that happens to -+ Microphone jack. -+ - Example: - - sound { -@@ -43,4 +49,6 @@ - "DMICDAT", "DMIC"; - mux-int-port = <2>; - mux-ext-port = <3>; -+ hp-det-gpios = <&gpio7 8 1>; -+ mic-det-gpios = <&gpio1 9 1>; - }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/sound/wm8962.txt linux-3.14.22/Documentation/devicetree/bindings/sound/wm8962.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/sound/wm8962.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/sound/wm8962.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -13,6 +13,14 @@ - of R51 (Class D Control 2) gets set, indicating that the speaker is - in mono mode. - -+ - amic-mono: This is a boolean property. If present, indicating that the -+ analog micphone is hardware mono input, the driver would enable monomix -+ for it. -+ -+ - dmic-mono: This is a boolean property. If present, indicating that the -+ digital micphone is hardware mono input, the driver would enable monomix -+ for it. -+ - - mic-cfg : Default register value for R48 (Additional Control 4). - If absent, the default should be the register default. - -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/usb/mxs-phy.txt linux-3.14.22/Documentation/devicetree/bindings/usb/mxs-phy.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/usb/mxs-phy.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/devicetree/bindings/usb/mxs-phy.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -1,13 +1,16 @@ - * Freescale MXS USB Phy Device - - Required properties: --- compatible: Should be "fsl,imx23-usbphy" -+- compatible: "fsl,imx23-usbphy" for imx23 and imx28, "fsl,imx6q-usbphy" -+for imx6dq and imx6dl, "fsl,imx6sl-usbphy" for imx6sl - - reg: Should contain registers location and length - - interrupts: Should contain phy interrupt -+- fsl,anatop: phandle for anatop register, it is only for imx6 SoC series - - Example: - usbphy1: usbphy@020c9000 { - compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; - reg = <0x020c9000 0x1000>; - interrupts = <0 44 0x04>; -+ fsl,anatop = <&anatop>; - }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt linux-3.14.22/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,61 @@ -+* Freescale CMOS Sensor Interface (CSI) V4L2 Capture -+ -+Required properties for CSI -+- compatible: "fsl,-csi". Supported chip includes imx6sl -+- reg: Address and length of the register set for CSI -+- interrupts: Should contain CSI interrupts -+ -+Required properties for v4l2_capture -+- compatible: should be "fsl,-csi-v4l2", supported socs include imx6sl -+ -+Required properties for sensor -+- compatible: "," -+ please check the supported sensor in the Supported Sensor fields. -+- reg: sensor I2C slave address -+- pinctrl-names: should be "default" for parallel sensor -+- pinctrl-0: should depend on the connection between sensor and i.MX -+ connection between sensor and i.MX could be only legacy parallel on i.MX6SL -+- clocks: should be the clock source provided to sensor. -+- clock-names: should be "csi_mclk" -+- AVDD-supply: set according to the board. -+- DVDD-supply: set according to the board. -+- pwn-gpios: set according to the board. -+- rst-gpios: set according to the board. -+- csi_id: csi id for v4l2 capture device -+ should be 0 for i.MX6SL -+- mclk: should the value of mclk clock send out the sensor. unit is Hz. -+- mclk_source: should be 0 for i.MX6SL -+ -+Supported Sensor -+- ovti, ov5640 -+ -+Example for CSI: -+ csi: csi@020e4000 { -+ compatible = "fsl,imx6sl-csi"; -+ reg = <0x020e4000 0x4000>; -+ interrupts = <0 7 0x04>; -+ status = "disabled"; -+ }; -+ -+Examples for v4l2_capture: -+ csi_v4l2_cap { -+ compatible = "fsl,imx6q-v4l2-capture"; -+ status = "okay"; -+ }; -+ -+Examples for sensors: -+ ov564x: ov564x@3c { -+ compatible = "ovti,ov564x"; -+ reg = <0x3c>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_csi_0>; -+ clocks = <&clks IMX6SL_CLK_CSI>; -+ clock-names = "csi_mclk"; -+ AVDD-supply = <&vgen6_reg>; /* 2.8v */ -+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/ -+ pwn-gpios = <&gpio1 25 1>; -+ rst-gpios = <&gpio1 26 0>; -+ csi_id = <0>; -+ mclk = <24000000>; -+ mclk_source = <0>; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt linux-3.14.22/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,42 @@ -+* Freescale MIPI CSI2 Controller for i.MX6DQ/i.MX6SDL -+ -+Required properties for mipi csi2 controller: -+- compatible: should be "fsl,imx6q-mipi-csi2" -+- reg: contains mipi csi2 register base address and range -+- interrupts: where type is a interrupt type, num is the -+ interrupt number and flag is a field that level/trigger information for -+ the interrupt. -+- clocks: the clock sources that mipi csi2 depends on. -+- clock-names: the name is related to the clock source one by one. -+- status: should be set to "disable". -+ -+Required properties for mipi csi2 on specified board: -+- ipu_id: ipu id which mipi csi2 connected to. -+ should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL -+- csi_id: csi id which mipi csi2 connected to. -+ should be 0 or 1 for i.MX6DQ/i.MX6SDL -+- v_channel: virtual channel which send to MIPI CSI2 controller -+ should keep consistent with the input MIPI signal. -+- lanes: data lanes of input MIPI signal. The maximum data lanes is 4. -+ should keep consistent with the input MIPI signal. -+- status: should be set to "okay". -+ -+Examples: -+for SOC imx6qdl.dtsi: -+ mipi_csi@021dc000 { -+ compatible = "fsl,imx6q-mipi-csi2"; -+ reg = <0x021dc000 0x4000>; -+ interrupts = <0 100 0x04>, <0 101 0x04>; -+ clocks = <&clks 138>, <&clks 53>, <&clks 204>; -+ clock-names = "dphy_clk", "pixel_clk", "cfg_clk"; -+ status = "disabled"; -+ }; -+ -+for board imx6qdl-sabresd.dtsi: -+ mipi_csi@021dc000 { -+ status = "okay"; -+ ipu_id = <0>; -+ csi_id = <1>; -+ v_channel = <0>; -+ lanes = <2>; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,pxp.txt linux-3.14.22/Documentation/devicetree/bindings/video/fsl,pxp.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,pxp.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/video/fsl,pxp.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,30 @@ -+* Freescale PxP Controller for i.MX6DL, i.MX6SL -+ -+Required properties for PxP controller: -+- compatible: should be "fsl,-pxp-dma" -+- reg: contains pxp register base address and range -+- interrupts: where type is an interrupt type, num is the -+ interrupt number and flag is a field that level/trigger information for -+ the interrupt. -+- clocks: the clock sources that pxp depends on. -+- clock-names: the name is related to the clock source -+ -+Required properties for pxp on specified board: -+- status: should be set to "okay" if want to use PxP -+ -+Examples: -+for SOC imx6dl.dtsi: -+ pxp@020f0000 { -+ compatible = "fsl,imx6dl-pxp-dma"; -+ reg = <0x020f0000 0x4000>; -+ interrupts = <0 98 0x04>; -+ clocks = <&clks 133>; -+ clock-names = "pxp-axi"; -+ status = "disabled"; -+ }; -+ -+ -+for board imx6dl-sabresd.dts: -+ &pxp { -+ status = "okay"; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt linux-3.14.22/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,102 @@ -+* Freescale V4L2 Capture for i.MX6DQ/i.MX6SDL -+ -+Required board properties for IPUv3 capture: -+- clocks: should include the clock provided by i.MX6 to sensor -+- clock-names: sensor clock's name should be "ipux_csiy" -+ x should be 1 or 2 for i.MX6DQ; should be 1 for i.MX6SDL -+ y is 0 or 1 for i.MX6DQ/i.MX6SDL -+Note: other detailed information for IPUv3, please refer to -+Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt -+ -+Required properties for v4l2_capture -+- compatible: should be "fsl,imx6q-v4l2-capture" -+- ipu_id: ipu id for v4l2 capture device -+ should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL -+- csi_id: csi id for v4l2 capture device -+ should be 0 or 1 for i.MX6DQ/i.MX6SDL -+- mclk_source: should be 0 or 1. two mclk sources at most now -+- status: should be set to "okay" to enable this device -+ -+Required properties for sensor -+- compatible: "," -+ please check the supported sensor in the Supported Sensor fields. -+- reg: sensor I2C slave address -+- pinctrl-names: should be "default" for parallel sensor -+- pinctrl-0: should depend on the connection between sensor and i.MX -+ connection between sensor and i.MX could be MIPI-CSI2 or legacy parallel -+- clocks: should be the clock source provided to sensor. -+- clock-names: should be "csi_mclk" -+- DOVDD-supply: set according to the board. -+- AVDD-supply: set according to the board. -+- DVDD-supply: set according to the board. -+- pwn-gpios: set according to the board. -+- rst-gpios: set according to the board. -+- csi_id: csi id for v4l2 capture device -+ should be 0 or 1 for i.MX6DQ/i.MX6SDL. -+- mclk: should the value of mclk clock send out the sensor. unit is Hz. -+- mclk_source: should be 0 or 1 and should be the same as the setting in -+ v4l2_capture. -+- cvbs: 1 for CVBS input, 0 YPbPr input. This property is only needed for -+ adv7180 tv decoder. -+ -+Supported Sensor -+- ov5640 -+- ov5642 -+- ov5640_mipi -+- adv7180 -+ -+ -+Example for IPUv3 including capture settings on imx6q-sabresd.dts: -+ ipu1: ipu@02400000 { /* IPU1 */ -+ compatible = "fsl,imx6q-ipuv3"; -+ reg = <0x02400000 0x400000>; -+ interrupts = <0 5 0x04>, < 0 6 0x04>; -+ clocks = <&clks 130>, <&clks 131>, <&clks 132>, <&clks 39>, <&clks 40>, <&clks 169>; -+ clock-names = "ipu1", "ipu1_di0", "ipu1_di1", "ipu1_di0_sel", "ipu1_di1_sel", "ipu1_csi0"; -+ status = "disabled"; -+ }; -+ -+Examples for v4l2_capture: -+ v4l2_cap { -+ compatible = "fsl,imx6q-v4l2-capture"; -+ ipu_id = <0>; -+ csi_id = <0>; -+ mclk_source = <0>; -+ status = "okay"; -+ }; -+ -+Examples for sensors: -+ ov5642: ov5642@3c { -+ compatible = "ovti,ov5642"; -+ reg = <0x3c>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ipu1_2>; -+ clocks = <&clks 201>; -+ clock-names = "csi_mclk"; -+ DOVDD-supply = <&vgen4_reg>; /* 1.8v */ -+ AVDD-supply = <&vgen3_reg>; /* 2.8v, on rev C board is VGEN3 */ -+ DVDD-supply = <&vgen2_reg>; /* 1.5v*/ -+ pwn-gpios = <&gpio1 16 1>; /* active low: SD1_DAT0 */ -+ rst-gpios = <&gpio1 17 0>; /* active high: SD1_DAT1 */ -+ csi_id = <0>; -+ mclk = <24000000>; -+ mclk_source = <0>; -+ }; -+ -+ adv7180: adv7180@21 { -+ compatible = "adv,adv7180"; -+ reg = <0x21>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_ipu1_3>; -+ clocks = <&clks 201>; -+ clock-names = "csi_mclk"; -+ DOVDD-supply = <®_3p3v>; /* 3.3v, enabled via 2.8 VGEN6 */ -+ AVDD-supply = <®_3p3v>; /* 1.8v */ -+ DVDD-supply = <®_3p3v>; /* 1.8v */ -+ PVDD-supply = <®_3p3v>; /* 1.8v */ -+ pwn-gpios = <&max7310_b 2 0>; -+ csi_id = <0>; -+ mclk = <24000000>; -+ mclk_source = <0>; -+ cvbs = <1>; -+ }; -diff -Nur linux-3.14.22.orig/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt linux-3.14.22/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt ---- linux-3.14.22.orig/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -0,0 +1,20 @@ -+Device-Tree bindings for hdmi video driver -+ -+Required properties: -+- compatible: value should be "fsl,imx6q-hdmi-video". -+- fsl,hdcp: define the property in dts, hdmi driver will initalize for hdcp, -+ otherwise hdcp function will not supported. -+- fsl,phy_reg_vlev: hdmi phy register,Voltage Level Control Register offset 0x0e, -+ adjust hdmi phy signal voltage level. -+- fsl,phy_reg_cksymtx: hdmi phy register, clock symbol and transmitter control -+ register offset 0x09, adjust hdmi signal pre-emphasis. -+ -+Example: -+ -+ hdmi_video { -+ compatible = "fsl,imx6q-hdmi-video"; -+ fsl,hdcp; -+ fsl,phy_reg_vlev = <0x0294>; -+ fsl,phy_reg_cksymtx = <0x800d>; -+ }; -+ -diff -Nur linux-3.14.22.orig/Documentation/filesystems/hfsplus.txt linux-3.14.22/Documentation/filesystems/hfsplus.txt ---- linux-3.14.22.orig/Documentation/filesystems/hfsplus.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/filesystems/hfsplus.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -56,4 +56,4 @@ - - kernel source: - --Apple Technote 1150 http://developer.apple.com/technotes/tn/tn1150.html -+Apple Technote 1150 https://developer.apple.com/legacy/library/technotes/tn/tn1150.html -diff -Nur linux-3.14.22.orig/Documentation/kernel-parameters.txt linux-3.14.22/Documentation/kernel-parameters.txt ---- linux-3.14.22.orig/Documentation/kernel-parameters.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/kernel-parameters.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -603,8 +603,11 @@ - Also note the kernel might malfunction if you disable - some critical bits. - -- cma=nn[MG] [ARM,KNL] -- Sets the size of kernel global memory area for contiguous -+ cma=nn[MG]@[start[MG][-end[MG]]] -+ [ARM,X86,KNL] -+ Sets the size of kernel global memory area for -+ contiguous memory allocations and optionally the -+ placement constraint by the physical address range of - memory allocations. For more information, see - include/linux/dma-contiguous.h - -diff -Nur linux-3.14.22.orig/Documentation/networking/gianfar.txt linux-3.14.22/Documentation/networking/gianfar.txt ---- linux-3.14.22.orig/Documentation/networking/gianfar.txt 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/Documentation/networking/gianfar.txt 2014-10-22 14:55:51.994220001 -0500 -@@ -1,38 +1,8 @@ - The Gianfar Ethernet Driver --Sysfs File description - - Author: Andy Fleming - Updated: 2005-07-28 - --SYSFS -- --Several of the features of the gianfar driver are controlled --through sysfs files. These are: -- --bd_stash: --To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to --bd_stash, echo 'off' or '0' to disable -- --rx_stash_len: --To stash the first n bytes of the packet in L2, echo the number --of bytes to buf_stash_len. echo 0 to disable. -- --WARNING: You could really screw these up if you set them too low or high! --fifo_threshold: --To change the number of bytes the controller needs in the --fifo before it starts transmission, echo the number of bytes to --fifo_thresh. Range should be 0-511. -- --fifo_starve: --When the FIFO has less than this many bytes during a transmit, it --enters starve mode, and increases the priority of TX memory --transactions. To change, echo the number of bytes to --fifo_starve. Range should be 0-511. -- --fifo_starve_off: --Once in starve mode, the FIFO remains there until it has this --many bytes. To change, echo the number of bytes to --fifo_starve_off. Range should be 0-511. - - CHECKSUM OFFLOADING - -diff -Nur linux-3.14.22.orig/drivers/ata/acard-ahci.c linux-3.14.22/drivers/ata/acard-ahci.c ---- linux-3.14.22.orig/drivers/ata/acard-ahci.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/acard-ahci.c 2014-10-22 14:55:51.994220001 -0500 -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/ahci.c linux-3.14.22/drivers/ata/ahci.c ---- linux-3.14.22.orig/drivers/ata/ahci.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/ahci.c 2014-10-22 14:55:51.998220001 -0500 -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -593,6 +592,7 @@ - unsigned long deadline) - { - struct ata_port *ap = link->ap; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - bool online; - int rc; - -@@ -603,7 +603,7 @@ - rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), - deadline, &online, NULL); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); - -@@ -618,6 +618,7 @@ - { - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -633,7 +634,7 @@ - rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), - deadline, &online, NULL); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* The pseudo configuration device on SIMG4726 attached to - * ASUS P5W-DH Deluxe doesn't send signature FIS after -@@ -1129,6 +1130,17 @@ - return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); - } - -+static bool ahci_broken_devslp(struct pci_dev *pdev) -+{ -+ /* device with broken DEVSLP but still showing SDS capability */ -+ static const struct pci_device_id ids[] = { -+ { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ -+ {} -+ }; -+ -+ return pci_match_id(ids, pdev); -+} -+ - #ifdef CONFIG_ATA_ACPI - static void ahci_gtf_filter_workaround(struct ata_host *host) - { -@@ -1380,6 +1392,10 @@ - - hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; - -+ /* must set flag prior to save config in order to take effect */ -+ if (ahci_broken_devslp(pdev)) -+ hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; -+ - /* save initial config */ - ahci_pci_save_initial_config(pdev, hpriv); - -diff -Nur linux-3.14.22.orig/drivers/ata/ahci.h linux-3.14.22/drivers/ata/ahci.h ---- linux-3.14.22.orig/drivers/ata/ahci.h 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/ahci.h 2014-10-22 14:55:51.998220001 -0500 -@@ -37,6 +37,8 @@ - - #include - #include -+#include -+#include - - /* Enclosure Management Control */ - #define EM_CTRL_MSG_TYPE 0x000f0000 -@@ -51,6 +53,7 @@ - - enum { - AHCI_MAX_PORTS = 32, -+ AHCI_MAX_CLKS = 3, - AHCI_MAX_SG = 168, /* hardware max is 64K */ - AHCI_DMA_BOUNDARY = 0xffffffff, - AHCI_MAX_CMDS = 32, -@@ -233,6 +236,8 @@ - port start (wait until - error-handling stage) */ - AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */ -+ AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */ -+ AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */ - - /* ap->flags bits */ - -@@ -322,8 +327,17 @@ - u32 em_loc; /* enclosure management location */ - u32 em_buf_sz; /* EM buffer size in byte */ - u32 em_msg_type; /* EM message type */ -- struct clk *clk; /* Only for platforms supporting clk */ -+ bool got_runtime_pm; /* Did we do pm_runtime_get? */ -+ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ -+ struct regulator *target_pwr; /* Optional */ -+ struct phy *phy; /* If platform uses phy */ - void *plat_data; /* Other platform data */ -+ /* -+ * Optional ahci_start_engine override, if not set this gets set to the -+ * default ahci_start_engine during ahci_save_initial_config, this can -+ * be overridden anytime before the host is activated. -+ */ -+ void (*start_engine)(struct ata_port *ap); - }; - - extern int ahci_ignore_sss; -diff -Nur linux-3.14.22.orig/drivers/ata/ahci_imx.c linux-3.14.22/drivers/ata/ahci_imx.c ---- linux-3.14.22.orig/drivers/ata/ahci_imx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/ahci_imx.c 2014-10-22 14:55:51.998220001 -0500 -@@ -26,12 +26,29 @@ - #include - #include - #include -+#include - #include "ahci.h" - - enum { -- PORT_PHY_CTL = 0x178, /* Port0 PHY Control */ -- PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */ -- HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ -+ /* Timer 1-ms Register */ -+ IMX_TIMER1MS = 0x00e0, -+ /* Port0 PHY Control Register */ -+ IMX_P0PHYCR = 0x0178, -+ IMX_P0PHYCR_TEST_PDDQ = 1 << 20, -+ IMX_P0PHYCR_CR_READ = 1 << 19, -+ IMX_P0PHYCR_CR_WRITE = 1 << 18, -+ IMX_P0PHYCR_CR_CAP_DATA = 1 << 17, -+ IMX_P0PHYCR_CR_CAP_ADDR = 1 << 16, -+ /* Port0 PHY Status Register */ -+ IMX_P0PHYSR = 0x017c, -+ IMX_P0PHYSR_CR_ACK = 1 << 18, -+ IMX_P0PHYSR_CR_DATA_OUT = 0xffff << 0, -+ /* Lane0 Output Status Register */ -+ IMX_LANE0_OUT_STAT = 0x2003, -+ IMX_LANE0_OUT_STAT_RX_PLL_STATE = 1 << 1, -+ /* Clock Reset Register */ -+ IMX_CLOCK_RESET = 0x7f3f, -+ IMX_CLOCK_RESET_RESET = 1 << 0, - }; - - enum ahci_imx_type { -@@ -42,62 +59,230 @@ - struct imx_ahci_priv { - struct platform_device *ahci_pdev; - enum ahci_imx_type type; -- -- /* i.MX53 clock */ -- struct clk *sata_gate_clk; -- /* Common clock */ -- struct clk *sata_ref_clk; - struct clk *ahb_clk; -- - struct regmap *gpr; - bool no_device; - bool first_time; -+ u32 phy_params; - }; - - static int ahci_imx_hotplug; - module_param_named(hotplug, ahci_imx_hotplug, int, 0644); - MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); - --static int imx_sata_clock_enable(struct device *dev) -+static void ahci_imx_host_stop(struct ata_host *host); -+ -+static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert) -+{ -+ int timeout = 10; -+ u32 crval; -+ u32 srval; -+ -+ /* Assert or deassert the bit */ -+ crval = readl(mmio + IMX_P0PHYCR); -+ if (assert) -+ crval |= bit; -+ else -+ crval &= ~bit; -+ writel(crval, mmio + IMX_P0PHYCR); -+ -+ /* Wait for the cr_ack signal */ -+ do { -+ srval = readl(mmio + IMX_P0PHYSR); -+ if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK) -+ break; -+ usleep_range(100, 200); -+ } while (--timeout); -+ -+ return timeout ? 0 : -ETIMEDOUT; -+} -+ -+static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio) - { -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); -+ u32 crval = addr; - int ret; - -- if (imxpriv->type == AHCI_IMX53) { -- ret = clk_prepare_enable(imxpriv->sata_gate_clk); -- if (ret < 0) { -- dev_err(dev, "prepare-enable sata_gate clock err:%d\n", -- ret); -- return ret; -- } -+ /* Supply the address on cr_data_in */ -+ writel(crval, mmio + IMX_P0PHYCR); -+ -+ /* Assert the cr_cap_addr signal */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true); -+ if (ret) -+ return ret; -+ -+ /* Deassert cr_cap_addr */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int imx_phy_reg_write(u16 val, void __iomem *mmio) -+{ -+ u32 crval = val; -+ int ret; -+ -+ /* Supply the data on cr_data_in */ -+ writel(crval, mmio + IMX_P0PHYCR); -+ -+ /* Assert the cr_cap_data signal */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true); -+ if (ret) -+ return ret; -+ -+ /* Deassert cr_cap_data */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false); -+ if (ret) -+ return ret; -+ -+ if (val & IMX_CLOCK_RESET_RESET) { -+ /* -+ * In case we're resetting the phy, it's unable to acknowledge, -+ * so we return immediately here. -+ */ -+ crval |= IMX_P0PHYCR_CR_WRITE; -+ writel(crval, mmio + IMX_P0PHYCR); -+ goto out; - } - -- ret = clk_prepare_enable(imxpriv->sata_ref_clk); -- if (ret < 0) { -- dev_err(dev, "prepare-enable sata_ref clock err:%d\n", -- ret); -- goto clk_err; -+ /* Assert the cr_write signal */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true); -+ if (ret) -+ return ret; -+ -+ /* Deassert cr_write */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false); -+ if (ret) -+ return ret; -+ -+out: -+ return 0; -+} -+ -+static int imx_phy_reg_read(u16 *val, void __iomem *mmio) -+{ -+ int ret; -+ -+ /* Assert the cr_read signal */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true); -+ if (ret) -+ return ret; -+ -+ /* Capture the data from cr_data_out[] */ -+ *val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT; -+ -+ /* Deassert cr_read */ -+ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ -+static int imx_sata_phy_reset(struct ahci_host_priv *hpriv) -+{ -+ void __iomem *mmio = hpriv->mmio; -+ int timeout = 10; -+ u16 val; -+ int ret; -+ -+ /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */ -+ ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio); -+ if (ret) -+ return ret; -+ ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio); -+ if (ret) -+ return ret; -+ -+ /* Wait for PHY RX_PLL to be stable */ -+ do { -+ usleep_range(100, 200); -+ ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio); -+ if (ret) -+ return ret; -+ ret = imx_phy_reg_read(&val, mmio); -+ if (ret) -+ return ret; -+ if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE) -+ break; -+ } while (--timeout); -+ -+ return timeout ? 0 : -ETIMEDOUT; -+} -+ -+static int imx_sata_enable(struct ahci_host_priv *hpriv) -+{ -+ struct imx_ahci_priv *imxpriv = hpriv->plat_data; -+ struct device *dev = &imxpriv->ahci_pdev->dev; -+ int ret; -+ -+ if (imxpriv->no_device) -+ return 0; -+ -+ if (hpriv->target_pwr) { -+ ret = regulator_enable(hpriv->target_pwr); -+ if (ret) -+ return ret; - } - -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ ret = ahci_platform_enable_clks(hpriv); -+ if (ret < 0) -+ goto disable_regulator; -+ - if (imxpriv->type == AHCI_IMX6Q) { -+ /* -+ * set PHY Paremeters, two steps to configure the GPR13, -+ * one write for rest of parameters, mask of first write -+ * is 0x07ffffff, and the other one write for setting -+ * the mpll_clk_en. -+ */ -+ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, -+ IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | -+ IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | -+ IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | -+ IMX6Q_GPR13_SATA_SPD_MODE_MASK | -+ IMX6Q_GPR13_SATA_MPLL_SS_EN | -+ IMX6Q_GPR13_SATA_TX_ATTEN_MASK | -+ IMX6Q_GPR13_SATA_TX_BOOST_MASK | -+ IMX6Q_GPR13_SATA_TX_LVL_MASK | -+ IMX6Q_GPR13_SATA_MPLL_CLK_EN | -+ IMX6Q_GPR13_SATA_TX_EDGE_RATE, -+ imxpriv->phy_params); - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - IMX6Q_GPR13_SATA_MPLL_CLK_EN); -+ -+ usleep_range(100, 200); -+ -+ ret = imx_sata_phy_reset(hpriv); -+ if (ret) { -+ dev_err(dev, "failed to reset phy: %d\n", ret); -+ goto disable_regulator; -+ } - } - - usleep_range(1000, 2000); - - return 0; - --clk_err: -- if (imxpriv->type == AHCI_IMX53) -- clk_disable_unprepare(imxpriv->sata_gate_clk); -+disable_regulator: -+ release_bus_freq(BUS_FREQ_HIGH); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+ - return ret; - } - --static void imx_sata_clock_disable(struct device *dev) -+static void imx_sata_disable(struct ahci_host_priv *hpriv) - { -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); -+ struct imx_ahci_priv *imxpriv = hpriv->plat_data; -+ -+ if (imxpriv->no_device) -+ return; - - if (imxpriv->type == AHCI_IMX6Q) { - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, -@@ -105,10 +290,12 @@ - !IMX6Q_GPR13_SATA_MPLL_CLK_EN); - } - -- clk_disable_unprepare(imxpriv->sata_ref_clk); -+ ahci_platform_disable_clks(hpriv); - -- if (imxpriv->type == AHCI_IMX53) -- clk_disable_unprepare(imxpriv->sata_gate_clk); -+ release_bus_freq(BUS_FREQ_HIGH); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); - } - - static void ahci_imx_error_handler(struct ata_port *ap) -@@ -118,7 +305,7 @@ - struct ata_host *host = dev_get_drvdata(ap->dev); - struct ahci_host_priv *hpriv = host->private_data; - void __iomem *mmio = hpriv->mmio; -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); -+ struct imx_ahci_priv *imxpriv = hpriv->plat_data; - - ahci_error_handler(ap); - -@@ -134,17 +321,23 @@ - * without full reset once the pddq mode is enabled making it - * impossible to use as part of libata LPM. - */ -- reg_val = readl(mmio + PORT_PHY_CTL); -- writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); -- imx_sata_clock_disable(ap->dev); -+ reg_val = readl(mmio + IMX_P0PHYCR); -+ writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR); -+ imx_sata_disable(hpriv); - imxpriv->no_device = true; -+ -+ dev_info(ap->dev, "no device found, disabling link.\n"); -+ dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX -+ ".hotplug=1 to enable hotplug\n"); - } - - static int ahci_imx_softreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) - { - struct ata_port *ap = link->ap; -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); -+ struct ata_host *host = dev_get_drvdata(ap->dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ struct imx_ahci_priv *imxpriv = hpriv->plat_data; - int ret = -EIO; - - if (imxpriv->type == AHCI_IMX53) -@@ -156,7 +349,8 @@ - } - - static struct ata_port_operations ahci_imx_ops = { -- .inherits = &ahci_platform_ops, -+ .inherits = &ahci_ops, -+ .host_stop = ahci_imx_host_stop, - .error_handler = ahci_imx_error_handler, - .softreset = ahci_imx_softreset, - }; -@@ -168,234 +362,306 @@ - .port_ops = &ahci_imx_ops, - }; - --static int imx_sata_init(struct device *dev, void __iomem *mmio) --{ -- int ret = 0; -- unsigned int reg_val; -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); -- -- ret = imx_sata_clock_enable(dev); -- if (ret < 0) -- return ret; -+static const struct of_device_id imx_ahci_of_match[] = { -+ { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, -+ { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, imx_ahci_of_match); - -- /* -- * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, -- * and IP vendor specific register HOST_TIMER1MS. -- * Configure CAP_SSS (support stagered spin up). -- * Implement the port0. -- * Get the ahb clock rate, and configure the TIMER1MS register. -- */ -- reg_val = readl(mmio + HOST_CAP); -- if (!(reg_val & HOST_CAP_SSS)) { -- reg_val |= HOST_CAP_SSS; -- writel(reg_val, mmio + HOST_CAP); -- } -- reg_val = readl(mmio + HOST_PORTS_IMPL); -- if (!(reg_val & 0x1)) { -- reg_val |= 0x1; -- writel(reg_val, mmio + HOST_PORTS_IMPL); -- } -+struct reg_value { -+ u32 of_value; -+ u32 reg_value; -+}; - -- reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; -- writel(reg_val, mmio + HOST_TIMER1MS); -+struct reg_property { -+ const char *name; -+ const struct reg_value *values; -+ size_t num_values; -+ u32 def_value; -+ u32 set_value; -+}; - -- return 0; --} -+static const struct reg_value gpr13_tx_level[] = { -+ { 937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V }, -+ { 947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V }, -+ { 957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V }, -+ { 966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V }, -+ { 976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V }, -+ { 986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V }, -+ { 996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V }, -+ { 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V }, -+ { 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V }, -+ { 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V }, -+ { 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V }, -+ { 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V }, -+ { 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V }, -+ { 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V }, -+ { 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V }, -+ { 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V }, -+ { 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V }, -+ { 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V }, -+ { 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V }, -+ { 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V }, -+ { 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V }, -+ { 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V }, -+ { 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V }, -+ { 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V }, -+ { 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V }, -+ { 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V }, -+ { 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V }, -+ { 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V }, -+ { 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V }, -+ { 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V }, -+ { 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V }, -+ { 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V } -+}; - --static void imx_sata_exit(struct device *dev) --{ -- imx_sata_clock_disable(dev); --} -+static const struct reg_value gpr13_tx_boost[] = { -+ { 0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB }, -+ { 370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB }, -+ { 740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB }, -+ { 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB }, -+ { 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB }, -+ { 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB }, -+ { 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB }, -+ { 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB }, -+ { 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB }, -+ { 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB }, -+ { 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB }, -+ { 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB }, -+ { 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB }, -+ { 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB }, -+ { 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB }, -+ { 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB } -+}; - --static int imx_ahci_suspend(struct device *dev) --{ -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); -+static const struct reg_value gpr13_tx_atten[] = { -+ { 8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 }, -+ { 9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 }, -+ { 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 }, -+ { 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 }, -+ { 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 }, -+ { 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 }, -+}; - -- /* -- * If no_device is set, The CLKs had been gated off in the -- * initialization so don't do it again here. -- */ -- if (!imxpriv->no_device) -- imx_sata_clock_disable(dev); -+static const struct reg_value gpr13_rx_eq[] = { -+ { 500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB }, -+ { 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB }, -+ { 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB }, -+ { 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB }, -+ { 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB }, -+ { 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB }, -+ { 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB }, -+ { 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB }, -+}; - -- return 0; --} -+static const struct reg_property gpr13_props[] = { -+ { -+ .name = "fsl,transmit-level-mV", -+ .values = gpr13_tx_level, -+ .num_values = ARRAY_SIZE(gpr13_tx_level), -+ .def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V, -+ }, { -+ .name = "fsl,transmit-boost-mdB", -+ .values = gpr13_tx_boost, -+ .num_values = ARRAY_SIZE(gpr13_tx_boost), -+ .def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB, -+ }, { -+ .name = "fsl,transmit-atten-16ths", -+ .values = gpr13_tx_atten, -+ .num_values = ARRAY_SIZE(gpr13_tx_atten), -+ .def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16, -+ }, { -+ .name = "fsl,receive-eq-mdB", -+ .values = gpr13_rx_eq, -+ .num_values = ARRAY_SIZE(gpr13_rx_eq), -+ .def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB, -+ }, { -+ .name = "fsl,no-spread-spectrum", -+ .def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN, -+ .set_value = 0, -+ }, -+}; - --static int imx_ahci_resume(struct device *dev) -+static u32 imx_ahci_parse_props(struct device *dev, -+ const struct reg_property *prop, size_t num) - { -- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); -- int ret = 0; -- -- if (!imxpriv->no_device) -- ret = imx_sata_clock_enable(dev); -+ struct device_node *np = dev->of_node; -+ u32 reg_value = 0; -+ int i, j; -+ -+ for (i = 0; i < num; i++, prop++) { -+ u32 of_val; -+ -+ if (prop->num_values == 0) { -+ if (of_property_read_bool(np, prop->name)) -+ reg_value |= prop->set_value; -+ else -+ reg_value |= prop->def_value; -+ continue; -+ } - -- return ret; --} -+ if (of_property_read_u32(np, prop->name, &of_val)) { -+ dev_info(dev, "%s not specified, using %08x\n", -+ prop->name, prop->def_value); -+ reg_value |= prop->def_value; -+ continue; -+ } - --static struct ahci_platform_data imx_sata_pdata = { -- .init = imx_sata_init, -- .exit = imx_sata_exit, -- .ata_port_info = &ahci_imx_port_info, -- .suspend = imx_ahci_suspend, -- .resume = imx_ahci_resume, -+ for (j = 0; j < prop->num_values; j++) { -+ if (prop->values[j].of_value == of_val) { -+ dev_info(dev, "%s value %u, using %08x\n", -+ prop->name, of_val, prop->values[j].reg_value); -+ reg_value |= prop->values[j].reg_value; -+ break; -+ } -+ } - --}; -+ if (j == prop->num_values) { -+ dev_err(dev, "DT property %s is not a valid value\n", -+ prop->name); -+ reg_value |= prop->def_value; -+ } -+ } - --static const struct of_device_id imx_ahci_of_match[] = { -- { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, -- { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, -- {}, --}; --MODULE_DEVICE_TABLE(of, imx_ahci_of_match); -+ return reg_value; -+} - - static int imx_ahci_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; -- struct resource *mem, *irq, res[2]; - const struct of_device_id *of_id; -- enum ahci_imx_type type; -- const struct ahci_platform_data *pdata = NULL; -+ struct ahci_host_priv *hpriv; - struct imx_ahci_priv *imxpriv; -- struct device *ahci_dev; -- struct platform_device *ahci_pdev; -+ unsigned int reg_val; - int ret; - - of_id = of_match_device(imx_ahci_of_match, dev); - if (!of_id) - return -EINVAL; - -- type = (enum ahci_imx_type)of_id->data; -- pdata = &imx_sata_pdata; -- - imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); -- if (!imxpriv) { -- dev_err(dev, "can't alloc ahci_host_priv\n"); -+ if (!imxpriv) - return -ENOMEM; -- } -- -- ahci_pdev = platform_device_alloc("ahci", -1); -- if (!ahci_pdev) -- return -ENODEV; -- -- ahci_dev = &ahci_pdev->dev; -- ahci_dev->parent = dev; - -+ imxpriv->ahci_pdev = pdev; - imxpriv->no_device = false; - imxpriv->first_time = true; -- imxpriv->type = type; -- -+ imxpriv->type = (enum ahci_imx_type)of_id->data; - imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(imxpriv->ahb_clk)) { - dev_err(dev, "can't get ahb clock.\n"); -- ret = PTR_ERR(imxpriv->ahb_clk); -- goto err_out; -- } -- -- if (type == AHCI_IMX53) { -- imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate"); -- if (IS_ERR(imxpriv->sata_gate_clk)) { -- dev_err(dev, "can't get sata_gate clock.\n"); -- ret = PTR_ERR(imxpriv->sata_gate_clk); -- goto err_out; -- } -- } -- -- imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); -- if (IS_ERR(imxpriv->sata_ref_clk)) { -- dev_err(dev, "can't get sata_ref clock.\n"); -- ret = PTR_ERR(imxpriv->sata_ref_clk); -- goto err_out; -+ return PTR_ERR(imxpriv->ahb_clk); - } - -- imxpriv->ahci_pdev = ahci_pdev; -- platform_set_drvdata(pdev, imxpriv); -- -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -- if (!mem || !irq) { -- dev_err(dev, "no mmio/irq resource\n"); -- ret = -ENOMEM; -- goto err_out; -- } -- -- res[0] = *mem; -- res[1] = *irq; -- -- ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32); -- ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; -- ahci_dev->of_node = dev->of_node; -+ if (imxpriv->type == AHCI_IMX6Q) { -+ u32 reg_value; - -- if (type == AHCI_IMX6Q) { - imxpriv->gpr = syscon_regmap_lookup_by_compatible( - "fsl,imx6q-iomuxc-gpr"); - if (IS_ERR(imxpriv->gpr)) { - dev_err(dev, - "failed to find fsl,imx6q-iomux-gpr regmap\n"); -- ret = PTR_ERR(imxpriv->gpr); -- goto err_out; -+ return PTR_ERR(imxpriv->gpr); - } - -- /* -- * Set PHY Paremeters, two steps to configure the GPR13, -- * one write for rest of parameters, mask of first write -- * is 0x07fffffe, and the other one write for setting -- * the mpll_clk_en happens in imx_sata_clock_enable(). -- */ -- regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, -- IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | -- IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | -- IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | -- IMX6Q_GPR13_SATA_SPD_MODE_MASK | -- IMX6Q_GPR13_SATA_MPLL_SS_EN | -- IMX6Q_GPR13_SATA_TX_ATTEN_MASK | -- IMX6Q_GPR13_SATA_TX_BOOST_MASK | -- IMX6Q_GPR13_SATA_TX_LVL_MASK | -- IMX6Q_GPR13_SATA_MPLL_CLK_EN | -- IMX6Q_GPR13_SATA_TX_EDGE_RATE, -- IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | -+ reg_value = imx_ahci_parse_props(dev, gpr13_props, -+ ARRAY_SIZE(gpr13_props)); -+ -+ imxpriv->phy_params = - IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | - IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | - IMX6Q_GPR13_SATA_SPD_MODE_3P0G | -- IMX6Q_GPR13_SATA_MPLL_SS_EN | -- IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | -- IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | -- IMX6Q_GPR13_SATA_TX_LVL_1_025_V); -+ reg_value; - } - -- ret = platform_device_add_resources(ahci_pdev, res, 2); -+ hpriv = ahci_platform_get_resources(pdev); -+ if (IS_ERR(hpriv)) -+ return PTR_ERR(hpriv); -+ -+ hpriv->plat_data = imxpriv; -+ -+ ret = imx_sata_enable(hpriv); - if (ret) -- goto err_out; -+ return ret; - -- ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata)); -+ /* -+ * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, -+ * and IP vendor specific register IMX_TIMER1MS. -+ * Configure CAP_SSS (support stagered spin up). -+ * Implement the port0. -+ * Get the ahb clock rate, and configure the TIMER1MS register. -+ */ -+ reg_val = readl(hpriv->mmio + HOST_CAP); -+ if (!(reg_val & HOST_CAP_SSS)) { -+ reg_val |= HOST_CAP_SSS; -+ writel(reg_val, hpriv->mmio + HOST_CAP); -+ } -+ reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL); -+ if (!(reg_val & 0x1)) { -+ reg_val |= 0x1; -+ writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL); -+ } -+ -+ reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; -+ writel(reg_val, hpriv->mmio + IMX_TIMER1MS); -+ -+ ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, -+ 0, 0, 0); - if (ret) -- goto err_out; -+ imx_sata_disable(hpriv); -+ -+ return ret; -+} - -- ret = platform_device_add(ahci_pdev); -- if (ret) { --err_out: -- platform_device_put(ahci_pdev); -+static void ahci_imx_host_stop(struct ata_host *host) -+{ -+ struct ahci_host_priv *hpriv = host->private_data; -+ -+ imx_sata_disable(hpriv); -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int imx_ahci_suspend(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int ret; -+ -+ ret = ahci_platform_suspend_host(dev); -+ if (ret) - return ret; -- } -+ -+ imx_sata_disable(hpriv); - - return 0; - } - --static int imx_ahci_remove(struct platform_device *pdev) -+static int imx_ahci_resume(struct device *dev) - { -- struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev); -- struct platform_device *ahci_pdev = imxpriv->ahci_pdev; -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int ret; - -- platform_device_unregister(ahci_pdev); -- return 0; -+ ret = imx_sata_enable(hpriv); -+ if (ret) -+ return ret; -+ -+ return ahci_platform_resume_host(dev); - } -+#endif -+ -+static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); - - static struct platform_driver imx_ahci_driver = { - .probe = imx_ahci_probe, -- .remove = imx_ahci_remove, -+ .remove = ata_platform_remove_one, - .driver = { - .name = "ahci-imx", - .owner = THIS_MODULE, - .of_match_table = imx_ahci_of_match, -+ .pm = &ahci_imx_pm_ops, - }, - }; - module_platform_driver(imx_ahci_driver); -diff -Nur linux-3.14.22.orig/drivers/ata/ahci_platform.c linux-3.14.22/drivers/ata/ahci_platform.c ---- linux-3.14.22.orig/drivers/ata/ahci_platform.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/ahci_platform.c 2014-10-22 14:55:51.998220001 -0500 -@@ -12,135 +12,36 @@ - * any later version. - */ - --#include - #include --#include - #include - #include --#include --#include - #include - #include - #include - #include - #include "ahci.h" - --static void ahci_host_stop(struct ata_host *host); -- --enum ahci_type { -- AHCI, /* standard platform ahci */ -- IMX53_AHCI, /* ahci on i.mx53 */ -- STRICT_AHCI, /* delayed DMA engine start */ --}; -- --static struct platform_device_id ahci_devtype[] = { -- { -- .name = "ahci", -- .driver_data = AHCI, -- }, { -- .name = "imx53-ahci", -- .driver_data = IMX53_AHCI, -- }, { -- .name = "strict-ahci", -- .driver_data = STRICT_AHCI, -- }, { -- /* sentinel */ -- } --}; --MODULE_DEVICE_TABLE(platform, ahci_devtype); -- --struct ata_port_operations ahci_platform_ops = { -- .inherits = &ahci_ops, -- .host_stop = ahci_host_stop, --}; --EXPORT_SYMBOL_GPL(ahci_platform_ops); -- --static struct ata_port_operations ahci_platform_retry_srst_ops = { -- .inherits = &ahci_pmp_retry_srst_ops, -- .host_stop = ahci_host_stop, --}; -- --static const struct ata_port_info ahci_port_info[] = { -- /* by features */ -- [AHCI] = { -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_ops, -- }, -- [IMX53_AHCI] = { -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_retry_srst_ops, -- }, -- [STRICT_AHCI] = { -- AHCI_HFLAGS (AHCI_HFLAG_DELAY_ENGINE), -- .flags = AHCI_FLAG_COMMON, -- .pio_mask = ATA_PIO4, -- .udma_mask = ATA_UDMA6, -- .port_ops = &ahci_platform_ops, -- }, --}; -- --static struct scsi_host_template ahci_platform_sht = { -- AHCI_SHT("ahci_platform"), -+static const struct ata_port_info ahci_port_info = { -+ .flags = AHCI_FLAG_COMMON, -+ .pio_mask = ATA_PIO4, -+ .udma_mask = ATA_UDMA6, -+ .port_ops = &ahci_platform_ops, - }; - - static int ahci_probe(struct platform_device *pdev) - { - struct device *dev = &pdev->dev; - struct ahci_platform_data *pdata = dev_get_platdata(dev); -- const struct platform_device_id *id = platform_get_device_id(pdev); -- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0]; -- const struct ata_port_info *ppi[] = { &pi, NULL }; - struct ahci_host_priv *hpriv; -- struct ata_host *host; -- struct resource *mem; -- int irq; -- int n_ports; -- int i; - int rc; - -- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- if (!mem) { -- dev_err(dev, "no mmio space\n"); -- return -EINVAL; -- } -- -- irq = platform_get_irq(pdev, 0); -- if (irq <= 0) { -- dev_err(dev, "no irq\n"); -- return -EINVAL; -- } -- -- if (pdata && pdata->ata_port_info) -- pi = *pdata->ata_port_info; -- -- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); -- if (!hpriv) { -- dev_err(dev, "can't alloc ahci_host_priv\n"); -- return -ENOMEM; -- } -- -- hpriv->flags |= (unsigned long)pi.private_data; -+ hpriv = ahci_platform_get_resources(pdev); -+ if (IS_ERR(hpriv)) -+ return PTR_ERR(hpriv); - -- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); -- if (!hpriv->mmio) { -- dev_err(dev, "can't map %pR\n", mem); -- return -ENOMEM; -- } -- -- hpriv->clk = clk_get(dev, NULL); -- if (IS_ERR(hpriv->clk)) { -- dev_err(dev, "can't get clock\n"); -- } else { -- rc = clk_prepare_enable(hpriv->clk); -- if (rc) { -- dev_err(dev, "clock prepare enable failed"); -- goto free_clk; -- } -- } -+ rc = ahci_platform_enable_resources(hpriv); -+ if (rc) -+ return rc; - - /* - * Some platforms might need to prepare for mmio region access, -@@ -151,69 +52,10 @@ - if (pdata && pdata->init) { - rc = pdata->init(dev, hpriv->mmio); - if (rc) -- goto disable_unprepare_clk; -- } -- -- ahci_save_initial_config(dev, hpriv, -- pdata ? pdata->force_port_map : 0, -- pdata ? pdata->mask_port_map : 0); -- -- /* prepare host */ -- if (hpriv->cap & HOST_CAP_NCQ) -- pi.flags |= ATA_FLAG_NCQ; -- -- if (hpriv->cap & HOST_CAP_PMP) -- pi.flags |= ATA_FLAG_PMP; -- -- ahci_set_em_messages(hpriv, &pi); -- -- /* CAP.NP sometimes indicate the index of the last enabled -- * port, at other times, that of the last possible port, so -- * determining the maximum port number requires looking at -- * both CAP.NP and port_map. -- */ -- n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -- -- host = ata_host_alloc_pinfo(dev, ppi, n_ports); -- if (!host) { -- rc = -ENOMEM; -- goto pdata_exit; -+ goto disable_resources; - } - -- host->private_data = hpriv; -- -- if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -- host->flags |= ATA_HOST_PARALLEL_SCAN; -- else -- dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); -- -- if (pi.flags & ATA_FLAG_EM) -- ahci_reset_em(host); -- -- for (i = 0; i < host->n_ports; i++) { -- struct ata_port *ap = host->ports[i]; -- -- ata_port_desc(ap, "mmio %pR", mem); -- ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -- -- /* set enclosure management message type */ -- if (ap->flags & ATA_FLAG_EM) -- ap->em_message_type = hpriv->em_msg_type; -- -- /* disabled/not-implemented port */ -- if (!(hpriv->port_map & (1 << i))) -- ap->ops = &ata_dummy_port_ops; -- } -- -- rc = ahci_reset_controller(host); -- if (rc) -- goto pdata_exit; -- -- ahci_init_controller(host); -- ahci_print_info(host, "platform"); -- -- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -- &ahci_platform_sht); -+ rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0, 0); - if (rc) - goto pdata_exit; - -@@ -221,115 +63,19 @@ - pdata_exit: - if (pdata && pdata->exit) - pdata->exit(dev); --disable_unprepare_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); --free_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_put(hpriv->clk); -- return rc; --} -- --static void ahci_host_stop(struct ata_host *host) --{ -- struct device *dev = host->dev; -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- -- if (pdata && pdata->exit) -- pdata->exit(dev); -- -- if (!IS_ERR(hpriv->clk)) { -- clk_disable_unprepare(hpriv->clk); -- clk_put(hpriv->clk); -- } --} -- --#ifdef CONFIG_PM_SLEEP --static int ahci_suspend(struct device *dev) --{ -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ata_host *host = dev_get_drvdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- void __iomem *mmio = hpriv->mmio; -- u32 ctl; -- int rc; -- -- if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -- dev_err(dev, "firmware update required for suspend/resume\n"); -- return -EIO; -- } -- -- /* -- * AHCI spec rev1.1 section 8.3.3: -- * Software must disable interrupts prior to requesting a -- * transition of the HBA to D3 state. -- */ -- ctl = readl(mmio + HOST_CTL); -- ctl &= ~HOST_IRQ_EN; -- writel(ctl, mmio + HOST_CTL); -- readl(mmio + HOST_CTL); /* flush */ -- -- rc = ata_host_suspend(host, PMSG_SUSPEND); -- if (rc) -- return rc; -- -- if (pdata && pdata->suspend) -- return pdata->suspend(dev); -- -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); -- -- return 0; --} -- --static int ahci_resume(struct device *dev) --{ -- struct ahci_platform_data *pdata = dev_get_platdata(dev); -- struct ata_host *host = dev_get_drvdata(dev); -- struct ahci_host_priv *hpriv = host->private_data; -- int rc; -- -- if (!IS_ERR(hpriv->clk)) { -- rc = clk_prepare_enable(hpriv->clk); -- if (rc) { -- dev_err(dev, "clock prepare enable failed"); -- return rc; -- } -- } -- -- if (pdata && pdata->resume) { -- rc = pdata->resume(dev); -- if (rc) -- goto disable_unprepare_clk; -- } -- -- if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -- rc = ahci_reset_controller(host); -- if (rc) -- goto disable_unprepare_clk; -- -- ahci_init_controller(host); -- } -- -- ata_host_resume(host); -- -- return 0; -- --disable_unprepare_clk: -- if (!IS_ERR(hpriv->clk)) -- clk_disable_unprepare(hpriv->clk); -- -+disable_resources: -+ ahci_platform_disable_resources(hpriv); - return rc; - } --#endif - --static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); -+static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, -+ ahci_platform_resume); - - static const struct of_device_id ahci_of_match[] = { - { .compatible = "snps,spear-ahci", }, - { .compatible = "snps,exynos5440-ahci", }, - { .compatible = "ibm,476gtr-ahci", }, -+ { .compatible = "snps,dwc-ahci", }, - {}, - }; - MODULE_DEVICE_TABLE(of, ahci_of_match); -@@ -343,7 +89,6 @@ - .of_match_table = ahci_of_match, - .pm = &ahci_pm_ops, - }, -- .id_table = ahci_devtype, - }; - module_platform_driver(ahci_driver); - -diff -Nur linux-3.14.22.orig/drivers/ata/ata_generic.c linux-3.14.22/drivers/ata/ata_generic.c ---- linux-3.14.22.orig/drivers/ata/ata_generic.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/ata_generic.c 2014-10-22 14:55:51.998220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/Kconfig linux-3.14.22/drivers/ata/Kconfig ---- linux-3.14.22.orig/drivers/ata/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/Kconfig 2014-10-22 14:55:51.998220001 -0500 -@@ -99,7 +99,7 @@ - - config AHCI_IMX - tristate "Freescale i.MX AHCI SATA support" -- depends on SATA_AHCI_PLATFORM && MFD_SYSCON -+ depends on MFD_SYSCON - help - This option enables support for the Freescale i.MX SoC's - onboard AHCI SATA. -diff -Nur linux-3.14.22.orig/drivers/ata/libahci.c linux-3.14.22/drivers/ata/libahci.c ---- linux-3.14.22.orig/drivers/ata/libahci.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/libahci.c 2014-10-22 14:55:52.002220001 -0500 -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -394,6 +393,9 @@ - * - * If inconsistent, config values are fixed up by this function. - * -+ * If it is not set already this function sets hpriv->start_engine to -+ * ahci_start_engine. -+ * - * LOCKING: - * None. - */ -@@ -450,11 +452,23 @@ - cap &= ~HOST_CAP_SNTF; - } - -+ if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) { -+ dev_info(dev, -+ "controller can't do DEVSLP, turning off\n"); -+ cap2 &= ~HOST_CAP2_SDS; -+ cap2 &= ~HOST_CAP2_SADM; -+ } -+ - if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { - dev_info(dev, "controller can do FBS, turning on CAP_FBS\n"); - cap |= HOST_CAP_FBS; - } - -+ if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) { -+ dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n"); -+ cap &= ~HOST_CAP_FBS; -+ } -+ - if (force_port_map && port_map != force_port_map) { - dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", - port_map, force_port_map); -@@ -500,6 +514,9 @@ - hpriv->cap = cap; - hpriv->cap2 = cap2; - hpriv->port_map = port_map; -+ -+ if (!hpriv->start_engine) -+ hpriv->start_engine = ahci_start_engine; - } - EXPORT_SYMBOL_GPL(ahci_save_initial_config); - -@@ -766,7 +783,7 @@ - - /* enable DMA */ - if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* turn on LEDs */ - if (ap->flags & ATA_FLAG_EM) { -@@ -1234,7 +1251,7 @@ - - /* restart engine */ - out_restart: -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - return rc; - } - EXPORT_SYMBOL_GPL(ahci_kick_engine); -@@ -1426,6 +1443,7 @@ - const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -1443,7 +1461,7 @@ - rc = sata_link_hardreset(link, timing, deadline, &online, - ahci_check_ready); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - if (online) - *class = ahci_dev_classify(ap); -@@ -2007,10 +2025,12 @@ - - void ahci_error_handler(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; -+ - if (!(ap->pflags & ATA_PFLAG_FROZEN)) { - /* restart engine */ - ahci_stop_engine(ap); -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - sata_pmp_error_handler(ap); -@@ -2031,6 +2051,7 @@ - - static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - struct ata_device *dev = ap->link.device; - u32 devslp, dm, dito, mdat, deto; -@@ -2094,7 +2115,7 @@ - PORT_DEVSLP_ADSE); - writel(devslp, port_mmio + PORT_DEVSLP); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - /* enable device sleep feature for the drive */ - err_mask = ata_dev_set_feature(dev, -@@ -2106,6 +2127,7 @@ - - static void ahci_enable_fbs(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - u32 fbs; -@@ -2134,11 +2156,12 @@ - } else - dev_err(ap->host->dev, "Failed to enable FBS\n"); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - static void ahci_disable_fbs(struct ata_port *ap) - { -+ struct ahci_host_priv *hpriv = ap->host->private_data; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *port_mmio = ahci_port_base(ap); - u32 fbs; -@@ -2166,7 +2189,7 @@ - pp->fbs_enabled = false; - } - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - } - - static void ahci_pmp_attach(struct ata_port *ap) -diff -Nur linux-3.14.22.orig/drivers/ata/libahci_platform.c linux-3.14.22/drivers/ata/libahci_platform.c ---- linux-3.14.22.orig/drivers/ata/libahci_platform.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/ata/libahci_platform.c 2014-10-22 14:55:52.002220001 -0500 -@@ -0,0 +1,544 @@ -+/* -+ * AHCI SATA platform library -+ * -+ * Copyright 2004-2005 Red Hat, Inc. -+ * Jeff Garzik -+ * Copyright 2010 MontaVista Software, LLC. -+ * Anton Vorontsov -+ * -+ * 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, or (at your option) -+ * any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "ahci.h" -+ -+static void ahci_host_stop(struct ata_host *host); -+ -+struct ata_port_operations ahci_platform_ops = { -+ .inherits = &ahci_ops, -+ .host_stop = ahci_host_stop, -+}; -+EXPORT_SYMBOL_GPL(ahci_platform_ops); -+ -+static struct scsi_host_template ahci_platform_sht = { -+ AHCI_SHT("ahci_platform"), -+}; -+ -+/** -+ * ahci_platform_enable_clks - Enable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all the clks found in hpriv->clks, starting at -+ * index 0. If any clk fails to enable it disables all the clks already -+ * enabled in reverse order, and then returns an error. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c, rc; -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { -+ rc = clk_prepare_enable(hpriv->clks[c]); -+ if (rc) -+ goto disable_unprepare_clk; -+ } -+ return 0; -+ -+disable_unprepare_clk: -+ while (--c >= 0) -+ clk_disable_unprepare(hpriv->clks[c]); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); -+ -+/** -+ * ahci_platform_disable_clks - Disable platform clocks -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all the clks found in hpriv->clks, in reverse -+ * order of ahci_platform_enable_clks (starting at the end of the array). -+ */ -+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) -+{ -+ int c; -+ -+ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) -+ if (hpriv->clks[c]) -+ clk_disable_unprepare(hpriv->clks[c]); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); -+ -+/** -+ * ahci_platform_enable_resources - Enable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function enables all ahci_platform managed resources in the -+ * following order: -+ * 1) Regulator -+ * 2) Clocks (through ahci_platform_enable_clks) -+ * 3) Phy -+ * -+ * If resource enabling fails at any point the previous enabled resources -+ * are disabled in reverse order. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) -+{ -+ int rc; -+ -+ if (hpriv->target_pwr) { -+ rc = regulator_enable(hpriv->target_pwr); -+ if (rc) -+ return rc; -+ } -+ -+ rc = ahci_platform_enable_clks(hpriv); -+ if (rc) -+ goto disable_regulator; -+ -+ if (hpriv->phy) { -+ rc = phy_init(hpriv->phy); -+ if (rc) -+ goto disable_clks; -+ -+ rc = phy_power_on(hpriv->phy); -+ if (rc) { -+ phy_exit(hpriv->phy); -+ goto disable_clks; -+ } -+ } -+ -+ return 0; -+ -+disable_clks: -+ ahci_platform_disable_clks(hpriv); -+ -+disable_regulator: -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); -+ -+/** -+ * ahci_platform_disable_resources - Disable platform resources -+ * @hpriv: host private area to store config values -+ * -+ * This function disables all ahci_platform managed resources in the -+ * following order: -+ * 1) Phy -+ * 2) Clocks (through ahci_platform_disable_clks) -+ * 3) Regulator -+ */ -+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) -+{ -+ if (hpriv->phy) { -+ phy_power_off(hpriv->phy); -+ phy_exit(hpriv->phy); -+ } -+ -+ ahci_platform_disable_clks(hpriv); -+ -+ if (hpriv->target_pwr) -+ regulator_disable(hpriv->target_pwr); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); -+ -+static void ahci_platform_put_resources(struct device *dev, void *res) -+{ -+ struct ahci_host_priv *hpriv = res; -+ int c; -+ -+ if (hpriv->got_runtime_pm) { -+ pm_runtime_put_sync(dev); -+ pm_runtime_disable(dev); -+ } -+ -+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) -+ clk_put(hpriv->clks[c]); -+} -+ -+/** -+ * ahci_platform_get_resources - Get platform resources -+ * @pdev: platform device to get resources for -+ * -+ * This function allocates an ahci_host_priv struct, and gets the following -+ * resources, storing a reference to them inside the returned struct: -+ * -+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory) -+ * 2) regulator for controlling the targets power (optional) -+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, -+ * or for non devicetree enabled platforms a single clock -+ * 4) phy (optional) -+ * -+ * RETURNS: -+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value -+ */ -+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct ahci_host_priv *hpriv; -+ struct clk *clk; -+ int i, rc = -ENOMEM; -+ -+ if (!devres_open_group(dev, NULL, GFP_KERNEL)) -+ return ERR_PTR(-ENOMEM); -+ -+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), -+ GFP_KERNEL); -+ if (!hpriv) -+ goto err_out; -+ -+ devres_add(dev, hpriv); -+ -+ hpriv->mmio = devm_ioremap_resource(dev, -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); -+ if (IS_ERR(hpriv->mmio)) { -+ dev_err(dev, "no mmio space\n"); -+ rc = PTR_ERR(hpriv->mmio); -+ goto err_out; -+ } -+ -+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); -+ if (IS_ERR(hpriv->target_pwr)) { -+ rc = PTR_ERR(hpriv->target_pwr); -+ if (rc == -EPROBE_DEFER) -+ goto err_out; -+ hpriv->target_pwr = NULL; -+ } -+ -+ for (i = 0; i < AHCI_MAX_CLKS; i++) { -+ /* -+ * For now we must use clk_get(dev, NULL) for the first clock, -+ * because some platforms (da850, spear13xx) are not yet -+ * converted to use devicetree for clocks. For new platforms -+ * this is equivalent to of_clk_get(dev->of_node, 0). -+ */ -+ if (i == 0) -+ clk = clk_get(dev, NULL); -+ else -+ clk = of_clk_get(dev->of_node, i); -+ -+ if (IS_ERR(clk)) { -+ rc = PTR_ERR(clk); -+ if (rc == -EPROBE_DEFER) -+ goto err_out; -+ break; -+ } -+ hpriv->clks[i] = clk; -+ } -+ -+ hpriv->phy = devm_phy_get(dev, "sata-phy"); -+ if (IS_ERR(hpriv->phy)) { -+ rc = PTR_ERR(hpriv->phy); -+ switch (rc) { -+ case -ENODEV: -+ case -ENOSYS: -+ /* continue normally */ -+ hpriv->phy = NULL; -+ break; -+ -+ case -EPROBE_DEFER: -+ goto err_out; -+ -+ default: -+ dev_err(dev, "couldn't get sata-phy\n"); -+ goto err_out; -+ } -+ } -+ -+ pm_runtime_enable(dev); -+ pm_runtime_get_sync(dev); -+ hpriv->got_runtime_pm = true; -+ -+ devres_remove_group(dev, NULL); -+ return hpriv; -+ -+err_out: -+ devres_release_group(dev, NULL); -+ return ERR_PTR(rc); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_get_resources); -+ -+/** -+ * ahci_platform_init_host - Bring up an ahci-platform host -+ * @pdev: platform device pointer for the host -+ * @hpriv: ahci-host private data for the host -+ * @pi_template: template for the ata_port_info to use -+ * @host_flags: ahci host flags used in ahci_host_priv -+ * @force_port_map: param passed to ahci_save_initial_config -+ * @mask_port_map: param passed to ahci_save_initial_config -+ * -+ * This function does all the usual steps needed to bring up an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_init_host(struct platform_device *pdev, -+ struct ahci_host_priv *hpriv, -+ const struct ata_port_info *pi_template, -+ unsigned long host_flags, -+ unsigned int force_port_map, -+ unsigned int mask_port_map) -+{ -+ struct device *dev = &pdev->dev; -+ struct ata_port_info pi = *pi_template; -+ const struct ata_port_info *ppi[] = { &pi, NULL }; -+ struct ata_host *host; -+ int i, irq, n_ports, rc; -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq <= 0) { -+ dev_err(dev, "no irq\n"); -+ return -EINVAL; -+ } -+ -+ /* prepare host */ -+ pi.private_data = (void *)host_flags; -+ hpriv->flags |= host_flags; -+ -+ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); -+ -+ if (hpriv->cap & HOST_CAP_NCQ) -+ pi.flags |= ATA_FLAG_NCQ; -+ -+ if (hpriv->cap & HOST_CAP_PMP) -+ pi.flags |= ATA_FLAG_PMP; -+ -+ ahci_set_em_messages(hpriv, &pi); -+ -+ /* CAP.NP sometimes indicate the index of the last enabled -+ * port, at other times, that of the last possible port, so -+ * determining the maximum port number requires looking at -+ * both CAP.NP and port_map. -+ */ -+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); -+ -+ host = ata_host_alloc_pinfo(dev, ppi, n_ports); -+ if (!host) -+ return -ENOMEM; -+ -+ host->private_data = hpriv; -+ -+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) -+ host->flags |= ATA_HOST_PARALLEL_SCAN; -+ else -+ dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); -+ -+ if (pi.flags & ATA_FLAG_EM) -+ ahci_reset_em(host); -+ -+ for (i = 0; i < host->n_ports; i++) { -+ struct ata_port *ap = host->ports[i]; -+ -+ ata_port_desc(ap, "mmio %pR", -+ platform_get_resource(pdev, IORESOURCE_MEM, 0)); -+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); -+ -+ /* set enclosure management message type */ -+ if (ap->flags & ATA_FLAG_EM) -+ ap->em_message_type = hpriv->em_msg_type; -+ -+ /* disabled/not-implemented port */ -+ if (!(hpriv->port_map & (1 << i))) -+ ap->ops = &ata_dummy_port_ops; -+ } -+ -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ ahci_print_info(host, "platform"); -+ -+ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, -+ &ahci_platform_sht); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_init_host); -+ -+static void ahci_host_stop(struct ata_host *host) -+{ -+ struct device *dev = host->dev; -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ -+ if (pdata && pdata->exit) -+ pdata->exit(dev); -+ -+ ahci_platform_disable_resources(hpriv); -+} -+ -+#ifdef CONFIG_PM_SLEEP -+/** -+ * ahci_platform_suspend_host - Suspend an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to suspend an -+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) -+ * must be disabled after calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend_host(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ void __iomem *mmio = hpriv->mmio; -+ u32 ctl; -+ -+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { -+ dev_err(dev, "firmware update required for suspend/resume\n"); -+ return -EIO; -+ } -+ -+ /* -+ * AHCI spec rev1.1 section 8.3.3: -+ * Software must disable interrupts prior to requesting a -+ * transition of the HBA to D3 state. -+ */ -+ ctl = readl(mmio + HOST_CTL); -+ ctl &= ~HOST_IRQ_EN; -+ writel(ctl, mmio + HOST_CTL); -+ readl(mmio + HOST_CTL); /* flush */ -+ -+ return ata_host_suspend(host, PMSG_SUSPEND); -+} -+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); -+ -+/** -+ * ahci_platform_resume_host - Resume an ahci-platform host -+ * @dev: device pointer for the host -+ * -+ * This function does all the usual steps needed to resume an ahci-platform -+ * host, note any necessary resources (ie clks, phy, etc.) must be -+ * initialized / enabled before calling this. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume_host(struct device *dev) -+{ -+ struct ata_host *host = dev_get_drvdata(dev); -+ int rc; -+ -+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { -+ rc = ahci_reset_controller(host); -+ if (rc) -+ return rc; -+ -+ ahci_init_controller(host); -+ } -+ -+ ata_host_resume(host); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_resume_host); -+ -+/** -+ * ahci_platform_suspend - Suspend an ahci-platform device -+ * @dev: the platform device to suspend -+ * -+ * This function suspends the host associated with the device, followed by -+ * disabling all the resources of the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_suspend(struct device *dev) -+{ -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int rc; -+ -+ rc = ahci_platform_suspend_host(dev); -+ if (rc) -+ return rc; -+ -+ if (pdata && pdata->suspend) { -+ rc = pdata->suspend(dev); -+ if (rc) -+ goto resume_host; -+ } -+ -+ ahci_platform_disable_resources(hpriv); -+ -+ return 0; -+ -+resume_host: -+ ahci_platform_resume_host(dev); -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_suspend); -+ -+/** -+ * ahci_platform_resume - Resume an ahci-platform device -+ * @dev: the platform device to resume -+ * -+ * This function enables all the resources of the device followed by -+ * resuming the host associated with the device. -+ * -+ * RETURNS: -+ * 0 on success otherwise a negative error code -+ */ -+int ahci_platform_resume(struct device *dev) -+{ -+ struct ahci_platform_data *pdata = dev_get_platdata(dev); -+ struct ata_host *host = dev_get_drvdata(dev); -+ struct ahci_host_priv *hpriv = host->private_data; -+ int rc; -+ -+ rc = ahci_platform_enable_resources(hpriv); -+ if (rc) -+ return rc; -+ -+ if (pdata && pdata->resume) { -+ rc = pdata->resume(dev); -+ if (rc) -+ goto disable_resources; -+ } -+ -+ rc = ahci_platform_resume_host(dev); -+ if (rc) -+ goto disable_resources; -+ -+ /* We resumed so update PM runtime state */ -+ pm_runtime_disable(dev); -+ pm_runtime_set_active(dev); -+ pm_runtime_enable(dev); -+ -+ return 0; -+ -+disable_resources: -+ ahci_platform_disable_resources(hpriv); -+ -+ return rc; -+} -+EXPORT_SYMBOL_GPL(ahci_platform_resume); -+#endif -+ -+MODULE_DESCRIPTION("AHCI SATA platform library"); -+MODULE_AUTHOR("Anton Vorontsov "); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/ata/libata-core.c linux-3.14.22/drivers/ata/libata-core.c ---- linux-3.14.22.orig/drivers/ata/libata-core.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/libata-core.c 2014-10-22 14:55:52.002220001 -0500 -@@ -1524,7 +1524,7 @@ - * @dev: Device to which the command is sent - * @tf: Taskfile registers for the command and the result - * @cdb: CDB for packet command -- * @dma_dir: Data tranfer direction of the command -+ * @dma_dir: Data transfer direction of the command - * @sgl: sg list for the data buffer of the command - * @n_elem: Number of sg entries - * @timeout: Timeout in msecs (0 for default) -@@ -1712,7 +1712,7 @@ - * @dev: Device to which the command is sent - * @tf: Taskfile registers for the command and the result - * @cdb: CDB for packet command -- * @dma_dir: Data tranfer direction of the command -+ * @dma_dir: Data transfer direction of the command - * @buf: Data buffer of the command - * @buflen: Length of data buffer - * @timeout: Timeout in msecs (0 for default) -diff -Nur linux-3.14.22.orig/drivers/ata/Makefile linux-3.14.22/drivers/ata/Makefile ---- linux-3.14.22.orig/drivers/ata/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/Makefile 2014-10-22 14:55:52.002220001 -0500 -@@ -4,13 +4,13 @@ - # non-SFF interface - obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o - obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o --obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o -+obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o - obj-$(CONFIG_SATA_FSL) += sata_fsl.o - obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o - obj-$(CONFIG_SATA_SIL24) += sata_sil24.o - obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o - obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o --obj-$(CONFIG_AHCI_IMX) += ahci_imx.o -+obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o - - # SFF w/ custom DMA - obj-$(CONFIG_PDC_ADMA) += pdc_adma.o -diff -Nur linux-3.14.22.orig/drivers/ata/pata_acpi.c linux-3.14.22/drivers/ata/pata_acpi.c ---- linux-3.14.22.orig/drivers/ata/pata_acpi.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_acpi.c 2014-10-22 14:55:52.002220001 -0500 -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_amd.c linux-3.14.22/drivers/ata/pata_amd.c ---- linux-3.14.22.orig/drivers/ata/pata_amd.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_amd.c 2014-10-22 14:55:52.002220001 -0500 -@@ -17,7 +17,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_artop.c linux-3.14.22/drivers/ata/pata_artop.c ---- linux-3.14.22.orig/drivers/ata/pata_artop.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_artop.c 2014-10-22 14:55:52.002220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_at91.c linux-3.14.22/drivers/ata/pata_at91.c ---- linux-3.14.22.orig/drivers/ata/pata_at91.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_at91.c 2014-10-22 14:55:52.002220001 -0500 -@@ -18,7 +18,6 @@ - - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_atiixp.c linux-3.14.22/drivers/ata/pata_atiixp.c ---- linux-3.14.22.orig/drivers/ata/pata_atiixp.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_atiixp.c 2014-10-22 14:55:52.002220001 -0500 -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_atp867x.c linux-3.14.22/drivers/ata/pata_atp867x.c ---- linux-3.14.22.orig/drivers/ata/pata_atp867x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_atp867x.c 2014-10-22 14:55:52.002220001 -0500 -@@ -29,7 +29,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cmd640.c linux-3.14.22/drivers/ata/pata_cmd640.c ---- linux-3.14.22.orig/drivers/ata/pata_cmd640.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cmd640.c 2014-10-22 14:55:52.006220001 -0500 -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cmd64x.c linux-3.14.22/drivers/ata/pata_cmd64x.c ---- linux-3.14.22.orig/drivers/ata/pata_cmd64x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cmd64x.c 2014-10-22 14:55:52.006220001 -0500 -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cs5520.c linux-3.14.22/drivers/ata/pata_cs5520.c ---- linux-3.14.22.orig/drivers/ata/pata_cs5520.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cs5520.c 2014-10-22 14:55:52.006220001 -0500 -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cs5530.c linux-3.14.22/drivers/ata/pata_cs5530.c ---- linux-3.14.22.orig/drivers/ata/pata_cs5530.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cs5530.c 2014-10-22 14:55:52.006220001 -0500 -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cs5535.c linux-3.14.22/drivers/ata/pata_cs5535.c ---- linux-3.14.22.orig/drivers/ata/pata_cs5535.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cs5535.c 2014-10-22 14:55:52.006220001 -0500 -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cs5536.c linux-3.14.22/drivers/ata/pata_cs5536.c ---- linux-3.14.22.orig/drivers/ata/pata_cs5536.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cs5536.c 2014-10-22 14:55:52.006220001 -0500 -@@ -33,7 +33,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_cypress.c linux-3.14.22/drivers/ata/pata_cypress.c ---- linux-3.14.22.orig/drivers/ata/pata_cypress.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_cypress.c 2014-10-22 14:55:52.006220001 -0500 -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_efar.c linux-3.14.22/drivers/ata/pata_efar.c ---- linux-3.14.22.orig/drivers/ata/pata_efar.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_efar.c 2014-10-22 14:55:52.006220001 -0500 -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_ep93xx.c linux-3.14.22/drivers/ata/pata_ep93xx.c ---- linux-3.14.22.orig/drivers/ata/pata_ep93xx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_ep93xx.c 2014-10-22 14:55:52.006220001 -0500 -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_hpt366.c linux-3.14.22/drivers/ata/pata_hpt366.c ---- linux-3.14.22.orig/drivers/ata/pata_hpt366.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_hpt366.c 2014-10-22 14:55:52.006220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_hpt37x.c linux-3.14.22/drivers/ata/pata_hpt37x.c ---- linux-3.14.22.orig/drivers/ata/pata_hpt37x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_hpt37x.c 2014-10-22 14:55:52.006220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_hpt3x2n.c linux-3.14.22/drivers/ata/pata_hpt3x2n.c ---- linux-3.14.22.orig/drivers/ata/pata_hpt3x2n.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_hpt3x2n.c 2014-10-22 14:55:52.006220001 -0500 -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_hpt3x3.c linux-3.14.22/drivers/ata/pata_hpt3x3.c ---- linux-3.14.22.orig/drivers/ata/pata_hpt3x3.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_hpt3x3.c 2014-10-22 14:55:52.010220001 -0500 -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_imx.c linux-3.14.22/drivers/ata/pata_imx.c ---- linux-3.14.22.orig/drivers/ata/pata_imx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_imx.c 2014-10-22 14:55:52.010220001 -0500 -@@ -15,7 +15,6 @@ - */ - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_it8213.c linux-3.14.22/drivers/ata/pata_it8213.c ---- linux-3.14.22.orig/drivers/ata/pata_it8213.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_it8213.c 2014-10-22 14:55:52.010220001 -0500 -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_it821x.c linux-3.14.22/drivers/ata/pata_it821x.c ---- linux-3.14.22.orig/drivers/ata/pata_it821x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_it821x.c 2014-10-22 14:55:52.010220001 -0500 -@@ -72,7 +72,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_jmicron.c linux-3.14.22/drivers/ata/pata_jmicron.c ---- linux-3.14.22.orig/drivers/ata/pata_jmicron.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_jmicron.c 2014-10-22 14:55:52.010220001 -0500 -@@ -10,7 +10,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_marvell.c linux-3.14.22/drivers/ata/pata_marvell.c ---- linux-3.14.22.orig/drivers/ata/pata_marvell.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_marvell.c 2014-10-22 14:55:52.010220001 -0500 -@@ -11,7 +11,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_mpiix.c linux-3.14.22/drivers/ata/pata_mpiix.c ---- linux-3.14.22.orig/drivers/ata/pata_mpiix.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_mpiix.c 2014-10-22 14:55:52.010220001 -0500 -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_netcell.c linux-3.14.22/drivers/ata/pata_netcell.c ---- linux-3.14.22.orig/drivers/ata/pata_netcell.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_netcell.c 2014-10-22 14:55:52.010220001 -0500 -@@ -7,7 +7,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_ninja32.c linux-3.14.22/drivers/ata/pata_ninja32.c ---- linux-3.14.22.orig/drivers/ata/pata_ninja32.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_ninja32.c 2014-10-22 14:55:52.010220001 -0500 -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_ns87410.c linux-3.14.22/drivers/ata/pata_ns87410.c ---- linux-3.14.22.orig/drivers/ata/pata_ns87410.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_ns87410.c 2014-10-22 14:55:52.010220001 -0500 -@@ -20,7 +20,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_ns87415.c linux-3.14.22/drivers/ata/pata_ns87415.c ---- linux-3.14.22.orig/drivers/ata/pata_ns87415.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_ns87415.c 2014-10-22 14:55:52.010220001 -0500 -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_oldpiix.c linux-3.14.22/drivers/ata/pata_oldpiix.c ---- linux-3.14.22.orig/drivers/ata/pata_oldpiix.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_oldpiix.c 2014-10-22 14:55:52.010220001 -0500 -@@ -16,7 +16,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_opti.c linux-3.14.22/drivers/ata/pata_opti.c ---- linux-3.14.22.orig/drivers/ata/pata_opti.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_opti.c 2014-10-22 14:55:52.010220001 -0500 -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_optidma.c linux-3.14.22/drivers/ata/pata_optidma.c ---- linux-3.14.22.orig/drivers/ata/pata_optidma.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_optidma.c 2014-10-22 14:55:52.010220001 -0500 -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_pcmcia.c linux-3.14.22/drivers/ata/pata_pcmcia.c ---- linux-3.14.22.orig/drivers/ata/pata_pcmcia.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_pcmcia.c 2014-10-22 14:55:52.010220001 -0500 -@@ -26,7 +26,6 @@ - - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_pdc2027x.c linux-3.14.22/drivers/ata/pata_pdc2027x.c ---- linux-3.14.22.orig/drivers/ata/pata_pdc2027x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_pdc2027x.c 2014-10-22 14:55:52.014220001 -0500 -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_pdc202xx_old.c linux-3.14.22/drivers/ata/pata_pdc202xx_old.c ---- linux-3.14.22.orig/drivers/ata/pata_pdc202xx_old.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_pdc202xx_old.c 2014-10-22 14:55:52.014220001 -0500 -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_piccolo.c linux-3.14.22/drivers/ata/pata_piccolo.c ---- linux-3.14.22.orig/drivers/ata/pata_piccolo.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_piccolo.c 2014-10-22 14:55:52.014220001 -0500 -@@ -18,7 +18,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_platform.c linux-3.14.22/drivers/ata/pata_platform.c ---- linux-3.14.22.orig/drivers/ata/pata_platform.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_platform.c 2014-10-22 14:55:52.014220001 -0500 -@@ -13,7 +13,6 @@ - */ - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_pxa.c linux-3.14.22/drivers/ata/pata_pxa.c ---- linux-3.14.22.orig/drivers/ata/pata_pxa.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_pxa.c 2014-10-22 14:55:52.014220001 -0500 -@@ -20,7 +20,6 @@ - - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_radisys.c linux-3.14.22/drivers/ata/pata_radisys.c ---- linux-3.14.22.orig/drivers/ata/pata_radisys.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_radisys.c 2014-10-22 14:55:52.014220001 -0500 -@@ -15,7 +15,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_rdc.c linux-3.14.22/drivers/ata/pata_rdc.c ---- linux-3.14.22.orig/drivers/ata/pata_rdc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_rdc.c 2014-10-22 14:55:52.014220001 -0500 -@@ -24,7 +24,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_rz1000.c linux-3.14.22/drivers/ata/pata_rz1000.c ---- linux-3.14.22.orig/drivers/ata/pata_rz1000.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_rz1000.c 2014-10-22 14:55:52.014220001 -0500 -@@ -14,7 +14,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_sc1200.c linux-3.14.22/drivers/ata/pata_sc1200.c ---- linux-3.14.22.orig/drivers/ata/pata_sc1200.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_sc1200.c 2014-10-22 14:55:52.014220001 -0500 -@@ -32,7 +32,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_scc.c linux-3.14.22/drivers/ata/pata_scc.c ---- linux-3.14.22.orig/drivers/ata/pata_scc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_scc.c 2014-10-22 14:55:52.014220001 -0500 -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_sch.c linux-3.14.22/drivers/ata/pata_sch.c ---- linux-3.14.22.orig/drivers/ata/pata_sch.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_sch.c 2014-10-22 14:55:52.014220001 -0500 -@@ -27,7 +27,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_serverworks.c linux-3.14.22/drivers/ata/pata_serverworks.c ---- linux-3.14.22.orig/drivers/ata/pata_serverworks.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_serverworks.c 2014-10-22 14:55:52.014220001 -0500 -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_sil680.c linux-3.14.22/drivers/ata/pata_sil680.c ---- linux-3.14.22.orig/drivers/ata/pata_sil680.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_sil680.c 2014-10-22 14:55:52.014220001 -0500 -@@ -25,7 +25,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_sis.c linux-3.14.22/drivers/ata/pata_sis.c ---- linux-3.14.22.orig/drivers/ata/pata_sis.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_sis.c 2014-10-22 14:55:52.014220001 -0500 -@@ -26,7 +26,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_sl82c105.c linux-3.14.22/drivers/ata/pata_sl82c105.c ---- linux-3.14.22.orig/drivers/ata/pata_sl82c105.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_sl82c105.c 2014-10-22 14:55:52.018220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_triflex.c linux-3.14.22/drivers/ata/pata_triflex.c ---- linux-3.14.22.orig/drivers/ata/pata_triflex.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_triflex.c 2014-10-22 14:55:52.018220001 -0500 -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pata_via.c linux-3.14.22/drivers/ata/pata_via.c ---- linux-3.14.22.orig/drivers/ata/pata_via.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pata_via.c 2014-10-22 14:55:52.018220001 -0500 -@@ -55,7 +55,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/pdc_adma.c linux-3.14.22/drivers/ata/pdc_adma.c ---- linux-3.14.22.orig/drivers/ata/pdc_adma.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/pdc_adma.c 2014-10-22 14:55:52.018220001 -0500 -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_dwc_460ex.c linux-3.14.22/drivers/ata/sata_dwc_460ex.c ---- linux-3.14.22.orig/drivers/ata/sata_dwc_460ex.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_dwc_460ex.c 2014-10-22 14:55:52.018220001 -0500 -@@ -29,7 +29,6 @@ - - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_highbank.c linux-3.14.22/drivers/ata/sata_highbank.c ---- linux-3.14.22.orig/drivers/ata/sata_highbank.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_highbank.c 2014-10-22 14:55:52.018220001 -0500 -@@ -19,7 +19,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -403,6 +402,7 @@ - static const unsigned long timing[] = { 5, 100, 500}; - struct ata_port *ap = link->ap; - struct ahci_port_priv *pp = ap->private_data; -+ struct ahci_host_priv *hpriv = ap->host->private_data; - u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; - struct ata_taskfile tf; - bool online; -@@ -431,7 +431,7 @@ - break; - } while (!online && retry--); - -- ahci_start_engine(ap); -+ hpriv->start_engine(ap); - - if (online) - *class = ahci_dev_classify(ap); -diff -Nur linux-3.14.22.orig/drivers/ata/sata_nv.c linux-3.14.22/drivers/ata/sata_nv.c ---- linux-3.14.22.orig/drivers/ata/sata_nv.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_nv.c 2014-10-22 14:55:52.018220001 -0500 -@@ -40,7 +40,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_promise.c linux-3.14.22/drivers/ata/sata_promise.c ---- linux-3.14.22.orig/drivers/ata/sata_promise.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_promise.c 2014-10-22 14:55:52.018220001 -0500 -@@ -35,7 +35,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_qstor.c linux-3.14.22/drivers/ata/sata_qstor.c ---- linux-3.14.22.orig/drivers/ata/sata_qstor.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_qstor.c 2014-10-22 14:55:52.018220001 -0500 -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_sil.c linux-3.14.22/drivers/ata/sata_sil.c ---- linux-3.14.22.orig/drivers/ata/sata_sil.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_sil.c 2014-10-22 14:55:52.018220001 -0500 -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_sis.c linux-3.14.22/drivers/ata/sata_sis.c ---- linux-3.14.22.orig/drivers/ata/sata_sis.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_sis.c 2014-10-22 14:55:52.018220001 -0500 -@@ -33,7 +33,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_svw.c linux-3.14.22/drivers/ata/sata_svw.c ---- linux-3.14.22.orig/drivers/ata/sata_svw.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_svw.c 2014-10-22 14:55:52.022220001 -0500 -@@ -39,7 +39,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_sx4.c linux-3.14.22/drivers/ata/sata_sx4.c ---- linux-3.14.22.orig/drivers/ata/sata_sx4.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_sx4.c 2014-10-22 14:55:52.022220001 -0500 -@@ -82,7 +82,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_uli.c linux-3.14.22/drivers/ata/sata_uli.c ---- linux-3.14.22.orig/drivers/ata/sata_uli.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_uli.c 2014-10-22 14:55:52.022220001 -0500 -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_via.c linux-3.14.22/drivers/ata/sata_via.c ---- linux-3.14.22.orig/drivers/ata/sata_via.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_via.c 2014-10-22 14:55:52.022220001 -0500 -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/ata/sata_vsc.c linux-3.14.22/drivers/ata/sata_vsc.c ---- linux-3.14.22.orig/drivers/ata/sata_vsc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/ata/sata_vsc.c 2014-10-22 14:55:52.022220001 -0500 -@@ -37,7 +37,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -Nur linux-3.14.22.orig/drivers/base/bus.c linux-3.14.22/drivers/base/bus.c ---- linux-3.14.22.orig/drivers/base/bus.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/base/bus.c 2014-10-22 14:55:52.022220001 -0500 -@@ -1218,7 +1218,7 @@ - * with the name of the subsystem. The root device can carry subsystem- - * wide attributes. All registered devices are below this single root - * device and are named after the subsystem with a simple enumeration -- * number appended. The registered devices are not explicitely named; -+ * number appended. The registered devices are not explicitly named; - * only 'id' in the device needs to be set. - * - * Do not use this interface for anything new, it exists for compatibility -diff -Nur linux-3.14.22.orig/drivers/base/cpu.c linux-3.14.22/drivers/base/cpu.c ---- linux-3.14.22.orig/drivers/base/cpu.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/base/cpu.c 2014-10-22 14:55:52.022220001 -0500 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - - #include "base.h" - -@@ -286,6 +287,45 @@ - */ - } - -+#ifdef CONFIG_HAVE_CPU_AUTOPROBE -+#ifdef CONFIG_GENERIC_CPU_AUTOPROBE -+static ssize_t print_cpu_modalias(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ ssize_t n; -+ u32 i; -+ -+ n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", -+ CPU_FEATURE_TYPEVAL); -+ -+ for (i = 0; i < MAX_CPU_FEATURES; i++) -+ if (cpu_have_feature(i)) { -+ if (PAGE_SIZE < n + sizeof(",XXXX\n")) { -+ WARN(1, "CPU features overflow page\n"); -+ break; -+ } -+ n += sprintf(&buf[n], ",%04X", i); -+ } -+ buf[n++] = '\n'; -+ return n; -+} -+#else -+#define print_cpu_modalias arch_print_cpu_modalias -+#endif -+ -+static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) -+{ -+ char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); -+ if (buf) { -+ print_cpu_modalias(NULL, NULL, buf); -+ add_uevent_var(env, "MODALIAS=%s", buf); -+ kfree(buf); -+ } -+ return 0; -+} -+#endif -+ - /* - * register_cpu - Setup a sysfs device for a CPU. - * @cpu - cpu->hotpluggable field set to 1 will generate a control file in -@@ -306,8 +346,8 @@ - cpu->dev.offline_disabled = !cpu->hotpluggable; - cpu->dev.offline = !cpu_online(num); - cpu->dev.of_node = of_get_cpu_node(num, NULL); --#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE -- cpu->dev.bus->uevent = arch_cpu_uevent; -+#ifdef CONFIG_HAVE_CPU_AUTOPROBE -+ cpu->dev.bus->uevent = cpu_uevent; - #endif - cpu->dev.groups = common_cpu_attr_groups; - if (cpu->hotpluggable) -@@ -330,8 +370,8 @@ - } - EXPORT_SYMBOL_GPL(get_cpu_device); - --#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE --static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); -+#ifdef CONFIG_HAVE_CPU_AUTOPROBE -+static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); - #endif - - static struct attribute *cpu_root_attrs[] = { -@@ -344,7 +384,7 @@ - &cpu_attrs[2].attr.attr, - &dev_attr_kernel_max.attr, - &dev_attr_offline.attr, --#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE -+#ifdef CONFIG_HAVE_CPU_AUTOPROBE - &dev_attr_modalias.attr, - #endif - NULL -diff -Nur linux-3.14.22.orig/drivers/base/dma-buf.c linux-3.14.22/drivers/base/dma-buf.c ---- linux-3.14.22.orig/drivers/base/dma-buf.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/base/dma-buf.c 2014-10-22 14:55:52.022220001 -0500 -@@ -251,9 +251,8 @@ - * @dmabuf: [in] buffer to attach device to. - * @dev: [in] device to be attached. - * -- * Returns struct dma_buf_attachment * for this attachment; may return negative -- * error codes. -- * -+ * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on -+ * error. - */ - struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, - struct device *dev) -@@ -319,9 +318,8 @@ - * @attach: [in] attachment whose scatterlist is to be returned - * @direction: [in] direction of DMA transfer - * -- * Returns sg_table containing the scatterlist to be returned; may return NULL -- * or ERR_PTR. -- * -+ * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR -+ * on error. - */ - struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, - enum dma_data_direction direction) -@@ -334,6 +332,8 @@ - return ERR_PTR(-EINVAL); - - sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); -+ if (!sg_table) -+ sg_table = ERR_PTR(-ENOMEM); - - return sg_table; - } -@@ -544,6 +544,8 @@ - * These calls are optional in drivers. The intended use for them - * is for mapping objects linear in kernel space for high use objects. - * Please attempt to use kmap/kunmap before thinking about these interfaces. -+ * -+ * Returns NULL on error. - */ - void *dma_buf_vmap(struct dma_buf *dmabuf) - { -@@ -566,7 +568,9 @@ - BUG_ON(dmabuf->vmap_ptr); - - ptr = dmabuf->ops->vmap(dmabuf); -- if (IS_ERR_OR_NULL(ptr)) -+ if (WARN_ON_ONCE(IS_ERR(ptr))) -+ ptr = NULL; -+ if (!ptr) - goto out_unlock; - - dmabuf->vmap_ptr = ptr; -diff -Nur linux-3.14.22.orig/drivers/base/dma-contiguous.c linux-3.14.22/drivers/base/dma-contiguous.c ---- linux-3.14.22.orig/drivers/base/dma-contiguous.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/base/dma-contiguous.c 2014-10-22 14:55:52.022220001 -0500 -@@ -24,22 +24,9 @@ - - #include - #include --#include --#include --#include - #include --#include --#include --#include - #include -- --struct cma { -- unsigned long base_pfn; -- unsigned long count; -- unsigned long *bitmap; --}; -- --struct cma *dma_contiguous_default_area; -+#include - - #ifdef CONFIG_CMA_SIZE_MBYTES - #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES -@@ -47,6 +34,8 @@ - #define CMA_SIZE_MBYTES 0 - #endif - -+struct cma *dma_contiguous_default_area; -+ - /* - * Default global CMA area size can be defined in kernel's .config. - * This is useful mainly for distro maintainers to create a kernel -@@ -59,11 +48,22 @@ - */ - static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M; - static phys_addr_t size_cmdline = -1; -+static phys_addr_t base_cmdline; -+static phys_addr_t limit_cmdline; - - static int __init early_cma(char *p) - { - pr_debug("%s(%s)\n", __func__, p); - size_cmdline = memparse(p, &p); -+ if (*p != '@') -+ return 0; -+ base_cmdline = memparse(p + 1, &p); -+ if (*p != '-') { -+ limit_cmdline = base_cmdline + size_cmdline; -+ return 0; -+ } -+ limit_cmdline = memparse(p + 1, &p); -+ - return 0; - } - early_param("cma", early_cma); -@@ -107,11 +107,18 @@ - void __init dma_contiguous_reserve(phys_addr_t limit) - { - phys_addr_t selected_size = 0; -+ phys_addr_t selected_base = 0; -+ phys_addr_t selected_limit = limit; -+ bool fixed = false; - - pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); - - if (size_cmdline != -1) { - selected_size = size_cmdline; -+ selected_base = base_cmdline; -+ selected_limit = min_not_zero(limit_cmdline, limit); -+ if (base_cmdline + size_cmdline == limit_cmdline) -+ fixed = true; - } else { - #ifdef CONFIG_CMA_SIZE_SEL_MBYTES - selected_size = size_bytes; -@@ -128,68 +135,12 @@ - pr_debug("%s: reserving %ld MiB for global area\n", __func__, - (unsigned long)selected_size / SZ_1M); - -- dma_contiguous_reserve_area(selected_size, 0, limit, -- &dma_contiguous_default_area); -- } --}; -- --static DEFINE_MUTEX(cma_mutex); -- --static int __init cma_activate_area(struct cma *cma) --{ -- int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long); -- unsigned long base_pfn = cma->base_pfn, pfn = base_pfn; -- unsigned i = cma->count >> pageblock_order; -- struct zone *zone; -- -- cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); -- -- if (!cma->bitmap) -- return -ENOMEM; -- -- WARN_ON_ONCE(!pfn_valid(pfn)); -- zone = page_zone(pfn_to_page(pfn)); -- -- do { -- unsigned j; -- base_pfn = pfn; -- for (j = pageblock_nr_pages; j; --j, pfn++) { -- WARN_ON_ONCE(!pfn_valid(pfn)); -- /* -- * alloc_contig_range requires the pfn range -- * specified to be in the same zone. Make this -- * simple by forcing the entire CMA resv range -- * to be in the same zone. -- */ -- if (page_zone(pfn_to_page(pfn)) != zone) -- goto err; -- } -- init_cma_reserved_pageblock(pfn_to_page(base_pfn)); -- } while (--i); -- -- return 0; -- --err: -- kfree(cma->bitmap); -- return -EINVAL; --} -- --static struct cma cma_areas[MAX_CMA_AREAS]; --static unsigned cma_area_count; -- --static int __init cma_init_reserved_areas(void) --{ -- int i; -- -- for (i = 0; i < cma_area_count; i++) { -- int ret = cma_activate_area(&cma_areas[i]); -- if (ret) -- return ret; -+ dma_contiguous_reserve_area(selected_size, selected_base, -+ selected_limit, -+ &dma_contiguous_default_area, -+ fixed); - } -- -- return 0; - } --core_initcall(cma_init_reserved_areas); - - /** - * dma_contiguous_reserve_area() - reserve custom contiguous area -@@ -197,78 +148,32 @@ - * @base: Base address of the reserved area optional, use 0 for any - * @limit: End address of the reserved memory (optional, 0 for any). - * @res_cma: Pointer to store the created cma region. -+ * @fixed: hint about where to place the reserved area - * - * This function reserves memory from early allocator. It should be - * called by arch specific code once the early allocator (memblock or bootmem) - * has been activated and all other subsystems have already allocated/reserved - * memory. This function allows to create custom reserved areas for specific - * devices. -+ * -+ * If @fixed is true, reserve contiguous area at exactly @base. If false, -+ * reserve in range from @base to @limit. - */ - int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, -- phys_addr_t limit, struct cma **res_cma) -+ phys_addr_t limit, struct cma **res_cma, -+ bool fixed) - { -- struct cma *cma = &cma_areas[cma_area_count]; -- phys_addr_t alignment; -- int ret = 0; -- -- pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__, -- (unsigned long)size, (unsigned long)base, -- (unsigned long)limit); -- -- /* Sanity checks */ -- if (cma_area_count == ARRAY_SIZE(cma_areas)) { -- pr_err("Not enough slots for CMA reserved regions!\n"); -- return -ENOSPC; -- } -- -- if (!size) -- return -EINVAL; -- -- /* Sanitise input arguments */ -- alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); -- base = ALIGN(base, alignment); -- size = ALIGN(size, alignment); -- limit &= ~(alignment - 1); -- -- /* Reserve memory */ -- if (base) { -- if (memblock_is_region_reserved(base, size) || -- memblock_reserve(base, size) < 0) { -- ret = -EBUSY; -- goto err; -- } -- } else { -- /* -- * Use __memblock_alloc_base() since -- * memblock_alloc_base() panic()s. -- */ -- phys_addr_t addr = __memblock_alloc_base(size, alignment, limit); -- if (!addr) { -- ret = -ENOMEM; -- goto err; -- } else { -- base = addr; -- } -- } -- -- /* -- * Each reserved area must be initialised later, when more kernel -- * subsystems (like slab allocator) are available. -- */ -- cma->base_pfn = PFN_DOWN(base); -- cma->count = size >> PAGE_SHIFT; -- *res_cma = cma; -- cma_area_count++; -+ int ret; - -- pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M, -- (unsigned long)base); -+ ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma); -+ if (ret) -+ return ret; - - /* Architecture specific contiguous memory fixup. */ -- dma_contiguous_early_fixup(base, size); -+ dma_contiguous_early_fixup(cma_get_base(*res_cma), -+ cma_get_size(*res_cma)); -+ - return 0; --err: -- pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M); -- return ret; - } - - /** -@@ -279,57 +184,16 @@ - * - * This function allocates memory buffer for specified device. It uses - * device specific contiguous memory area if available or the default -- * global one. Requires architecture specific get_dev_cma_area() helper -+ * global one. Requires architecture specific dev_get_cma_area() helper - * function. - */ - struct page *dma_alloc_from_contiguous(struct device *dev, int count, - unsigned int align) - { -- unsigned long mask, pfn, pageno, start = 0; -- struct cma *cma = dev_get_cma_area(dev); -- struct page *page = NULL; -- int ret; -- -- if (!cma || !cma->count) -- return NULL; -- - if (align > CONFIG_CMA_ALIGNMENT) - align = CONFIG_CMA_ALIGNMENT; - -- pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma, -- count, align); -- -- if (!count) -- return NULL; -- -- mask = (1 << align) - 1; -- -- mutex_lock(&cma_mutex); -- -- for (;;) { -- pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count, -- start, count, mask); -- if (pageno >= cma->count) -- break; -- -- pfn = cma->base_pfn + pageno; -- ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA); -- if (ret == 0) { -- bitmap_set(cma->bitmap, pageno, count); -- page = pfn_to_page(pfn); -- break; -- } else if (ret != -EBUSY) { -- break; -- } -- pr_debug("%s(): memory range at %p is busy, retrying\n", -- __func__, pfn_to_page(pfn)); -- /* try again with a bit different memory target */ -- start = pageno + mask + 1; -- } -- -- mutex_unlock(&cma_mutex); -- pr_debug("%s(): returned %p\n", __func__, page); -- return page; -+ return cma_alloc(dev_get_cma_area(dev), count, align); - } - - /** -@@ -345,25 +209,5 @@ - bool dma_release_from_contiguous(struct device *dev, struct page *pages, - int count) - { -- struct cma *cma = dev_get_cma_area(dev); -- unsigned long pfn; -- -- if (!cma || !pages) -- return false; -- -- pr_debug("%s(page %p)\n", __func__, (void *)pages); -- -- pfn = page_to_pfn(pages); -- -- if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count) -- return false; -- -- VM_BUG_ON(pfn + count > cma->base_pfn + cma->count); -- -- mutex_lock(&cma_mutex); -- bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count); -- free_contig_range(pfn, count); -- mutex_unlock(&cma_mutex); -- -- return true; -+ return cma_release(dev_get_cma_area(dev), pages, count); - } -diff -Nur linux-3.14.22.orig/drivers/base/Kconfig linux-3.14.22/drivers/base/Kconfig ---- linux-3.14.22.orig/drivers/base/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/base/Kconfig 2014-10-22 14:55:52.022220001 -0500 -@@ -185,6 +185,14 @@ - bool - default n - -+config HAVE_CPU_AUTOPROBE -+ def_bool ARCH_HAS_CPU_AUTOPROBE -+ -+config GENERIC_CPU_AUTOPROBE -+ bool -+ depends on !ARCH_HAS_CPU_AUTOPROBE -+ select HAVE_CPU_AUTOPROBE -+ - config SOC_BUS - bool - -@@ -266,16 +274,6 @@ - - If unsure, leave the default value "8". - --config CMA_AREAS -- int "Maximum count of the CMA device-private areas" -- default 7 -- help -- CMA allows to create CMA areas for particular devices. This parameter -- sets the maximum number of such device private CMA areas in the -- system. -- -- If unsure, leave the default value "7". -- - endif - - endmenu -diff -Nur linux-3.14.22.orig/drivers/bus/arm-cci.c linux-3.14.22/drivers/bus/arm-cci.c ---- linux-3.14.22.orig/drivers/bus/arm-cci.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/bus/arm-cci.c 2014-10-22 14:55:52.022220001 -0500 -@@ -26,6 +26,7 @@ - - #include - #include -+#include - #include - #include - -@@ -544,6 +545,7 @@ - - cci_pmu->plat_device = pdev; - cci_pmu->num_events = pmu_get_max_counters(); -+ cpumask_setall(&cci_pmu->valid_cpus); - - return armpmu_register(cci_pmu, -1); - } -@@ -969,6 +971,11 @@ - const char *match_str; - bool is_ace; - -+ if (psci_probe() == 0) { -+ pr_debug("psci found. Aborting cci probe\n"); -+ return -ENODEV; -+ } -+ - np = of_find_matching_node(NULL, arm_cci_matches); - if (!np) - return -ENODEV; -diff -Nur linux-3.14.22.orig/drivers/char/fsl_otp.c linux-3.14.22/drivers/char/fsl_otp.c ---- linux-3.14.22.orig/drivers/char/fsl_otp.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/char/fsl_otp.c 2014-10-22 14:55:52.026220001 -0500 -@@ -0,0 +1,299 @@ -+/* -+ * Freescale On-Chip OTP driver -+ * -+ * Copyright (C) 2010-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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define HW_OCOTP_CTRL 0x00000000 -+#define HW_OCOTP_CTRL_SET 0x00000004 -+#define BP_OCOTP_CTRL_WR_UNLOCK 16 -+#define BM_OCOTP_CTRL_WR_UNLOCK 0xFFFF0000 -+#define BM_OCOTP_CTRL_RELOAD_SHADOWS 0x00000400 -+#define BM_OCOTP_CTRL_ERROR 0x00000200 -+#define BM_OCOTP_CTRL_BUSY 0x00000100 -+#define BP_OCOTP_CTRL_ADDR 0 -+#define BM_OCOTP_CTRL_ADDR 0x0000007F -+ -+#define HW_OCOTP_TIMING 0x00000010 -+#define BP_OCOTP_TIMING_STROBE_READ 16 -+#define BM_OCOTP_TIMING_STROBE_READ 0x003F0000 -+#define BP_OCOTP_TIMING_RELAX 12 -+#define BM_OCOTP_TIMING_RELAX 0x0000F000 -+#define BP_OCOTP_TIMING_STROBE_PROG 0 -+#define BM_OCOTP_TIMING_STROBE_PROG 0x00000FFF -+ -+#define HW_OCOTP_DATA 0x00000020 -+ -+#define HW_OCOTP_CUST_N(n) (0x00000400 + (n) * 0x10) -+#define BF(value, field) (((value) << BP_##field) & BM_##field) -+ -+#define DEF_RELAX 20 /* > 16.5ns */ -+ -+#define BANK(a, b, c, d, e, f, g, h) { \ -+ "HW_OCOTP_"#a, "HW_OCOTP_"#b, "HW_OCOTP_"#c, "HW_OCOTP_"#d, \ -+ "HW_OCOTP_"#e, "HW_OCOTP_"#f, "HW_OCOTP_"#g, "HW_OCOTP_"#h, \ -+} -+ -+static const char *imx6q_otp_desc[16][8] = { -+ BANK(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6), -+ BANK(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2), -+ BANK(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7), -+ BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7), -+ BANK(RESP0, HSJC_RESP1, MAC0, MAC1, HDCP_KSV0, HDCP_KSV1, GP1, GP2), -+ BANK(DTCP_KEY0, DTCP_KEY1, DTCP_KEY2, DTCP_KEY3, DTCP_KEY4, MISC_CONF, FIELD_RETURN, SRK_REVOKE), -+ BANK(HDCP_KEY0, HDCP_KEY1, HDCP_KEY2, HDCP_KEY3, HDCP_KEY4, HDCP_KEY5, HDCP_KEY6, HDCP_KEY7), -+ BANK(HDCP_KEY8, HDCP_KEY9, HDCP_KEY10, HDCP_KEY11, HDCP_KEY12, HDCP_KEY13, HDCP_KEY14, HDCP_KEY15), -+ BANK(HDCP_KEY16, HDCP_KEY17, HDCP_KEY18, HDCP_KEY19, HDCP_KEY20, HDCP_KEY21, HDCP_KEY22, HDCP_KEY23), -+ BANK(HDCP_KEY24, HDCP_KEY25, HDCP_KEY26, HDCP_KEY27, HDCP_KEY28, HDCP_KEY29, HDCP_KEY30, HDCP_KEY31), -+ BANK(HDCP_KEY32, HDCP_KEY33, HDCP_KEY34, HDCP_KEY35, HDCP_KEY36, HDCP_KEY37, HDCP_KEY38, HDCP_KEY39), -+ BANK(HDCP_KEY40, HDCP_KEY41, HDCP_KEY42, HDCP_KEY43, HDCP_KEY44, HDCP_KEY45, HDCP_KEY46, HDCP_KEY47), -+ BANK(HDCP_KEY48, HDCP_KEY49, HDCP_KEY50, HDCP_KEY51, HDCP_KEY52, HDCP_KEY53, HDCP_KEY54, HDCP_KEY55), -+ BANK(HDCP_KEY56, HDCP_KEY57, HDCP_KEY58, HDCP_KEY59, HDCP_KEY60, HDCP_KEY61, HDCP_KEY62, HDCP_KEY63), -+ BANK(HDCP_KEY64, HDCP_KEY65, HDCP_KEY66, HDCP_KEY67, HDCP_KEY68, HDCP_KEY69, HDCP_KEY70, HDCP_KEY71), -+ BANK(CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6, CRC7), -+}; -+ -+static DEFINE_MUTEX(otp_mutex); -+static void __iomem *otp_base; -+static struct clk *otp_clk; -+struct kobject *otp_kobj; -+struct kobj_attribute *otp_kattr; -+struct attribute_group *otp_attr_group; -+ -+static void set_otp_timing(void) -+{ -+ unsigned long clk_rate = 0; -+ unsigned long strobe_read, relex, strobe_prog; -+ u32 timing = 0; -+ -+ clk_rate = clk_get_rate(otp_clk); -+ -+ /* do optimization for too many zeros */ -+ relex = clk_rate / (1000000000 / DEF_RELAX) - 1; -+ strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; -+ strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; -+ -+ timing = BF(relex, OCOTP_TIMING_RELAX); -+ timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ); -+ timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG); -+ -+ __raw_writel(timing, otp_base + HW_OCOTP_TIMING); -+} -+ -+static int otp_wait_busy(u32 flags) -+{ -+ int count; -+ u32 c; -+ -+ for (count = 10000; count >= 0; count--) { -+ c = __raw_readl(otp_base + HW_OCOTP_CTRL); -+ if (!(c & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR | flags))) -+ break; -+ cpu_relax(); -+ } -+ -+ if (count < 0) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr, -+ char *buf) -+{ -+ unsigned int index = attr - otp_kattr; -+ u32 value = 0; -+ int ret; -+ -+ ret = clk_prepare_enable(otp_clk); -+ if (ret) -+ return 0; -+ -+ mutex_lock(&otp_mutex); -+ -+ set_otp_timing(); -+ ret = otp_wait_busy(0); -+ if (ret) -+ goto out; -+ -+ value = __raw_readl(otp_base + HW_OCOTP_CUST_N(index)); -+ -+out: -+ mutex_unlock(&otp_mutex); -+ clk_disable_unprepare(otp_clk); -+ return ret ? 0 : sprintf(buf, "0x%x\n", value); -+} -+ -+static int otp_write_bits(int addr, u32 data, u32 magic) -+{ -+ u32 c; /* for control register */ -+ -+ /* init the control register */ -+ c = __raw_readl(otp_base + HW_OCOTP_CTRL); -+ c &= ~BM_OCOTP_CTRL_ADDR; -+ c |= BF(addr, OCOTP_CTRL_ADDR); -+ c |= BF(magic, OCOTP_CTRL_WR_UNLOCK); -+ __raw_writel(c, otp_base + HW_OCOTP_CTRL); -+ -+ /* init the data register */ -+ __raw_writel(data, otp_base + HW_OCOTP_DATA); -+ otp_wait_busy(0); -+ -+ mdelay(2); /* Write Postamble */ -+ -+ return 0; -+} -+ -+static ssize_t fsl_otp_store(struct kobject *kobj, struct kobj_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned int index = attr - otp_kattr; -+ u32 value; -+ int ret; -+ -+ sscanf(buf, "0x%x", &value); -+ -+ ret = clk_prepare_enable(otp_clk); -+ if (ret) -+ return 0; -+ -+ mutex_lock(&otp_mutex); -+ -+ set_otp_timing(); -+ ret = otp_wait_busy(0); -+ if (ret) -+ goto out; -+ -+ otp_write_bits(index, value, 0x3e77); -+ -+ /* Reload all the shadow registers */ -+ __raw_writel(BM_OCOTP_CTRL_RELOAD_SHADOWS, -+ otp_base + HW_OCOTP_CTRL_SET); -+ udelay(1); -+ otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS); -+ -+out: -+ mutex_unlock(&otp_mutex); -+ clk_disable_unprepare(otp_clk); -+ return ret ? 0 : count; -+} -+ -+static int fsl_otp_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct attribute **attrs; -+ const char **desc; -+ int i, num; -+ int ret; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ otp_base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(otp_base)) { -+ ret = PTR_ERR(otp_base); -+ dev_err(&pdev->dev, "failed to ioremap resource: %d\n", ret); -+ return ret; -+ } -+ -+ otp_clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(otp_clk)) { -+ ret = PTR_ERR(otp_clk); -+ dev_err(&pdev->dev, "failed to get clock: %d\n", ret); -+ return ret; -+ } -+ -+ desc = (const char **) imx6q_otp_desc; -+ num = sizeof(imx6q_otp_desc) / sizeof(void *); -+ -+ /* The last one is NULL, which is used to detect the end */ -+ attrs = devm_kzalloc(&pdev->dev, (num + 1) * sizeof(*attrs), -+ GFP_KERNEL); -+ otp_kattr = devm_kzalloc(&pdev->dev, num * sizeof(*otp_kattr), -+ GFP_KERNEL); -+ otp_attr_group = devm_kzalloc(&pdev->dev, sizeof(*otp_attr_group), -+ GFP_KERNEL); -+ if (!attrs || !otp_kattr || !otp_attr_group) -+ return -ENOMEM; -+ -+ for (i = 0; i < num; i++) { -+ sysfs_attr_init(&otp_kattr[i].attr); -+ otp_kattr[i].attr.name = desc[i]; -+ otp_kattr[i].attr.mode = 0600; -+ otp_kattr[i].show = fsl_otp_show; -+ otp_kattr[i].store = fsl_otp_store; -+ attrs[i] = &otp_kattr[i].attr; -+ } -+ otp_attr_group->attrs = attrs; -+ -+ otp_kobj = kobject_create_and_add("fsl_otp", NULL); -+ if (!otp_kobj) { -+ dev_err(&pdev->dev, "failed to add kobject\n"); -+ return -ENOMEM; -+ } -+ -+ ret = sysfs_create_group(otp_kobj, otp_attr_group); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret); -+ kobject_put(otp_kobj); -+ return ret; -+ } -+ -+ mutex_init(&otp_mutex); -+ -+ return 0; -+} -+ -+static int fsl_otp_remove(struct platform_device *pdev) -+{ -+ sysfs_remove_group(otp_kobj, otp_attr_group); -+ kobject_put(otp_kobj); -+ -+ return 0; -+} -+ -+static const struct of_device_id fsl_otp_dt_ids[] = { -+ { .compatible = "fsl,imx6q-ocotp", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, fsl_otp_dt_ids); -+ -+static struct platform_driver fsl_otp_driver = { -+ .driver = { -+ .name = "imx-ocotp", -+ .owner = THIS_MODULE, -+ .of_match_table = fsl_otp_dt_ids, -+ }, -+ .probe = fsl_otp_probe, -+ .remove = fsl_otp_remove, -+}; -+module_platform_driver(fsl_otp_driver); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Huang Shijie "); -+MODULE_DESCRIPTION("Freescale i.MX OCOTP driver"); -diff -Nur linux-3.14.22.orig/drivers/char/Kconfig linux-3.14.22/drivers/char/Kconfig ---- linux-3.14.22.orig/drivers/char/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/char/Kconfig 2014-10-22 14:55:52.026220001 -0500 -@@ -82,6 +82,21 @@ - - If unsure, say N. - -+config FSL_OTP -+ tristate "Freescale On-Chip OTP Memory Support" -+ depends on HAS_IOMEM && OF -+ help -+ If you say Y here, you will get support for a character device -+ interface into the One Time Programmable memory pages that are -+ stored on the some Freescale i.MX processors. This will not get -+ you access to the secure memory pages however. You will need to -+ write your own secure code and reader for that. -+ -+ To compile this driver as a module, choose M here: the module -+ will be called fsl_otp. -+ -+ If unsure, it is safe to say Y. -+ - config PRINTER - tristate "Parallel printer support" - depends on PARPORT -diff -Nur linux-3.14.22.orig/drivers/char/Makefile linux-3.14.22/drivers/char/Makefile ---- linux-3.14.22.orig/drivers/char/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/char/Makefile 2014-10-22 14:55:52.026220001 -0500 -@@ -16,6 +16,7 @@ - obj-$(CONFIG_IBM_BSR) += bsr.o - obj-$(CONFIG_SGI_MBCS) += mbcs.o - obj-$(CONFIG_BFIN_OTP) += bfin-otp.o -+obj-$(CONFIG_FSL_OTP) += fsl_otp.o - - obj-$(CONFIG_PRINTER) += lp.o - -diff -Nur linux-3.14.22.orig/drivers/clk/clk.c linux-3.14.22/drivers/clk/clk.c ---- linux-3.14.22.orig/drivers/clk/clk.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/clk/clk.c 2014-10-22 14:55:52.026220001 -0500 -@@ -1707,6 +1707,7 @@ - */ - int clk_set_parent(struct clk *clk, struct clk *parent) - { -+ struct clk *child; - int ret = 0; - int p_index = 0; - unsigned long p_rate = 0; -@@ -1733,6 +1734,18 @@ - goto out; - } - -+ /* check two consecutive basic mux clocks */ -+ if (clk->flags & CLK_IS_BASIC_MUX) { -+ hlist_for_each_entry(child, &clk->children, child_node) { -+ if (child->flags & CLK_IS_BASIC_MUX) { -+ pr_err("%s: failed to switch parent of %s due to child mux %s\n", -+ __func__, clk->name, child->name); -+ ret = -EBUSY; -+ goto out; -+ } -+ } -+ } -+ - /* try finding the new parent index */ - if (parent) { - p_index = clk_fetch_parent_index(clk, parent); -diff -Nur linux-3.14.22.orig/drivers/clk/clk-mux.c linux-3.14.22/drivers/clk/clk-mux.c ---- linux-3.14.22.orig/drivers/clk/clk-mux.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/clk/clk-mux.c 2014-10-22 14:55:52.026220001 -0500 -@@ -143,7 +143,7 @@ - init.ops = &clk_mux_ro_ops; - else - init.ops = &clk_mux_ops; -- init.flags = flags | CLK_IS_BASIC; -+ init.flags = flags | CLK_IS_BASIC | CLK_IS_BASIC_MUX; - init.parent_names = parent_names; - init.num_parents = num_parents; - -diff -Nur linux-3.14.22.orig/drivers/cpufreq/cpufreq_interactive.c linux-3.14.22/drivers/cpufreq/cpufreq_interactive.c ---- linux-3.14.22.orig/drivers/cpufreq/cpufreq_interactive.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/cpufreq/cpufreq_interactive.c 2014-10-22 14:55:52.026220001 -0500 -@@ -0,0 +1,1349 @@ -+/* -+ * drivers/cpufreq/cpufreq_interactive.c -+ * -+ * Copyright (C) 2010 Google, Inc. -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * Author: Mike Chan (mike@android.com) -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CREATE_TRACE_POINTS -+#include -+ -+struct cpufreq_interactive_cpuinfo { -+ struct timer_list cpu_timer; -+ struct timer_list cpu_slack_timer; -+ spinlock_t load_lock; /* protects the next 4 fields */ -+ u64 time_in_idle; -+ u64 time_in_idle_timestamp; -+ u64 cputime_speedadj; -+ u64 cputime_speedadj_timestamp; -+ struct cpufreq_policy *policy; -+ struct cpufreq_frequency_table *freq_table; -+ unsigned int target_freq; -+ unsigned int floor_freq; -+ u64 floor_validate_time; -+ u64 hispeed_validate_time; -+ struct rw_semaphore enable_sem; -+ int governor_enabled; -+}; -+ -+static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo); -+ -+/* realtime thread handles frequency scaling */ -+static struct task_struct *speedchange_task; -+static cpumask_t speedchange_cpumask; -+static spinlock_t speedchange_cpumask_lock; -+static struct mutex gov_lock; -+ -+/* Target load. Lower values result in higher CPU speeds. */ -+#define DEFAULT_TARGET_LOAD 90 -+static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; -+ -+#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC) -+#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE -+static unsigned int default_above_hispeed_delay[] = { -+ DEFAULT_ABOVE_HISPEED_DELAY }; -+ -+struct cpufreq_interactive_tunables { -+ int usage_count; -+ /* Hi speed to bump to from lo speed when load burst (default max) */ -+ unsigned int hispeed_freq; -+ /* Go to hi speed when CPU load at or above this value. */ -+#define DEFAULT_GO_HISPEED_LOAD 99 -+ unsigned long go_hispeed_load; -+ /* Target load. Lower values result in higher CPU speeds. */ -+ spinlock_t target_loads_lock; -+ unsigned int *target_loads; -+ int ntarget_loads; -+ /* -+ * The minimum amount of time to spend at a frequency before we can ramp -+ * down. -+ */ -+#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC) -+ unsigned long min_sample_time; -+ /* -+ * The sample rate of the timer used to increase frequency -+ */ -+ unsigned long timer_rate; -+ /* -+ * Wait this long before raising speed above hispeed, by default a -+ * single timer interval. -+ */ -+ spinlock_t above_hispeed_delay_lock; -+ unsigned int *above_hispeed_delay; -+ int nabove_hispeed_delay; -+ /* Non-zero means indefinite speed boost active */ -+ int boost_val; -+ /* Duration of a boot pulse in usecs */ -+ int boostpulse_duration_val; -+ /* End time of boost pulse in ktime converted to usecs */ -+ u64 boostpulse_endtime; -+ /* -+ * Max additional time to wait in idle, beyond timer_rate, at speeds -+ * above minimum before wakeup to reduce speed, or -1 if unnecessary. -+ */ -+#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE) -+ int timer_slack_val; -+ bool io_is_busy; -+}; -+ -+/* For cases where we have single governor instance for system */ -+struct cpufreq_interactive_tunables *common_tunables; -+ -+static struct attribute_group *get_sysfs_attr(void); -+ -+static void cpufreq_interactive_timer_resched( -+ struct cpufreq_interactive_cpuinfo *pcpu) -+{ -+ struct cpufreq_interactive_tunables *tunables = -+ pcpu->policy->governor_data; -+ unsigned long expires; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pcpu->load_lock, flags); -+ pcpu->time_in_idle = -+ get_cpu_idle_time(smp_processor_id(), -+ &pcpu->time_in_idle_timestamp, -+ tunables->io_is_busy); -+ pcpu->cputime_speedadj = 0; -+ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; -+ expires = jiffies + usecs_to_jiffies(tunables->timer_rate); -+ mod_timer_pinned(&pcpu->cpu_timer, expires); -+ -+ if (tunables->timer_slack_val >= 0 && -+ pcpu->target_freq > pcpu->policy->min) { -+ expires += usecs_to_jiffies(tunables->timer_slack_val); -+ mod_timer_pinned(&pcpu->cpu_slack_timer, expires); -+ } -+ -+ spin_unlock_irqrestore(&pcpu->load_lock, flags); -+} -+ -+/* The caller shall take enable_sem write semaphore to avoid any timer race. -+ * The cpu_timer and cpu_slack_timer must be deactivated when calling this -+ * function. -+ */ -+static void cpufreq_interactive_timer_start( -+ struct cpufreq_interactive_tunables *tunables, int cpu) -+{ -+ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); -+ unsigned long expires = jiffies + -+ usecs_to_jiffies(tunables->timer_rate); -+ unsigned long flags; -+ -+ pcpu->cpu_timer.expires = expires; -+ add_timer_on(&pcpu->cpu_timer, cpu); -+ if (tunables->timer_slack_val >= 0 && -+ pcpu->target_freq > pcpu->policy->min) { -+ expires += usecs_to_jiffies(tunables->timer_slack_val); -+ pcpu->cpu_slack_timer.expires = expires; -+ add_timer_on(&pcpu->cpu_slack_timer, cpu); -+ } -+ -+ spin_lock_irqsave(&pcpu->load_lock, flags); -+ pcpu->time_in_idle = -+ get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp, -+ tunables->io_is_busy); -+ pcpu->cputime_speedadj = 0; -+ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; -+ spin_unlock_irqrestore(&pcpu->load_lock, flags); -+} -+ -+static unsigned int freq_to_above_hispeed_delay( -+ struct cpufreq_interactive_tunables *tunables, -+ unsigned int freq) -+{ -+ int i; -+ unsigned int ret; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); -+ -+ for (i = 0; i < tunables->nabove_hispeed_delay - 1 && -+ freq >= tunables->above_hispeed_delay[i+1]; i += 2) -+ ; -+ -+ ret = tunables->above_hispeed_delay[i]; -+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); -+ return ret; -+} -+ -+static unsigned int freq_to_targetload( -+ struct cpufreq_interactive_tunables *tunables, unsigned int freq) -+{ -+ int i; -+ unsigned int ret; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&tunables->target_loads_lock, flags); -+ -+ for (i = 0; i < tunables->ntarget_loads - 1 && -+ freq >= tunables->target_loads[i+1]; i += 2) -+ ; -+ -+ ret = tunables->target_loads[i]; -+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); -+ return ret; -+} -+ -+/* -+ * If increasing frequencies never map to a lower target load then -+ * choose_freq() will find the minimum frequency that does not exceed its -+ * target load given the current load. -+ */ -+static unsigned int choose_freq(struct cpufreq_interactive_cpuinfo *pcpu, -+ unsigned int loadadjfreq) -+{ -+ unsigned int freq = pcpu->policy->cur; -+ unsigned int prevfreq, freqmin, freqmax; -+ unsigned int tl; -+ int index; -+ -+ freqmin = 0; -+ freqmax = UINT_MAX; -+ -+ do { -+ prevfreq = freq; -+ tl = freq_to_targetload(pcpu->policy->governor_data, freq); -+ -+ /* -+ * Find the lowest frequency where the computed load is less -+ * than or equal to the target load. -+ */ -+ -+ if (cpufreq_frequency_table_target( -+ pcpu->policy, pcpu->freq_table, loadadjfreq / tl, -+ CPUFREQ_RELATION_L, &index)) -+ break; -+ freq = pcpu->freq_table[index].frequency; -+ -+ if (freq > prevfreq) { -+ /* The previous frequency is too low. */ -+ freqmin = prevfreq; -+ -+ if (freq >= freqmax) { -+ /* -+ * Find the highest frequency that is less -+ * than freqmax. -+ */ -+ if (cpufreq_frequency_table_target( -+ pcpu->policy, pcpu->freq_table, -+ freqmax - 1, CPUFREQ_RELATION_H, -+ &index)) -+ break; -+ freq = pcpu->freq_table[index].frequency; -+ -+ if (freq == freqmin) { -+ /* -+ * The first frequency below freqmax -+ * has already been found to be too -+ * low. freqmax is the lowest speed -+ * we found that is fast enough. -+ */ -+ freq = freqmax; -+ break; -+ } -+ } -+ } else if (freq < prevfreq) { -+ /* The previous frequency is high enough. */ -+ freqmax = prevfreq; -+ -+ if (freq <= freqmin) { -+ /* -+ * Find the lowest frequency that is higher -+ * than freqmin. -+ */ -+ if (cpufreq_frequency_table_target( -+ pcpu->policy, pcpu->freq_table, -+ freqmin + 1, CPUFREQ_RELATION_L, -+ &index)) -+ break; -+ freq = pcpu->freq_table[index].frequency; -+ -+ /* -+ * If freqmax is the first frequency above -+ * freqmin then we have already found that -+ * this speed is fast enough. -+ */ -+ if (freq == freqmax) -+ break; -+ } -+ } -+ -+ /* If same frequency chosen as previous then done. */ -+ } while (freq != prevfreq); -+ -+ return freq; -+} -+ -+static u64 update_load(int cpu) -+{ -+ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); -+ struct cpufreq_interactive_tunables *tunables = -+ pcpu->policy->governor_data; -+ u64 now; -+ u64 now_idle; -+ unsigned int delta_idle; -+ unsigned int delta_time; -+ u64 active_time; -+ -+ now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy); -+ delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle); -+ delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp); -+ -+ if (delta_time <= delta_idle) -+ active_time = 0; -+ else -+ active_time = delta_time - delta_idle; -+ -+ pcpu->cputime_speedadj += active_time * pcpu->policy->cur; -+ -+ pcpu->time_in_idle = now_idle; -+ pcpu->time_in_idle_timestamp = now; -+ return now; -+} -+ -+static void cpufreq_interactive_timer(unsigned long data) -+{ -+ u64 now; -+ unsigned int delta_time; -+ u64 cputime_speedadj; -+ int cpu_load; -+ struct cpufreq_interactive_cpuinfo *pcpu = -+ &per_cpu(cpuinfo, data); -+ struct cpufreq_interactive_tunables *tunables = -+ pcpu->policy->governor_data; -+ unsigned int new_freq; -+ unsigned int loadadjfreq; -+ unsigned int index; -+ unsigned long flags; -+ bool boosted; -+ -+ if (!down_read_trylock(&pcpu->enable_sem)) -+ return; -+ if (!pcpu->governor_enabled) -+ goto exit; -+ -+ spin_lock_irqsave(&pcpu->load_lock, flags); -+ now = update_load(data); -+ delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp); -+ cputime_speedadj = pcpu->cputime_speedadj; -+ spin_unlock_irqrestore(&pcpu->load_lock, flags); -+ -+ if (WARN_ON_ONCE(!delta_time)) -+ goto rearm; -+ -+ do_div(cputime_speedadj, delta_time); -+ loadadjfreq = (unsigned int)cputime_speedadj * 100; -+ cpu_load = loadadjfreq / pcpu->target_freq; -+ boosted = tunables->boost_val || now < tunables->boostpulse_endtime; -+ -+ if (cpu_load >= tunables->go_hispeed_load || boosted) { -+ if (pcpu->target_freq < tunables->hispeed_freq) { -+ new_freq = tunables->hispeed_freq; -+ } else { -+ new_freq = choose_freq(pcpu, loadadjfreq); -+ -+ if (new_freq < tunables->hispeed_freq) -+ new_freq = tunables->hispeed_freq; -+ } -+ } else { -+ new_freq = choose_freq(pcpu, loadadjfreq); -+ } -+ -+ if (pcpu->target_freq >= tunables->hispeed_freq && -+ new_freq > pcpu->target_freq && -+ now - pcpu->hispeed_validate_time < -+ freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) { -+ trace_cpufreq_interactive_notyet( -+ data, cpu_load, pcpu->target_freq, -+ pcpu->policy->cur, new_freq); -+ goto rearm; -+ } -+ -+ pcpu->hispeed_validate_time = now; -+ -+ if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, -+ new_freq, CPUFREQ_RELATION_L, -+ &index)) -+ goto rearm; -+ -+ new_freq = pcpu->freq_table[index].frequency; -+ -+ /* -+ * Do not scale below floor_freq unless we have been at or above the -+ * floor frequency for the minimum sample time since last validated. -+ */ -+ if (new_freq < pcpu->floor_freq) { -+ if (now - pcpu->floor_validate_time < -+ tunables->min_sample_time) { -+ trace_cpufreq_interactive_notyet( -+ data, cpu_load, pcpu->target_freq, -+ pcpu->policy->cur, new_freq); -+ goto rearm; -+ } -+ } -+ -+ /* -+ * Update the timestamp for checking whether speed has been held at -+ * or above the selected frequency for a minimum of min_sample_time, -+ * if not boosted to hispeed_freq. If boosted to hispeed_freq then we -+ * allow the speed to drop as soon as the boostpulse duration expires -+ * (or the indefinite boost is turned off). -+ */ -+ -+ if (!boosted || new_freq > tunables->hispeed_freq) { -+ pcpu->floor_freq = new_freq; -+ pcpu->floor_validate_time = now; -+ } -+ -+ if (pcpu->target_freq == new_freq) { -+ trace_cpufreq_interactive_already( -+ data, cpu_load, pcpu->target_freq, -+ pcpu->policy->cur, new_freq); -+ goto rearm_if_notmax; -+ } -+ -+ trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq, -+ pcpu->policy->cur, new_freq); -+ -+ pcpu->target_freq = new_freq; -+ spin_lock_irqsave(&speedchange_cpumask_lock, flags); -+ cpumask_set_cpu(data, &speedchange_cpumask); -+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); -+ wake_up_process(speedchange_task); -+ -+rearm_if_notmax: -+ /* -+ * Already set max speed and don't see a need to change that, -+ * wait until next idle to re-evaluate, don't need timer. -+ */ -+ if (pcpu->target_freq == pcpu->policy->max) -+ goto exit; -+ -+rearm: -+ if (!timer_pending(&pcpu->cpu_timer)) -+ cpufreq_interactive_timer_resched(pcpu); -+ -+exit: -+ up_read(&pcpu->enable_sem); -+ return; -+} -+ -+static void cpufreq_interactive_idle_start(void) -+{ -+ struct cpufreq_interactive_cpuinfo *pcpu = -+ &per_cpu(cpuinfo, smp_processor_id()); -+ int pending; -+ -+ if (!down_read_trylock(&pcpu->enable_sem)) -+ return; -+ if (!pcpu->governor_enabled) { -+ up_read(&pcpu->enable_sem); -+ return; -+ } -+ -+ pending = timer_pending(&pcpu->cpu_timer); -+ -+ if (pcpu->target_freq != pcpu->policy->min) { -+ /* -+ * Entering idle while not at lowest speed. On some -+ * platforms this can hold the other CPU(s) at that speed -+ * even though the CPU is idle. Set a timer to re-evaluate -+ * speed so this idle CPU doesn't hold the other CPUs above -+ * min indefinitely. This should probably be a quirk of -+ * the CPUFreq driver. -+ */ -+ if (!pending) -+ cpufreq_interactive_timer_resched(pcpu); -+ } -+ -+ up_read(&pcpu->enable_sem); -+} -+ -+static void cpufreq_interactive_idle_end(void) -+{ -+ struct cpufreq_interactive_cpuinfo *pcpu = -+ &per_cpu(cpuinfo, smp_processor_id()); -+ -+ if (!down_read_trylock(&pcpu->enable_sem)) -+ return; -+ if (!pcpu->governor_enabled) { -+ up_read(&pcpu->enable_sem); -+ return; -+ } -+ -+ /* Arm the timer for 1-2 ticks later if not already. */ -+ if (!timer_pending(&pcpu->cpu_timer)) { -+ cpufreq_interactive_timer_resched(pcpu); -+ } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) { -+ del_timer(&pcpu->cpu_timer); -+ del_timer(&pcpu->cpu_slack_timer); -+ cpufreq_interactive_timer(smp_processor_id()); -+ } -+ -+ up_read(&pcpu->enable_sem); -+} -+ -+static int cpufreq_interactive_speedchange_task(void *data) -+{ -+ unsigned int cpu; -+ cpumask_t tmp_mask; -+ unsigned long flags; -+ struct cpufreq_interactive_cpuinfo *pcpu; -+ -+ while (1) { -+ set_current_state(TASK_INTERRUPTIBLE); -+ spin_lock_irqsave(&speedchange_cpumask_lock, flags); -+ -+ if (cpumask_empty(&speedchange_cpumask)) { -+ spin_unlock_irqrestore(&speedchange_cpumask_lock, -+ flags); -+ schedule(); -+ -+ if (kthread_should_stop()) -+ break; -+ -+ spin_lock_irqsave(&speedchange_cpumask_lock, flags); -+ } -+ -+ set_current_state(TASK_RUNNING); -+ tmp_mask = speedchange_cpumask; -+ cpumask_clear(&speedchange_cpumask); -+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); -+ -+ for_each_cpu(cpu, &tmp_mask) { -+ unsigned int j; -+ unsigned int max_freq = 0; -+ -+ pcpu = &per_cpu(cpuinfo, cpu); -+ if (!down_read_trylock(&pcpu->enable_sem)) -+ continue; -+ if (!pcpu->governor_enabled) { -+ up_read(&pcpu->enable_sem); -+ continue; -+ } -+ -+ for_each_cpu(j, pcpu->policy->cpus) { -+ struct cpufreq_interactive_cpuinfo *pjcpu = -+ &per_cpu(cpuinfo, j); -+ -+ if (pjcpu->target_freq > max_freq) -+ max_freq = pjcpu->target_freq; -+ } -+ -+ if (max_freq != pcpu->policy->cur) -+ __cpufreq_driver_target(pcpu->policy, -+ max_freq, -+ CPUFREQ_RELATION_H); -+ trace_cpufreq_interactive_setspeed(cpu, -+ pcpu->target_freq, -+ pcpu->policy->cur); -+ -+ up_read(&pcpu->enable_sem); -+ } -+ } -+ -+ return 0; -+} -+ -+static void cpufreq_interactive_boost(void) -+{ -+ int i; -+ int anyboost = 0; -+ unsigned long flags; -+ struct cpufreq_interactive_cpuinfo *pcpu; -+ struct cpufreq_interactive_tunables *tunables; -+ -+ spin_lock_irqsave(&speedchange_cpumask_lock, flags); -+ -+ for_each_online_cpu(i) { -+ pcpu = &per_cpu(cpuinfo, i); -+ tunables = pcpu->policy->governor_data; -+ -+ if (pcpu->target_freq < tunables->hispeed_freq) { -+ pcpu->target_freq = tunables->hispeed_freq; -+ cpumask_set_cpu(i, &speedchange_cpumask); -+ pcpu->hispeed_validate_time = -+ ktime_to_us(ktime_get()); -+ anyboost = 1; -+ } -+ -+ /* -+ * Set floor freq and (re)start timer for when last -+ * validated. -+ */ -+ -+ pcpu->floor_freq = tunables->hispeed_freq; -+ pcpu->floor_validate_time = ktime_to_us(ktime_get()); -+ } -+ -+ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); -+ -+ if (anyboost) -+ wake_up_process(speedchange_task); -+} -+ -+static int cpufreq_interactive_notifier( -+ struct notifier_block *nb, unsigned long val, void *data) -+{ -+ struct cpufreq_freqs *freq = data; -+ struct cpufreq_interactive_cpuinfo *pcpu; -+ int cpu; -+ unsigned long flags; -+ -+ if (val == CPUFREQ_POSTCHANGE) { -+ pcpu = &per_cpu(cpuinfo, freq->cpu); -+ if (!down_read_trylock(&pcpu->enable_sem)) -+ return 0; -+ if (!pcpu->governor_enabled) { -+ up_read(&pcpu->enable_sem); -+ return 0; -+ } -+ -+ for_each_cpu(cpu, pcpu->policy->cpus) { -+ struct cpufreq_interactive_cpuinfo *pjcpu = -+ &per_cpu(cpuinfo, cpu); -+ if (cpu != freq->cpu) { -+ if (!down_read_trylock(&pjcpu->enable_sem)) -+ continue; -+ if (!pjcpu->governor_enabled) { -+ up_read(&pjcpu->enable_sem); -+ continue; -+ } -+ } -+ spin_lock_irqsave(&pjcpu->load_lock, flags); -+ update_load(cpu); -+ spin_unlock_irqrestore(&pjcpu->load_lock, flags); -+ if (cpu != freq->cpu) -+ up_read(&pjcpu->enable_sem); -+ } -+ -+ up_read(&pcpu->enable_sem); -+ } -+ return 0; -+} -+ -+static struct notifier_block cpufreq_notifier_block = { -+ .notifier_call = cpufreq_interactive_notifier, -+}; -+ -+static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) -+{ -+ const char *cp; -+ int i; -+ int ntokens = 1; -+ unsigned int *tokenized_data; -+ int err = -EINVAL; -+ -+ cp = buf; -+ while ((cp = strpbrk(cp + 1, " :"))) -+ ntokens++; -+ -+ if (!(ntokens & 0x1)) -+ goto err; -+ -+ tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); -+ if (!tokenized_data) { -+ err = -ENOMEM; -+ goto err; -+ } -+ -+ cp = buf; -+ i = 0; -+ while (i < ntokens) { -+ if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) -+ goto err_kfree; -+ -+ cp = strpbrk(cp, " :"); -+ if (!cp) -+ break; -+ cp++; -+ } -+ -+ if (i != ntokens) -+ goto err_kfree; -+ -+ *num_tokens = ntokens; -+ return tokenized_data; -+ -+err_kfree: -+ kfree(tokenized_data); -+err: -+ return ERR_PTR(err); -+} -+ -+static ssize_t show_target_loads( -+ struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ int i; -+ ssize_t ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&tunables->target_loads_lock, flags); -+ -+ for (i = 0; i < tunables->ntarget_loads; i++) -+ ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i], -+ i & 0x1 ? ":" : " "); -+ -+ sprintf(buf + ret - 1, "\n"); -+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); -+ return ret; -+} -+ -+static ssize_t store_target_loads( -+ struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ntokens; -+ unsigned int *new_target_loads = NULL; -+ unsigned long flags; -+ -+ new_target_loads = get_tokenized_data(buf, &ntokens); -+ if (IS_ERR(new_target_loads)) -+ return PTR_RET(new_target_loads); -+ -+ spin_lock_irqsave(&tunables->target_loads_lock, flags); -+ if (tunables->target_loads != default_target_loads) -+ kfree(tunables->target_loads); -+ tunables->target_loads = new_target_loads; -+ tunables->ntarget_loads = ntokens; -+ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); -+ return count; -+} -+ -+static ssize_t show_above_hispeed_delay( -+ struct cpufreq_interactive_tunables *tunables, char *buf) -+{ -+ int i; -+ ssize_t ret = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); -+ -+ for (i = 0; i < tunables->nabove_hispeed_delay; i++) -+ ret += sprintf(buf + ret, "%u%s", -+ tunables->above_hispeed_delay[i], -+ i & 0x1 ? ":" : " "); -+ -+ sprintf(buf + ret - 1, "\n"); -+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); -+ return ret; -+} -+ -+static ssize_t store_above_hispeed_delay( -+ struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ntokens; -+ unsigned int *new_above_hispeed_delay = NULL; -+ unsigned long flags; -+ -+ new_above_hispeed_delay = get_tokenized_data(buf, &ntokens); -+ if (IS_ERR(new_above_hispeed_delay)) -+ return PTR_RET(new_above_hispeed_delay); -+ -+ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); -+ if (tunables->above_hispeed_delay != default_above_hispeed_delay) -+ kfree(tunables->above_hispeed_delay); -+ tunables->above_hispeed_delay = new_above_hispeed_delay; -+ tunables->nabove_hispeed_delay = ntokens; -+ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); -+ return count; -+ -+} -+ -+static ssize_t show_hispeed_freq(struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ return sprintf(buf, "%u\n", tunables->hispeed_freq); -+} -+ -+static ssize_t store_hispeed_freq(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ long unsigned int val; -+ -+ ret = strict_strtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ tunables->hispeed_freq = val; -+ return count; -+} -+ -+static ssize_t show_go_hispeed_load(struct cpufreq_interactive_tunables -+ *tunables, char *buf) -+{ -+ return sprintf(buf, "%lu\n", tunables->go_hispeed_load); -+} -+ -+static ssize_t store_go_hispeed_load(struct cpufreq_interactive_tunables -+ *tunables, const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = strict_strtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ tunables->go_hispeed_load = val; -+ return count; -+} -+ -+static ssize_t show_min_sample_time(struct cpufreq_interactive_tunables -+ *tunables, char *buf) -+{ -+ return sprintf(buf, "%lu\n", tunables->min_sample_time); -+} -+ -+static ssize_t store_min_sample_time(struct cpufreq_interactive_tunables -+ *tunables, const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = strict_strtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ tunables->min_sample_time = val; -+ return count; -+} -+ -+static ssize_t show_timer_rate(struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ return sprintf(buf, "%lu\n", tunables->timer_rate); -+} -+ -+static ssize_t store_timer_rate(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = strict_strtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ tunables->timer_rate = val; -+ return count; -+} -+ -+static ssize_t show_timer_slack(struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ return sprintf(buf, "%d\n", tunables->timer_slack_val); -+} -+ -+static ssize_t store_timer_slack(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = kstrtol(buf, 10, &val); -+ if (ret < 0) -+ return ret; -+ -+ tunables->timer_slack_val = val; -+ return count; -+} -+ -+static ssize_t show_boost(struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ return sprintf(buf, "%d\n", tunables->boost_val); -+} -+ -+static ssize_t store_boost(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = kstrtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ -+ tunables->boost_val = val; -+ -+ if (tunables->boost_val) { -+ trace_cpufreq_interactive_boost("on"); -+ cpufreq_interactive_boost(); -+ } else { -+ trace_cpufreq_interactive_unboost("off"); -+ } -+ -+ return count; -+} -+ -+static ssize_t store_boostpulse(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = kstrtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ -+ tunables->boostpulse_endtime = ktime_to_us(ktime_get()) + -+ tunables->boostpulse_duration_val; -+ trace_cpufreq_interactive_boost("pulse"); -+ cpufreq_interactive_boost(); -+ return count; -+} -+ -+static ssize_t show_boostpulse_duration(struct cpufreq_interactive_tunables -+ *tunables, char *buf) -+{ -+ return sprintf(buf, "%d\n", tunables->boostpulse_duration_val); -+} -+ -+static ssize_t store_boostpulse_duration(struct cpufreq_interactive_tunables -+ *tunables, const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = kstrtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ -+ tunables->boostpulse_duration_val = val; -+ return count; -+} -+ -+static ssize_t show_io_is_busy(struct cpufreq_interactive_tunables *tunables, -+ char *buf) -+{ -+ return sprintf(buf, "%u\n", tunables->io_is_busy); -+} -+ -+static ssize_t store_io_is_busy(struct cpufreq_interactive_tunables *tunables, -+ const char *buf, size_t count) -+{ -+ int ret; -+ unsigned long val; -+ -+ ret = kstrtoul(buf, 0, &val); -+ if (ret < 0) -+ return ret; -+ tunables->io_is_busy = val; -+ return count; -+} -+ -+/* -+ * Create show/store routines -+ * - sys: One governor instance for complete SYSTEM -+ * - pol: One governor instance per struct cpufreq_policy -+ */ -+#define show_gov_pol_sys(file_name) \ -+static ssize_t show_##file_name##_gov_sys \ -+(struct kobject *kobj, struct attribute *attr, char *buf) \ -+{ \ -+ return show_##file_name(common_tunables, buf); \ -+} \ -+ \ -+static ssize_t show_##file_name##_gov_pol \ -+(struct cpufreq_policy *policy, char *buf) \ -+{ \ -+ return show_##file_name(policy->governor_data, buf); \ -+} -+ -+#define store_gov_pol_sys(file_name) \ -+static ssize_t store_##file_name##_gov_sys \ -+(struct kobject *kobj, struct attribute *attr, const char *buf, \ -+ size_t count) \ -+{ \ -+ return store_##file_name(common_tunables, buf, count); \ -+} \ -+ \ -+static ssize_t store_##file_name##_gov_pol \ -+(struct cpufreq_policy *policy, const char *buf, size_t count) \ -+{ \ -+ return store_##file_name(policy->governor_data, buf, count); \ -+} -+ -+#define show_store_gov_pol_sys(file_name) \ -+show_gov_pol_sys(file_name); \ -+store_gov_pol_sys(file_name) -+ -+show_store_gov_pol_sys(target_loads); -+show_store_gov_pol_sys(above_hispeed_delay); -+show_store_gov_pol_sys(hispeed_freq); -+show_store_gov_pol_sys(go_hispeed_load); -+show_store_gov_pol_sys(min_sample_time); -+show_store_gov_pol_sys(timer_rate); -+show_store_gov_pol_sys(timer_slack); -+show_store_gov_pol_sys(boost); -+store_gov_pol_sys(boostpulse); -+show_store_gov_pol_sys(boostpulse_duration); -+show_store_gov_pol_sys(io_is_busy); -+ -+#define gov_sys_attr_rw(_name) \ -+static struct global_attr _name##_gov_sys = \ -+__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys) -+ -+#define gov_pol_attr_rw(_name) \ -+static struct freq_attr _name##_gov_pol = \ -+__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol) -+ -+#define gov_sys_pol_attr_rw(_name) \ -+ gov_sys_attr_rw(_name); \ -+ gov_pol_attr_rw(_name) -+ -+gov_sys_pol_attr_rw(target_loads); -+gov_sys_pol_attr_rw(above_hispeed_delay); -+gov_sys_pol_attr_rw(hispeed_freq); -+gov_sys_pol_attr_rw(go_hispeed_load); -+gov_sys_pol_attr_rw(min_sample_time); -+gov_sys_pol_attr_rw(timer_rate); -+gov_sys_pol_attr_rw(timer_slack); -+gov_sys_pol_attr_rw(boost); -+gov_sys_pol_attr_rw(boostpulse_duration); -+gov_sys_pol_attr_rw(io_is_busy); -+ -+static struct global_attr boostpulse_gov_sys = -+ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_sys); -+ -+static struct freq_attr boostpulse_gov_pol = -+ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_pol); -+ -+/* One Governor instance for entire system */ -+static struct attribute *interactive_attributes_gov_sys[] = { -+ &target_loads_gov_sys.attr, -+ &above_hispeed_delay_gov_sys.attr, -+ &hispeed_freq_gov_sys.attr, -+ &go_hispeed_load_gov_sys.attr, -+ &min_sample_time_gov_sys.attr, -+ &timer_rate_gov_sys.attr, -+ &timer_slack_gov_sys.attr, -+ &boost_gov_sys.attr, -+ &boostpulse_gov_sys.attr, -+ &boostpulse_duration_gov_sys.attr, -+ &io_is_busy_gov_sys.attr, -+ NULL, -+}; -+ -+static struct attribute_group interactive_attr_group_gov_sys = { -+ .attrs = interactive_attributes_gov_sys, -+ .name = "interactive", -+}; -+ -+/* Per policy governor instance */ -+static struct attribute *interactive_attributes_gov_pol[] = { -+ &target_loads_gov_pol.attr, -+ &above_hispeed_delay_gov_pol.attr, -+ &hispeed_freq_gov_pol.attr, -+ &go_hispeed_load_gov_pol.attr, -+ &min_sample_time_gov_pol.attr, -+ &timer_rate_gov_pol.attr, -+ &timer_slack_gov_pol.attr, -+ &boost_gov_pol.attr, -+ &boostpulse_gov_pol.attr, -+ &boostpulse_duration_gov_pol.attr, -+ &io_is_busy_gov_pol.attr, -+ NULL, -+}; -+ -+static struct attribute_group interactive_attr_group_gov_pol = { -+ .attrs = interactive_attributes_gov_pol, -+ .name = "interactive", -+}; -+ -+static struct attribute_group *get_sysfs_attr(void) -+{ -+ if (have_governor_per_policy()) -+ return &interactive_attr_group_gov_pol; -+ else -+ return &interactive_attr_group_gov_sys; -+} -+ -+static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, -+ unsigned long val, -+ void *data) -+{ -+ switch (val) { -+ case IDLE_START: -+ cpufreq_interactive_idle_start(); -+ break; -+ case IDLE_END: -+ cpufreq_interactive_idle_end(); -+ break; -+ } -+ -+ return 0; -+} -+ -+static struct notifier_block cpufreq_interactive_idle_nb = { -+ .notifier_call = cpufreq_interactive_idle_notifier, -+}; -+ -+static int cpufreq_governor_interactive(struct cpufreq_policy *policy, -+ unsigned int event) -+{ -+ int rc; -+ unsigned int j; -+ struct cpufreq_interactive_cpuinfo *pcpu; -+ struct cpufreq_frequency_table *freq_table; -+ struct cpufreq_interactive_tunables *tunables; -+ -+ if (have_governor_per_policy()) -+ tunables = policy->governor_data; -+ else -+ tunables = common_tunables; -+ -+ WARN_ON(!tunables && (event != CPUFREQ_GOV_POLICY_INIT)); -+ -+ switch (event) { -+ case CPUFREQ_GOV_POLICY_INIT: -+ if (have_governor_per_policy()) { -+ WARN_ON(tunables); -+ } else if (tunables) { -+ tunables->usage_count++; -+ policy->governor_data = tunables; -+ return 0; -+ } -+ -+ tunables = kzalloc(sizeof(*tunables), GFP_KERNEL); -+ if (!tunables) { -+ pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__); -+ return -ENOMEM; -+ } -+ -+ tunables->usage_count = 1; -+ tunables->above_hispeed_delay = default_above_hispeed_delay; -+ tunables->nabove_hispeed_delay = -+ ARRAY_SIZE(default_above_hispeed_delay); -+ tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; -+ tunables->target_loads = default_target_loads; -+ tunables->ntarget_loads = ARRAY_SIZE(default_target_loads); -+ tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME; -+ tunables->timer_rate = DEFAULT_TIMER_RATE; -+ tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; -+ tunables->timer_slack_val = DEFAULT_TIMER_SLACK; -+ -+ spin_lock_init(&tunables->target_loads_lock); -+ spin_lock_init(&tunables->above_hispeed_delay_lock); -+ -+ policy->governor_data = tunables; -+ if (!have_governor_per_policy()) { -+ common_tunables = tunables; -+ WARN_ON(cpufreq_get_global_kobject()); -+ } -+ -+ rc = sysfs_create_group(get_governor_parent_kobj(policy), -+ get_sysfs_attr()); -+ if (rc) { -+ kfree(tunables); -+ policy->governor_data = NULL; -+ if (!have_governor_per_policy()) -+ common_tunables = NULL; -+ return rc; -+ } -+ -+ if (!policy->governor->initialized) { -+ idle_notifier_register(&cpufreq_interactive_idle_nb); -+ cpufreq_register_notifier(&cpufreq_notifier_block, -+ CPUFREQ_TRANSITION_NOTIFIER); -+ } -+ -+ break; -+ -+ case CPUFREQ_GOV_POLICY_EXIT: -+ if (!--tunables->usage_count) { -+ sysfs_remove_group(get_governor_parent_kobj(policy), -+ get_sysfs_attr()); -+ -+ if (!have_governor_per_policy()) -+ cpufreq_put_global_kobject(); -+ -+ if (policy->governor->initialized == 1) { -+ cpufreq_unregister_notifier(&cpufreq_notifier_block, -+ CPUFREQ_TRANSITION_NOTIFIER); -+ idle_notifier_unregister(&cpufreq_interactive_idle_nb); -+ } -+ -+ kfree(tunables); -+ common_tunables = NULL; -+ } -+ -+ policy->governor_data = NULL; -+ break; -+ -+ case CPUFREQ_GOV_START: -+ mutex_lock(&gov_lock); -+ -+ freq_table = cpufreq_frequency_get_table(policy->cpu); -+ if (!tunables->hispeed_freq) -+ tunables->hispeed_freq = policy->max; -+ -+ for_each_cpu(j, policy->cpus) { -+ pcpu = &per_cpu(cpuinfo, j); -+ pcpu->policy = policy; -+ pcpu->target_freq = policy->cur; -+ pcpu->freq_table = freq_table; -+ pcpu->floor_freq = pcpu->target_freq; -+ pcpu->floor_validate_time = -+ ktime_to_us(ktime_get()); -+ pcpu->hispeed_validate_time = -+ pcpu->floor_validate_time; -+ down_write(&pcpu->enable_sem); -+ del_timer_sync(&pcpu->cpu_timer); -+ del_timer_sync(&pcpu->cpu_slack_timer); -+ cpufreq_interactive_timer_start(tunables, j); -+ pcpu->governor_enabled = 1; -+ up_write(&pcpu->enable_sem); -+ } -+ -+ mutex_unlock(&gov_lock); -+ break; -+ -+ case CPUFREQ_GOV_STOP: -+ mutex_lock(&gov_lock); -+ for_each_cpu(j, policy->cpus) { -+ pcpu = &per_cpu(cpuinfo, j); -+ down_write(&pcpu->enable_sem); -+ pcpu->governor_enabled = 0; -+ del_timer_sync(&pcpu->cpu_timer); -+ del_timer_sync(&pcpu->cpu_slack_timer); -+ up_write(&pcpu->enable_sem); -+ } -+ -+ mutex_unlock(&gov_lock); -+ break; -+ -+ case CPUFREQ_GOV_LIMITS: -+ if (policy->max < policy->cur) -+ __cpufreq_driver_target(policy, -+ policy->max, CPUFREQ_RELATION_H); -+ else if (policy->min > policy->cur) -+ __cpufreq_driver_target(policy, -+ policy->min, CPUFREQ_RELATION_L); -+ for_each_cpu(j, policy->cpus) { -+ pcpu = &per_cpu(cpuinfo, j); -+ -+ /* hold write semaphore to avoid race */ -+ down_write(&pcpu->enable_sem); -+ if (pcpu->governor_enabled == 0) { -+ up_write(&pcpu->enable_sem); -+ continue; -+ } -+ -+ /* update target_freq firstly */ -+ if (policy->max < pcpu->target_freq) -+ pcpu->target_freq = policy->max; -+ else if (policy->min > pcpu->target_freq) -+ pcpu->target_freq = policy->min; -+ -+ /* Reschedule timer. -+ * Delete the timers, else the timer callback may -+ * return without re-arm the timer when failed -+ * acquire the semaphore. This race may cause timer -+ * stopped unexpectedly. -+ */ -+ del_timer_sync(&pcpu->cpu_timer); -+ del_timer_sync(&pcpu->cpu_slack_timer); -+ cpufreq_interactive_timer_start(tunables, j); -+ up_write(&pcpu->enable_sem); -+ } -+ break; -+ } -+ return 0; -+} -+ -+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE -+static -+#endif -+struct cpufreq_governor cpufreq_gov_interactive = { -+ .name = "interactive", -+ .governor = cpufreq_governor_interactive, -+ .max_transition_latency = 10000000, -+ .owner = THIS_MODULE, -+}; -+ -+static void cpufreq_interactive_nop_timer(unsigned long data) -+{ -+} -+ -+static int __init cpufreq_interactive_init(void) -+{ -+ unsigned int i; -+ struct cpufreq_interactive_cpuinfo *pcpu; -+ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; -+ -+ /* Initalize per-cpu timers */ -+ for_each_possible_cpu(i) { -+ pcpu = &per_cpu(cpuinfo, i); -+ init_timer_deferrable(&pcpu->cpu_timer); -+ pcpu->cpu_timer.function = cpufreq_interactive_timer; -+ pcpu->cpu_timer.data = i; -+ init_timer(&pcpu->cpu_slack_timer); -+ pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; -+ spin_lock_init(&pcpu->load_lock); -+ init_rwsem(&pcpu->enable_sem); -+ } -+ -+ spin_lock_init(&speedchange_cpumask_lock); -+ mutex_init(&gov_lock); -+ speedchange_task = -+ kthread_create(cpufreq_interactive_speedchange_task, NULL, -+ "cfinteractive"); -+ if (IS_ERR(speedchange_task)) -+ return PTR_ERR(speedchange_task); -+ -+ sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, ¶m); -+ get_task_struct(speedchange_task); -+ -+ /* NB: wake up so the thread does not look hung to the freezer */ -+ wake_up_process(speedchange_task); -+ -+ return cpufreq_register_governor(&cpufreq_gov_interactive); -+} -+ -+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE -+fs_initcall(cpufreq_interactive_init); -+#else -+module_init(cpufreq_interactive_init); -+#endif -+ -+static void __exit cpufreq_interactive_exit(void) -+{ -+ cpufreq_unregister_governor(&cpufreq_gov_interactive); -+ kthread_stop(speedchange_task); -+ put_task_struct(speedchange_task); -+} -+ -+module_exit(cpufreq_interactive_exit); -+ -+MODULE_AUTHOR("Mike Chan "); -+MODULE_DESCRIPTION("'cpufreq_interactive' - A cpufreq governor for " -+ "Latency sensitive workloads"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/cpufreq/highbank-cpufreq.c linux-3.14.22/drivers/cpufreq/highbank-cpufreq.c ---- linux-3.14.22.orig/drivers/cpufreq/highbank-cpufreq.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/cpufreq/highbank-cpufreq.c 2014-10-22 14:55:52.026220001 -0500 -@@ -19,7 +19,7 @@ - #include - #include - #include --#include -+#include - #include - - #define HB_CPUFREQ_CHANGE_NOTE 0x80000001 -diff -Nur linux-3.14.22.orig/drivers/cpufreq/imx6-cpufreq.c linux-3.14.22/drivers/cpufreq/imx6-cpufreq.c ---- linux-3.14.22.orig/drivers/cpufreq/imx6-cpufreq.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/cpufreq/imx6-cpufreq.c 2014-10-22 14:55:52.026220001 -0500 -@@ -0,0 +1,393 @@ -+/* -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define PU_SOC_VOLTAGE_NORMAL 1250000 -+#define PU_SOC_VOLTAGE_HIGH 1275000 -+#define FREQ_1P2_GHZ 1200000000 -+ -+static struct regulator *arm_reg; -+static struct regulator *pu_reg; -+static struct regulator *soc_reg; -+ -+static struct clk *arm_clk; -+static struct clk *pll1_sys_clk; -+static struct clk *pll1_sw_clk; -+static struct clk *step_clk; -+static struct clk *pll2_pfd2_396m_clk; -+ -+static struct device *cpu_dev; -+static struct cpufreq_frequency_table *freq_table; -+static unsigned int transition_latency; -+static struct mutex set_cpufreq_lock; -+ -+static u32 *imx6_soc_volt; -+static u32 soc_opp_count; -+ -+static int imx6_set_target(struct cpufreq_policy *policy, unsigned int index) -+{ -+ struct dev_pm_opp *opp; -+ unsigned long freq_hz, volt, volt_old; -+ unsigned int old_freq, new_freq; -+ int ret; -+ -+ mutex_lock(&set_cpufreq_lock); -+ -+ new_freq = freq_table[index].frequency; -+ freq_hz = new_freq * 1000; -+ old_freq = clk_get_rate(arm_clk) / 1000; -+ -+ rcu_read_lock(); -+ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); -+ if (IS_ERR(opp)) { -+ rcu_read_unlock(); -+ dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); -+ ret = PTR_ERR(opp); -+ goto unlock; -+ } -+ -+ volt = dev_pm_opp_get_voltage(opp); -+ rcu_read_unlock(); -+ volt_old = regulator_get_voltage(arm_reg); -+ -+ dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", -+ old_freq / 1000, volt_old / 1000, -+ new_freq / 1000, volt / 1000); -+ -+ /* -+ * CPU freq is increasing, so need to ensure -+ * that bus frequency is increased too. -+ */ -+ if (old_freq == freq_table[0].frequency) -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ /* scaling up? scale voltage before frequency */ -+ if (new_freq > old_freq) { -+ if (regulator_is_enabled(pu_reg)) { -+ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); -+ if (ret) { -+ dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); -+ goto unlock; -+ } -+ } -+ ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); -+ if (ret) { -+ dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); -+ goto unlock; -+ } -+ ret = regulator_set_voltage_tol(arm_reg, volt, 0); -+ if (ret) { -+ dev_err(cpu_dev, -+ "failed to scale vddarm up: %d\n", ret); -+ goto unlock; -+ } -+ } -+ -+ /* -+ * The setpoints are selected per PLL/PDF frequencies, so we need to -+ * reprogram PLL for frequency scaling. The procedure of reprogramming -+ * PLL1 is as below. -+ * -+ * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it -+ * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it -+ * - Disable pll2_pfd2_396m_clk -+ */ -+ clk_set_parent(step_clk, pll2_pfd2_396m_clk); -+ clk_set_parent(pll1_sw_clk, step_clk); -+ if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { -+ clk_set_rate(pll1_sys_clk, new_freq * 1000); -+ clk_set_parent(pll1_sw_clk, pll1_sys_clk); -+ } -+ -+ /* Ensure the arm clock divider is what we expect */ -+ ret = clk_set_rate(arm_clk, new_freq * 1000); -+ if (ret) { -+ dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); -+ regulator_set_voltage_tol(arm_reg, volt_old, 0); -+ goto unlock; -+ } -+ -+ /* scaling down? scale voltage after frequency */ -+ if (new_freq < old_freq) { -+ ret = regulator_set_voltage_tol(arm_reg, volt, 0); -+ if (ret) { -+ dev_warn(cpu_dev, -+ "failed to scale vddarm down: %d\n", ret); -+ ret = 0; -+ } -+ ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); -+ if (ret) { -+ dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); -+ ret = 0; -+ } -+ if (regulator_is_enabled(pu_reg)) { -+ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); -+ if (ret) { -+ dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); -+ ret = 0; -+ } -+ } -+ } -+ -+ if (policy->cur == freq_table[0].frequency) -+ release_bus_freq(BUS_FREQ_HIGH); -+ -+unlock: -+ mutex_unlock(&set_cpufreq_lock); -+ return ret; -+} -+ -+static int imx6_cpufreq_init(struct cpufreq_policy *policy) -+{ -+ policy->clk = arm_clk; -+ -+ if (policy->cur > freq_table[0].frequency) -+ request_bus_freq(BUS_FREQ_HIGH); -+ -+ return cpufreq_generic_init(policy, freq_table, transition_latency); -+} -+ -+static struct cpufreq_driver imx6_cpufreq_driver = { -+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, -+ .verify = cpufreq_generic_frequency_table_verify, -+ .target_index = imx6_set_target, -+ .get = cpufreq_generic_get, -+ .init = imx6_cpufreq_init, -+ .exit = cpufreq_generic_exit, -+ .name = "imx6-cpufreq", -+ .attr = cpufreq_generic_attr, -+}; -+ -+static int imx6_cpufreq_pm_notify(struct notifier_block *nb, -+ unsigned long event, void *dummy) -+{ -+ struct cpufreq_policy *data = cpufreq_cpu_get(0); -+ static u32 cpufreq_policy_min_pre_suspend; -+ -+ /* -+ * During suspend/resume, When cpufreq driver try to increase -+ * voltage/freq, it needs to control I2C/SPI to communicate -+ * with external PMIC to adjust voltage, but these I2C/SPI -+ * devices may be already suspended, to avoid such scenario, -+ * we just increase cpufreq to highest setpoint before suspend. -+ */ -+ switch (event) { -+ case PM_SUSPEND_PREPARE: -+ cpufreq_policy_min_pre_suspend = data->user_policy.min; -+ data->user_policy.min = data->user_policy.max; -+ break; -+ case PM_POST_SUSPEND: -+ data->user_policy.min = cpufreq_policy_min_pre_suspend; -+ break; -+ default: -+ break; -+ } -+ -+ cpufreq_update_policy(0); -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block imx6_cpufreq_pm_notifier = { -+ .notifier_call = imx6_cpufreq_pm_notify, -+}; -+ -+static int imx6_cpufreq_probe(struct platform_device *pdev) -+{ -+ struct device_node *np; -+ struct dev_pm_opp *opp; -+ unsigned long min_volt, max_volt; -+ int num, ret; -+ const struct property *prop; -+ const __be32 *val; -+ u32 nr, i, j; -+ -+ cpu_dev = get_cpu_device(0); -+ if (!cpu_dev) { -+ pr_err("failed to get cpu0 device\n"); -+ return -ENODEV; -+ } -+ -+ np = of_node_get(cpu_dev->of_node); -+ if (!np) { -+ dev_err(cpu_dev, "failed to find cpu0 node\n"); -+ return -ENOENT; -+ } -+ -+ arm_clk = devm_clk_get(cpu_dev, "arm"); -+ pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); -+ pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); -+ step_clk = devm_clk_get(cpu_dev, "step"); -+ pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m"); -+ if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || -+ IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { -+ dev_err(cpu_dev, "failed to get clocks\n"); -+ ret = -ENOENT; -+ goto put_node; -+ } -+ -+ arm_reg = devm_regulator_get(cpu_dev, "arm"); -+ pu_reg = devm_regulator_get(cpu_dev, "pu"); -+ soc_reg = devm_regulator_get(cpu_dev, "soc"); -+ if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) { -+ dev_err(cpu_dev, "failed to get regulators\n"); -+ ret = -ENOENT; -+ goto put_node; -+ } -+ -+ /* -+ * We expect an OPP table supplied by platform. -+ * Just, incase the platform did not supply the OPP -+ * table, it will try to get it. -+ */ -+ num = dev_pm_opp_get_opp_count(cpu_dev); -+ if (num < 0) { -+ ret = of_init_opp_table(cpu_dev); -+ if (ret < 0) { -+ dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); -+ goto put_node; -+ } -+ -+ num = dev_pm_opp_get_opp_count(cpu_dev); -+ if (num < 0) { -+ ret = num; -+ dev_err(cpu_dev, "no OPP table is found: %d\n", ret); -+ goto put_node; -+ } -+ } -+ -+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); -+ if (ret) { -+ dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); -+ goto put_node; -+ } -+ -+ /* Make imx6_soc_volt array's size same as arm opp number */ -+ imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); -+ if (imx6_soc_volt == NULL) { -+ ret = -ENOMEM; -+ goto free_freq_table; -+ } -+ -+ prop = of_find_property(np, "fsl,soc-operating-points", NULL); -+ if (!prop || !prop->value) -+ goto soc_opp_out; -+ -+ /* -+ * Each OPP is a set of tuples consisting of frequency and -+ * voltage like . -+ */ -+ nr = prop->length / sizeof(u32); -+ if (nr % 2 || (nr / 2) < num) -+ goto soc_opp_out; -+ -+ for (j = 0; j < num; j++) { -+ val = prop->value; -+ for (i = 0; i < nr / 2; i++) { -+ unsigned long freq = be32_to_cpup(val++); -+ unsigned long volt = be32_to_cpup(val++); -+ if (freq_table[j].frequency == freq) { -+ imx6_soc_volt[soc_opp_count++] = volt; -+ break; -+ } -+ } -+ } -+ -+soc_opp_out: -+ /* use fixed soc opp volt if no valid soc opp info found in dtb */ -+ if (soc_opp_count != num) { -+ dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); -+ for (j = 0; j < num; j++) -+ imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; -+ if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) -+ imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; -+ } -+ -+ if (of_property_read_u32(np, "clock-latency", &transition_latency)) -+ transition_latency = CPUFREQ_ETERNAL; -+ -+ /* -+ * Calculate the ramp time for max voltage change in the -+ * VDDSOC and VDDPU regulators. -+ */ -+ ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); -+ if (ret > 0) -+ transition_latency += ret * 1000; -+ ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); -+ if (ret > 0) -+ transition_latency += ret * 1000; -+ -+ /* -+ * OPP is maintained in order of increasing frequency, and -+ * freq_table initialised from OPP is therefore sorted in the -+ * same order. -+ */ -+ rcu_read_lock(); -+ opp = dev_pm_opp_find_freq_exact(cpu_dev, -+ freq_table[0].frequency * 1000, true); -+ min_volt = dev_pm_opp_get_voltage(opp); -+ opp = dev_pm_opp_find_freq_exact(cpu_dev, -+ freq_table[--num].frequency * 1000, true); -+ max_volt = dev_pm_opp_get_voltage(opp); -+ rcu_read_unlock(); -+ ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); -+ if (ret > 0) -+ transition_latency += ret * 1000; -+ -+ mutex_init(&set_cpufreq_lock); -+ register_pm_notifier(&imx6_cpufreq_pm_notifier); -+ -+ ret = cpufreq_register_driver(&imx6_cpufreq_driver); -+ if (ret) { -+ dev_err(cpu_dev, "failed register driver: %d\n", ret); -+ goto free_freq_table; -+ } -+ -+ of_node_put(np); -+ return 0; -+ -+free_freq_table: -+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -+put_node: -+ of_node_put(np); -+ return ret; -+} -+ -+static int imx6_cpufreq_remove(struct platform_device *pdev) -+{ -+ cpufreq_unregister_driver(&imx6_cpufreq_driver); -+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -+ -+ return 0; -+} -+ -+static struct platform_driver imx6_cpufreq_platdrv = { -+ .driver = { -+ .name = "imx6-cpufreq", -+ .owner = THIS_MODULE, -+ }, -+ .probe = imx6_cpufreq_probe, -+ .remove = imx6_cpufreq_remove, -+}; -+module_platform_driver(imx6_cpufreq_platdrv); -+ -+MODULE_AUTHOR("Shawn Guo "); -+MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/cpufreq/imx6q-cpufreq.c linux-3.14.22/drivers/cpufreq/imx6q-cpufreq.c ---- linux-3.14.22.orig/drivers/cpufreq/imx6q-cpufreq.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/cpufreq/imx6q-cpufreq.c 1969-12-31 18:00:00.000000000 -0600 -@@ -1,330 +0,0 @@ --/* -- * Copyright (C) 2013 Freescale Semiconductor, Inc. -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License version 2 as -- * published by the Free Software Foundation. -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#define PU_SOC_VOLTAGE_NORMAL 1250000 --#define PU_SOC_VOLTAGE_HIGH 1275000 --#define FREQ_1P2_GHZ 1200000000 -- --static struct regulator *arm_reg; --static struct regulator *pu_reg; --static struct regulator *soc_reg; -- --static struct clk *arm_clk; --static struct clk *pll1_sys_clk; --static struct clk *pll1_sw_clk; --static struct clk *step_clk; --static struct clk *pll2_pfd2_396m_clk; -- --static struct device *cpu_dev; --static struct cpufreq_frequency_table *freq_table; --static unsigned int transition_latency; -- --static u32 *imx6_soc_volt; --static u32 soc_opp_count; -- --static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) --{ -- struct dev_pm_opp *opp; -- unsigned long freq_hz, volt, volt_old; -- unsigned int old_freq, new_freq; -- int ret; -- -- new_freq = freq_table[index].frequency; -- freq_hz = new_freq * 1000; -- old_freq = clk_get_rate(arm_clk) / 1000; -- -- rcu_read_lock(); -- opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); -- if (IS_ERR(opp)) { -- rcu_read_unlock(); -- dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); -- return PTR_ERR(opp); -- } -- -- volt = dev_pm_opp_get_voltage(opp); -- rcu_read_unlock(); -- volt_old = regulator_get_voltage(arm_reg); -- -- dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", -- old_freq / 1000, volt_old / 1000, -- new_freq / 1000, volt / 1000); -- -- /* scaling up? scale voltage before frequency */ -- if (new_freq > old_freq) { -- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); -- if (ret) { -- dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); -- return ret; -- } -- ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); -- if (ret) { -- dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); -- return ret; -- } -- ret = regulator_set_voltage_tol(arm_reg, volt, 0); -- if (ret) { -- dev_err(cpu_dev, -- "failed to scale vddarm up: %d\n", ret); -- return ret; -- } -- } -- -- /* -- * The setpoints are selected per PLL/PDF frequencies, so we need to -- * reprogram PLL for frequency scaling. The procedure of reprogramming -- * PLL1 is as below. -- * -- * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it -- * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it -- * - Disable pll2_pfd2_396m_clk -- */ -- clk_set_parent(step_clk, pll2_pfd2_396m_clk); -- clk_set_parent(pll1_sw_clk, step_clk); -- if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { -- clk_set_rate(pll1_sys_clk, new_freq * 1000); -- clk_set_parent(pll1_sw_clk, pll1_sys_clk); -- } -- -- /* Ensure the arm clock divider is what we expect */ -- ret = clk_set_rate(arm_clk, new_freq * 1000); -- if (ret) { -- dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); -- regulator_set_voltage_tol(arm_reg, volt_old, 0); -- return ret; -- } -- -- /* scaling down? scale voltage after frequency */ -- if (new_freq < old_freq) { -- ret = regulator_set_voltage_tol(arm_reg, volt, 0); -- if (ret) { -- dev_warn(cpu_dev, -- "failed to scale vddarm down: %d\n", ret); -- ret = 0; -- } -- ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); -- if (ret) { -- dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); -- ret = 0; -- } -- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); -- if (ret) { -- dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); -- ret = 0; -- } -- } -- -- return 0; --} -- --static int imx6q_cpufreq_init(struct cpufreq_policy *policy) --{ -- policy->clk = arm_clk; -- return cpufreq_generic_init(policy, freq_table, transition_latency); --} -- --static struct cpufreq_driver imx6q_cpufreq_driver = { -- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, -- .verify = cpufreq_generic_frequency_table_verify, -- .target_index = imx6q_set_target, -- .get = cpufreq_generic_get, -- .init = imx6q_cpufreq_init, -- .exit = cpufreq_generic_exit, -- .name = "imx6q-cpufreq", -- .attr = cpufreq_generic_attr, --}; -- --static int imx6q_cpufreq_probe(struct platform_device *pdev) --{ -- struct device_node *np; -- struct dev_pm_opp *opp; -- unsigned long min_volt, max_volt; -- int num, ret; -- const struct property *prop; -- const __be32 *val; -- u32 nr, i, j; -- -- cpu_dev = get_cpu_device(0); -- if (!cpu_dev) { -- pr_err("failed to get cpu0 device\n"); -- return -ENODEV; -- } -- -- np = of_node_get(cpu_dev->of_node); -- if (!np) { -- dev_err(cpu_dev, "failed to find cpu0 node\n"); -- return -ENOENT; -- } -- -- arm_clk = devm_clk_get(cpu_dev, "arm"); -- pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); -- pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); -- step_clk = devm_clk_get(cpu_dev, "step"); -- pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m"); -- if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || -- IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { -- dev_err(cpu_dev, "failed to get clocks\n"); -- ret = -ENOENT; -- goto put_node; -- } -- -- arm_reg = devm_regulator_get(cpu_dev, "arm"); -- pu_reg = devm_regulator_get(cpu_dev, "pu"); -- soc_reg = devm_regulator_get(cpu_dev, "soc"); -- if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) { -- dev_err(cpu_dev, "failed to get regulators\n"); -- ret = -ENOENT; -- goto put_node; -- } -- -- /* -- * We expect an OPP table supplied by platform. -- * Just, incase the platform did not supply the OPP -- * table, it will try to get it. -- */ -- num = dev_pm_opp_get_opp_count(cpu_dev); -- if (num < 0) { -- ret = of_init_opp_table(cpu_dev); -- if (ret < 0) { -- dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); -- goto put_node; -- } -- -- num = dev_pm_opp_get_opp_count(cpu_dev); -- if (num < 0) { -- ret = num; -- dev_err(cpu_dev, "no OPP table is found: %d\n", ret); -- goto put_node; -- } -- } -- -- ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); -- if (ret) { -- dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); -- goto put_node; -- } -- -- /* Make imx6_soc_volt array's size same as arm opp number */ -- imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); -- if (imx6_soc_volt == NULL) { -- ret = -ENOMEM; -- goto free_freq_table; -- } -- -- prop = of_find_property(np, "fsl,soc-operating-points", NULL); -- if (!prop || !prop->value) -- goto soc_opp_out; -- -- /* -- * Each OPP is a set of tuples consisting of frequency and -- * voltage like . -- */ -- nr = prop->length / sizeof(u32); -- if (nr % 2 || (nr / 2) < num) -- goto soc_opp_out; -- -- for (j = 0; j < num; j++) { -- val = prop->value; -- for (i = 0; i < nr / 2; i++) { -- unsigned long freq = be32_to_cpup(val++); -- unsigned long volt = be32_to_cpup(val++); -- if (freq_table[j].frequency == freq) { -- imx6_soc_volt[soc_opp_count++] = volt; -- break; -- } -- } -- } -- --soc_opp_out: -- /* use fixed soc opp volt if no valid soc opp info found in dtb */ -- if (soc_opp_count != num) { -- dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); -- for (j = 0; j < num; j++) -- imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; -- if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) -- imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; -- } -- -- if (of_property_read_u32(np, "clock-latency", &transition_latency)) -- transition_latency = CPUFREQ_ETERNAL; -- -- /* -- * Calculate the ramp time for max voltage change in the -- * VDDSOC and VDDPU regulators. -- */ -- ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); -- if (ret > 0) -- transition_latency += ret * 1000; -- ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); -- if (ret > 0) -- transition_latency += ret * 1000; -- -- /* -- * OPP is maintained in order of increasing frequency, and -- * freq_table initialised from OPP is therefore sorted in the -- * same order. -- */ -- rcu_read_lock(); -- opp = dev_pm_opp_find_freq_exact(cpu_dev, -- freq_table[0].frequency * 1000, true); -- min_volt = dev_pm_opp_get_voltage(opp); -- opp = dev_pm_opp_find_freq_exact(cpu_dev, -- freq_table[--num].frequency * 1000, true); -- max_volt = dev_pm_opp_get_voltage(opp); -- rcu_read_unlock(); -- ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); -- if (ret > 0) -- transition_latency += ret * 1000; -- -- ret = cpufreq_register_driver(&imx6q_cpufreq_driver); -- if (ret) { -- dev_err(cpu_dev, "failed register driver: %d\n", ret); -- goto free_freq_table; -- } -- -- of_node_put(np); -- return 0; -- --free_freq_table: -- dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); --put_node: -- of_node_put(np); -- return ret; --} -- --static int imx6q_cpufreq_remove(struct platform_device *pdev) --{ -- cpufreq_unregister_driver(&imx6q_cpufreq_driver); -- dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); -- -- return 0; --} -- --static struct platform_driver imx6q_cpufreq_platdrv = { -- .driver = { -- .name = "imx6q-cpufreq", -- .owner = THIS_MODULE, -- }, -- .probe = imx6q_cpufreq_probe, -- .remove = imx6q_cpufreq_remove, --}; --module_platform_driver(imx6q_cpufreq_platdrv); -- --MODULE_AUTHOR("Shawn Guo "); --MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); --MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/cpufreq/Kconfig linux-3.14.22/drivers/cpufreq/Kconfig ---- linux-3.14.22.orig/drivers/cpufreq/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/cpufreq/Kconfig 2014-10-22 14:55:52.042220001 -0500 -@@ -91,6 +91,15 @@ - governor. If unsure have a look at the help section of the - driver. Fallback governor will be the performance governor. - -+config CPU_FREQ_DEFAULT_GOV_INTERACTIVE -+ bool "interactive" -+ select CPU_FREQ_GOV_INTERACTIVE -+ help -+ Use the CPUFreq governor 'interactive' as default. This allows -+ you to get a full dynamic cpu frequency capable system by simply -+ loading your cpufreq low-level hardware driver, using the -+ 'interactive' governor for latency-sensitive workloads. -+ - config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE - bool "conservative" - select CPU_FREQ_GOV_CONSERVATIVE -@@ -157,6 +166,24 @@ - - For details, take a look at linux/Documentation/cpu-freq. - -+ If in doubt, say N. -+ -+config CPU_FREQ_GOV_INTERACTIVE -+ tristate "'interactive' cpufreq policy governor" -+ default n -+ help -+ 'interactive' - This driver adds a dynamic cpufreq policy governor -+ designed for latency-sensitive workloads. -+ -+ This governor attempts to reduce the latency of clock -+ increases so that the system is more responsive to -+ interactive workloads. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called cpufreq_interactive. -+ -+ For details, take a look at linux/Documentation/cpu-freq. -+ - If in doubt, say N. - - config CPU_FREQ_GOV_CONSERVATIVE -diff -Nur linux-3.14.22.orig/drivers/cpufreq/Kconfig.arm linux-3.14.22/drivers/cpufreq/Kconfig.arm ---- linux-3.14.22.orig/drivers/cpufreq/Kconfig.arm 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/cpufreq/Kconfig.arm 2014-10-22 14:55:52.042220001 -0500 -@@ -4,7 +4,8 @@ - - config ARM_BIG_LITTLE_CPUFREQ - tristate "Generic ARM big LITTLE CPUfreq driver" -- depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK -+ depends on (BIG_LITTLE && ARM_CPU_TOPOLOGY) || (ARM64 && SMP) -+ depends on HAVE_CLK - select PM_OPP - help - This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. -@@ -95,7 +96,7 @@ - - If in doubt, say N. - --config ARM_IMX6Q_CPUFREQ -+config ARM_IMX6_CPUFREQ - tristate "Freescale i.MX6 cpufreq support" - depends on ARCH_MXC - depends on REGULATOR_ANATOP -diff -Nur linux-3.14.22.orig/drivers/cpufreq/Makefile linux-3.14.22/drivers/cpufreq/Makefile ---- linux-3.14.22.orig/drivers/cpufreq/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/cpufreq/Makefile 2014-10-22 14:55:52.042220001 -0500 -@@ -8,6 +8,7 @@ - obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o - obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o - obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o -+obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o - obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o - obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o - -@@ -55,7 +56,7 @@ - obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o - obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o - obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o --obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o -+obj-$(CONFIG_ARM_IMX6_CPUFREQ) += imx6-cpufreq.o - obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o - obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o - obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/secvio.c linux-3.14.22/drivers/crypto/caam/secvio.c ---- linux-3.14.22.orig/drivers/crypto/caam/secvio.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/secvio.c 2014-10-22 14:55:52.042220001 -0500 -@@ -0,0 +1,335 @@ -+ -+/* -+ * CAAM/SEC 4.x Security Violation Handler -+ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved -+ */ -+ -+#include "compat.h" -+#include "intern.h" -+#include "secvio.h" -+#include "regs.h" -+ -+/* -+ * These names are associated with each violation handler. -+ * The source names were taken from MX6, and are based on recommendations -+ * for most common SoCs. -+ */ -+static const u8 *violation_src_name[] = { -+ "CAAM Security Violation", -+ "JTAG Alarm", -+ "Watchdog", -+ "(reserved)", -+ "External Boot", -+ "Tamper Detect", -+}; -+ -+/* Top-level security violation interrupt */ -+static irqreturn_t caam_secvio_interrupt(int irq, void *snvsdev) -+{ -+ struct device *dev = snvsdev; -+ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); -+ u32 irqstate; -+ -+ /* Check the HP secvio status register */ -+ irqstate = rd_reg32(&svpriv->svregs->hp.secvio_status) | -+ HP_SECVIOST_SECVIOMASK; -+ -+ if (!irqstate) -+ return IRQ_NONE; -+ -+ /* Mask out one or more causes for deferred service */ -+ clrbits32(&svpriv->svregs->hp.secvio_int_ctl, irqstate); -+ -+ /* Now ACK causes */ -+ setbits32(&svpriv->svregs->hp.secvio_status, irqstate); -+ -+ /* And run deferred service */ -+ preempt_disable(); -+ tasklet_schedule(&svpriv->irqtask[smp_processor_id()]); -+ preempt_enable(); -+ -+ return IRQ_HANDLED; -+} -+ -+/* Deferred service handler. Tasklet arg is simply the SNVS dev */ -+static void caam_secvio_dispatch(unsigned long indev) -+{ -+ struct device *dev = (struct device *)indev; -+ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); -+ unsigned long flags, cause; -+ int i; -+ -+ -+ /* -+ * Capture the interrupt cause, using masked interrupts as -+ * identification. This only works if all are enabled; if -+ * this changes in the future, a "cause queue" will have to -+ * be built -+ */ -+ cause = rd_reg32(&svpriv->svregs->hp.secvio_int_ctl) & -+ (HP_SECVIO_INTEN_SRC5 | HP_SECVIO_INTEN_SRC4 | -+ HP_SECVIO_INTEN_SRC3 | HP_SECVIO_INTEN_SRC2 | -+ HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0); -+ -+ /* Look through causes, call each handler if exists */ -+ for (i = 0; i < MAX_SECVIO_SOURCES; i++) -+ if (cause & (1 << i)) { -+ spin_lock_irqsave(&svpriv->svlock, flags); -+ svpriv->intsrc[i].handler(dev, i, -+ svpriv->intsrc[i].ext); -+ spin_unlock_irqrestore(&svpriv->svlock, flags); -+ }; -+ -+ /* Re-enable now-serviced interrupts */ -+ setbits32(&svpriv->svregs->hp.secvio_int_ctl, cause); -+} -+ -+/* -+ * Default cause handler, used in lieu of an application-defined handler. -+ * All it does at this time is print a console message. It could force a halt. -+ */ -+static void caam_secvio_default(struct device *dev, u32 cause, void *ext) -+{ -+ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); -+ -+ dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n", -+ cause, svpriv->intsrc[cause].intname); -+} -+ -+/* -+ * Install an application-defined handler for a specified cause -+ * Arguments: -+ * - dev points to SNVS-owning device -+ * - cause interrupt source cause -+ * - handler application-defined handler, gets called with dev -+ * source cause, and locally-defined handler argument -+ * - cause_description points to a string to override the default cause -+ * name, this can be used as an alternate for error -+ * messages and such. If left NULL, the default -+ * description string is used. -+ * - ext pointer to any extra data needed by the handler. -+ */ -+int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, -+ void (*handler)(struct device *dev, u32 cause, -+ void *ext), -+ u8 *cause_description, void *ext) -+{ -+ unsigned long flags; -+ struct caam_drv_private_secvio *svpriv; -+ -+ svpriv = dev_get_drvdata(dev); -+ -+ if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&svpriv->svlock, flags); -+ svpriv->intsrc[cause].handler = handler; -+ if (cause_description != NULL) -+ svpriv->intsrc[cause].intname = cause_description; -+ if (ext != NULL) -+ svpriv->intsrc[cause].ext = ext; -+ spin_unlock_irqrestore(&svpriv->svlock, flags); -+ -+ return 0; -+} -+EXPORT_SYMBOL(caam_secvio_install_handler); -+ -+/* -+ * Remove an application-defined handler for a specified cause (and, by -+ * implication, restore the "default". -+ * Arguments: -+ * - dev points to SNVS-owning device -+ * - cause interrupt source cause -+ */ -+int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause) -+{ -+ unsigned long flags; -+ struct caam_drv_private_secvio *svpriv; -+ -+ svpriv = dev_get_drvdata(dev); -+ -+ if (cause > SECVIO_CAUSE_SOURCE_5) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&svpriv->svlock, flags); -+ svpriv->intsrc[cause].intname = violation_src_name[cause]; -+ svpriv->intsrc[cause].handler = caam_secvio_default; -+ svpriv->intsrc[cause].ext = NULL; -+ spin_unlock_irqrestore(&svpriv->svlock, flags); -+ return 0; -+} -+EXPORT_SYMBOL(caam_secvio_remove_handler); -+ -+int caam_secvio_startup(struct platform_device *pdev) -+{ -+ struct device *ctrldev, *svdev; -+ struct caam_drv_private *ctrlpriv; -+ struct caam_drv_private_secvio *svpriv; -+ struct platform_device *svpdev; -+ struct device_node *np; -+ const void *prop; -+ int i, error, secvio_inten_src; -+ -+ ctrldev = &pdev->dev; -+ ctrlpriv = dev_get_drvdata(ctrldev); -+ /* -+ * Set up the private block for secure memory -+ * Only one instance is possible -+ */ -+ svpriv = kzalloc(sizeof(struct caam_drv_private_secvio), GFP_KERNEL); -+ if (svpriv == NULL) { -+ dev_err(ctrldev, "can't alloc private mem for secvio\n"); -+ return -ENOMEM; -+ } -+ svpriv->parentdev = ctrldev; -+ -+ /* Create the security violation dev */ -+#ifdef CONFIG_OF -+ -+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio"); -+ if (!np) -+ return -ENODEV; -+ -+ ctrlpriv->secvio_irq = of_irq_to_resource(np, 0, NULL); -+ -+ prop = of_get_property(np, "secvio_src", NULL); -+ if (prop) -+ secvio_inten_src = of_read_ulong(prop, 1); -+ else -+ secvio_inten_src = HP_SECVIO_INTEN_ALL; -+ -+ printk(KERN_ERR "secvio_inten_src = %x\n", secvio_inten_src); -+ -+ svpdev = of_platform_device_create(np, NULL, ctrldev); -+ if (!svpdev) -+ return -ENODEV; -+ -+#else -+ svpdev = platform_device_register_data(ctrldev, "caam_secvio", 0, -+ svpriv, -+ sizeof(struct caam_drv_private_secvio)); -+ -+ secvio_inten_src = HP_SECVIO_INTEN_ALL; -+#endif -+ if (svpdev == NULL) { -+ kfree(svpriv); -+ return -EINVAL; -+ } -+ svdev = &svpdev->dev; -+ dev_set_drvdata(svdev, svpriv); -+ ctrlpriv->secviodev = svdev; -+ svpriv->svregs = ctrlpriv->snvs; -+ -+ /* -+ * Now we have all the dev data set up. Init interrupt -+ * source descriptions -+ */ -+ for (i = 0; i < MAX_SECVIO_SOURCES; i++) { -+ svpriv->intsrc[i].intname = violation_src_name[i]; -+ svpriv->intsrc[i].handler = caam_secvio_default; -+ } -+ -+ /* Connect main handler */ -+ for_each_possible_cpu(i) -+ tasklet_init(&svpriv->irqtask[i], caam_secvio_dispatch, -+ (unsigned long)svdev); -+ -+ error = request_irq(ctrlpriv->secvio_irq, caam_secvio_interrupt, -+ IRQF_SHARED, "caam_secvio", svdev); -+ if (error) { -+ dev_err(svdev, "can't connect secvio interrupt\n"); -+ irq_dispose_mapping(ctrlpriv->secvio_irq); -+ ctrlpriv->secvio_irq = 0; -+ return -EINVAL; -+ } -+ -+ /* Enable all sources */ -+ wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, secvio_inten_src); -+ -+ dev_info(svdev, "security violation service handlers armed\n"); -+ -+ return 0; -+} -+ -+void caam_secvio_shutdown(struct platform_device *pdev) -+{ -+ struct device *ctrldev, *svdev; -+ struct caam_drv_private *priv; -+ struct caam_drv_private_secvio *svpriv; -+ int i; -+ -+ ctrldev = &pdev->dev; -+ priv = dev_get_drvdata(ctrldev); -+ svdev = priv->secviodev; -+ svpriv = dev_get_drvdata(svdev); -+ -+ /* Shut off all sources */ -+ -+ wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, 0); -+ -+ /* Remove tasklets and release interrupt */ -+ for_each_possible_cpu(i) -+ tasklet_kill(&svpriv->irqtask[i]); -+ -+ free_irq(priv->secvio_irq, svdev); -+ -+ kfree(svpriv); -+} -+ -+ -+#ifdef CONFIG_OF -+static void __exit caam_secvio_exit(void) -+{ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -+ if (!dev_node) -+ return; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return; -+ -+ of_node_get(dev_node); -+ -+ caam_secvio_shutdown(pdev); -+ -+} -+ -+static int __init caam_secvio_init(void) -+{ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ /* -+ * Do of_find_compatible_node() then of_find_device_by_node() -+ * once a functional device tree is available -+ */ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, -+ "arm,imx6-caam-secvio"); -+ if (!dev_node) -+ return -ENODEV; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return -ENODEV; -+ -+ of_node_put(dev_node); -+ -+ return caam_secvio_startup(pdev); -+} -+ -+module_init(caam_secvio_init); -+module_exit(caam_secvio_exit); -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_DESCRIPTION("FSL CAAM/SNVS Security Violation Handler"); -+MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); -+#endif -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/secvio.h linux-3.14.22/drivers/crypto/caam/secvio.h ---- linux-3.14.22.orig/drivers/crypto/caam/secvio.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/secvio.h 2014-10-22 14:55:52.042220001 -0500 -@@ -0,0 +1,64 @@ -+ -+/* -+ * CAAM Security Violation Handler -+ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved -+ */ -+ -+#ifndef SECVIO_H -+#define SECVIO_H -+ -+#include "snvsregs.h" -+ -+ -+/* -+ * Defines the published interfaces to install/remove application-specified -+ * handlers for catching violations -+ */ -+ -+#define MAX_SECVIO_SOURCES 6 -+ -+/* these are the untranslated causes */ -+enum secvio_cause { -+ SECVIO_CAUSE_SOURCE_0, -+ SECVIO_CAUSE_SOURCE_1, -+ SECVIO_CAUSE_SOURCE_2, -+ SECVIO_CAUSE_SOURCE_3, -+ SECVIO_CAUSE_SOURCE_4, -+ SECVIO_CAUSE_SOURCE_5 -+}; -+ -+/* These are common "recommended" cause definitions for most devices */ -+#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0 -+#define SECVIO_CAUSE JTAG_ALARM SECVIO_CAUSE_SOURCE_1 -+#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2 -+#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4 -+#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5 -+ -+int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, -+ void (*handler)(struct device *dev, u32 cause, -+ void *ext), -+ u8 *cause_description, void *ext); -+int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause); -+ -+/* -+ * Private data definitions for the secvio "driver" -+ */ -+ -+struct secvio_int_src { -+ const u8 *intname; /* Points to a descriptive name for source */ -+ void *ext; /* Extended data to pass to the handler */ -+ void (*handler)(struct device *dev, u32 cause, void *ext); -+}; -+ -+struct caam_drv_private_secvio { -+ struct device *parentdev; /* points back to the controller */ -+ spinlock_t svlock ____cacheline_aligned; -+ struct tasklet_struct irqtask[NR_CPUS]; -+ struct snvs_full __iomem *svregs; /* both HP and LP domains */ -+ -+ /* Registered handlers for each violation */ -+ struct secvio_int_src intsrc[MAX_SECVIO_SOURCES]; -+ -+}; -+ -+#endif /* SECVIO_H */ -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/sm.h linux-3.14.22/drivers/crypto/caam/sm.h ---- linux-3.14.22.orig/drivers/crypto/caam/sm.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/sm.h 2014-10-22 14:55:52.042220001 -0500 -@@ -0,0 +1,88 @@ -+ -+/* -+ * CAAM Secure Memory/Keywrap API Definitions -+ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. -+ */ -+ -+#ifndef SM_H -+#define SM_H -+ -+ -+/* Storage access permissions */ -+#define SM_PERM_READ 0x01 -+#define SM_PERM_WRITE 0x02 -+#define SM_PERM_BLOB 0x03 -+ -+ -+/* Keystore maintenance functions */ -+void sm_init_keystore(struct device *dev); -+u32 sm_detect_keystore_units(struct device *dev); -+int sm_establish_keystore(struct device *dev, u32 unit); -+void sm_release_keystore(struct device *dev, u32 unit); -+void caam_sm_shutdown(struct platform_device *pdev); -+int caam_sm_example_init(struct platform_device *pdev); -+ -+/* Keystore accessor functions */ -+extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, -+ u32 *slot); -+extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot); -+extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, -+ const u8 *key_data, u32 key_length); -+extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, -+ u32 key_length, u8 *key_data); -+extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, -+ u32 inslot, u32 outslot, u16 secretlen, -+ u8 *keymod, u16 keymodlen); -+extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, -+ u32 inslot, u32 outslot, u16 secretlen, -+ u8 *keymod, u16 keymodlen); -+ -+/* Data structure to hold per-slot information */ -+struct keystore_data_slot_info { -+ u8 allocated; /* Track slot assignments */ -+ u32 key_length; /* Size of the key */ -+}; -+ -+/* Data structure to hold keystore information */ -+struct keystore_data { -+ void *base_address; /* Base of the Secure Partition */ -+ u32 slot_count; /* Number of slots in the keystore */ -+ struct keystore_data_slot_info *slot; /* Per-slot information */ -+}; -+ -+/* store the detected attributes of a secure memory page */ -+struct sm_page_descriptor { -+ u16 phys_pagenum; /* may be discontiguous */ -+ u16 own_part; /* Owning partition */ -+ void *pg_base; /* Calculated virtual address */ -+ struct keystore_data *ksdata; -+}; -+ -+struct caam_drv_private_sm { -+ struct device *parentdev; /* this ends up as the controller */ -+ struct device *smringdev; /* ring that owns this instance */ -+ spinlock_t kslock ____cacheline_aligned; -+ -+ /* Default parameters for geometry */ -+ u32 max_pages; /* maximum pages this instance can support */ -+ u32 top_partition; /* highest partition number in this instance */ -+ u32 top_page; /* highest page number in this instance */ -+ u32 page_size; /* page size */ -+ u32 slot_size; /* selected size of each storage block */ -+ -+ /* Partition/Page Allocation Map */ -+ u32 localpages; /* Number of pages we can access */ -+ struct sm_page_descriptor *pagedesc; /* Allocated per-page */ -+ -+ /* Installed handlers for keystore access */ -+ int (*data_init)(struct device *dev, u32 unit); -+ void (*data_cleanup)(struct device *dev, u32 unit); -+ int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot); -+ int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot); -+ void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle); -+ u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle); -+ u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle); -+ u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle); -+}; -+ -+#endif /* SM_H */ -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/sm_store.c linux-3.14.22/drivers/crypto/caam/sm_store.c ---- linux-3.14.22.orig/drivers/crypto/caam/sm_store.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/sm_store.c 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,896 @@ -+ -+/* -+ * CAAM Secure Memory Storage Interface -+ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. -+ * -+ * Loosely based on the SHW Keystore API for SCC/SCC2 -+ * Experimental implementation and NOT intended for upstream use. Expect -+ * this interface to be amended significantly in the future once it becomes -+ * integrated into live applications. -+ * -+ * Known issues: -+ * -+ * - Executes one instance of an secure memory "driver". This is tied to the -+ * fact that job rings can't run as standalone instances in the present -+ * configuration. -+ * -+ * - It does not expose a userspace interface. The value of a userspace -+ * interface for access to secrets is a point for further architectural -+ * discussion. -+ * -+ * - Partition/permission management is not part of this interface. It -+ * depends on some level of "knowledge" agreed upon between bootloader, -+ * provisioning applications, and OS-hosted software (which uses this -+ * driver). -+ * -+ * - No means of identifying the location or purpose of secrets managed by -+ * this interface exists; "slot location" and format of a given secret -+ * needs to be agreed upon between bootloader, provisioner, and OS-hosted -+ * application. -+ */ -+ -+#include "compat.h" -+#include "regs.h" -+#include "jr.h" -+#include "desc.h" -+#include "intern.h" -+#include "error.h" -+#include "sm.h" -+ -+#ifdef SM_DEBUG_CONT -+void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ u32 i, *smdata; -+ -+ dev_info(dev, "physical page %d content at 0x%08x\n", -+ pgdesc->phys_pagenum, pgdesc->pg_base); -+ smdata = pgdesc->pg_base; -+ for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4) -+ dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", -+ (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2], -+ smdata[i+3]); -+} -+#endif -+ -+/* -+ * Construct a secure memory blob encapsulation job descriptor -+ * -+ * - desc pointer to hold new (to be allocated) pointer to the generated -+ * descriptor for later use. Calling thread can kfree the -+ * descriptor after execution. -+ * - keymod Physical pointer to key modifier (contiguous piece). -+ * - keymodsz Size of key modifier in bytes (should normally be 8). -+ * - secretbuf Physical pointer (within an accessible secure memory page) -+ * of the secret to be encapsulated. -+ * - outbuf Physical pointer (within an accessible secure memory page) -+ * of the encapsulated output. This will be larger than the -+ * input secret because of the added encapsulation data. -+ * - secretsz Size of input secret, in bytes. -+ * - auth If nonzero, use AES-CCM for encapsulation, else use ECB -+ * -+ * Note: this uses 32-bit pointers at present -+ */ -+#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ -+static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, -+ dma_addr_t secretbuf, dma_addr_t outbuf, -+ u16 secretsz, bool auth) -+{ -+ u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; -+ u16 dsize, idx; -+ -+ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); -+ idx = 1; -+ -+ /* Load key modifier */ -+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | -+ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | -+ (keymodsz & LDST_LEN_MASK); -+ -+ tmpdesc[idx++] = (u32)keymod; -+ -+ /* Encapsulate to secure memory */ -+ tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz; -+ tmpdesc[idx++] = (u32)secretbuf; -+ -+ /* Add space for BKEK and MAC tag */ -+ tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16)); -+ -+ tmpdesc[idx++] = (u32)outbuf; -+ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | -+ OP_PCL_BLOB_PTXT_SECMEM; -+ if (auth) -+ tmpdesc[idx] |= OP_PCL_BLOB_EKT; -+ -+ idx++; -+ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); -+ dsize = idx * sizeof(u32); -+ -+ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); -+ if (tdesc == NULL) -+ return 0; -+ -+ memcpy(tdesc, tmpdesc, dsize); -+ *desc = tdesc; -+ return dsize; -+} -+ -+/* -+ * Construct a secure memory blob decapsulation job descriptor -+ * -+ * - desc pointer to hold new (to be allocated) pointer to the generated -+ * descriptor for later use. Calling thread can kfree the -+ * descriptor after execution. -+ * - keymod Physical pointer to key modifier (contiguous piece). -+ * - keymodsz Size of key modifier in bytes (should normally be 16). -+ * - blobbuf Physical pointer (within an accessible secure memory page) -+ * of the blob to be decapsulated. -+ * - outbuf Physical pointer (within an accessible secure memory page) -+ * of the decapsulated output. -+ * - secretsz Size of input blob, in bytes. -+ * - auth If nonzero, assume AES-CCM for decapsulation, else use ECB -+ * -+ * Note: this uses 32-bit pointers at present -+ */ -+static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, -+ dma_addr_t blobbuf, dma_addr_t outbuf, -+ u16 blobsz, bool auth) -+{ -+ u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; -+ u16 dsize, idx; -+ -+ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); -+ idx = 1; -+ -+ /* Load key modifier */ -+ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | -+ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | -+ (keymodsz & LDST_LEN_MASK); -+ -+ tmpdesc[idx++] = (u32)keymod; -+ -+ /* Compensate BKEK + MAC tag */ -+ tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16); -+ -+ tmpdesc[idx++] = (u32)blobbuf; -+ tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz; -+ tmpdesc[idx++] = (u32)outbuf; -+ -+ /* Decapsulate from secure memory partition to black blob */ -+ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB | -+ OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK; -+ if (auth) -+ tmpdesc[idx] |= OP_PCL_BLOB_EKT; -+ -+ idx++; -+ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); -+ dsize = idx * sizeof(u32); -+ -+ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); -+ if (tdesc == NULL) -+ return 0; -+ -+ memcpy(tdesc, tmpdesc, dsize); -+ *desc = tdesc; -+ return dsize; -+} -+ -+/* -+ * Pseudo-synchronous ring access functions for carrying out key -+ * encapsulation and decapsulation -+ */ -+ -+struct sm_key_job_result { -+ int error; -+ struct completion completion; -+}; -+ -+void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context) -+{ -+ struct sm_key_job_result *res = context; -+ -+ res->error = err; /* save off the error for postprocessing */ -+ complete(&res->completion); /* mark us complete */ -+} -+ -+static int sm_key_job(struct device *ksdev, u32 *jobdesc) -+{ -+ struct sm_key_job_result testres; -+ struct caam_drv_private_sm *kspriv; -+ int rtn = 0; -+ -+ kspriv = dev_get_drvdata(ksdev); -+ -+ init_completion(&testres.completion); -+ -+ rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done, -+ &testres); -+ if (!rtn) { -+ wait_for_completion_interruptible(&testres.completion); -+ rtn = testres.error; -+ } -+ return rtn; -+} -+ -+/* -+ * Following section establishes the default methods for keystore access -+ * They are NOT intended for use external to this module -+ * -+ * In the present version, these are the only means for the higher-level -+ * interface to deal with the mechanics of accessing the phyiscal keystore -+ */ -+ -+ -+int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; -+ u32 i; -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size); -+#endif -+ -+ if (size > smpriv->slot_size) -+ return -EKEYREJECTED; -+ -+ for (i = 0; i < ksdata->slot_count; i++) { -+ if (ksdata->slot[i].allocated == 0) { -+ ksdata->slot[i].allocated = 1; -+ (*slot) = i; -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_alloc(): new slot %d allocated\n", -+ *slot); -+#endif -+ return 0; -+ } -+ } -+ -+ return -ENOSPC; -+} -+EXPORT_SYMBOL(slot_alloc); -+ -+int slot_dealloc(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; -+ u8 __iomem *slotdata; -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot); -+#endif -+ if (slot >= ksdata->slot_count) -+ return -EINVAL; -+ slotdata = ksdata->base_address + slot * smpriv->slot_size; -+ -+ if (ksdata->slot[slot].allocated == 1) { -+ /* Forcibly overwrite the data from the keystore */ -+ memset(ksdata->base_address + slot * smpriv->slot_size, 0, -+ smpriv->slot_size); -+ -+ ksdata->slot[slot].allocated = 0; -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_dealloc(): slot %d released\n", slot); -+#endif -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+EXPORT_SYMBOL(slot_dealloc); -+ -+void *slot_get_address(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; -+ -+ if (slot >= ksdata->slot_count) -+ return NULL; -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot, -+ (u32)ksdata->base_address + slot * smpriv->slot_size); -+#endif -+ -+ return ksdata->base_address + slot * smpriv->slot_size; -+} -+ -+u32 slot_get_base(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; -+ -+ /* -+ * There could potentially be more than one secure partition object -+ * associated with this keystore. For now, there is just one. -+ */ -+ -+ (void)slot; -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n", -+ slot, (u32)ksdata->base_address); -+#endif -+ -+ return (u32)(ksdata->base_address); -+} -+ -+u32 slot_get_offset(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; -+ -+ if (slot >= ksdata->slot_count) -+ return -EINVAL; -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot, -+ slot * smpriv->slot_size); -+#endif -+ -+ return slot * smpriv->slot_size; -+} -+ -+u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot, -+ smpriv->slot_size); -+#endif -+ /* All slots are the same size in the default implementation */ -+ return smpriv->slot_size; -+} -+ -+ -+ -+int kso_init_data(struct device *dev, u32 unit) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = -EINVAL; -+ struct keystore_data *keystore_data = NULL; -+ u32 slot_count; -+ u32 keystore_data_size; -+ -+ /* -+ * Calculate the required size of the keystore data structure, based -+ * on the number of keys that can fit in the partition. -+ */ -+ slot_count = smpriv->page_size / smpriv->slot_size; -+#ifdef SM_DEBUG -+ dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count); -+#endif -+ -+ keystore_data_size = sizeof(struct keystore_data) + -+ slot_count * -+ sizeof(struct keystore_data_slot_info); -+ -+ keystore_data = kzalloc(keystore_data_size, GFP_KERNEL); -+ -+ if (keystore_data == NULL) { -+ retval = -ENOSPC; -+ goto out; -+ } -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "kso_init_data: keystore data size = %d\n", -+ keystore_data_size); -+#endif -+ -+ /* -+ * Place the slot information structure directly after the keystore data -+ * structure. -+ */ -+ keystore_data->slot = (struct keystore_data_slot_info *) -+ (keystore_data + 1); -+ keystore_data->slot_count = slot_count; -+ -+ smpriv->pagedesc[unit].ksdata = keystore_data; -+ smpriv->pagedesc[unit].ksdata->base_address = -+ smpriv->pagedesc[unit].pg_base; -+ -+ retval = 0; -+ -+out: -+ if (retval != 0) -+ if (keystore_data != NULL) -+ kfree(keystore_data); -+ -+ -+ return retval; -+} -+ -+void kso_cleanup_data(struct device *dev, u32 unit) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ struct keystore_data *keystore_data = NULL; -+ -+ if (smpriv->pagedesc[unit].ksdata != NULL) -+ keystore_data = smpriv->pagedesc[unit].ksdata; -+ -+ /* Release the allocated keystore management data */ -+ kfree(smpriv->pagedesc[unit].ksdata); -+ -+ return; -+} -+ -+ -+ -+/* -+ * Keystore management section -+ */ -+ -+void sm_init_keystore(struct device *dev) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ -+ smpriv->data_init = kso_init_data; -+ smpriv->data_cleanup = kso_cleanup_data; -+ smpriv->slot_alloc = slot_alloc; -+ smpriv->slot_dealloc = slot_dealloc; -+ smpriv->slot_get_address = slot_get_address; -+ smpriv->slot_get_base = slot_get_base; -+ smpriv->slot_get_offset = slot_get_offset; -+ smpriv->slot_get_slot_size = slot_get_slot_size; -+#ifdef SM_DEBUG -+ dev_info(dev, "sm_init_keystore(): handlers installed\n"); -+#endif -+} -+EXPORT_SYMBOL(sm_init_keystore); -+ -+/* Return available pages/units */ -+u32 sm_detect_keystore_units(struct device *dev) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ -+ return smpriv->localpages; -+} -+EXPORT_SYMBOL(sm_detect_keystore_units); -+ -+/* -+ * Do any keystore specific initializations -+ */ -+int sm_establish_keystore(struct device *dev, u32 unit) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit); -+#endif -+ -+ if (smpriv->data_init == NULL) -+ return -EINVAL; -+ -+ /* Call the data_init function for any user setup */ -+ return smpriv->data_init(dev, unit); -+} -+EXPORT_SYMBOL(sm_establish_keystore); -+ -+void sm_release_keystore(struct device *dev, u32 unit) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ -+#ifdef SM_DEBUG -+ dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit); -+#endif -+ if ((smpriv != NULL) && (smpriv->data_cleanup != NULL)) -+ smpriv->data_cleanup(dev, unit); -+ -+ return; -+} -+EXPORT_SYMBOL(sm_release_keystore); -+ -+/* -+ * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to -+ * the keystore -+ */ -+int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = -EINVAL; -+ -+ spin_lock(&smpriv->kslock); -+ -+ if ((smpriv->slot_alloc == NULL) || -+ (smpriv->pagedesc[unit].ksdata == NULL)) -+ goto out; -+ -+ retval = smpriv->slot_alloc(dev, unit, size, slot); -+ -+out: -+ spin_unlock(&smpriv->kslock); -+ return retval; -+} -+EXPORT_SYMBOL(sm_keystore_slot_alloc); -+ -+int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = -EINVAL; -+ -+ spin_lock(&smpriv->kslock); -+ -+ if ((smpriv->slot_alloc == NULL) || -+ (smpriv->pagedesc[unit].ksdata == NULL)) -+ goto out; -+ -+ retval = smpriv->slot_dealloc(dev, unit, slot); -+out: -+ spin_unlock(&smpriv->kslock); -+ return retval; -+} -+EXPORT_SYMBOL(sm_keystore_slot_dealloc); -+ -+int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, -+ const u8 *key_data, u32 key_length) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = -EINVAL; -+ u32 slot_size; -+ u32 i; -+ u8 __iomem *slot_location; -+ -+ spin_lock(&smpriv->kslock); -+ -+ slot_size = smpriv->slot_get_slot_size(dev, unit, slot); -+ -+ if (key_length > slot_size) { -+ retval = -EFBIG; -+ goto out; -+ } -+ -+ slot_location = smpriv->slot_get_address(dev, unit, slot); -+ -+ for (i = 0; i < key_length; i++) -+ slot_location[i] = key_data[i]; -+ -+ retval = 0; -+ -+out: -+ spin_unlock(&smpriv->kslock); -+ return retval; -+} -+EXPORT_SYMBOL(sm_keystore_slot_load); -+ -+int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, -+ u32 key_length, u8 *key_data) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = -EINVAL; -+ u8 __iomem *slot_addr; -+ u32 slot_size; -+ -+ spin_lock(&smpriv->kslock); -+ -+ slot_addr = smpriv->slot_get_address(dev, unit, slot); -+ slot_size = smpriv->slot_get_slot_size(dev, unit, slot); -+ -+ if (key_length > slot_size) { -+ retval = -EKEYREJECTED; -+ goto out; -+ } -+ -+ memcpy(key_data, slot_addr, key_length); -+ retval = 0; -+ -+out: -+ spin_unlock(&smpriv->kslock); -+ return retval; -+} -+EXPORT_SYMBOL(sm_keystore_slot_read); -+ -+int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot, -+ u32 outslot, u16 secretlen, u8 *keymod, -+ u16 keymodlen) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = 0; -+ u32 slot_length, dsize, jstat; -+ u32 __iomem *encapdesc = NULL; -+ u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; -+ dma_addr_t keymod_dma; -+ -+ /* Ensure that the full blob will fit in the key slot */ -+ slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); -+ if ((secretlen + 48) > slot_length) -+ goto out; -+ -+ /* Get the base addresses of both keystore slots */ -+ inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); -+ outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); -+ -+ /* Build the key modifier */ -+ lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); -+ memcpy(lkeymod, keymod, keymodlen); -+ keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); -+ dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); -+ -+ /* Build the encapsulation job descriptor */ -+ dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen, -+ __pa(inpslotaddr), __pa(outslotaddr), -+ secretlen, 0); -+ if (!dsize) { -+ dev_err(dev, "can't alloc an encap descriptor\n"); -+ retval = -ENOMEM; -+ goto out; -+ } -+ jstat = sm_key_job(dev, encapdesc); -+ -+ dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); -+ kfree(encapdesc); -+ -+out: -+ return retval; -+ -+} -+EXPORT_SYMBOL(sm_keystore_slot_encapsulate); -+ -+int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot, -+ u32 outslot, u16 secretlen, u8 *keymod, -+ u16 keymodlen) -+{ -+ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); -+ int retval = 0; -+ u32 slot_length, dsize, jstat; -+ u32 __iomem *decapdesc = NULL; -+ u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; -+ dma_addr_t keymod_dma; -+ -+ /* Ensure that the decap data will fit in the key slot */ -+ slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); -+ if (secretlen > slot_length) -+ goto out; -+ -+ /* Get the base addresses of both keystore slots */ -+ inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); -+ outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); -+ -+ /* Build the key modifier */ -+ lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); -+ memcpy(lkeymod, keymod, keymodlen); -+ keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); -+ dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); -+ -+ /* Build the decapsulation job descriptor */ -+ dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen, -+ __pa(inpslotaddr), __pa(outslotaddr), -+ secretlen, 0); -+ if (!dsize) { -+ dev_err(dev, "can't alloc a decap descriptor\n"); -+ retval = -ENOMEM; -+ goto out; -+ } -+ jstat = sm_key_job(dev, decapdesc); -+ -+ dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); -+ kfree(decapdesc); -+ -+out: -+ return retval; -+ -+} -+EXPORT_SYMBOL(sm_keystore_slot_decapsulate); -+ -+ -+/* -+ * Initialization/shutdown subsystem -+ * Assumes statically-invoked startup/shutdown from the controller driver -+ * for the present time, to be reworked when a device tree becomes -+ * available. This code will not modularize in present form. -+ * -+ * Also, simply uses ring 0 for execution at the present -+ */ -+ -+int caam_sm_startup(struct platform_device *pdev) -+{ -+ struct device *ctrldev, *smdev; -+ struct caam_drv_private *ctrlpriv; -+ struct caam_drv_private_sm *smpriv; -+ struct caam_drv_private_jr *jrpriv; /* need this for reg page */ -+ struct platform_device *sm_pdev; -+ struct sm_page_descriptor *lpagedesc; -+ u32 page, pgstat, lpagect, detectedpage; -+ -+ struct device_node *np; -+ ctrldev = &pdev->dev; -+ ctrlpriv = dev_get_drvdata(ctrldev); -+ -+ /* -+ * Set up the private block for secure memory -+ * Only one instance is possible -+ */ -+ smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL); -+ if (smpriv == NULL) { -+ dev_err(ctrldev, "can't alloc private mem for secure memory\n"); -+ return -ENOMEM; -+ } -+ smpriv->parentdev = ctrldev; /* copy of parent dev is handy */ -+ -+ /* Create the dev */ -+#ifdef CONFIG_OF -+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm"); -+ sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev); -+#else -+ sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0, -+ smpriv, -+ sizeof(struct caam_drv_private_sm)); -+#endif -+ if (sm_pdev == NULL) { -+ kfree(smpriv); -+ return -EINVAL; -+ } -+ smdev = &sm_pdev->dev; -+ dev_set_drvdata(smdev, smpriv); -+ ctrlpriv->smdev = smdev; -+ -+ /* -+ * Collect configuration limit data for reference -+ * This batch comes from the partition data/vid registers in perfmon -+ */ -+ smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) -+ & SMPART_MAX_NUMPG_MASK) >> -+ SMPART_MAX_NUMPG_SHIFT) + 1; -+ smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) -+ & SMPART_MAX_PNUM_MASK) >> -+ SMPART_MAX_PNUM_SHIFT) + 1; -+ smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) -+ & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1; -+ smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid) -+ & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT); -+ smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE; -+ -+#ifdef SM_DEBUG -+ dev_info(smdev, "max pages = %d, top partition = %d\n", -+ smpriv->max_pages, smpriv->top_partition); -+ dev_info(smdev, "top page = %d, page size = %d (total = %d)\n", -+ smpriv->top_page, smpriv->page_size, -+ smpriv->top_page * smpriv->page_size); -+ dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size); -+#endif -+ -+ /* -+ * Now probe for partitions/pages to which we have access. Note that -+ * these have likely been set up by a bootloader or platform -+ * provisioning application, so we have to assume that we "inherit" -+ * a configuration and work within the constraints of what it might be. -+ * -+ * Assume use of the zeroth ring in the present iteration (until -+ * we can divorce the controller and ring drivers, and then assign -+ * an SM instance to any ring instance). -+ */ -+ smpriv->smringdev = ctrlpriv->jrdev[0]; -+ jrpriv = dev_get_drvdata(smpriv->smringdev); -+ lpagect = 0; -+ lpagedesc = kzalloc(sizeof(struct sm_page_descriptor) -+ * smpriv->max_pages, GFP_KERNEL); -+ if (lpagedesc == NULL) { -+ kfree(smpriv); -+ return -ENOMEM; -+ } -+ -+ for (page = 0; page < smpriv->max_pages; page++) { -+ wr_reg32(&jrpriv->rregs->sm_cmd, -+ ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) | -+ (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)); -+ pgstat = rd_reg32(&jrpriv->rregs->sm_status); -+ if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT) -+ == SMCS_PGOWN_OWNED) { /* our page? */ -+ lpagedesc[page].phys_pagenum = -+ (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT; -+ lpagedesc[page].own_part = -+ (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK; -+ lpagedesc[page].pg_base = ctrlpriv->sm_base + -+ ((smpriv->page_size * page) / sizeof(u32)); -+ lpagect++; -+#ifdef SM_DEBUG -+ dev_info(smdev, -+ "physical page %d, owning partition = %d\n", -+ lpagedesc[page].phys_pagenum, -+ lpagedesc[page].own_part); -+#endif -+ } -+ } -+ -+ smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect, -+ GFP_KERNEL); -+ if (smpriv->pagedesc == NULL) { -+ kfree(lpagedesc); -+ kfree(smpriv); -+ return -ENOMEM; -+ } -+ smpriv->localpages = lpagect; -+ -+ detectedpage = 0; -+ for (page = 0; page < smpriv->max_pages; page++) { -+ if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */ -+ memcpy(&smpriv->pagedesc[detectedpage], -+ &lpagedesc[page], -+ sizeof(struct sm_page_descriptor)); -+#ifdef SM_DEBUG_CONT -+ sm_show_page(smdev, &smpriv->pagedesc[detectedpage]); -+#endif -+ detectedpage++; -+ } -+ } -+ -+ kfree(lpagedesc); -+ -+ sm_init_keystore(smdev); -+ -+ return 0; -+} -+ -+void caam_sm_shutdown(struct platform_device *pdev) -+{ -+ struct device *ctrldev, *smdev; -+ struct caam_drv_private *priv; -+ struct caam_drv_private_sm *smpriv; -+ -+ ctrldev = &pdev->dev; -+ priv = dev_get_drvdata(ctrldev); -+ smdev = priv->smdev; -+ smpriv = dev_get_drvdata(smdev); -+ -+ kfree(smpriv->pagedesc); -+ kfree(smpriv); -+} -+EXPORT_SYMBOL(caam_sm_shutdown); -+#ifdef CONFIG_OF -+static void __exit caam_sm_exit(void) -+{ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -+ if (!dev_node) -+ return; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return; -+ -+ of_node_put(dev_node); -+ -+ caam_sm_shutdown(pdev); -+ -+ return; -+} -+ -+static int __init caam_sm_init(void) -+{ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ /* -+ * Do of_find_compatible_node() then of_find_device_by_node() -+ * once a functional device tree is available -+ */ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -+ if (!dev_node) -+ return -ENODEV; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return -ENODEV; -+ -+ of_node_get(dev_node); -+ -+ caam_sm_startup(pdev); -+ -+ return 0; -+} -+ -+module_init(caam_sm_init); -+module_exit(caam_sm_exit); -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore"); -+MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); -+#endif -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/sm_test.c linux-3.14.22/drivers/crypto/caam/sm_test.c ---- linux-3.14.22.orig/drivers/crypto/caam/sm_test.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/sm_test.c 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,844 @@ -+/* -+ * Secure Memory / Keystore Exemplification Module -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved -+ * -+ * Serves as a functional example, and as a self-contained unit test for -+ * the functionality contained in sm_store.c. -+ * -+ * The example function, caam_sm_example_init(), runs a thread that: -+ * -+ * - initializes a set of fixed keys -+ * - stores one copy in clear buffers -+ * - stores them again in secure memory -+ * - extracts stored keys back out for use -+ * - intializes 3 data buffers for a test: -+ * (1) containing cleartext -+ * (2) to hold ciphertext encrypted with an extracted black key -+ * (3) to hold extracted cleartext decrypted with an equivalent clear key -+ * -+ * The function then builds simple job descriptors that reference the key -+ * material and buffers as initialized, and executes an encryption job -+ * with a black key, and a decryption job using a the same key held in the -+ * clear. The output of the decryption job is compared to the original -+ * cleartext; if they don't compare correctly, one can assume a key problem -+ * exists, where the function will exit with an error. -+ * -+ * This module can use a substantial amount of refactoring, which may occur -+ * after the API gets some mileage. Furthermore, expect this module to -+ * eventually disappear once the API is integrated into "real" software. -+ */ -+ -+#include "compat.h" -+#include "intern.h" -+#include "desc.h" -+#include "error.h" -+#include "jr.h" -+#include "sm.h" -+ -+static u8 skeymod[] = { -+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, -+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 -+}; -+static u8 symkey[] = { -+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, -+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, -+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f -+}; -+ -+static u8 symdata[] = { -+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07, -+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, -+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, -+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, -+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, -+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, -+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, -+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, -+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, -+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, -+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, -+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, -+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, -+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, -+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, -+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, -+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, -+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, -+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, -+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, -+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, -+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, -+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, -+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, -+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, -+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, -+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, -+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, -+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, -+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -+}; -+ -+static int mk_job_desc(u32 *desc, dma_addr_t key, u16 keysz, dma_addr_t indata, -+ dma_addr_t outdata, u16 sz, u32 cipherdir, u32 keymode) -+{ -+ desc[1] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK) | keymode; -+ desc[2] = (u32)key; -+ desc[3] = CMD_OPERATION | OP_TYPE_CLASS1_ALG | OP_ALG_AAI_ECB | -+ cipherdir; -+ desc[4] = CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1 | sz; -+ desc[5] = (u32)indata; -+ desc[6] = CMD_FIFO_STORE | FIFOST_TYPE_MESSAGE_DATA | sz; -+ desc[7] = (u32)outdata; -+ -+ desc[0] = CMD_DESC_HDR | HDR_ONE | (8 & HDR_DESCLEN_MASK); -+ return 8 * sizeof(u32); -+} -+ -+struct exec_test_result { -+ int error; -+ struct completion completion; -+}; -+ -+void exec_test_done(struct device *dev, u32 *desc, u32 err, void *context) -+{ -+ struct exec_test_result *res = context; -+ -+ if (err) { -+ char tmp[CAAM_ERROR_STR_MAX]; -+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); -+ } -+ -+ res->error = err; -+ complete(&res->completion); -+} -+ -+static int exec_test_job(struct device *ksdev, u32 *jobdesc) -+{ -+ struct exec_test_result testres; -+ struct caam_drv_private_sm *kspriv; -+ int rtn = 0; -+ -+ kspriv = dev_get_drvdata(ksdev); -+ -+ init_completion(&testres.completion); -+ -+ rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done, -+ &testres); -+ if (!rtn) { -+ wait_for_completion_interruptible(&testres.completion); -+ rtn = testres.error; -+ } -+ return rtn; -+} -+ -+ -+int caam_sm_example_init(struct platform_device *pdev) -+{ -+ struct device *ctrldev, *ksdev; -+ struct caam_drv_private *ctrlpriv; -+ struct caam_drv_private_sm *kspriv; -+ u32 unit, units, jdescsz; -+ int stat, jstat, rtnval = 0; -+ u8 __iomem *syminp, *symint, *symout = NULL; -+ dma_addr_t syminp_dma, symint_dma, symout_dma; -+ u8 __iomem *black_key_des, *black_key_aes128; -+ u8 __iomem *black_key_aes256; -+ dma_addr_t black_key_des_dma, black_key_aes128_dma; -+ dma_addr_t black_key_aes256_dma; -+ u8 __iomem *clear_key_des, *clear_key_aes128, *clear_key_aes256; -+ dma_addr_t clear_key_des_dma, clear_key_aes128_dma; -+ dma_addr_t clear_key_aes256_dma; -+ u32 __iomem *jdesc; -+ u32 keyslot_des, keyslot_aes128, keyslot_aes256 = 0; -+ -+ jdesc = NULL; -+ black_key_des = black_key_aes128 = black_key_aes256 = NULL; -+ clear_key_des = clear_key_aes128 = clear_key_aes256 = NULL; -+ -+ /* We can lose this cruft once we can get a pdev by name */ -+ ctrldev = &pdev->dev; -+ ctrlpriv = dev_get_drvdata(ctrldev); -+ ksdev = ctrlpriv->smdev; -+ kspriv = dev_get_drvdata(ksdev); -+ if (kspriv == NULL) -+ return -ENODEV; -+ -+ /* Now that we have the dev for the single SM instance, connect */ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test_init() running\n"); -+#endif -+ /* Probe to see what keystores are available to us */ -+ units = sm_detect_keystore_units(ksdev); -+ if (!units) -+ dev_err(ksdev, "caam_sm_test: no keystore units available\n"); -+ -+ /* -+ * MX6 bootloader stores some stuff in unit 0, so let's -+ * use 1 or above -+ */ -+ if (units < 2) { -+ dev_err(ksdev, "caam_sm_test: insufficient keystore units\n"); -+ return -ENODEV; -+ } -+ unit = 1; -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: %d keystore units available\n", units); -+#endif -+ -+ /* Initialize/Establish Keystore */ -+ sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */ -+ -+ /* -+ * Top of main test thread -+ */ -+ -+ /* Allocate test data blocks (input, intermediate, output) */ -+ syminp = kmalloc(256, GFP_KERNEL | GFP_DMA); -+ symint = kmalloc(256, GFP_KERNEL | GFP_DMA); -+ symout = kmalloc(256, GFP_KERNEL | GFP_DMA); -+ if ((syminp == NULL) || (symint == NULL) || (symout == NULL)) { -+ rtnval = -ENOMEM; -+ dev_err(ksdev, "caam_sm_test: can't get test data buffers\n"); -+ goto freemem; -+ } -+ -+ /* Allocate storage for 3 black keys: encapsulated 8, 16, 32 */ -+ black_key_des = kmalloc(16, GFP_KERNEL | GFP_DMA); /* padded to 16... */ -+ black_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); -+ black_key_aes256 = kmalloc(16, GFP_KERNEL | GFP_DMA); -+ if ((black_key_des == NULL) || (black_key_aes128 == NULL) || -+ (black_key_aes256 == NULL)) { -+ rtnval = -ENOMEM; -+ dev_err(ksdev, "caam_sm_test: can't black key buffers\n"); -+ goto freemem; -+ } -+ -+ clear_key_des = kmalloc(8, GFP_KERNEL | GFP_DMA); -+ clear_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); -+ clear_key_aes256 = kmalloc(32, GFP_KERNEL | GFP_DMA); -+ if ((clear_key_des == NULL) || (clear_key_aes128 == NULL) || -+ (clear_key_aes256 == NULL)) { -+ rtnval = -ENOMEM; -+ dev_err(ksdev, "caam_sm_test: can't get clear key buffers\n"); -+ goto freemem; -+ } -+ -+ /* Allocate storage for job descriptor */ -+ jdesc = kmalloc(8 * sizeof(u32), GFP_KERNEL | GFP_DMA); -+ if (jdesc == NULL) { -+ rtnval = -ENOMEM; -+ dev_err(ksdev, "caam_sm_test: can't get descriptor buffers\n"); -+ goto freemem; -+ } -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: all buffers allocated\n"); -+#endif -+ -+ /* Load up input data block, clear outputs */ -+ memcpy(syminp, symdata, 256); -+ memset(symint, 0, 256); -+ memset(symout, 0, 256); -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[0], syminp[1], syminp[2], syminp[3], -+ syminp[4], syminp[5], syminp[6], syminp[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[0], symout[1], symout[2], symout[3], -+ symout[4], symout[5], symout[6], symout[7]); -+ -+ dev_info(ksdev, "caam_sm_test: data buffers initialized\n"); -+#endif -+ -+ /* Load up clear keys */ -+ memcpy(clear_key_des, symkey, 8); -+ memcpy(clear_key_aes128, symkey, 16); -+ memcpy(clear_key_aes256, symkey, 32); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: all clear keys loaded\n"); -+#endif -+ -+ /* -+ * Place clear keys in keystore. -+ * All the interesting stuff happens here. -+ */ -+ /* 8 bit DES key */ -+ stat = sm_keystore_slot_alloc(ksdev, unit, 8, &keyslot_des); -+ if (stat) -+ goto freemem; -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: 8 byte key slot in %d\n", keyslot_des); -+#endif -+ stat = sm_keystore_slot_load(ksdev, unit, keyslot_des, clear_key_des, -+ 8); -+ if (stat) { -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: can't load 8 byte key in %d\n", -+ keyslot_des); -+#endif -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ goto freemem; -+ } -+ -+ /* 16 bit AES key */ -+ stat = sm_keystore_slot_alloc(ksdev, unit, 16, &keyslot_aes128); -+ if (stat) { -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ goto freemem; -+ } -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: 16 byte key slot in %d\n", -+ keyslot_aes128); -+#endif -+ stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes128, -+ clear_key_aes128, 16); -+ if (stat) { -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: can't load 16 byte key in %d\n", -+ keyslot_aes128); -+#endif -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ goto freemem; -+ } -+ -+ /* 32 bit AES key */ -+ stat = sm_keystore_slot_alloc(ksdev, unit, 32, &keyslot_aes256); -+ if (stat) { -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ goto freemem; -+ } -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: 32 byte key slot in %d\n", -+ keyslot_aes256); -+#endif -+ stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes256, -+ clear_key_aes256, 32); -+ if (stat) { -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: can't load 32 byte key in %d\n", -+ keyslot_aes128); -+#endif -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); -+ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ goto freemem; -+ } -+ -+ /* Encapsulate all keys as SM blobs */ -+ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_des, -+ keyslot_des, 8, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't encapsulate DES key\n"); -+ goto freekeys; -+ } -+ -+ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes128, -+ keyslot_aes128, 16, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't encapsulate AES128 key\n"); -+ goto freekeys; -+ } -+ -+ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes256, -+ keyslot_aes256, 32, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't encapsulate AES256 key\n"); -+ goto freekeys; -+ } -+ -+ /* Now decapsulate as black key blobs */ -+ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_des, -+ keyslot_des, 8, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't decapsulate DES key\n"); -+ goto freekeys; -+ } -+ -+ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes128, -+ keyslot_aes128, 16, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); -+ goto freekeys; -+ } -+ -+ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes256, -+ keyslot_aes256, 32, skeymod, 8); -+ if (stat) { -+ dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); -+ goto freekeys; -+ } -+ -+ /* Extract 8/16/32 byte black keys */ -+ sm_keystore_slot_read(ksdev, unit, keyslot_des, 8, black_key_des); -+ sm_keystore_slot_read(ksdev, unit, keyslot_aes128, 16, -+ black_key_aes128); -+ sm_keystore_slot_read(ksdev, unit, keyslot_aes256, 32, -+ black_key_aes256); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: all black keys extracted\n"); -+#endif -+ -+ /* DES encrypt using 8 byte black key */ -+ black_key_des_dma = dma_map_single(ksdev, black_key_des, 8, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); -+ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, black_key_des_dma, 8, syminp_dma, -+ symint_dma, 256, -+ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_DES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "input block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[0], syminp[1], syminp[2], syminp[3], -+ syminp[4], syminp[5], syminp[6], syminp[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[8], syminp[9], syminp[10], syminp[11], -+ syminp[12], syminp[13], syminp[14], syminp[15]); -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "caam_sm_test: encrypt cycle with 8 byte key\n"); -+#endif -+ -+ /* DES decrypt using 8 byte clear key */ -+ clear_key_des_dma = dma_map_single(ksdev, clear_key_des, 8, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, clear_key_des_dma, 8, symint_dma, -+ symout_dma, 256, -+ OP_ALG_DECRYPT | OP_ALG_ALGSEL_DES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "decrypted block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[0], symout[1], symout[2], symout[3], -+ symout[4], symout[5], symout[6], symout[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[8], symout[9], symout[10], symout[11], -+ symout[12], symout[13], symout[14], symout[15]); -+ dev_info(ksdev, "caam_sm_test: decrypt cycle with 8 byte key\n"); -+#endif -+ -+ /* Check result */ -+ if (memcmp(symout, syminp, 256)) { -+ dev_info(ksdev, "caam_sm_test: 8-byte key test mismatch\n"); -+ rtnval = -1; -+ goto freekeys; -+ } else -+ dev_info(ksdev, "caam_sm_test: 8-byte key test match OK\n"); -+ -+ /* AES-128 encrypt using 16 byte black key */ -+ black_key_aes128_dma = dma_map_single(ksdev, black_key_aes128, 16, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, black_key_aes128_dma, 16, -+ DMA_TO_DEVICE); -+ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, black_key_aes128_dma, 16, syminp_dma, -+ symint_dma, 256, -+ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, black_key_aes128_dma, 16, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "input block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[0], syminp[1], syminp[2], syminp[3], -+ syminp[4], syminp[5], syminp[6], syminp[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[8], syminp[9], syminp[10], syminp[11], -+ syminp[12], syminp[13], syminp[14], syminp[15]); -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "caam_sm_test: encrypt cycle with 16 byte key\n"); -+#endif -+ -+ /* AES-128 decrypt using 16 byte clear key */ -+ clear_key_aes128_dma = dma_map_single(ksdev, clear_key_aes128, 16, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, clear_key_aes128_dma, 16, -+ DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, clear_key_aes128_dma, 16, symint_dma, -+ symout_dma, 256, -+ OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, clear_key_aes128_dma, 16, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "decrypted block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[0], symout[1], symout[2], symout[3], -+ symout[4], symout[5], symout[6], symout[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[8], symout[9], symout[10], symout[11], -+ symout[12], symout[13], symout[14], symout[15]); -+ dev_info(ksdev, "caam_sm_test: decrypt cycle with 16 byte key\n"); -+#endif -+ -+ /* Check result */ -+ if (memcmp(symout, syminp, 256)) { -+ dev_info(ksdev, "caam_sm_test: 16-byte key test mismatch\n"); -+ rtnval = -1; -+ goto freekeys; -+ } else -+ dev_info(ksdev, "caam_sm_test: 16-byte key test match OK\n"); -+ -+ /* AES-256 encrypt using 32 byte black key */ -+ black_key_aes256_dma = dma_map_single(ksdev, black_key_aes256, 32, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, black_key_aes256_dma, 32, -+ DMA_TO_DEVICE); -+ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, black_key_aes256_dma, 32, syminp_dma, -+ symint_dma, 256, -+ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, black_key_aes256_dma, 32, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "input block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[0], syminp[1], syminp[2], syminp[3], -+ syminp[4], syminp[5], syminp[6], syminp[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ syminp[8], syminp[9], syminp[10], syminp[11], -+ syminp[12], syminp[13], syminp[14], syminp[15]); -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "caam_sm_test: encrypt cycle with 32 byte key\n"); -+#endif -+ -+ /* AES-256 decrypt using 32-byte black key */ -+ clear_key_aes256_dma = dma_map_single(ksdev, clear_key_aes256, 32, -+ DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, clear_key_aes256_dma, 32, -+ DMA_TO_DEVICE); -+ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); -+ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); -+ -+ jdescsz = mk_job_desc(jdesc, clear_key_aes256_dma, 32, symint_dma, -+ symout_dma, 256, -+ OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "jobdesc:\n"); -+ dev_info(ksdev, "0x%08x\n", jdesc[0]); -+ dev_info(ksdev, "0x%08x\n", jdesc[1]); -+ dev_info(ksdev, "0x%08x\n", jdesc[2]); -+ dev_info(ksdev, "0x%08x\n", jdesc[3]); -+ dev_info(ksdev, "0x%08x\n", jdesc[4]); -+ dev_info(ksdev, "0x%08x\n", jdesc[5]); -+ dev_info(ksdev, "0x%08x\n", jdesc[6]); -+ dev_info(ksdev, "0x%08x\n", jdesc[7]); -+#endif -+ -+ jstat = exec_test_job(ksdev, jdesc); -+ -+ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); -+ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); -+ dma_unmap_single(ksdev, clear_key_aes256_dma, 32, DMA_TO_DEVICE); -+ -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "intermediate block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[0], symint[1], symint[2], symint[3], -+ symint[4], symint[5], symint[6], symint[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symint[8], symint[9], symint[10], symint[11], -+ symint[12], symint[13], symint[14], symint[15]); -+ dev_info(ksdev, "decrypted block:\n"); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[0], symout[1], symout[2], symout[3], -+ symout[4], symout[5], symout[6], symout[7]); -+ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ -+ "0x%02x 0x%02x 0x%02x 0x%02x\n", -+ symout[8], symout[9], symout[10], symout[11], -+ symout[12], symout[13], symout[14], symout[15]); -+ dev_info(ksdev, "caam_sm_test: decrypt cycle with 32 byte key\n"); -+#endif -+ -+ /* Check result */ -+ if (memcmp(symout, syminp, 256)) { -+ dev_info(ksdev, "caam_sm_test: 32-byte key test mismatch\n"); -+ rtnval = -1; -+ goto freekeys; -+ } else -+ dev_info(ksdev, "caam_sm_test: 32-byte key test match OK\n"); -+ -+ -+ /* Remove 8/16/32 byte keys from keystore */ -+freekeys: -+ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); -+ if (stat) -+ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", -+ keyslot_des); -+ -+ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); -+ if (stat) -+ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", -+ keyslot_aes128); -+ -+ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); -+ if (stat) -+ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", -+ keyslot_aes256); -+ -+ -+ /* Free resources */ -+freemem: -+#ifdef SM_TEST_DETAIL -+ dev_info(ksdev, "caam_sm_test: cleaning up\n"); -+#endif -+ kfree(syminp); -+ kfree(symint); -+ kfree(symout); -+ kfree(clear_key_des); -+ kfree(clear_key_aes128); -+ kfree(clear_key_aes256); -+ kfree(black_key_des); -+ kfree(black_key_aes128); -+ kfree(black_key_aes256); -+ kfree(jdesc); -+ -+ /* Disconnect from keystore and leave */ -+ sm_release_keystore(ksdev, unit); -+ -+ return rtnval; -+} -+EXPORT_SYMBOL(caam_sm_example_init); -+ -+void caam_sm_example_shutdown(void) -+{ -+ /* unused in present version */ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ /* -+ * Do of_find_compatible_node() then of_find_device_by_node() -+ * once a functional device tree is available -+ */ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -+ if (!dev_node) -+ return; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return; -+ -+ of_node_get(dev_node); -+ -+} -+ -+static int __init caam_sm_test_init(void) -+{ -+ struct device_node *dev_node; -+ struct platform_device *pdev; -+ -+ /* -+ * Do of_find_compatible_node() then of_find_device_by_node() -+ * once a functional device tree is available -+ */ -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -+ if (!dev_node) { -+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -+ if (!dev_node) -+ return -ENODEV; -+ } -+ -+ pdev = of_find_device_by_node(dev_node); -+ if (!pdev) -+ return -ENODEV; -+ -+ of_node_put(dev_node); -+ -+ caam_sm_example_init(pdev); -+ -+ return 0; -+} -+ -+ -+/* Module-based initialization needs to wait for dev tree */ -+#ifdef CONFIG_OF -+module_init(caam_sm_test_init); -+module_exit(caam_sm_example_shutdown); -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_DESCRIPTION("FSL CAAM Keystore Usage Example"); -+MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); -+#endif -diff -Nur linux-3.14.22.orig/drivers/crypto/caam/snvsregs.h linux-3.14.22/drivers/crypto/caam/snvsregs.h ---- linux-3.14.22.orig/drivers/crypto/caam/snvsregs.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/crypto/caam/snvsregs.h 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,237 @@ -+/* -+ * SNVS hardware register-level view -+ * -+ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved -+ */ -+ -+#ifndef SNVSREGS_H -+#define SNVSREGS_H -+ -+#include -+#include -+ -+/* -+ * SNVS High Power Domain -+ * Includes security violations, HA counter, RTC, alarm -+ */ -+struct snvs_hp { -+ u32 lock; -+ u32 cmd; -+ u32 ctl; -+ u32 secvio_int_en; /* Security Violation Interrupt Enable */ -+ u32 secvio_int_ctl; /* Security Violation Interrupt Control */ -+ u32 status; -+ u32 secvio_status; /* Security Violation Status */ -+ u32 ha_counteriv; /* High Assurance Counter IV */ -+ u32 ha_counter; /* High Assurance Counter */ -+ u32 rtc_msb; /* Real Time Clock/Counter MSB */ -+ u32 rtc_lsb; /* Real Time Counter LSB */ -+ u32 time_alarm_msb; /* Time Alarm MSB */ -+ u32 time_alarm_lsb; /* Time Alarm LSB */ -+}; -+ -+#define HP_LOCK_HAC_LCK 0x00040000 -+#define HP_LOCK_HPSICR_LCK 0x00020000 -+#define HP_LOCK_HPSVCR_LCK 0x00010000 -+#define HP_LOCK_MKEYSEL_LCK 0x00000200 -+#define HP_LOCK_TAMPCFG_LCK 0x00000100 -+#define HP_LOCK_TAMPFLT_LCK 0x00000080 -+#define HP_LOCK_SECVIO_LCK 0x00000040 -+#define HP_LOCK_GENP_LCK 0x00000020 -+#define HP_LOCK_MONOCTR_LCK 0x00000010 -+#define HP_LOCK_CALIB_LCK 0x00000008 -+#define HP_LOCK_SRTC_LCK 0x00000004 -+#define HP_LOCK_ZMK_RD_LCK 0x00000002 -+#define HP_LOCK_ZMK_WT_LCK 0x00000001 -+ -+#define HP_CMD_NONPRIV_AXS 0x80000000 -+#define HP_CMD_HAC_STOP 0x00080000 -+#define HP_CMD_HAC_CLEAR 0x00040000 -+#define HP_CMD_HAC_LOAD 0x00020000 -+#define HP_CMD_HAC_CFG_EN 0x00010000 -+#define HP_CMD_SNVS_MSTR_KEY 0x00002000 -+#define HP_CMD_PROG_ZMK 0x00001000 -+#define HP_CMD_SW_LPSV 0x00000400 -+#define HP_CMD_SW_FSV 0x00000200 -+#define HP_CMD_SW_SV 0x00000100 -+#define HP_CMD_LP_SWR_DIS 0x00000020 -+#define HP_CMD_LP_SWR 0x00000010 -+#define HP_CMD_SSM_SFNS_DIS 0x00000004 -+#define HP_CMD_SSM_ST_DIS 0x00000002 -+#define HP_CMD_SMM_ST 0x00000001 -+ -+#define HP_CTL_TIME_SYNC 0x00010000 -+#define HP_CTL_CAL_VAL_SHIFT 10 -+#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT) -+#define HP_CTL_CALIB_EN 0x00000100 -+#define HP_CTL_PI_FREQ_SHIFT 4 -+#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT) -+#define HP_CTL_PI_EN 0x00000008 -+#define HP_CTL_TIMEALARM_EN 0x00000002 -+#define HP_CTL_RTC_EN 0x00000001 -+ -+#define HP_SECVIO_INTEN_EN 0x10000000 -+#define HP_SECVIO_INTEN_SRC5 0x00000020 -+#define HP_SECVIO_INTEN_SRC4 0x00000010 -+#define HP_SECVIO_INTEN_SRC3 0x00000008 -+#define HP_SECVIO_INTEN_SRC2 0x00000004 -+#define HP_SECVIO_INTEN_SRC1 0x00000002 -+#define HP_SECVIO_INTEN_SRC0 0x00000001 -+#define HP_SECVIO_INTEN_ALL 0x8000003f -+ -+#define HP_SECVIO_ICTL_CFG_SHIFT 30 -+#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT) -+#define HP_SECVIO_ICTL_CFG5_SHIFT 5 -+#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT) -+#define HP_SECVIO_ICTL_CFG_DISABLE 0 -+#define HP_SECVIO_ICTL_CFG_NONFATAL 1 -+#define HP_SECVIO_ICTL_CFG_FATAL 2 -+#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010 -+#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008 -+#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004 -+#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002 -+#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001 -+ -+#define HP_STATUS_ZMK_ZERO 0x80000000 -+#define HP_STATUS_OTPMK_ZERO 0x08000000 -+#define HP_STATUS_OTPMK_SYN_SHIFT 16 -+#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT) -+#define HP_STATUS_SSM_ST_SHIFT 8 -+#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT) -+#define HP_STATUS_SSM_ST_INIT 0 -+#define HP_STATUS_SSM_ST_HARDFAIL 1 -+#define HP_STATUS_SSM_ST_SOFTFAIL 3 -+#define HP_STATUS_SSM_ST_INITINT 8 -+#define HP_STATUS_SSM_ST_CHECK 9 -+#define HP_STATUS_SSM_ST_NONSECURE 11 -+#define HP_STATUS_SSM_ST_TRUSTED 13 -+#define HP_STATUS_SSM_ST_SECURE 15 -+ -+#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */ -+#define HP_SECVIOST_ZMK_SYN_SHIFT 16 -+#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT) -+#define HP_SECVIOST_SECVIO5 0x00000020 -+#define HP_SECVIOST_SECVIO4 0x00000010 -+#define HP_SECVIOST_SECVIO3 0x00000008 -+#define HP_SECVIOST_SECVIO2 0x00000004 -+#define HP_SECVIOST_SECVIO1 0x00000002 -+#define HP_SECVIOST_SECVIO0 0x00000001 -+#define HP_SECVIOST_SECVIOMASK 0x0000003f -+ -+/* -+ * SNVS Low Power Domain -+ * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK -+ */ -+struct snvs_lp { -+ u32 lock; -+ u32 ctl; -+ u32 mstr_key_ctl; /* Master Key Control */ -+ u32 secvio_ctl; /* Security Violation Control */ -+ u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */ -+ u32 tamper_det_cfg; /* Tamper Detectors Configuration */ -+ u32 status; -+ u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */ -+ u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */ -+ u32 time_alarm; /* Time Alarm */ -+ u32 smc_msb; /* Secure Monotonic Counter MSB */ -+ u32 smc_lsb; /* Secure Monotonic Counter LSB */ -+ u32 pwr_glitch_det; /* Power Glitch Detector */ -+ u32 gen_purpose; -+ u32 zmk[8]; /* Zeroizable Master Key */ -+}; -+ -+#define LP_LOCK_MKEYSEL_LCK 0x00000200 -+#define LP_LOCK_TAMPDET_LCK 0x00000100 -+#define LP_LOCK_TAMPFLT_LCK 0x00000080 -+#define LP_LOCK_SECVIO_LCK 0x00000040 -+#define LP_LOCK_GENP_LCK 0x00000020 -+#define LP_LOCK_MONOCTR_LCK 0x00000010 -+#define LP_LOCK_CALIB_LCK 0x00000008 -+#define LP_LOCK_SRTC_LCK 0x00000004 -+#define LP_LOCK_ZMK_RD_LCK 0x00000002 -+#define LP_LOCK_ZMK_WT_LCK 0x00000001 -+ -+#define LP_CTL_CAL_VAL_SHIFT 10 -+#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT) -+#define LP_CTL_CALIB_EN 0x00000100 -+#define LP_CTL_SRTC_INVAL_EN 0x00000010 -+#define LP_CTL_WAKE_INT_EN 0x00000008 -+#define LP_CTL_MONOCTR_EN 0x00000004 -+#define LP_CTL_TIMEALARM_EN 0x00000002 -+#define LP_CTL_SRTC_EN 0x00000001 -+ -+#define LP_MKEYCTL_ZMKECC_SHIFT 8 -+#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT) -+#define LP_MKEYCTL_ZMKECC_EN 0x00000010 -+#define LP_MKEYCTL_ZMKECC_VAL 0x00000008 -+#define LP_MKEYCTL_ZMKECC_PROG 0x00000004 -+#define LP_MKEYCTL_MKSEL_SHIFT 0 -+#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT) -+#define LP_MKEYCTL_MK_OTP 0 -+#define LP_MKEYCTL_MK_ZMK 2 -+#define LP_MKEYCTL_MK_COMB 3 -+ -+#define LP_SECVIO_CTL_SRC5 0x20 -+#define LP_SECVIO_CTL_SRC4 0x10 -+#define LP_SECVIO_CTL_SRC3 0x08 -+#define LP_SECVIO_CTL_SRC2 0x04 -+#define LP_SECVIO_CTL_SRC1 0x02 -+#define LP_SECVIO_CTL_SRC0 0x01 -+ -+#define LP_TAMPFILT_EXT2_EN 0x80000000 -+#define LP_TAMPFILT_EXT2_SHIFT 24 -+#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT) -+#define LP_TAMPFILT_EXT1_EN 0x00800000 -+#define LP_TAMPFILT_EXT1_SHIFT 16 -+#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT) -+#define LP_TAMPFILT_WM_EN 0x00000080 -+#define LP_TAMPFILT_WM_SHIFT 0 -+#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT) -+ -+#define LP_TAMPDET_OSC_BPS 0x10000000 -+#define LP_TAMPDET_VRC_SHIFT 24 -+#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT) -+#define LP_TAMPDET_HTDC_SHIFT 20 -+#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT) -+#define LP_TAMPDET_LTDC_SHIFT 16 -+#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT) -+#define LP_TAMPDET_POR_OBS 0x00008000 -+#define LP_TAMPDET_PFD_OBS 0x00004000 -+#define LP_TAMPDET_ET2_EN 0x00000400 -+#define LP_TAMPDET_ET1_EN 0x00000200 -+#define LP_TAMPDET_WMT2_EN 0x00000100 -+#define LP_TAMPDET_WMT1_EN 0x00000080 -+#define LP_TAMPDET_VT_EN 0x00000040 -+#define LP_TAMPDET_TT_EN 0x00000020 -+#define LP_TAMPDET_CT_EN 0x00000010 -+#define LP_TAMPDET_MCR_EN 0x00000004 -+#define LP_TAMPDET_SRTCR_EN 0x00000002 -+ -+#define LP_STATUS_SECURE -+#define LP_STATUS_NONSECURE -+#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */ -+#define LP_STATUS_EXT_SECVIO 0x00010000 -+#define LP_STATUS_ET2 0x00000400 -+#define LP_STATUS_ET1 0x00000200 -+#define LP_STATUS_WMT2 0x00000100 -+#define LP_STATUS_WMT1 0x00000080 -+#define LP_STATUS_VTD 0x00000040 -+#define LP_STATUS_TTD 0x00000020 -+#define LP_STATUS_CTD 0x00000010 -+#define LP_STATUS_PGD 0x00000008 -+#define LP_STATUS_MCR 0x00000004 -+#define LP_STATUS_SRTCR 0x00000002 -+#define LP_STATUS_LPTA 0x00000001 -+ -+/* Full SNVS register page, including version/options */ -+struct snvs_full { -+ struct snvs_hp hp; -+ struct snvs_lp lp; -+ u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */ -+ -+ /* Version / Revision / Option ID space - end of register page */ -+ u32 vid; /* 0xbf8 HP Version ID (VID 1) */ -+ u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */ -+}; -+ -+#endif /* SNVSREGS_H */ -diff -Nur linux-3.14.22.orig/drivers/dma/imx-sdma.c linux-3.14.22/drivers/dma/imx-sdma.c ---- linux-3.14.22.orig/drivers/dma/imx-sdma.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/dma/imx-sdma.c 2014-10-22 14:55:52.046220001 -0500 -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -232,6 +233,14 @@ - - struct sdma_engine; - -+enum sdma_mode { -+ SDMA_MODE_INVALID = 0, -+ SDMA_MODE_LOOP, -+ SDMA_MODE_NORMAL, -+ SDMA_MODE_P2P, -+ SDMA_MODE_NO_BD, -+}; -+ - /** - * struct sdma_channel - housekeeping for a SDMA channel - * -@@ -244,6 +253,7 @@ - * @word_size peripheral access size - * @buf_tail ID of the buffer that was processed - * @num_bd max NUM_BD. number of descriptors currently handling -+ * @bd_iram flag indicating the memory location of buffer descriptor - */ - struct sdma_channel { - struct sdma_engine *sdma; -@@ -255,14 +265,19 @@ - enum dma_slave_buswidth word_size; - unsigned int buf_tail; - unsigned int num_bd; -+ unsigned int period_len; - struct sdma_buffer_descriptor *bd; - dma_addr_t bd_phys; -+ bool bd_iram; - unsigned int pc_from_device, pc_to_device; -- unsigned long flags; -- dma_addr_t per_address; -+ unsigned int device_to_device; -+ unsigned int other_script; -+ enum sdma_mode mode; -+ dma_addr_t per_address, per_address2; - unsigned long event_mask[2]; - unsigned long watermark_level; - u32 shp_addr, per_addr; -+ u32 data_addr1, data_addr2; - struct dma_chan chan; - spinlock_t lock; - struct dma_async_tx_descriptor desc; -@@ -272,8 +287,6 @@ - struct tasklet_struct tasklet; - }; - --#define IMX_DMA_SG_LOOP BIT(0) -- - #define MAX_DMA_CHANNELS 32 - #define MXC_SDMA_DEFAULT_PRIORITY 1 - #define MXC_SDMA_MIN_PRIORITY 1 -@@ -325,6 +338,7 @@ - spinlock_t channel_0_lock; - u32 script_number; - struct sdma_script_start_addrs *script_addrs; -+ struct gen_pool *iram_pool; - const struct sdma_driver_data *drvdata; - }; - -@@ -540,12 +554,14 @@ - dma_addr_t buf_phys; - int ret; - unsigned long flags; -+ bool use_iram = true; - -- buf_virt = dma_alloc_coherent(NULL, -- size, -- &buf_phys, GFP_KERNEL); -+ buf_virt = gen_pool_dma_alloc(sdma->iram_pool, size, &buf_phys); - if (!buf_virt) { -- return -ENOMEM; -+ use_iram = false; -+ buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL); -+ if (!buf_virt) -+ return -ENOMEM; - } - - spin_lock_irqsave(&sdma->channel_0_lock, flags); -@@ -562,7 +578,10 @@ - - spin_unlock_irqrestore(&sdma->channel_0_lock, flags); - -- dma_free_coherent(NULL, size, buf_virt, buf_phys); -+ if (use_iram) -+ gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size); -+ else -+ dma_free_coherent(NULL, size, buf_virt, buf_phys); - - return ret; - } -@@ -593,6 +612,12 @@ - - static void sdma_handle_channel_loop(struct sdma_channel *sdmac) - { -+ if (sdmac->desc.callback) -+ sdmac->desc.callback(sdmac->desc.callback_param); -+} -+ -+static void sdma_update_channel_loop(struct sdma_channel *sdmac) -+{ - struct sdma_buffer_descriptor *bd; - - /* -@@ -607,15 +632,10 @@ - - if (bd->mode.status & BD_RROR) - sdmac->status = DMA_ERROR; -- else -- sdmac->status = DMA_IN_PROGRESS; - - bd->mode.status |= BD_DONE; - sdmac->buf_tail++; - sdmac->buf_tail %= sdmac->num_bd; -- -- if (sdmac->desc.callback) -- sdmac->desc.callback(sdmac->desc.callback_param); - } - } - -@@ -647,14 +667,31 @@ - sdmac->desc.callback(sdmac->desc.callback_param); - } - -+static void sdma_handle_other_intr(struct sdma_channel *sdmac) -+{ -+ if (sdmac->desc.callback) -+ sdmac->desc.callback(sdmac->desc.callback_param); -+} -+ - static void sdma_tasklet(unsigned long data) - { - struct sdma_channel *sdmac = (struct sdma_channel *) data; -+ struct sdma_engine *sdma = sdmac->sdma; - -- if (sdmac->flags & IMX_DMA_SG_LOOP) -+ switch (sdmac->mode) { -+ case SDMA_MODE_LOOP: - sdma_handle_channel_loop(sdmac); -- else -+ break; -+ case SDMA_MODE_NORMAL: - mxc_sdma_handle_channel_normal(sdmac); -+ break; -+ case SDMA_MODE_NO_BD: -+ sdma_handle_other_intr(sdmac); -+ break; -+ default: -+ dev_err(sdma->dev, "invalid SDMA MODE!\n"); -+ break; -+ } - } - - static irqreturn_t sdma_int_handler(int irq, void *dev_id) -@@ -671,6 +708,9 @@ - int channel = fls(stat) - 1; - struct sdma_channel *sdmac = &sdma->channel[channel]; - -+ if (sdmac->mode & SDMA_MODE_LOOP) -+ sdma_update_channel_loop(sdmac); -+ - tasklet_schedule(&sdmac->tasklet); - - __clear_bit(channel, &stat); -@@ -692,9 +732,12 @@ - * two peripherals or memory-to-memory transfers - */ - int per_2_per = 0, emi_2_emi = 0; -+ int other = 0; - - sdmac->pc_from_device = 0; - sdmac->pc_to_device = 0; -+ sdmac->device_to_device = 0; -+ sdmac->other_script = 0; - - switch (peripheral_type) { - case IMX_DMATYPE_MEMORY: -@@ -740,8 +783,8 @@ - emi_2_per = sdma->script_addrs->mcu_2_shp_addr; - break; - case IMX_DMATYPE_ASRC: -- per_2_emi = sdma->script_addrs->asrc_2_mcu_addr; -- emi_2_per = sdma->script_addrs->asrc_2_mcu_addr; -+ per_2_emi = sdma->script_addrs->shp_2_mcu_addr; -+ emi_2_per = sdma->script_addrs->mcu_2_shp_addr; - per_2_per = sdma->script_addrs->per_2_per_addr; - break; - case IMX_DMATYPE_MSHC: -@@ -758,12 +801,17 @@ - case IMX_DMATYPE_IPU_MEMORY: - emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr; - break; -+ case IMX_DMATYPE_HDMI: -+ other = sdma->script_addrs->hdmi_dma_addr; -+ break; - default: - break; - } - - sdmac->pc_from_device = per_2_emi; - sdmac->pc_to_device = emi_2_per; -+ sdmac->device_to_device = per_2_per; -+ sdmac->other_script = other; - } - - static int sdma_load_context(struct sdma_channel *sdmac) -@@ -776,11 +824,14 @@ - int ret; - unsigned long flags; - -- if (sdmac->direction == DMA_DEV_TO_MEM) { -+ if (sdmac->direction == DMA_DEV_TO_MEM) - load_address = sdmac->pc_from_device; -- } else { -+ else if (sdmac->direction == DMA_DEV_TO_DEV) -+ load_address = sdmac->device_to_device; -+ else if (sdmac->direction == DMA_MEM_TO_DEV) - load_address = sdmac->pc_to_device; -- } -+ else -+ load_address = sdmac->other_script; - - if (load_address < 0) - return load_address; -@@ -800,11 +851,16 @@ - /* Send by context the event mask,base address for peripheral - * and watermark level - */ -- context->gReg[0] = sdmac->event_mask[1]; -- context->gReg[1] = sdmac->event_mask[0]; -- context->gReg[2] = sdmac->per_addr; -- context->gReg[6] = sdmac->shp_addr; -- context->gReg[7] = sdmac->watermark_level; -+ if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) { -+ context->gReg[4] = sdmac->data_addr1; -+ context->gReg[6] = sdmac->data_addr2; -+ } else { -+ context->gReg[0] = sdmac->event_mask[1]; -+ context->gReg[1] = sdmac->event_mask[0]; -+ context->gReg[2] = sdmac->per_addr; -+ context->gReg[6] = sdmac->shp_addr; -+ context->gReg[7] = sdmac->watermark_level; -+ } - - bd0->mode.command = C0_SETDM; - bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; -@@ -829,6 +885,7 @@ - - static int sdma_config_channel(struct sdma_channel *sdmac) - { -+ struct imx_dma_data *data = sdmac->chan.private; - int ret; - - sdma_disable_channel(sdmac); -@@ -837,12 +894,19 @@ - sdmac->event_mask[1] = 0; - sdmac->shp_addr = 0; - sdmac->per_addr = 0; -+ sdmac->data_addr1 = 0; -+ sdmac->data_addr2 = 0; - - if (sdmac->event_id0) { - if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) - return -EINVAL; - sdma_event_enable(sdmac, sdmac->event_id0); - } -+ if (sdmac->event_id1) { -+ if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events) -+ return -EINVAL; -+ sdma_event_enable(sdmac, sdmac->event_id1); -+ } - - switch (sdmac->peripheral_type) { - case IMX_DMATYPE_DSP: -@@ -862,19 +926,75 @@ - (sdmac->peripheral_type != IMX_DMATYPE_DSP)) { - /* Handle multiple event channels differently */ - if (sdmac->event_id1) { -- sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32); -- if (sdmac->event_id1 > 31) -- __set_bit(31, &sdmac->watermark_level); -- sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32); -- if (sdmac->event_id0 > 31) -- __set_bit(30, &sdmac->watermark_level); -+ if (sdmac->event_id0 > 31) { -+ sdmac->event_mask[0] |= 0; -+ __set_bit(28, &sdmac->watermark_level); -+ sdmac->event_mask[1] |= -+ BIT(sdmac->event_id0 % 32); -+ } else { -+ sdmac->event_mask[1] |= 0; -+ sdmac->event_mask[0] |= -+ BIT(sdmac->event_id0 % 32); -+ } -+ if (sdmac->event_id1 > 31) { -+ sdmac->event_mask[0] |= 0; -+ __set_bit(29, &sdmac->watermark_level); -+ sdmac->event_mask[1] |= -+ BIT(sdmac->event_id1 % 32); -+ } else { -+ sdmac->event_mask[1] |= 0; -+ sdmac->event_mask[0] |= -+ BIT(sdmac->event_id1 % 32); -+ } -+ /* BIT 11: -+ * 1 : Source on SPBA -+ * 0 : Source on AIPS -+ */ -+ __set_bit(11, &sdmac->watermark_level); -+ /* BIT 12: -+ * 1 : Destination on SPBA -+ * 0 : Destination on AIPS -+ */ -+ __set_bit(12, &sdmac->watermark_level); -+ __set_bit(31, &sdmac->watermark_level); -+ /* BIT 31: -+ * 1 : Amount of samples to be transferred is -+ * unknown and script will keep on transferring -+ * samples as long as both events are detected -+ * and script must be manually stopped by the -+ * application. -+ * 0 : The amount of samples to be is equal to -+ * the count field of mode word -+ * */ -+ __set_bit(25, &sdmac->watermark_level); -+ __clear_bit(24, &sdmac->watermark_level); - } else { -- __set_bit(sdmac->event_id0, sdmac->event_mask); -+ if (sdmac->event_id0 > 31) { -+ sdmac->event_mask[0] = 0; -+ sdmac->event_mask[1] |= -+ BIT(sdmac->event_id0 % 32); -+ } else { -+ sdmac->event_mask[0] |= -+ BIT(sdmac->event_id0 % 32); -+ sdmac->event_mask[1] = 0; -+ } - } - /* Watermark Level */ - sdmac->watermark_level |= sdmac->watermark_level; - /* Address */ -- sdmac->shp_addr = sdmac->per_address; -+ if (sdmac->direction == DMA_DEV_TO_DEV) { -+ sdmac->shp_addr = sdmac->per_address2; -+ sdmac->per_addr = sdmac->per_address; -+ } else if (sdmac->direction == DMA_TRANS_NONE) { -+ if (sdmac->peripheral_type != IMX_DMATYPE_HDMI || -+ !data->data_addr1 || !data->data_addr2) -+ return -EINVAL; -+ sdmac->data_addr1 = *(u32 *)data->data_addr1; -+ sdmac->data_addr2 = *(u32 *)data->data_addr2; -+ sdmac->watermark_level = 0; -+ } else { -+ sdmac->shp_addr = sdmac->per_address; -+ } - } else { - sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */ - } -@@ -906,10 +1026,15 @@ - int channel = sdmac->channel; - int ret = -EBUSY; - -- sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL); -+ sdmac->bd_iram = true; -+ sdmac->bd = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE, &sdmac->bd_phys); - if (!sdmac->bd) { -- ret = -ENOMEM; -- goto out; -+ sdmac->bd_iram = false; -+ sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL); -+ if (!sdmac->bd) { -+ ret = -ENOMEM; -+ goto out; -+ } - } - - memset(sdmac->bd, 0, PAGE_SIZE); -@@ -967,7 +1092,8 @@ - } - - sdmac->peripheral_type = data->peripheral_type; -- sdmac->event_id0 = data->dma_request; -+ sdmac->event_id0 = data->dma_request0; -+ sdmac->event_id1 = data->dma_request1; - - clk_enable(sdmac->sdma->clk_ipg); - clk_enable(sdmac->sdma->clk_ahb); -@@ -985,6 +1111,9 @@ - /* txd.flags will be overwritten in prep funcs */ - sdmac->desc.flags = DMA_CTRL_ACK; - -+ /* Set SDMA channel mode to unvalid to avoid misconfig */ -+ sdmac->mode = SDMA_MODE_INVALID; -+ - return 0; - } - -@@ -1005,7 +1134,10 @@ - - sdma_set_channel_priority(sdmac, 0); - -- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); -+ if (sdmac->bd_iram) -+ gen_pool_free(sdma->iram_pool, (unsigned long)sdmac->bd, PAGE_SIZE); -+ else -+ dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); - - clk_disable(sdma->clk_ipg); - clk_disable(sdma->clk_ahb); -@@ -1026,7 +1158,7 @@ - return NULL; - sdmac->status = DMA_IN_PROGRESS; - -- sdmac->flags = 0; -+ sdmac->mode = SDMA_MODE_NORMAL; - - sdmac->buf_tail = 0; - -@@ -1119,9 +1251,9 @@ - { - struct sdma_channel *sdmac = to_sdma_chan(chan); - struct sdma_engine *sdma = sdmac->sdma; -- int num_periods = buf_len / period_len; - int channel = sdmac->channel; - int ret, i = 0, buf = 0; -+ int num_periods; - - dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); - -@@ -1131,13 +1263,35 @@ - sdmac->status = DMA_IN_PROGRESS; - - sdmac->buf_tail = 0; -+ sdmac->period_len = period_len; - -- sdmac->flags |= IMX_DMA_SG_LOOP; - sdmac->direction = direction; -+ -+ switch (sdmac->direction) { -+ case DMA_DEV_TO_DEV: -+ sdmac->mode = SDMA_MODE_P2P; -+ break; -+ case DMA_TRANS_NONE: -+ sdmac->mode = SDMA_MODE_NO_BD; -+ break; -+ case DMA_MEM_TO_DEV: -+ case DMA_DEV_TO_MEM: -+ sdmac->mode = SDMA_MODE_LOOP; -+ break; -+ default: -+ dev_err(sdma->dev, "invalid SDMA direction %d\n", direction); -+ return NULL; -+ } -+ - ret = sdma_load_context(sdmac); - if (ret) - goto err_out; - -+ if (period_len) -+ num_periods = buf_len / period_len; -+ else -+ return &sdmac->desc; -+ - if (num_periods > NUM_BD) { - dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n", - channel, num_periods, NUM_BD); -@@ -1202,18 +1356,31 @@ - sdma_disable_channel(sdmac); - return 0; - case DMA_SLAVE_CONFIG: -- if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { -+ if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) { -+ sdmac->per_address = dmaengine_cfg->src_addr; -+ sdmac->per_address2 = dmaengine_cfg->dst_addr; -+ sdmac->watermark_level = 0; -+ sdmac->watermark_level |= -+ dmaengine_cfg->src_maxburst; -+ sdmac->watermark_level |= -+ dmaengine_cfg->dst_maxburst << 16; -+ sdmac->word_size = dmaengine_cfg->dst_addr_width; -+ } else if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { - sdmac->per_address = dmaengine_cfg->src_addr; - sdmac->watermark_level = dmaengine_cfg->src_maxburst * - dmaengine_cfg->src_addr_width; - sdmac->word_size = dmaengine_cfg->src_addr_width; -- } else { -+ } else if (dmaengine_cfg->direction == DMA_MEM_TO_DEV) { - sdmac->per_address = dmaengine_cfg->dst_addr; - sdmac->watermark_level = dmaengine_cfg->dst_maxburst * - dmaengine_cfg->dst_addr_width; - sdmac->word_size = dmaengine_cfg->dst_addr_width; - } - sdmac->direction = dmaengine_cfg->direction; -+ if (dmaengine_cfg->dma_request0) -+ sdmac->event_id0 = dmaengine_cfg->dma_request0; -+ if (dmaengine_cfg->dma_request1) -+ sdmac->event_id1 = dmaengine_cfg->dma_request1; - return sdma_config_channel(sdmac); - default: - return -ENOSYS; -@@ -1227,9 +1394,15 @@ - struct dma_tx_state *txstate) - { - struct sdma_channel *sdmac = to_sdma_chan(chan); -+ u32 residue; -+ -+ if (sdmac->mode & SDMA_MODE_LOOP) -+ residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len; -+ else -+ residue = sdmac->chn_count - sdmac->chn_real_count; - - dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, -- sdmac->chn_count - sdmac->chn_real_count); -+ residue); - - return sdmac->status; - } -@@ -1285,7 +1458,10 @@ - goto err_firmware; - switch (header->version_major) { - case 1: -- sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; -+ if (header->version_minor > 0) -+ sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; -+ else -+ sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; - break; - case 2: - sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; -@@ -1331,7 +1507,7 @@ - - static int __init sdma_init(struct sdma_engine *sdma) - { -- int i, ret; -+ int i, ret, ccbsize; - dma_addr_t ccb_phys; - - clk_enable(sdma->clk_ipg); -@@ -1340,14 +1516,17 @@ - /* Be sure SDMA has not started yet */ - writel_relaxed(0, sdma->regs + SDMA_H_C0PTR); - -- sdma->channel_control = dma_alloc_coherent(NULL, -- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) + -- sizeof(struct sdma_context_data), -- &ccb_phys, GFP_KERNEL); -+ ccbsize = MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) -+ + sizeof(struct sdma_context_data); - -+ sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool, ccbsize, &ccb_phys); - if (!sdma->channel_control) { -- ret = -ENOMEM; -- goto err_dma_alloc; -+ sdma->channel_control = dma_alloc_coherent(NULL, ccbsize, -+ &ccb_phys, GFP_KERNEL); -+ if (!sdma->channel_control) { -+ ret = -ENOMEM; -+ goto err_dma_alloc; -+ } - } - - sdma->context = (void *)sdma->channel_control + -@@ -1422,9 +1601,10 @@ - if (dma_spec->args_count != 3) - return NULL; - -- data.dma_request = dma_spec->args[0]; -+ data.dma_request0 = dma_spec->args[0]; - data.peripheral_type = dma_spec->args[1]; - data.priority = dma_spec->args[2]; -+ data.dma_request1 = 0; - - return dma_request_channel(mask, sdma_filter_fn, &data); - } -@@ -1542,6 +1722,11 @@ - &sdma->dma_device.channels); - } - -+ if (np) -+ sdma->iram_pool = of_get_named_gen_pool(np, "iram", 0); -+ if (!sdma->iram_pool) -+ dev_warn(&pdev->dev, "no iram assigned, using external mem\n"); -+ - ret = sdma_init(sdma); - if (ret) - goto err_init; -diff -Nur linux-3.14.22.orig/drivers/dma/Kconfig linux-3.14.22/drivers/dma/Kconfig ---- linux-3.14.22.orig/drivers/dma/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/dma/Kconfig 2014-10-22 14:55:52.046220001 -0500 -@@ -137,6 +137,19 @@ - To avoid bloating the irq_desc[] array we allocate a sufficient - number of IRQ slots and map them dynamically to specific sources. - -+config MXC_PXP_V2 -+ bool "MXC PxP V2 support" -+ depends on ARM -+ select DMA_ENGINE -+ help -+ Support the PxP (Pixel Pipeline) on i.MX6 DualLite and i.MX6 SoloLite. -+ If unsure, select N. -+ -+config MXC_PXP_CLIENT_DEVICE -+ bool "MXC PxP Client Device" -+ default y -+ depends on MXC_PXP_V2 -+ - config TXX9_DMAC - tristate "Toshiba TXx9 SoC DMA support" - depends on MACH_TX49XX || MACH_TX39XX -diff -Nur linux-3.14.22.orig/drivers/dma/Makefile linux-3.14.22/drivers/dma/Makefile ---- linux-3.14.22.orig/drivers/dma/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/dma/Makefile 2014-10-22 14:55:52.046220001 -0500 -@@ -18,6 +18,7 @@ - obj-$(CONFIG_DW_DMAC_CORE) += dw/ - obj-$(CONFIG_AT_HDMAC) += at_hdmac.o - obj-$(CONFIG_MX3_IPU) += ipu/ -+obj-$(CONFIG_MXC_PXP_V2) += pxp/ - obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o - obj-$(CONFIG_SH_DMAE_BASE) += sh/ - obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o -diff -Nur linux-3.14.22.orig/drivers/dma/pxp/Makefile linux-3.14.22/drivers/dma/pxp/Makefile ---- linux-3.14.22.orig/drivers/dma/pxp/Makefile 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/dma/pxp/Makefile 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o -+obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o -diff -Nur linux-3.14.22.orig/drivers/dma/pxp/pxp_device.c linux-3.14.22/drivers/dma/pxp/pxp_device.c ---- linux-3.14.22.orig/drivers/dma/pxp/pxp_device.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/dma/pxp/pxp_device.c 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,765 @@ -+/* -+ * Copyright (C) 2010-2014 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define BUFFER_HASH_ORDER 4 -+ -+static struct pxp_buffer_hash bufhash; -+static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL]; -+ -+static int pxp_ht_create(struct pxp_buffer_hash *hash, int order) -+{ -+ unsigned long i; -+ unsigned long table_size; -+ -+ table_size = 1U << order; -+ -+ hash->order = order; -+ hash->hash_table = kmalloc(sizeof(*hash->hash_table) * table_size, GFP_KERNEL); -+ -+ if (!hash->hash_table) { -+ pr_err("%s: Out of memory for hash table\n", __func__); -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < table_size; i++) -+ INIT_HLIST_HEAD(&hash->hash_table[i]); -+ -+ return 0; -+} -+ -+static int pxp_ht_insert_item(struct pxp_buffer_hash *hash, -+ struct pxp_buf_obj *new) -+{ -+ unsigned long hashkey; -+ struct hlist_head *h_list; -+ -+ hashkey = hash_long(new->offset >> PAGE_SHIFT, hash->order); -+ h_list = &hash->hash_table[hashkey]; -+ -+ spin_lock(&hash->hash_lock); -+ hlist_add_head_rcu(&new->item, h_list); -+ spin_unlock(&hash->hash_lock); -+ -+ return 0; -+} -+ -+static int pxp_ht_remove_item(struct pxp_buffer_hash *hash, -+ struct pxp_buf_obj *obj) -+{ -+ spin_lock(&hash->hash_lock); -+ hlist_del_init_rcu(&obj->item); -+ spin_unlock(&hash->hash_lock); -+ return 0; -+} -+ -+static struct hlist_node *pxp_ht_find_key(struct pxp_buffer_hash *hash, -+ unsigned long key) -+{ -+ struct pxp_buf_obj *entry; -+ struct hlist_head *h_list; -+ unsigned long hashkey; -+ -+ hashkey = hash_long(key, hash->order); -+ h_list = &hash->hash_table[hashkey]; -+ -+ hlist_for_each_entry_rcu(entry, h_list, item) { -+ if (entry->offset >> PAGE_SHIFT == key) -+ return &entry->item; -+ } -+ -+ return NULL; -+} -+ -+static void pxp_ht_destroy(struct pxp_buffer_hash *hash) -+{ -+ kfree(hash->hash_table); -+ hash->hash_table = NULL; -+} -+ -+static int pxp_buffer_handle_create(struct pxp_file *file_priv, -+ struct pxp_buf_obj *obj, -+ uint32_t *handlep) -+{ -+ int ret; -+ -+ idr_preload(GFP_KERNEL); -+ spin_lock(&file_priv->buffer_lock); -+ -+ ret = idr_alloc(&file_priv->buffer_idr, obj, 1, 0, GFP_NOWAIT); -+ -+ spin_unlock(&file_priv->buffer_lock); -+ idr_preload_end(); -+ -+ if (ret < 0) -+ return ret; -+ -+ *handlep = ret; -+ -+ return 0; -+} -+ -+static struct pxp_buf_obj * -+pxp_buffer_object_lookup(struct pxp_file *file_priv, -+ uint32_t handle) -+{ -+ struct pxp_buf_obj *obj; -+ -+ spin_lock(&file_priv->buffer_lock); -+ -+ obj = idr_find(&file_priv->buffer_idr, handle); -+ if (!obj) { -+ spin_unlock(&file_priv->buffer_lock); -+ return NULL; -+ } -+ -+ spin_unlock(&file_priv->buffer_lock); -+ -+ return obj; -+} -+ -+static int pxp_buffer_handle_delete(struct pxp_file *file_priv, -+ uint32_t handle) -+{ -+ struct pxp_buf_obj *obj; -+ -+ spin_lock(&file_priv->buffer_lock); -+ -+ obj = idr_find(&file_priv->buffer_idr, handle); -+ if (!obj) { -+ spin_unlock(&file_priv->buffer_lock); -+ return -EINVAL; -+ } -+ -+ idr_remove(&file_priv->buffer_idr, handle); -+ spin_unlock(&file_priv->buffer_lock); -+ -+ return 0; -+} -+ -+static int pxp_channel_handle_create(struct pxp_file *file_priv, -+ struct pxp_chan_obj *obj, -+ uint32_t *handlep) -+{ -+ int ret; -+ -+ idr_preload(GFP_KERNEL); -+ spin_lock(&file_priv->channel_lock); -+ -+ ret = idr_alloc(&file_priv->channel_idr, obj, 0, 0, GFP_NOWAIT); -+ -+ spin_unlock(&file_priv->channel_lock); -+ idr_preload_end(); -+ -+ if (ret < 0) -+ return ret; -+ -+ *handlep = ret; -+ -+ return 0; -+} -+ -+static struct pxp_chan_obj * -+pxp_channel_object_lookup(struct pxp_file *file_priv, -+ uint32_t handle) -+{ -+ struct pxp_chan_obj *obj; -+ -+ spin_lock(&file_priv->channel_lock); -+ -+ obj = idr_find(&file_priv->channel_idr, handle); -+ if (!obj) { -+ spin_unlock(&file_priv->channel_lock); -+ return NULL; -+ } -+ -+ spin_unlock(&file_priv->channel_lock); -+ -+ return obj; -+} -+ -+static int pxp_channel_handle_delete(struct pxp_file *file_priv, -+ uint32_t handle) -+{ -+ struct pxp_chan_obj *obj; -+ -+ spin_lock(&file_priv->channel_lock); -+ -+ obj = idr_find(&file_priv->channel_idr, handle); -+ if (!obj) { -+ spin_unlock(&file_priv->channel_lock); -+ return -EINVAL; -+ } -+ -+ idr_remove(&file_priv->channel_idr, handle); -+ spin_unlock(&file_priv->channel_lock); -+ -+ return 0; -+} -+ -+static int pxp_alloc_dma_buffer(struct pxp_buf_obj *obj) -+{ -+ obj->virtual = dma_alloc_coherent(NULL, PAGE_ALIGN(obj->size), -+ (dma_addr_t *) (&obj->offset), -+ GFP_DMA | GFP_KERNEL); -+ pr_debug("[ALLOC] mem alloc phys_addr = 0x%lx\n", obj->offset); -+ -+ if (obj->virtual == NULL) { -+ printk(KERN_ERR "Physical memory allocation error!\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static void pxp_free_dma_buffer(struct pxp_buf_obj *obj) -+{ -+ if (obj->virtual != NULL) { -+ dma_free_coherent(0, PAGE_ALIGN(obj->size), -+ obj->virtual, (dma_addr_t)obj->offset); -+ } -+} -+ -+static int -+pxp_buffer_object_free(int id, void *ptr, void *data) -+{ -+ struct pxp_file *file_priv = data; -+ struct pxp_buf_obj *obj = ptr; -+ int ret; -+ -+ ret = pxp_buffer_handle_delete(file_priv, obj->handle); -+ if (ret < 0) -+ return ret; -+ -+ pxp_ht_remove_item(&bufhash, obj); -+ pxp_free_dma_buffer(obj); -+ kfree(obj); -+ -+ return 0; -+} -+ -+static int -+pxp_channel_object_free(int id, void *ptr, void *data) -+{ -+ struct pxp_file *file_priv = data; -+ struct pxp_chan_obj *obj = ptr; -+ int chan_id; -+ -+ chan_id = obj->chan->chan_id; -+ wait_event(irq_info[chan_id].waitq, -+ atomic_read(&irq_info[chan_id].irq_pending) == 0); -+ -+ pxp_channel_handle_delete(file_priv, obj->handle); -+ dma_release_channel(obj->chan); -+ kfree(obj); -+ -+ return 0; -+} -+ -+static void pxp_free_buffers(struct pxp_file *file_priv) -+{ -+ idr_for_each(&file_priv->buffer_idr, -+ &pxp_buffer_object_free, file_priv); -+ idr_destroy(&file_priv->buffer_idr); -+} -+ -+static void pxp_free_channels(struct pxp_file *file_priv) -+{ -+ idr_for_each(&file_priv->channel_idr, -+ &pxp_channel_object_free, file_priv); -+ idr_destroy(&file_priv->channel_idr); -+} -+ -+/* Callback function triggered after PxP receives an EOF interrupt */ -+static void pxp_dma_done(void *arg) -+{ -+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg); -+ struct dma_chan *chan = tx_desc->txd.chan; -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ int chan_id = pxp_chan->dma_chan.chan_id; -+ -+ pr_debug("DMA Done ISR, chan_id %d\n", chan_id); -+ -+ atomic_dec(&irq_info[chan_id].irq_pending); -+ irq_info[chan_id].hist_status = tx_desc->hist_status; -+ -+ wake_up(&(irq_info[chan_id].waitq)); -+} -+ -+static int pxp_ioc_config_chan(struct pxp_file *priv, unsigned long arg) -+{ -+ struct scatterlist sg[3]; -+ struct pxp_tx_desc *desc; -+ struct dma_async_tx_descriptor *txd; -+ struct pxp_config_data pxp_conf; -+ dma_cookie_t cookie; -+ int handle, chan_id; -+ int i, length, ret; -+ struct dma_chan *chan; -+ struct pxp_chan_obj *obj; -+ -+ ret = copy_from_user(&pxp_conf, -+ (struct pxp_config_data *)arg, -+ sizeof(struct pxp_config_data)); -+ if (ret) -+ return -EFAULT; -+ -+ handle = pxp_conf.handle; -+ obj = pxp_channel_object_lookup(priv, handle); -+ if (!obj) -+ return -EINVAL; -+ chan = obj->chan; -+ chan_id = chan->chan_id; -+ -+ sg_init_table(sg, 3); -+ -+ txd = chan->device->device_prep_slave_sg(chan, -+ sg, 3, -+ DMA_TO_DEVICE, -+ DMA_PREP_INTERRUPT, -+ NULL); -+ if (!txd) { -+ pr_err("Error preparing a DMA transaction descriptor.\n"); -+ return -EIO; -+ } -+ -+ txd->callback_param = txd; -+ txd->callback = pxp_dma_done; -+ -+ desc = to_tx_desc(txd); -+ -+ length = desc->len; -+ for (i = 0; i < length; i++) { -+ if (i == 0) { /* S0 */ -+ memcpy(&desc->proc_data, -+ &pxp_conf.proc_data, -+ sizeof(struct pxp_proc_data)); -+ memcpy(&desc->layer_param.s0_param, -+ &pxp_conf.s0_param, -+ sizeof(struct pxp_layer_param)); -+ } else if (i == 1) { /* Output */ -+ memcpy(&desc->layer_param.out_param, -+ &pxp_conf.out_param, -+ sizeof(struct pxp_layer_param)); -+ } else { -+ /* OverLay */ -+ memcpy(&desc->layer_param.ol_param, -+ &pxp_conf.ol_param, -+ sizeof(struct pxp_layer_param)); -+ } -+ -+ desc = desc->next; -+ } -+ -+ cookie = txd->tx_submit(txd); -+ if (cookie < 0) { -+ pr_err("Error tx_submit\n"); -+ return -EIO; -+ } -+ -+ atomic_inc(&irq_info[chan_id].irq_pending); -+ -+ return 0; -+} -+ -+static int pxp_device_open(struct inode *inode, struct file *filp) -+{ -+ struct pxp_file *priv; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ -+ if (!priv) -+ return -ENOMEM; -+ -+ filp->private_data = priv; -+ priv->filp = filp; -+ -+ idr_init(&priv->buffer_idr); -+ spin_lock_init(&priv->buffer_lock); -+ -+ idr_init(&priv->channel_idr); -+ spin_lock_init(&priv->channel_lock); -+ -+ return 0; -+} -+ -+static int pxp_device_release(struct inode *inode, struct file *filp) -+{ -+ struct pxp_file *priv = filp->private_data; -+ -+ if (priv) { -+ pxp_free_channels(priv); -+ pxp_free_buffers(priv); -+ kfree(priv); -+ filp->private_data = NULL; -+ } -+ -+ return 0; -+} -+ -+static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int request_size; -+ struct hlist_node *node; -+ struct pxp_buf_obj *obj; -+ -+ request_size = vma->vm_end - vma->vm_start; -+ -+ pr_debug("start=0x%x, pgoff=0x%x, size=0x%x\n", -+ (unsigned int)(vma->vm_start), (unsigned int)(vma->vm_pgoff), -+ request_size); -+ -+ node = pxp_ht_find_key(&bufhash, vma->vm_pgoff); -+ if (!node) -+ return -EINVAL; -+ -+ obj = list_entry(node, struct pxp_buf_obj, item); -+ if (obj->offset + (obj->size >> PAGE_SHIFT) < -+ (vma->vm_pgoff + vma_pages(vma))) -+ return -ENOMEM; -+ -+ switch (obj->mem_type) { -+ case MEMORY_TYPE_UNCACHED: -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ break; -+ case MEMORY_TYPE_WC: -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ break; -+ case MEMORY_TYPE_CACHED: -+ break; -+ default: -+ pr_err("%s: invalid memory type!\n", __func__); -+ return -EINVAL; -+ } -+ -+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, -+ request_size, vma->vm_page_prot) ? -EAGAIN : 0; -+} -+ -+static bool chan_filter(struct dma_chan *chan, void *arg) -+{ -+ if (imx_dma_is_pxp(chan)) -+ return true; -+ else -+ return false; -+} -+ -+static long pxp_device_ioctl(struct file *filp, -+ unsigned int cmd, unsigned long arg) -+{ -+ int ret = 0; -+ struct pxp_file *file_priv = filp->private_data; -+ -+ switch (cmd) { -+ case PXP_IOC_GET_CHAN: -+ { -+ int ret; -+ struct dma_chan *chan = NULL; -+ dma_cap_mask_t mask; -+ struct pxp_chan_obj *obj = NULL; -+ -+ pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__); -+ -+ dma_cap_zero(mask); -+ dma_cap_set(DMA_SLAVE, mask); -+ dma_cap_set(DMA_PRIVATE, mask); -+ -+ chan = dma_request_channel(mask, chan_filter, NULL); -+ if (!chan) { -+ pr_err("Unsccessfully received channel!\n"); -+ return -EBUSY; -+ } -+ -+ pr_debug("Successfully received channel." -+ "chan_id %d\n", chan->chan_id); -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) { -+ dma_release_channel(chan); -+ return -ENOMEM; -+ } -+ obj->chan = chan; -+ -+ ret = pxp_channel_handle_create(file_priv, obj, -+ &obj->handle); -+ if (ret) { -+ dma_release_channel(chan); -+ kfree(obj); -+ return ret; -+ } -+ -+ init_waitqueue_head(&(irq_info[chan->chan_id].waitq)); -+ if (put_user(obj->handle, (u32 __user *) arg)) { -+ pxp_channel_handle_delete(file_priv, obj->handle); -+ dma_release_channel(chan); -+ kfree(obj); -+ return -EFAULT; -+ } -+ -+ break; -+ } -+ case PXP_IOC_PUT_CHAN: -+ { -+ int handle; -+ struct pxp_chan_obj *obj; -+ -+ if (get_user(handle, (u32 __user *) arg)) -+ return -EFAULT; -+ -+ pr_debug("%d release handle %d\n", __LINE__, handle); -+ -+ obj = pxp_channel_object_lookup(file_priv, handle); -+ if (!obj) -+ return -EINVAL; -+ -+ pxp_channel_handle_delete(file_priv, obj->handle); -+ dma_release_channel(obj->chan); -+ kfree(obj); -+ -+ break; -+ } -+ case PXP_IOC_CONFIG_CHAN: -+ { -+ int ret; -+ -+ ret = pxp_ioc_config_chan(file_priv, arg); -+ if (ret) -+ return ret; -+ -+ break; -+ } -+ case PXP_IOC_START_CHAN: -+ { -+ int handle; -+ struct pxp_chan_obj *obj = NULL; -+ -+ if (get_user(handle, (u32 __user *) arg)) -+ return -EFAULT; -+ -+ obj = pxp_channel_object_lookup(file_priv, handle); -+ if (!obj) -+ return -EINVAL; -+ -+ dma_async_issue_pending(obj->chan); -+ -+ break; -+ } -+ case PXP_IOC_GET_PHYMEM: -+ { -+ struct pxp_mem_desc buffer; -+ struct pxp_buf_obj *obj; -+ -+ ret = copy_from_user(&buffer, -+ (struct pxp_mem_desc *)arg, -+ sizeof(struct pxp_mem_desc)); -+ if (ret) -+ return -EFAULT; -+ -+ pr_debug("[ALLOC] mem alloc size = 0x%x\n", -+ buffer.size); -+ -+ obj = kzalloc(sizeof(*obj), GFP_KERNEL); -+ if (!obj) -+ return -ENOMEM; -+ obj->size = buffer.size; -+ obj->mem_type = buffer.mtype; -+ -+ ret = pxp_alloc_dma_buffer(obj); -+ if (ret == -1) { -+ printk(KERN_ERR -+ "Physical memory allocation error!\n"); -+ kfree(obj); -+ return ret; -+ } -+ -+ ret = pxp_buffer_handle_create(file_priv, obj, &obj->handle); -+ if (ret) { -+ pxp_free_dma_buffer(obj); -+ kfree(obj); -+ return ret; -+ } -+ buffer.handle = obj->handle; -+ buffer.phys_addr = obj->offset; -+ -+ ret = copy_to_user((void __user *)arg, &buffer, -+ sizeof(struct pxp_mem_desc)); -+ if (ret) { -+ pxp_buffer_handle_delete(file_priv, buffer.handle); -+ pxp_free_dma_buffer(obj); -+ kfree(obj); -+ return -EFAULT; -+ } -+ -+ pxp_ht_insert_item(&bufhash, obj); -+ -+ break; -+ } -+ case PXP_IOC_PUT_PHYMEM: -+ { -+ struct pxp_mem_desc pxp_mem; -+ struct pxp_buf_obj *obj; -+ -+ ret = copy_from_user(&pxp_mem, -+ (struct pxp_mem_desc *)arg, -+ sizeof(struct pxp_mem_desc)); -+ if (ret) -+ return -EACCES; -+ -+ obj = pxp_buffer_object_lookup(file_priv, pxp_mem.handle); -+ if (!obj) -+ return -EINVAL; -+ -+ ret = pxp_buffer_handle_delete(file_priv, obj->handle); -+ if (ret) -+ return ret; -+ -+ pxp_ht_remove_item(&bufhash, obj); -+ pxp_free_dma_buffer(obj); -+ kfree(obj); -+ -+ break; -+ } -+ case PXP_IOC_FLUSH_PHYMEM: -+ { -+ int ret; -+ struct pxp_mem_flush flush; -+ struct pxp_buf_obj *obj; -+ -+ ret = copy_from_user(&flush, -+ (struct pxp_mem_flush *)arg, -+ sizeof(struct pxp_mem_flush)); -+ if (ret) -+ return -EACCES; -+ -+ obj = pxp_buffer_object_lookup(file_priv, flush.handle); -+ if (!obj) -+ return -EINVAL; -+ -+ switch (flush.type) { -+ case CACHE_CLEAN: -+ dma_sync_single_for_device(NULL, obj->offset, -+ obj->size, DMA_TO_DEVICE); -+ break; -+ case CACHE_INVALIDATE: -+ dma_sync_single_for_device(NULL, obj->offset, -+ obj->size, DMA_FROM_DEVICE); -+ break; -+ case CACHE_FLUSH: -+ dma_sync_single_for_device(NULL, obj->offset, -+ obj->size, DMA_TO_DEVICE); -+ dma_sync_single_for_device(NULL, obj->offset, -+ obj->size, DMA_FROM_DEVICE); -+ break; -+ default: -+ pr_err("%s: invalid cache flush type\n", __func__); -+ return -EINVAL; -+ } -+ -+ break; -+ } -+ case PXP_IOC_WAIT4CMPLT: -+ { -+ struct pxp_chan_handle chan_handle; -+ int ret, chan_id, handle; -+ struct pxp_chan_obj *obj = NULL; -+ -+ ret = copy_from_user(&chan_handle, -+ (struct pxp_chan_handle *)arg, -+ sizeof(struct pxp_chan_handle)); -+ if (ret) -+ return -EFAULT; -+ -+ handle = chan_handle.handle; -+ obj = pxp_channel_object_lookup(file_priv, handle); -+ if (!obj) -+ return -EINVAL; -+ chan_id = obj->chan->chan_id; -+ -+ ret = wait_event_interruptible -+ (irq_info[chan_id].waitq, -+ (atomic_read(&irq_info[chan_id].irq_pending) == 0)); -+ if (ret < 0) { -+ printk(KERN_WARNING -+ "WAIT4CMPLT: signal received.\n"); -+ return -ERESTARTSYS; -+ } -+ -+ chan_handle.hist_status = irq_info[chan_id].hist_status; -+ ret = copy_to_user((struct pxp_chan_handle *)arg, -+ &chan_handle, -+ sizeof(struct pxp_chan_handle)); -+ if (ret) -+ return -EFAULT; -+ break; -+ } -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static const struct file_operations pxp_device_fops = { -+ .open = pxp_device_open, -+ .release = pxp_device_release, -+ .unlocked_ioctl = pxp_device_ioctl, -+ .mmap = pxp_device_mmap, -+}; -+ -+static struct miscdevice pxp_device_miscdev = { -+ .minor = MISC_DYNAMIC_MINOR, -+ .name = "pxp_device", -+ .fops = &pxp_device_fops, -+}; -+ -+int register_pxp_device(void) -+{ -+ int ret; -+ -+ ret = misc_register(&pxp_device_miscdev); -+ if (ret) -+ return ret; -+ -+ ret = pxp_ht_create(&bufhash, BUFFER_HASH_ORDER); -+ if (ret) -+ return ret; -+ spin_lock_init(&(bufhash.hash_lock)); -+ -+ pr_debug("PxP_Device registered Successfully\n"); -+ return 0; -+} -+ -+void unregister_pxp_device(void) -+{ -+ pxp_ht_destroy(&bufhash); -+ misc_deregister(&pxp_device_miscdev); -+} -diff -Nur linux-3.14.22.orig/drivers/dma/pxp/pxp_dma_v2.c linux-3.14.22/drivers/dma/pxp/pxp_dma_v2.c ---- linux-3.14.22.orig/drivers/dma/pxp/pxp_dma_v2.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/dma/pxp/pxp_dma_v2.c 2014-10-22 14:55:52.046220001 -0500 -@@ -0,0 +1,1854 @@ -+/* -+ * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+/* -+ * Based on STMP378X PxP driver -+ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "regs-pxp_v2.h" -+ -+#define PXP_DOWNSCALE_THRESHOLD 0x4000 -+ -+static LIST_HEAD(head); -+static int timeout_in_ms = 600; -+static unsigned int block_size; -+static struct kmem_cache *tx_desc_cache; -+ -+struct pxp_dma { -+ struct dma_device dma; -+}; -+ -+struct pxps { -+ struct platform_device *pdev; -+ struct clk *clk; -+ void __iomem *base; -+ int irq; /* PXP IRQ to the CPU */ -+ -+ spinlock_t lock; -+ struct mutex clk_mutex; -+ int clk_stat; -+#define CLK_STAT_OFF 0 -+#define CLK_STAT_ON 1 -+ int pxp_ongoing; -+ int lut_state; -+ -+ struct device *dev; -+ struct pxp_dma pxp_dma; -+ struct pxp_channel channel[NR_PXP_VIRT_CHANNEL]; -+ struct work_struct work; -+ -+ /* describes most recent processing configuration */ -+ struct pxp_config_data pxp_conf_state; -+ -+ /* to turn clock off when pxp is inactive */ -+ struct timer_list clk_timer; -+ -+ /* for pxp config dispatch asynchronously*/ -+ struct task_struct *dispatch; -+ wait_queue_head_t thread_waitq; -+ struct completion complete; -+}; -+ -+#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma) -+#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd) -+#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan) -+#define to_pxp(id) container_of(id, struct pxps, pxp_dma) -+ -+#define PXP_DEF_BUFS 2 -+#define PXP_MIN_PIX 8 -+ -+static uint32_t pxp_s0_formats[] = { -+ PXP_PIX_FMT_RGB32, -+ PXP_PIX_FMT_RGB565, -+ PXP_PIX_FMT_RGB555, -+ PXP_PIX_FMT_YUV420P, -+ PXP_PIX_FMT_YUV422P, -+}; -+ -+/* -+ * PXP common functions -+ */ -+static void dump_pxp_reg(struct pxps *pxp) -+{ -+ dev_dbg(pxp->dev, "PXP_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CTRL)); -+ dev_dbg(pxp->dev, "PXP_STAT 0x%x", -+ __raw_readl(pxp->base + HW_PXP_STAT)); -+ dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_CTRL)); -+ dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_BUF)); -+ dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_BUF2)); -+ dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_PITCH)); -+ dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_LRC)); -+ dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC)); -+ dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC)); -+ dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC)); -+ dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x", -+ __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC)); -+ dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_CTRL)); -+ dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_BUF)); -+ dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_UBUF)); -+ dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_VBUF)); -+ dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_PITCH)); -+ dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND)); -+ dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_SCALE)); -+ dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_OFFSET)); -+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW)); -+ dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x", -+ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH)); -+ dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_AS_CTRL)); -+ dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x", -+ __raw_readl(pxp->base + HW_PXP_AS_BUF)); -+ dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x", -+ __raw_readl(pxp->base + HW_PXP_AS_PITCH)); -+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x", -+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW)); -+ dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x", -+ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH)); -+ dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF0)); -+ dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF1)); -+ dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC1_COEF2)); -+ dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_CTRL)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF0)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF1)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF2)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF3)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF4)); -+ dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CSC2_COEF5)); -+ dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_LUT_CTRL)); -+ dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x", -+ __raw_readl(pxp->base + HW_PXP_LUT_ADDR)); -+ dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x", -+ __raw_readl(pxp->base + HW_PXP_LUT_DATA)); -+ dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x", -+ __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM)); -+ dev_dbg(pxp->dev, "PXP_CFA 0x%x", -+ __raw_readl(pxp->base + HW_PXP_CFA)); -+ dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST_CTRL)); -+ dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST2_PARAM)); -+ dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST4_PARAM)); -+ dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0)); -+ dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1)); -+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0)); -+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1)); -+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2)); -+ dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x", -+ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3)); -+ dev_dbg(pxp->dev, "PXP_POWER 0x%x", -+ __raw_readl(pxp->base + HW_PXP_POWER)); -+ dev_dbg(pxp->dev, "PXP_NEXT 0x%x", -+ __raw_readl(pxp->base + HW_PXP_NEXT)); -+ dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x", -+ __raw_readl(pxp->base + HW_PXP_DEBUGCTRL)); -+ dev_dbg(pxp->dev, "PXP_DEBUG 0x%x", -+ __raw_readl(pxp->base + HW_PXP_DEBUG)); -+ dev_dbg(pxp->dev, "PXP_VERSION 0x%x", -+ __raw_readl(pxp->base + HW_PXP_VERSION)); -+} -+ -+static bool is_yuv(u32 pix_fmt) -+{ -+ if ((pix_fmt == PXP_PIX_FMT_YUYV) | -+ (pix_fmt == PXP_PIX_FMT_UYVY) | -+ (pix_fmt == PXP_PIX_FMT_YVYU) | -+ (pix_fmt == PXP_PIX_FMT_VYUY) | -+ (pix_fmt == PXP_PIX_FMT_Y41P) | -+ (pix_fmt == PXP_PIX_FMT_YUV444) | -+ (pix_fmt == PXP_PIX_FMT_NV12) | -+ (pix_fmt == PXP_PIX_FMT_NV16) | -+ (pix_fmt == PXP_PIX_FMT_NV61) | -+ (pix_fmt == PXP_PIX_FMT_GREY) | -+ (pix_fmt == PXP_PIX_FMT_GY04) | -+ (pix_fmt == PXP_PIX_FMT_YVU410P) | -+ (pix_fmt == PXP_PIX_FMT_YUV410P) | -+ (pix_fmt == PXP_PIX_FMT_YVU420P) | -+ (pix_fmt == PXP_PIX_FMT_YUV420P) | -+ (pix_fmt == PXP_PIX_FMT_YUV420P2) | -+ (pix_fmt == PXP_PIX_FMT_YVU422P) | -+ (pix_fmt == PXP_PIX_FMT_YUV422P)) { -+ return true; -+ } else { -+ return false; -+ } -+} -+ -+static void pxp_set_ctrl(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; -+ u32 ctrl; -+ u32 fmt_ctrl; -+ int need_swap = 0; /* to support YUYV and YVYU formats */ -+ -+ /* Configure S0 input format */ -+ switch (pxp_conf->s0_param.pixel_fmt) { -+ case PXP_PIX_FMT_RGB32: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888; -+ break; -+ case PXP_PIX_FMT_RGB565: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565; -+ break; -+ case PXP_PIX_FMT_RGB555: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555; -+ break; -+ case PXP_PIX_FMT_YUV420P: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420; -+ break; -+ case PXP_PIX_FMT_YVU420P: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420; -+ break; -+ case PXP_PIX_FMT_GREY: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8; -+ break; -+ case PXP_PIX_FMT_GY04: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4; -+ break; -+ case PXP_PIX_FMT_YUV422P: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422; -+ break; -+ case PXP_PIX_FMT_UYVY: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; -+ break; -+ case PXP_PIX_FMT_YUYV: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; -+ need_swap = 1; -+ break; -+ case PXP_PIX_FMT_VYUY: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422; -+ break; -+ case PXP_PIX_FMT_YVYU: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422; -+ need_swap = 1; -+ break; -+ case PXP_PIX_FMT_NV12: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420; -+ break; -+ case PXP_PIX_FMT_NV21: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420; -+ break; -+ case PXP_PIX_FMT_NV16: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422; -+ break; -+ case PXP_PIX_FMT_NV61: -+ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422; -+ break; -+ default: -+ fmt_ctrl = 0; -+ } -+ -+ ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap); -+ __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET); -+ -+ /* Configure output format based on out_channel format */ -+ switch (pxp_conf->out_param.pixel_fmt) { -+ case PXP_PIX_FMT_RGB32: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888; -+ break; -+ case PXP_PIX_FMT_BGRA32: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888; -+ break; -+ case PXP_PIX_FMT_RGB24: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P; -+ break; -+ case PXP_PIX_FMT_RGB565: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565; -+ break; -+ case PXP_PIX_FMT_RGB555: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555; -+ break; -+ case PXP_PIX_FMT_GREY: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8; -+ break; -+ case PXP_PIX_FMT_GY04: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4; -+ break; -+ case PXP_PIX_FMT_UYVY: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422; -+ break; -+ case PXP_PIX_FMT_VYUY: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422; -+ break; -+ case PXP_PIX_FMT_NV12: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420; -+ break; -+ case PXP_PIX_FMT_NV21: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420; -+ break; -+ case PXP_PIX_FMT_NV16: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422; -+ break; -+ case PXP_PIX_FMT_NV61: -+ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422; -+ break; -+ default: -+ fmt_ctrl = 0; -+ } -+ -+ ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl); -+ __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL); -+ -+ ctrl = 0; -+ if (proc_data->scaling) -+ ; -+ if (proc_data->vflip) -+ ctrl |= BM_PXP_CTRL_VFLIP; -+ if (proc_data->hflip) -+ ctrl |= BM_PXP_CTRL_HFLIP; -+ if (proc_data->rotate) { -+ ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90); -+ if (proc_data->rot_pos) -+ ctrl |= BM_PXP_CTRL_ROT_POS; -+ } -+ -+ /* In default, the block size is set to 8x8 -+ * But block size can be set to 16x16 due to -+ * blocksize variable modification -+ */ -+ ctrl |= block_size << 23; -+ -+ __raw_writel(ctrl, pxp->base + HW_PXP_CTRL); -+} -+ -+static int pxp_start(struct pxps *pxp) -+{ -+ __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET); -+ __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET); -+ dump_pxp_reg(pxp); -+ -+ return 0; -+} -+ -+static void pxp_set_outbuf(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *out_params = &pxp_conf->out_param; -+ -+ __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF); -+ -+ __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) | -+ BF_PXP_OUT_LRC_Y(out_params->height - 1), -+ pxp->base + HW_PXP_OUT_LRC); -+ -+ if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) { -+ __raw_writel(out_params->stride * 3, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 || -+ out_params->pixel_fmt == PXP_PIX_FMT_RGB32) { -+ __raw_writel(out_params->stride << 2, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) { -+ __raw_writel(out_params->stride << 1, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY || -+ (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) { -+ __raw_writel(out_params->stride << 1, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY || -+ out_params->pixel_fmt == PXP_PIX_FMT_NV12 || -+ out_params->pixel_fmt == PXP_PIX_FMT_NV21 || -+ out_params->pixel_fmt == PXP_PIX_FMT_NV16 || -+ out_params->pixel_fmt == PXP_PIX_FMT_NV61) { -+ __raw_writel(out_params->stride, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) { -+ __raw_writel(out_params->stride >> 1, -+ pxp->base + HW_PXP_OUT_PITCH); -+ } else { -+ __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH); -+ } -+ -+ /* set global alpha if necessary */ -+ if (out_params->global_alpha_enable) { -+ __raw_writel(out_params->global_alpha << 24, -+ pxp->base + HW_PXP_OUT_CTRL_SET); -+ __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT, -+ pxp->base + HW_PXP_OUT_CTRL_SET); -+ } -+} -+ -+static void pxp_set_s0colorkey(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; -+ -+ /* Low and high are set equal. V4L does not allow a chromakey range */ -+ if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) { -+ /* disable color key */ -+ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW); -+ __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH); -+ } else { -+ __raw_writel(s0_params->color_key, -+ pxp->base + HW_PXP_PS_CLRKEYLOW); -+ __raw_writel(s0_params->color_key, -+ pxp->base + HW_PXP_PS_CLRKEYHIGH); -+ } -+} -+ -+static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no]; -+ -+ /* Low and high are set equal. V4L does not allow a chromakey range */ -+ if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) { -+ __raw_writel(ol_params->color_key, -+ pxp->base + HW_PXP_AS_CLRKEYLOW); -+ __raw_writel(ol_params->color_key, -+ pxp->base + HW_PXP_AS_CLRKEYHIGH); -+ } else { -+ /* disable color key */ -+ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW); -+ __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH); -+ } -+} -+ -+static void pxp_set_oln(int layer_no, struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; -+ dma_addr_t phys_addr = olparams_data->paddr; -+ u32 pitch = olparams_data->stride ? olparams_data->stride : -+ olparams_data->width; -+ -+ __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF); -+ -+ /* Fixme */ -+ if (olparams_data->width == 0 && olparams_data->height == 0) { -+ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC); -+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC); -+ } else { -+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC); -+ if (pxp_conf->proc_data.rotate == 90 || -+ pxp_conf->proc_data.rotate == 270) { -+ if (pxp_conf->proc_data.rot_pos == 1) { -+ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) | -+ BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1), -+ pxp->base + HW_PXP_OUT_AS_LRC); -+ } else { -+ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) | -+ BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1), -+ pxp->base + HW_PXP_OUT_AS_LRC); -+ } -+ } else { -+ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) | -+ BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1), -+ pxp->base + HW_PXP_OUT_AS_LRC); -+ } -+ } -+ -+ if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) | -+ (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) { -+ __raw_writel(pitch << 2, -+ pxp->base + HW_PXP_AS_PITCH); -+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) { -+ __raw_writel(pitch << 1, -+ pxp->base + HW_PXP_AS_PITCH); -+ } else { -+ __raw_writel(0, pxp->base + HW_PXP_AS_PITCH); -+ } -+} -+ -+static void pxp_set_olparam(int layer_no, struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; -+ u32 olparam; -+ -+ olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha); -+ if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) { -+ olparam |= -+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888); -+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) { -+ olparam |= -+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888); -+ if (!olparams_data->combine_enable) { -+ olparam |= -+ BF_PXP_AS_CTRL_ALPHA_CTRL -+ (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs); -+ olparam |= 0x3 << 16; -+ } -+ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) { -+ olparam |= -+ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565); -+ } -+ if (olparams_data->global_alpha_enable) { -+ if (olparams_data->global_override) { -+ olparam |= -+ BF_PXP_AS_CTRL_ALPHA_CTRL -+ (BV_PXP_AS_CTRL_ALPHA_CTRL__Override); -+ } else { -+ olparam |= -+ BF_PXP_AS_CTRL_ALPHA_CTRL -+ (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply); -+ } -+ if (olparams_data->alpha_invert) -+ olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT; -+ } -+ if (olparams_data->color_key_enable) -+ olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY; -+ -+ __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL); -+} -+ -+static void pxp_set_s0param(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; -+ u32 s0param; -+ -+ /* contains the coordinate for the PS in the OUTPUT buffer. */ -+ if ((pxp_conf->s0_param).width == 0 && -+ (pxp_conf->s0_param).height == 0) { -+ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC); -+ __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC); -+ } else { -+ s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left); -+ s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top); -+ __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC); -+ s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left + -+ proc_data->drect.width - 1); -+ s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top + -+ proc_data->drect.height - 1); -+ __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC); -+ } -+} -+ -+/* crop behavior is re-designed in h/w. */ -+static void pxp_set_s0crop(struct pxps *pxp) -+{ -+ /* -+ * place-holder, it's implemented in other functions in this driver. -+ * Refer to "Clipping source images" section in RM for detail. -+ */ -+} -+ -+static int pxp_set_scaling(struct pxps *pxp) -+{ -+ int ret = 0; -+ u32 xscale, yscale, s0scale; -+ u32 decx, decy, xdec = 0, ydec = 0; -+ struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data; -+ -+ if (((proc_data->srect.width == proc_data->drect.width) && -+ (proc_data->srect.height == proc_data->drect.height)) || -+ ((proc_data->srect.width == 0) && (proc_data->srect.height == 0))) { -+ proc_data->scaling = 0; -+ __raw_writel(0x10001000, pxp->base + HW_PXP_PS_SCALE); -+ __raw_writel(0, pxp->base + HW_PXP_PS_CTRL); -+ goto out; -+ } -+ -+ proc_data->scaling = 1; -+ decx = proc_data->srect.width / proc_data->drect.width; -+ decy = proc_data->srect.height / proc_data->drect.height; -+ if (decx > 0) { -+ if (decx >= 2 && decx < 4) { -+ decx = 2; -+ xdec = 1; -+ } else if (decx >= 4 && decx < 8) { -+ decx = 4; -+ xdec = 2; -+ } else if (decx >= 8) { -+ decx = 8; -+ xdec = 3; -+ } -+ xscale = proc_data->srect.width * 0x1000 / -+ (proc_data->drect.width * decx); -+ } else -+ xscale = proc_data->srect.width * 0x1000 / -+ proc_data->drect.width; -+ if (decy > 0) { -+ if (decy >= 2 && decy < 4) { -+ decy = 2; -+ ydec = 1; -+ } else if (decy >= 4 && decy < 8) { -+ decy = 4; -+ ydec = 2; -+ } else if (decy >= 8) { -+ decy = 8; -+ ydec = 3; -+ } -+ yscale = proc_data->srect.height * 0x1000 / -+ (proc_data->drect.height * decy); -+ } else -+ yscale = proc_data->srect.height * 0x1000 / -+ proc_data->drect.height; -+ -+ __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL); -+ -+ if (xscale > PXP_DOWNSCALE_THRESHOLD) -+ xscale = PXP_DOWNSCALE_THRESHOLD; -+ if (yscale > PXP_DOWNSCALE_THRESHOLD) -+ yscale = PXP_DOWNSCALE_THRESHOLD; -+ s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) | -+ BF_PXP_PS_SCALE_XSCALE(xscale); -+ __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE); -+ -+out: -+ pxp_set_ctrl(pxp); -+ -+ return ret; -+} -+ -+static void pxp_set_bg(struct pxps *pxp) -+{ -+ __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor, -+ pxp->base + HW_PXP_PS_BACKGROUND); -+} -+ -+static void pxp_set_lut(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ int lut_op = pxp_conf->proc_data.lut_transform; -+ u32 reg_val; -+ int i; -+ bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false; -+ u8 *cmap = pxp_conf->proc_data.lut_map; -+ u32 entry_src; -+ u32 pix_val; -+ u8 entry[4]; -+ -+ /* -+ * If LUT already configured as needed, return... -+ * Unless CMAP is needed and it has been updated. -+ */ -+ if ((pxp->lut_state == lut_op) && -+ !(use_cmap && pxp_conf->proc_data.lut_map_updated)) -+ return; -+ -+ if (lut_op == PXP_LUT_NONE) { -+ __raw_writel(BM_PXP_LUT_CTRL_BYPASS, -+ pxp->base + HW_PXP_LUT_CTRL); -+ } else if (((lut_op & PXP_LUT_INVERT) != 0) -+ && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) { -+ /* Fill out LUT table with inverted monochromized values */ -+ -+ /* clear bypass bit, set lookup mode & out mode */ -+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE -+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | -+ BF_PXP_LUT_CTRL_OUT_MODE -+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), -+ pxp->base + HW_PXP_LUT_CTRL); -+ -+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ -+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); -+ -+ /* LUT address pointer auto-increments after each data write */ -+ for (pix_val = 0; pix_val < 256; pix_val += 4) { -+ for (i = 0; i < 4; i++) { -+ entry_src = use_cmap ? -+ cmap[pix_val + i] : pix_val + i; -+ entry[i] = (entry_src < 0x80) ? 0xFF : 0x00; -+ } -+ reg_val = (entry[3] << 24) | (entry[2] << 16) | -+ (entry[1] << 8) | entry[0]; -+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); -+ } -+ } else if ((lut_op & PXP_LUT_INVERT) != 0) { -+ /* Fill out LUT table with 8-bit inverted values */ -+ -+ /* clear bypass bit, set lookup mode & out mode */ -+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE -+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | -+ BF_PXP_LUT_CTRL_OUT_MODE -+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), -+ pxp->base + HW_PXP_LUT_CTRL); -+ -+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ -+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); -+ -+ /* LUT address pointer auto-increments after each data write */ -+ for (pix_val = 0; pix_val < 256; pix_val += 4) { -+ for (i = 0; i < 4; i++) { -+ entry_src = use_cmap ? -+ cmap[pix_val + i] : pix_val + i; -+ entry[i] = ~entry_src & 0xFF; -+ } -+ reg_val = (entry[3] << 24) | (entry[2] << 16) | -+ (entry[1] << 8) | entry[0]; -+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); -+ } -+ } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) { -+ /* Fill out LUT table with 8-bit monochromized values */ -+ -+ /* clear bypass bit, set lookup mode & out mode */ -+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE -+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | -+ BF_PXP_LUT_CTRL_OUT_MODE -+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), -+ pxp->base + HW_PXP_LUT_CTRL); -+ -+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ -+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); -+ -+ /* LUT address pointer auto-increments after each data write */ -+ for (pix_val = 0; pix_val < 256; pix_val += 4) { -+ for (i = 0; i < 4; i++) { -+ entry_src = use_cmap ? -+ cmap[pix_val + i] : pix_val + i; -+ entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF; -+ } -+ reg_val = (entry[3] << 24) | (entry[2] << 16) | -+ (entry[1] << 8) | entry[0]; -+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); -+ } -+ } else if (use_cmap) { -+ /* Fill out LUT table using colormap values */ -+ -+ /* clear bypass bit, set lookup mode & out mode */ -+ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE -+ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | -+ BF_PXP_LUT_CTRL_OUT_MODE -+ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), -+ pxp->base + HW_PXP_LUT_CTRL); -+ -+ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ -+ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); -+ -+ /* LUT address pointer auto-increments after each data write */ -+ for (pix_val = 0; pix_val < 256; pix_val += 4) { -+ for (i = 0; i < 4; i++) -+ entry[i] = cmap[pix_val + i]; -+ reg_val = (entry[3] << 24) | (entry[2] << 16) | -+ (entry[1] << 8) | entry[0]; -+ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); -+ } -+ } -+ -+ pxp->lut_state = lut_op; -+} -+ -+static void pxp_set_csc(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; -+ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0]; -+ struct pxp_layer_param *out_params = &pxp_conf->out_param; -+ -+ bool input_is_YUV = is_yuv(s0_params->pixel_fmt); -+ bool output_is_YUV = is_yuv(out_params->pixel_fmt); -+ -+ if (input_is_YUV && output_is_YUV) { -+ /* -+ * Input = YUV, Output = YUV -+ * No CSC unless we need to do combining -+ */ -+ if (ol_params->combine_enable) { -+ /* Must convert to RGB for combining with RGB overlay */ -+ -+ /* CSC1 - YUV->RGB */ -+ __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0); -+ __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1); -+ __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2); -+ -+ /* CSC2 - RGB->YUV */ -+ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); -+ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); -+ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); -+ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); -+ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); -+ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); -+ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); -+ } else { -+ /* Input & Output both YUV, so bypass both CSCs */ -+ -+ /* CSC1 - Bypass */ -+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); -+ -+ /* CSC2 - Bypass */ -+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); -+ } -+ } else if (input_is_YUV && !output_is_YUV) { -+ /* -+ * Input = YUV, Output = RGB -+ * Use CSC1 to convert to RGB -+ */ -+ -+ /* CSC1 - YUV->RGB */ -+ __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0); -+ __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1); -+ __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2); -+ -+ /* CSC2 - Bypass */ -+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); -+ } else if (!input_is_YUV && output_is_YUV) { -+ /* -+ * Input = RGB, Output = YUV -+ * Use CSC2 to convert to YUV -+ */ -+ -+ /* CSC1 - Bypass */ -+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); -+ -+ /* CSC2 - RGB->YUV */ -+ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); -+ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); -+ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); -+ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); -+ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); -+ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); -+ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); -+ } else { -+ /* -+ * Input = RGB, Output = RGB -+ * Input & Output both RGB, so bypass both CSCs -+ */ -+ -+ /* CSC1 - Bypass */ -+ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); -+ -+ /* CSC2 - Bypass */ -+ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); -+ } -+ -+ /* YCrCb colorspace */ -+ /* Not sure when we use this...no YCrCb formats are defined for PxP */ -+ /* -+ __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR); -+ __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR); -+ __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR); -+ */ -+ -+} -+ -+static void pxp_set_s0buf(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; -+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; -+ dma_addr_t Y, U, V; -+ dma_addr_t Y1, U1, V1; -+ u32 offset, bpp = 1; -+ u32 pitch = s0_params->stride ? s0_params->stride : -+ s0_params->width; -+ -+ Y = s0_params->paddr; -+ -+ if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) -+ bpp = 2; -+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32) -+ bpp = 4; -+ offset = (proc_data->srect.top * s0_params->width + -+ proc_data->srect.left) * bpp; -+ /* clipping or cropping */ -+ Y1 = Y + offset; -+ __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF); -+ if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) { -+ /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */ -+ int s = 2; -+ if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) -+ s = 1; -+ -+ offset = proc_data->srect.top * s0_params->width / 4 + -+ proc_data->srect.left / 2; -+ U = Y + (s0_params->width * s0_params->height); -+ U1 = U + offset; -+ V = U + ((s0_params->width * s0_params->height) >> s); -+ V1 = V + offset; -+ if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) { -+ __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF); -+ __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF); -+ } else { -+ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF); -+ __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF); -+ } -+ } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) { -+ int s = 2; -+ if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) || -+ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) -+ s = 1; -+ -+ offset = (proc_data->srect.top * s0_params->width + -+ proc_data->srect.left) / s; -+ U = Y + (s0_params->width * s0_params->height); -+ U1 = U + offset; -+ -+ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF); -+ } -+ -+ /* TODO: only support RGB565, Y8, Y4, YUV420 */ -+ if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY || -+ s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P || -+ s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P || -+ s0_params->pixel_fmt == PXP_PIX_FMT_NV12 || -+ s0_params->pixel_fmt == PXP_PIX_FMT_NV21 || -+ s0_params->pixel_fmt == PXP_PIX_FMT_NV16 || -+ s0_params->pixel_fmt == PXP_PIX_FMT_NV61 || -+ s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) { -+ __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH); -+ } -+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04) -+ __raw_writel(pitch >> 1, -+ pxp->base + HW_PXP_PS_PITCH); -+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32) -+ __raw_writel(pitch << 2, -+ pxp->base + HW_PXP_PS_PITCH); -+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY || -+ s0_params->pixel_fmt == PXP_PIX_FMT_YUYV || -+ s0_params->pixel_fmt == PXP_PIX_FMT_VYUY || -+ s0_params->pixel_fmt == PXP_PIX_FMT_YVYU) -+ __raw_writel(pitch << 1, -+ pxp->base + HW_PXP_PS_PITCH); -+ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) -+ __raw_writel(pitch << 1, -+ pxp->base + HW_PXP_PS_PITCH); -+ else -+ __raw_writel(0, pxp->base + HW_PXP_PS_PITCH); -+} -+ -+/** -+ * pxp_config() - configure PxP for a processing task -+ * @pxps: PXP context. -+ * @pxp_chan: PXP channel. -+ * @return: 0 on success or negative error code on failure. -+ */ -+static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan) -+{ -+ struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state; -+ int ol_nr; -+ int i; -+ -+ /* Configure PxP regs */ -+ pxp_set_ctrl(pxp); -+ pxp_set_s0param(pxp); -+ pxp_set_s0crop(pxp); -+ pxp_set_scaling(pxp); -+ ol_nr = pxp_conf_data->layer_nr - 2; -+ while (ol_nr > 0) { -+ i = pxp_conf_data->layer_nr - 2 - ol_nr; -+ pxp_set_oln(i, pxp); -+ pxp_set_olparam(i, pxp); -+ /* only the color key in higher overlay will take effect. */ -+ pxp_set_olcolorkey(i, pxp); -+ ol_nr--; -+ } -+ pxp_set_s0colorkey(pxp); -+ pxp_set_csc(pxp); -+ pxp_set_bg(pxp); -+ pxp_set_lut(pxp); -+ -+ pxp_set_s0buf(pxp); -+ pxp_set_outbuf(pxp); -+ -+ return 0; -+} -+ -+static void pxp_clk_enable(struct pxps *pxp) -+{ -+ mutex_lock(&pxp->clk_mutex); -+ -+ if (pxp->clk_stat == CLK_STAT_ON) { -+ mutex_unlock(&pxp->clk_mutex); -+ return; -+ } -+ -+ clk_prepare_enable(pxp->clk); -+ pxp->clk_stat = CLK_STAT_ON; -+ -+ mutex_unlock(&pxp->clk_mutex); -+} -+ -+static void pxp_clk_disable(struct pxps *pxp) -+{ -+ unsigned long flags; -+ -+ mutex_lock(&pxp->clk_mutex); -+ -+ if (pxp->clk_stat == CLK_STAT_OFF) { -+ mutex_unlock(&pxp->clk_mutex); -+ return; -+ } -+ -+ spin_lock_irqsave(&pxp->lock, flags); -+ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) { -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ clk_disable_unprepare(pxp->clk); -+ pxp->clk_stat = CLK_STAT_OFF; -+ } else -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ -+ mutex_unlock(&pxp->clk_mutex); -+} -+ -+static inline void clkoff_callback(struct work_struct *w) -+{ -+ struct pxps *pxp = container_of(w, struct pxps, work); -+ -+ pxp_clk_disable(pxp); -+} -+ -+static void pxp_clkoff_timer(unsigned long arg) -+{ -+ struct pxps *pxp = (struct pxps *)arg; -+ -+ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) -+ schedule_work(&pxp->work); -+ else -+ mod_timer(&pxp->clk_timer, -+ jiffies + msecs_to_jiffies(timeout_in_ms)); -+} -+ -+static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan) -+{ -+ return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list); -+} -+ -+/* called with pxp_chan->lock held */ -+static void __pxpdma_dostart(struct pxp_channel *pxp_chan) -+{ -+ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device); -+ struct pxps *pxp = to_pxp(pxp_dma); -+ struct pxp_tx_desc *desc; -+ struct pxp_tx_desc *child; -+ int i = 0; -+ -+ /* S0 */ -+ desc = list_first_entry(&head, struct pxp_tx_desc, list); -+ memcpy(&pxp->pxp_conf_state.s0_param, -+ &desc->layer_param.s0_param, sizeof(struct pxp_layer_param)); -+ memcpy(&pxp->pxp_conf_state.proc_data, -+ &desc->proc_data, sizeof(struct pxp_proc_data)); -+ -+ /* Save PxP configuration */ -+ list_for_each_entry(child, &desc->tx_list, list) { -+ if (i == 0) { /* Output */ -+ memcpy(&pxp->pxp_conf_state.out_param, -+ &child->layer_param.out_param, -+ sizeof(struct pxp_layer_param)); -+ } else { /* Overlay */ -+ memcpy(&pxp->pxp_conf_state.ol_param[i - 1], -+ &child->layer_param.ol_param, -+ sizeof(struct pxp_layer_param)); -+ } -+ -+ i++; -+ } -+ pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__, -+ pxp->pxp_conf_state.s0_param.width, -+ pxp->pxp_conf_state.s0_param.height, -+ pxp->pxp_conf_state.s0_param.paddr); -+ pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__, -+ pxp->pxp_conf_state.out_param.width, -+ pxp->pxp_conf_state.out_param.height, -+ pxp->pxp_conf_state.out_param.paddr); -+} -+ -+static void pxpdma_dostart_work(struct pxps *pxp) -+{ -+ struct pxp_channel *pxp_chan = NULL; -+ unsigned long flags; -+ struct pxp_tx_desc *desc = NULL; -+ -+ spin_lock_irqsave(&pxp->lock, flags); -+ -+ desc = list_entry(head.next, struct pxp_tx_desc, list); -+ pxp_chan = to_pxp_channel(desc->txd.chan); -+ -+ __pxpdma_dostart(pxp_chan); -+ -+ /* Configure PxP */ -+ pxp_config(pxp, pxp_chan); -+ -+ pxp_start(pxp); -+ -+ spin_unlock_irqrestore(&pxp->lock, flags); -+} -+ -+static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp) -+{ -+ unsigned long flags; -+ struct pxp_tx_desc *desc = NULL; -+ -+ do { -+ desc = pxpdma_first_queued(pxp_chan); -+ spin_lock_irqsave(&pxp->lock, flags); -+ list_move_tail(&desc->list, &head); -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ } while (!list_empty(&pxp_chan->queue)); -+} -+ -+static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx) -+{ -+ struct pxp_tx_desc *desc = to_tx_desc(tx); -+ struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan); -+ dma_cookie_t cookie; -+ -+ dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n"); -+ -+ /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */ -+ spin_lock(&pxp_chan->lock); -+ -+ cookie = pxp_chan->dma_chan.cookie; -+ -+ if (++cookie < 0) -+ cookie = 1; -+ -+ /* from dmaengine.h: "last cookie value returned to client" */ -+ pxp_chan->dma_chan.cookie = cookie; -+ tx->cookie = cookie; -+ -+ /* Here we add the tx descriptor to our PxP task queue. */ -+ list_add_tail(&desc->list, &pxp_chan->queue); -+ -+ spin_unlock(&pxp_chan->lock); -+ -+ dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n"); -+ -+ return cookie; -+} -+ -+/** -+ * pxp_init_channel() - initialize a PXP channel. -+ * @pxp_dma: PXP DMA context. -+ * @pchan: pointer to the channel object. -+ * @return 0 on success or negative error code on failure. -+ */ -+static int pxp_init_channel(struct pxp_dma *pxp_dma, -+ struct pxp_channel *pxp_chan) -+{ -+ int ret = 0; -+ -+ /* -+ * We are using _virtual_ channel here. -+ * Each channel contains all parameters of corresponding layers -+ * for one transaction; each layer is represented as one descriptor -+ * (i.e., pxp_tx_desc) here. -+ */ -+ -+ INIT_LIST_HEAD(&pxp_chan->queue); -+ -+ return ret; -+} -+ -+static irqreturn_t pxp_irq(int irq, void *dev_id) -+{ -+ struct pxps *pxp = dev_id; -+ struct pxp_channel *pxp_chan; -+ struct pxp_tx_desc *desc; -+ struct pxp_tx_desc *child, *_child; -+ dma_async_tx_callback callback; -+ void *callback_param; -+ unsigned long flags; -+ u32 hist_status; -+ -+ dump_pxp_reg(pxp); -+ -+ hist_status = -+ __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS; -+ -+ __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR); -+ -+ spin_lock_irqsave(&pxp->lock, flags); -+ -+ if (list_empty(&head)) { -+ pxp->pxp_ongoing = 0; -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ return IRQ_NONE; -+ } -+ -+ /* Get descriptor and call callback */ -+ desc = list_entry(head.next, struct pxp_tx_desc, list); -+ pxp_chan = to_pxp_channel(desc->txd.chan); -+ -+ pxp_chan->completed = desc->txd.cookie; -+ -+ callback = desc->txd.callback; -+ callback_param = desc->txd.callback_param; -+ -+ /* Send histogram status back to caller */ -+ desc->hist_status = hist_status; -+ -+ if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback) -+ callback(callback_param); -+ -+ pxp_chan->status = PXP_CHANNEL_INITIALIZED; -+ -+ list_for_each_entry_safe(child, _child, &desc->tx_list, list) { -+ list_del_init(&child->list); -+ kmem_cache_free(tx_desc_cache, (void *)child); -+ } -+ list_del_init(&desc->list); -+ kmem_cache_free(tx_desc_cache, (void *)desc); -+ -+ complete(&pxp->complete); -+ pxp->pxp_ongoing = 0; -+ mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms)); -+ -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ -+ return IRQ_HANDLED; -+} -+ -+/* allocate/free dma tx descriptor dynamically*/ -+static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan) -+{ -+ struct pxp_tx_desc *desc = NULL; -+ struct dma_async_tx_descriptor *txd = NULL; -+ -+ desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO); -+ if (desc == NULL) -+ return NULL; -+ -+ INIT_LIST_HEAD(&desc->list); -+ INIT_LIST_HEAD(&desc->tx_list); -+ txd = &desc->txd; -+ dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan); -+ txd->tx_submit = pxp_tx_submit; -+ -+ return desc; -+} -+ -+/* Allocate and initialise a transfer descriptor. */ -+static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan, -+ struct scatterlist -+ *sgl, -+ unsigned int sg_len, -+ enum -+ dma_transfer_direction -+ direction, -+ unsigned long tx_flags, -+ void *context) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); -+ struct pxps *pxp = to_pxp(pxp_dma); -+ struct pxp_tx_desc *desc = NULL; -+ struct pxp_tx_desc *first = NULL, *prev = NULL; -+ struct scatterlist *sg; -+ dma_addr_t phys_addr; -+ int i; -+ -+ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { -+ dev_err(chan->device->dev, "Invalid DMA direction %d!\n", -+ direction); -+ return NULL; -+ } -+ -+ if (unlikely(sg_len < 2)) -+ return NULL; -+ -+ for_each_sg(sgl, sg, sg_len, i) { -+ desc = pxpdma_desc_alloc(pxp_chan); -+ if (!desc) { -+ dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n"); -+ return NULL; -+ } -+ -+ phys_addr = sg_dma_address(sg); -+ -+ if (!first) { -+ first = desc; -+ -+ desc->layer_param.s0_param.paddr = phys_addr; -+ } else { -+ list_add_tail(&desc->list, &first->tx_list); -+ prev->next = desc; -+ desc->next = NULL; -+ -+ if (i == 1) -+ desc->layer_param.out_param.paddr = phys_addr; -+ else -+ desc->layer_param.ol_param.paddr = phys_addr; -+ } -+ -+ prev = desc; -+ } -+ -+ pxp->pxp_conf_state.layer_nr = sg_len; -+ first->txd.flags = tx_flags; -+ first->len = sg_len; -+ pr_debug("%s:%d first %p, first->len %d, flags %08x\n", -+ __func__, __LINE__, first, first->len, first->txd.flags); -+ -+ return &first->txd; -+} -+ -+static void pxp_issue_pending(struct dma_chan *chan) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); -+ struct pxps *pxp = to_pxp(pxp_dma); -+ -+ spin_lock(&pxp_chan->lock); -+ -+ if (list_empty(&pxp_chan->queue)) { -+ spin_unlock(&pxp_chan->lock); -+ return; -+ } -+ -+ pxpdma_dequeue(pxp_chan, pxp); -+ pxp_chan->status = PXP_CHANNEL_READY; -+ -+ spin_unlock(&pxp_chan->lock); -+ -+ pxp_clk_enable(pxp); -+ wake_up_interruptible(&pxp->thread_waitq); -+} -+ -+static void __pxp_terminate_all(struct dma_chan *chan) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ -+ pxp_chan->status = PXP_CHANNEL_INITIALIZED; -+} -+ -+static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, -+ unsigned long arg) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ -+ /* Only supports DMA_TERMINATE_ALL */ -+ if (cmd != DMA_TERMINATE_ALL) -+ return -ENXIO; -+ -+ spin_lock(&pxp_chan->lock); -+ __pxp_terminate_all(chan); -+ spin_unlock(&pxp_chan->lock); -+ -+ return 0; -+} -+ -+static int pxp_alloc_chan_resources(struct dma_chan *chan) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); -+ int ret; -+ -+ /* dmaengine.c now guarantees to only offer free channels */ -+ BUG_ON(chan->client_count > 1); -+ WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE); -+ -+ chan->cookie = 1; -+ pxp_chan->completed = -ENXIO; -+ -+ pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id); -+ ret = pxp_init_channel(pxp_dma, pxp_chan); -+ if (ret < 0) -+ goto err_chan; -+ -+ pxp_chan->status = PXP_CHANNEL_INITIALIZED; -+ -+ dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n", -+ chan->chan_id, pxp_chan->eof_irq); -+ -+ return ret; -+ -+err_chan: -+ return ret; -+} -+ -+static void pxp_free_chan_resources(struct dma_chan *chan) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ -+ spin_lock(&pxp_chan->lock); -+ -+ __pxp_terminate_all(chan); -+ -+ pxp_chan->status = PXP_CHANNEL_FREE; -+ -+ spin_unlock(&pxp_chan->lock); -+} -+ -+static enum dma_status pxp_tx_status(struct dma_chan *chan, -+ dma_cookie_t cookie, -+ struct dma_tx_state *txstate) -+{ -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ -+ if (cookie != chan->cookie) -+ return DMA_ERROR; -+ -+ if (txstate) { -+ txstate->last = pxp_chan->completed; -+ txstate->used = chan->cookie; -+ txstate->residue = 0; -+ } -+ return DMA_COMPLETE; -+} -+ -+static int pxp_hw_init(struct pxps *pxp) -+{ -+ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; -+ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; -+ u32 reg_val; -+ -+ /* Pull PxP out of reset */ -+ __raw_writel(0, pxp->base + HW_PXP_CTRL); -+ -+ /* Config defaults */ -+ -+ /* Initialize non-channel-specific PxP parameters */ -+ proc_data->drect.left = proc_data->srect.left = 0; -+ proc_data->drect.top = proc_data->srect.top = 0; -+ proc_data->drect.width = proc_data->srect.width = 0; -+ proc_data->drect.height = proc_data->srect.height = 0; -+ proc_data->scaling = 0; -+ proc_data->hflip = 0; -+ proc_data->vflip = 0; -+ proc_data->rotate = 0; -+ proc_data->bgcolor = 0; -+ -+ /* Initialize S0 channel parameters */ -+ pxp_conf->s0_param.pixel_fmt = pxp_s0_formats[0]; -+ pxp_conf->s0_param.width = 0; -+ pxp_conf->s0_param.height = 0; -+ pxp_conf->s0_param.color_key = -1; -+ pxp_conf->s0_param.color_key_enable = false; -+ -+ /* Initialize OL channel parameters */ -+ pxp_conf->ol_param[0].combine_enable = false; -+ pxp_conf->ol_param[0].width = 0; -+ pxp_conf->ol_param[0].height = 0; -+ pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565; -+ pxp_conf->ol_param[0].color_key_enable = false; -+ pxp_conf->ol_param[0].color_key = -1; -+ pxp_conf->ol_param[0].global_alpha_enable = false; -+ pxp_conf->ol_param[0].global_alpha = 0; -+ pxp_conf->ol_param[0].local_alpha_enable = false; -+ -+ /* Initialize Output channel parameters */ -+ pxp_conf->out_param.width = 0; -+ pxp_conf->out_param.height = 0; -+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565; -+ -+ proc_data->overlay_state = 0; -+ -+ /* Write default h/w config */ -+ pxp_set_ctrl(pxp); -+ pxp_set_s0param(pxp); -+ pxp_set_s0crop(pxp); -+ /* -+ * simply program the ULC to a higher value than the LRC -+ * to avoid any AS pixels to show up in the output buffer. -+ */ -+ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC); -+ pxp_set_olparam(0, pxp); -+ pxp_set_olcolorkey(0, pxp); -+ -+ pxp_set_s0colorkey(pxp); -+ pxp_set_csc(pxp); -+ pxp_set_bg(pxp); -+ pxp_set_lut(pxp); -+ -+ /* One-time histogram configuration */ -+ reg_val = -+ BF_PXP_HIST_CTRL_PANEL_MODE(BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST_CTRL); -+ -+ reg_val = BF_PXP_HIST2_PARAM_VALUE0(0x00) | -+ BF_PXP_HIST2_PARAM_VALUE1(0x00F); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST2_PARAM); -+ -+ reg_val = BF_PXP_HIST4_PARAM_VALUE0(0x00) | -+ BF_PXP_HIST4_PARAM_VALUE1(0x05) | -+ BF_PXP_HIST4_PARAM_VALUE2(0x0A) | BF_PXP_HIST4_PARAM_VALUE3(0x0F); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST4_PARAM); -+ -+ reg_val = BF_PXP_HIST8_PARAM0_VALUE0(0x00) | -+ BF_PXP_HIST8_PARAM0_VALUE1(0x02) | -+ BF_PXP_HIST8_PARAM0_VALUE2(0x04) | BF_PXP_HIST8_PARAM0_VALUE3(0x06); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM0); -+ reg_val = BF_PXP_HIST8_PARAM1_VALUE4(0x09) | -+ BF_PXP_HIST8_PARAM1_VALUE5(0x0B) | -+ BF_PXP_HIST8_PARAM1_VALUE6(0x0D) | BF_PXP_HIST8_PARAM1_VALUE7(0x0F); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM1); -+ -+ reg_val = BF_PXP_HIST16_PARAM0_VALUE0(0x00) | -+ BF_PXP_HIST16_PARAM0_VALUE1(0x01) | -+ BF_PXP_HIST16_PARAM0_VALUE2(0x02) | -+ BF_PXP_HIST16_PARAM0_VALUE3(0x03); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM0); -+ reg_val = BF_PXP_HIST16_PARAM1_VALUE4(0x04) | -+ BF_PXP_HIST16_PARAM1_VALUE5(0x05) | -+ BF_PXP_HIST16_PARAM1_VALUE6(0x06) | -+ BF_PXP_HIST16_PARAM1_VALUE7(0x07); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM1); -+ reg_val = BF_PXP_HIST16_PARAM2_VALUE8(0x08) | -+ BF_PXP_HIST16_PARAM2_VALUE9(0x09) | -+ BF_PXP_HIST16_PARAM2_VALUE10(0x0A) | -+ BF_PXP_HIST16_PARAM2_VALUE11(0x0B); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM2); -+ reg_val = BF_PXP_HIST16_PARAM3_VALUE12(0x0C) | -+ BF_PXP_HIST16_PARAM3_VALUE13(0x0D) | -+ BF_PXP_HIST16_PARAM3_VALUE14(0x0E) | -+ BF_PXP_HIST16_PARAM3_VALUE15(0x0F); -+ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM3); -+ -+ return 0; -+} -+ -+static int pxp_dma_init(struct pxps *pxp) -+{ -+ struct pxp_dma *pxp_dma = &pxp->pxp_dma; -+ struct dma_device *dma = &pxp_dma->dma; -+ int i; -+ -+ dma_cap_set(DMA_SLAVE, dma->cap_mask); -+ dma_cap_set(DMA_PRIVATE, dma->cap_mask); -+ -+ /* Compulsory common fields */ -+ dma->dev = pxp->dev; -+ dma->device_alloc_chan_resources = pxp_alloc_chan_resources; -+ dma->device_free_chan_resources = pxp_free_chan_resources; -+ dma->device_tx_status = pxp_tx_status; -+ dma->device_issue_pending = pxp_issue_pending; -+ -+ /* Compulsory for DMA_SLAVE fields */ -+ dma->device_prep_slave_sg = pxp_prep_slave_sg; -+ dma->device_control = pxp_control; -+ -+ /* Initialize PxP Channels */ -+ INIT_LIST_HEAD(&dma->channels); -+ for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) { -+ struct pxp_channel *pxp_chan = pxp->channel + i; -+ struct dma_chan *dma_chan = &pxp_chan->dma_chan; -+ -+ spin_lock_init(&pxp_chan->lock); -+ -+ /* Only one EOF IRQ for PxP, shared by all channels */ -+ pxp_chan->eof_irq = pxp->irq; -+ pxp_chan->status = PXP_CHANNEL_FREE; -+ pxp_chan->completed = -ENXIO; -+ snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name), -+ "PXP EOF %d", i); -+ -+ dma_chan->device = &pxp_dma->dma; -+ dma_chan->cookie = 1; -+ dma_chan->chan_id = i; -+ list_add_tail(&dma_chan->device_node, &dma->channels); -+ } -+ -+ return dma_async_device_register(&pxp_dma->dma); -+} -+ -+static ssize_t clk_off_timeout_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "%d\n", timeout_in_ms); -+} -+ -+static ssize_t clk_off_timeout_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int val; -+ if (sscanf(buf, "%d", &val) > 0) { -+ timeout_in_ms = val; -+ return count; -+ } -+ return -EINVAL; -+} -+ -+static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show, -+ clk_off_timeout_store); -+ -+static ssize_t block_size_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ return sprintf(buf, "%d\n", block_size); -+} -+ -+static ssize_t block_size_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ char **last = NULL; -+ -+ block_size = simple_strtoul(buf, last, 0); -+ if (block_size > 1) -+ block_size = 1; -+ -+ return count; -+} -+static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO, -+ block_size_show, block_size_store); -+ -+static const struct of_device_id imx_pxpdma_dt_ids[] = { -+ { .compatible = "fsl,imx6dl-pxp-dma", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids); -+ -+static int has_pending_task(struct pxps *pxp, struct pxp_channel *task) -+{ -+ int found; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&pxp->lock, flags); -+ found = !list_empty(&head); -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ -+ return found; -+} -+ -+static int pxp_dispatch_thread(void *argv) -+{ -+ struct pxps *pxp = (struct pxps *)argv; -+ struct pxp_channel *pending = NULL; -+ unsigned long flags; -+ -+ while (!kthread_should_stop()) { -+ int ret; -+ ret = wait_event_interruptible(pxp->thread_waitq, -+ has_pending_task(pxp, pending)); -+ if (signal_pending(current)) -+ continue; -+ -+ if (kthread_should_stop()) -+ break; -+ -+ spin_lock_irqsave(&pxp->lock, flags); -+ pxp->pxp_ongoing = 1; -+ spin_unlock_irqrestore(&pxp->lock, flags); -+ init_completion(&pxp->complete); -+ pxpdma_dostart_work(pxp); -+ ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ); -+ if (ret == 0) { -+ printk(KERN_EMERG "%s: task is timeout\n\n", __func__); -+ break; -+ } -+ } -+ -+ return 0; -+} -+ -+static int pxp_probe(struct platform_device *pdev) -+{ -+ struct pxps *pxp; -+ struct resource *res; -+ int irq; -+ int err = 0; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ irq = platform_get_irq(pdev, 0); -+ if (!res || irq < 0) { -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL); -+ if (!pxp) { -+ dev_err(&pdev->dev, "failed to allocate control object\n"); -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ pxp->dev = &pdev->dev; -+ -+ platform_set_drvdata(pdev, pxp); -+ pxp->irq = irq; -+ -+ pxp->pxp_ongoing = 0; -+ pxp->lut_state = 0; -+ -+ spin_lock_init(&pxp->lock); -+ mutex_init(&pxp->clk_mutex); -+ -+ pxp->base = devm_request_and_ioremap(&pdev->dev, res); -+ if (pxp->base == NULL) { -+ dev_err(&pdev->dev, "Couldn't ioremap regs\n"); -+ err = -ENODEV; -+ goto exit; -+ } -+ -+ pxp->pdev = pdev; -+ -+ pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi"); -+ clk_prepare_enable(pxp->clk); -+ -+ err = pxp_hw_init(pxp); -+ clk_disable_unprepare(pxp->clk); -+ if (err) { -+ dev_err(&pdev->dev, "failed to initialize hardware\n"); -+ goto exit; -+ } -+ -+ err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0, -+ "pxp-dmaengine", pxp); -+ if (err) -+ goto exit; -+ /* Initialize DMA engine */ -+ err = pxp_dma_init(pxp); -+ if (err < 0) -+ goto exit; -+ -+ if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) { -+ dev_err(&pdev->dev, -+ "Unable to create file from clk_off_timeout\n"); -+ goto exit; -+ } -+ -+ device_create_file(&pdev->dev, &dev_attr_block_size); -+ dump_pxp_reg(pxp); -+ -+ INIT_WORK(&pxp->work, clkoff_callback); -+ init_timer(&pxp->clk_timer); -+ pxp->clk_timer.function = pxp_clkoff_timer; -+ pxp->clk_timer.data = (unsigned long)pxp; -+ -+ /* allocate a kernel thread to dispatch pxp conf */ -+ pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch"); -+ if (IS_ERR(pxp->dispatch)) { -+ err = PTR_ERR(pxp->dispatch); -+ goto exit; -+ } -+ init_waitqueue_head(&pxp->thread_waitq); -+ tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc), -+ 0, SLAB_HWCACHE_ALIGN, NULL); -+ if (!tx_desc_cache) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ register_pxp_device(); -+ -+exit: -+ if (err) -+ dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n"); -+ return err; -+} -+ -+static int pxp_remove(struct platform_device *pdev) -+{ -+ struct pxps *pxp = platform_get_drvdata(pdev); -+ -+ unregister_pxp_device(); -+ kmem_cache_destroy(tx_desc_cache); -+ kthread_stop(pxp->dispatch); -+ cancel_work_sync(&pxp->work); -+ del_timer_sync(&pxp->clk_timer); -+ clk_disable_unprepare(pxp->clk); -+ device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout); -+ device_remove_file(&pdev->dev, &dev_attr_block_size); -+ dma_async_device_unregister(&(pxp->pxp_dma.dma)); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int pxp_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ struct pxps *pxp = platform_get_drvdata(pdev); -+ -+ pxp_clk_enable(pxp); -+ while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE) -+ ; -+ -+ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL); -+ pxp_clk_disable(pxp); -+ -+ return 0; -+} -+ -+static int pxp_resume(struct platform_device *pdev) -+{ -+ struct pxps *pxp = platform_get_drvdata(pdev); -+ -+ pxp_clk_enable(pxp); -+ /* Pull PxP out of reset */ -+ __raw_writel(0, pxp->base + HW_PXP_CTRL); -+ pxp_clk_disable(pxp); -+ -+ return 0; -+} -+#else -+#define pxp_suspend NULL -+#define pxp_resume NULL -+#endif -+ -+static struct platform_driver pxp_driver = { -+ .driver = { -+ .name = "imx-pxp", -+ .of_match_table = of_match_ptr(imx_pxpdma_dt_ids), -+ }, -+ .probe = pxp_probe, -+ .remove = pxp_remove, -+ .suspend = pxp_suspend, -+ .resume = pxp_resume, -+}; -+ -+module_platform_driver(pxp_driver); -+ -+ -+MODULE_DESCRIPTION("i.MX PxP driver"); -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/dma/pxp/regs-pxp_v2.h linux-3.14.22/drivers/dma/pxp/regs-pxp_v2.h ---- linux-3.14.22.orig/drivers/dma/pxp/regs-pxp_v2.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/dma/pxp/regs-pxp_v2.h 2014-10-22 14:55:52.050220001 -0500 -@@ -0,0 +1,1152 @@ -+/* -+ * Freescale PXP Register Definitions -+ * -+ * Copyright (C) 2012-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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ * This file is created by xml file. Don't Edit it. -+ * -+ * Xml Revision: 1.29 -+ * Template revision: 1.3 -+ */ -+ -+#ifndef __ARCH_ARM___PXP_H -+#define __ARCH_ARM___PXP_H -+ -+#define HW_PXP_CTRL (0x00000000) -+#define HW_PXP_CTRL_SET (0x00000004) -+#define HW_PXP_CTRL_CLR (0x00000008) -+#define HW_PXP_CTRL_TOG (0x0000000c) -+ -+#define BM_PXP_CTRL_SFTRST 0x80000000 -+#define BM_PXP_CTRL_CLKGATE 0x40000000 -+#define BM_PXP_CTRL_RSVD4 0x20000000 -+#define BM_PXP_CTRL_EN_REPEAT 0x10000000 -+#define BP_PXP_CTRL_RSVD3 26 -+#define BM_PXP_CTRL_RSVD3 0x0C000000 -+#define BF_PXP_CTRL_RSVD3(v) \ -+ (((v) << 26) & BM_PXP_CTRL_RSVD3) -+#define BP_PXP_CTRL_INTERLACED_INPUT 24 -+#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000 -+#define BF_PXP_CTRL_INTERLACED_INPUT(v) \ -+ (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT) -+#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0 -+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0 0x2 -+#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1 0x3 -+#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000 -+#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0 -+#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1 -+#define BM_PXP_CTRL_ROT_POS 0x00400000 -+#define BM_PXP_CTRL_IN_PLACE 0x00200000 -+#define BP_PXP_CTRL_RSVD1 12 -+#define BM_PXP_CTRL_RSVD1 0x001FF000 -+#define BF_PXP_CTRL_RSVD1(v) \ -+ (((v) << 12) & BM_PXP_CTRL_RSVD1) -+#define BM_PXP_CTRL_VFLIP 0x00000800 -+#define BM_PXP_CTRL_HFLIP 0x00000400 -+#define BP_PXP_CTRL_ROTATE 8 -+#define BM_PXP_CTRL_ROTATE 0x00000300 -+#define BF_PXP_CTRL_ROTATE(v) \ -+ (((v) << 8) & BM_PXP_CTRL_ROTATE) -+#define BV_PXP_CTRL_ROTATE__ROT_0 0x0 -+#define BV_PXP_CTRL_ROTATE__ROT_90 0x1 -+#define BV_PXP_CTRL_ROTATE__ROT_180 0x2 -+#define BV_PXP_CTRL_ROTATE__ROT_270 0x3 -+#define BP_PXP_CTRL_RSVD0 5 -+#define BM_PXP_CTRL_RSVD0 0x000000E0 -+#define BF_PXP_CTRL_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_CTRL_RSVD0) -+#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010 -+#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008 -+#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004 -+#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002 -+#define BM_PXP_CTRL_ENABLE 0x00000001 -+ -+#define HW_PXP_STAT (0x00000010) -+#define HW_PXP_STAT_SET (0x00000014) -+#define HW_PXP_STAT_CLR (0x00000018) -+#define HW_PXP_STAT_TOG (0x0000001c) -+ -+#define BP_PXP_STAT_BLOCKX 24 -+#define BM_PXP_STAT_BLOCKX 0xFF000000 -+#define BF_PXP_STAT_BLOCKX(v) \ -+ (((v) << 24) & BM_PXP_STAT_BLOCKX) -+#define BP_PXP_STAT_BLOCKY 16 -+#define BM_PXP_STAT_BLOCKY 0x00FF0000 -+#define BF_PXP_STAT_BLOCKY(v) \ -+ (((v) << 16) & BM_PXP_STAT_BLOCKY) -+#define BP_PXP_STAT_RSVD2 9 -+#define BM_PXP_STAT_RSVD2 0x0000FE00 -+#define BF_PXP_STAT_RSVD2(v) \ -+ (((v) << 9) & BM_PXP_STAT_RSVD2) -+#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100 -+#define BP_PXP_STAT_AXI_ERROR_ID 4 -+#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0 -+#define BF_PXP_STAT_AXI_ERROR_ID(v) \ -+ (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID) -+#define BM_PXP_STAT_NEXT_IRQ 0x00000008 -+#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004 -+#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002 -+#define BM_PXP_STAT_IRQ 0x00000001 -+ -+#define HW_PXP_OUT_CTRL (0x00000020) -+#define HW_PXP_OUT_CTRL_SET (0x00000024) -+#define HW_PXP_OUT_CTRL_CLR (0x00000028) -+#define HW_PXP_OUT_CTRL_TOG (0x0000002c) -+ -+#define BP_PXP_OUT_CTRL_ALPHA 24 -+#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000 -+#define BF_PXP_OUT_CTRL_ALPHA(v) \ -+ (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA) -+#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000 -+#define BP_PXP_OUT_CTRL_RSVD1 10 -+#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00 -+#define BF_PXP_OUT_CTRL_RSVD1(v) \ -+ (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1) -+#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8 -+#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300 -+#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \ -+ (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT) -+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0 -+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1 -+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2 -+#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3 -+#define BP_PXP_OUT_CTRL_RSVD0 5 -+#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0 -+#define BF_PXP_OUT_CTRL_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0) -+#define BP_PXP_OUT_CTRL_FORMAT 0 -+#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F -+#define BF_PXP_OUT_CTRL_FORMAT(v) \ -+ (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT) -+#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0 -+#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4 -+#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5 -+#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8 -+#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9 -+#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC -+#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD -+#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE -+#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10 -+#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12 -+#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13 -+#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14 -+#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15 -+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18 -+#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19 -+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A -+#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B -+ -+#define HW_PXP_OUT_BUF (0x00000030) -+ -+#define BP_PXP_OUT_BUF_ADDR 0 -+#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF -+#define BF_PXP_OUT_BUF_ADDR(v) (v) -+ -+#define HW_PXP_OUT_BUF2 (0x00000040) -+ -+#define BP_PXP_OUT_BUF2_ADDR 0 -+#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF -+#define BF_PXP_OUT_BUF2_ADDR(v) (v) -+ -+#define HW_PXP_OUT_PITCH (0x00000050) -+ -+#define BP_PXP_OUT_PITCH_RSVD 16 -+#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000 -+#define BF_PXP_OUT_PITCH_RSVD(v) \ -+ (((v) << 16) & BM_PXP_OUT_PITCH_RSVD) -+#define BP_PXP_OUT_PITCH_PITCH 0 -+#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF -+#define BF_PXP_OUT_PITCH_PITCH(v) \ -+ (((v) << 0) & BM_PXP_OUT_PITCH_PITCH) -+ -+#define HW_PXP_OUT_LRC (0x00000060) -+ -+#define BP_PXP_OUT_LRC_RSVD1 30 -+#define BM_PXP_OUT_LRC_RSVD1 0xC0000000 -+#define BF_PXP_OUT_LRC_RSVD1(v) \ -+ (((v) << 30) & BM_PXP_OUT_LRC_RSVD1) -+#define BP_PXP_OUT_LRC_X 16 -+#define BM_PXP_OUT_LRC_X 0x3FFF0000 -+#define BF_PXP_OUT_LRC_X(v) \ -+ (((v) << 16) & BM_PXP_OUT_LRC_X) -+#define BP_PXP_OUT_LRC_RSVD0 14 -+#define BM_PXP_OUT_LRC_RSVD0 0x0000C000 -+#define BF_PXP_OUT_LRC_RSVD0(v) \ -+ (((v) << 14) & BM_PXP_OUT_LRC_RSVD0) -+#define BP_PXP_OUT_LRC_Y 0 -+#define BM_PXP_OUT_LRC_Y 0x00003FFF -+#define BF_PXP_OUT_LRC_Y(v) \ -+ (((v) << 0) & BM_PXP_OUT_LRC_Y) -+ -+#define HW_PXP_OUT_PS_ULC (0x00000070) -+ -+#define BP_PXP_OUT_PS_ULC_RSVD1 30 -+#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000 -+#define BF_PXP_OUT_PS_ULC_RSVD1(v) \ -+ (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1) -+#define BP_PXP_OUT_PS_ULC_X 16 -+#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000 -+#define BF_PXP_OUT_PS_ULC_X(v) \ -+ (((v) << 16) & BM_PXP_OUT_PS_ULC_X) -+#define BP_PXP_OUT_PS_ULC_RSVD0 14 -+#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000 -+#define BF_PXP_OUT_PS_ULC_RSVD0(v) \ -+ (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0) -+#define BP_PXP_OUT_PS_ULC_Y 0 -+#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF -+#define BF_PXP_OUT_PS_ULC_Y(v) \ -+ (((v) << 0) & BM_PXP_OUT_PS_ULC_Y) -+ -+#define HW_PXP_OUT_PS_LRC (0x00000080) -+ -+#define BP_PXP_OUT_PS_LRC_RSVD1 30 -+#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000 -+#define BF_PXP_OUT_PS_LRC_RSVD1(v) \ -+ (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1) -+#define BP_PXP_OUT_PS_LRC_X 16 -+#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000 -+#define BF_PXP_OUT_PS_LRC_X(v) \ -+ (((v) << 16) & BM_PXP_OUT_PS_LRC_X) -+#define BP_PXP_OUT_PS_LRC_RSVD0 14 -+#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000 -+#define BF_PXP_OUT_PS_LRC_RSVD0(v) \ -+ (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0) -+#define BP_PXP_OUT_PS_LRC_Y 0 -+#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF -+#define BF_PXP_OUT_PS_LRC_Y(v) \ -+ (((v) << 0) & BM_PXP_OUT_PS_LRC_Y) -+ -+#define HW_PXP_OUT_AS_ULC (0x00000090) -+ -+#define BP_PXP_OUT_AS_ULC_RSVD1 30 -+#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000 -+#define BF_PXP_OUT_AS_ULC_RSVD1(v) \ -+ (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1) -+#define BP_PXP_OUT_AS_ULC_X 16 -+#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000 -+#define BF_PXP_OUT_AS_ULC_X(v) \ -+ (((v) << 16) & BM_PXP_OUT_AS_ULC_X) -+#define BP_PXP_OUT_AS_ULC_RSVD0 14 -+#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000 -+#define BF_PXP_OUT_AS_ULC_RSVD0(v) \ -+ (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0) -+#define BP_PXP_OUT_AS_ULC_Y 0 -+#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF -+#define BF_PXP_OUT_AS_ULC_Y(v) \ -+ (((v) << 0) & BM_PXP_OUT_AS_ULC_Y) -+ -+#define HW_PXP_OUT_AS_LRC (0x000000a0) -+ -+#define BP_PXP_OUT_AS_LRC_RSVD1 30 -+#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000 -+#define BF_PXP_OUT_AS_LRC_RSVD1(v) \ -+ (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1) -+#define BP_PXP_OUT_AS_LRC_X 16 -+#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000 -+#define BF_PXP_OUT_AS_LRC_X(v) \ -+ (((v) << 16) & BM_PXP_OUT_AS_LRC_X) -+#define BP_PXP_OUT_AS_LRC_RSVD0 14 -+#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000 -+#define BF_PXP_OUT_AS_LRC_RSVD0(v) \ -+ (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0) -+#define BP_PXP_OUT_AS_LRC_Y 0 -+#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF -+#define BF_PXP_OUT_AS_LRC_Y(v) \ -+ (((v) << 0) & BM_PXP_OUT_AS_LRC_Y) -+ -+#define HW_PXP_PS_CTRL (0x000000b0) -+#define HW_PXP_PS_CTRL_SET (0x000000b4) -+#define HW_PXP_PS_CTRL_CLR (0x000000b8) -+#define HW_PXP_PS_CTRL_TOG (0x000000bc) -+ -+#define BP_PXP_PS_CTRL_RSVD1 12 -+#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000 -+#define BF_PXP_PS_CTRL_RSVD1(v) \ -+ (((v) << 12) & BM_PXP_PS_CTRL_RSVD1) -+#define BP_PXP_PS_CTRL_DECX 10 -+#define BM_PXP_PS_CTRL_DECX 0x00000C00 -+#define BF_PXP_PS_CTRL_DECX(v) \ -+ (((v) << 10) & BM_PXP_PS_CTRL_DECX) -+#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0 -+#define BV_PXP_PS_CTRL_DECX__DECX2 0x1 -+#define BV_PXP_PS_CTRL_DECX__DECX4 0x2 -+#define BV_PXP_PS_CTRL_DECX__DECX8 0x3 -+#define BP_PXP_PS_CTRL_DECY 8 -+#define BM_PXP_PS_CTRL_DECY 0x00000300 -+#define BF_PXP_PS_CTRL_DECY(v) \ -+ (((v) << 8) & BM_PXP_PS_CTRL_DECY) -+#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0 -+#define BV_PXP_PS_CTRL_DECY__DECY2 0x1 -+#define BV_PXP_PS_CTRL_DECY__DECY4 0x2 -+#define BV_PXP_PS_CTRL_DECY__DECY8 0x3 -+#define BP_PXP_PS_CTRL_SWAP 5 -+#define BM_PXP_PS_CTRL_SWAP 0x000000E0 -+#define BF_PXP_PS_CTRL_SWAP(v) \ -+ (((v) << 5) & BM_PXP_PS_CTRL_SWAP) -+#define BP_PXP_PS_CTRL_FORMAT 0 -+#define BM_PXP_PS_CTRL_FORMAT 0x0000001F -+#define BF_PXP_PS_CTRL_FORMAT(v) \ -+ (((v) << 0) & BM_PXP_PS_CTRL_FORMAT) -+#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4 -+#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC -+#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD -+#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE -+#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10 -+#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12 -+#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13 -+#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14 -+#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15 -+#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18 -+#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19 -+#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A -+#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B -+#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E -+#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F -+ -+#define HW_PXP_PS_BUF (0x000000c0) -+ -+#define BP_PXP_PS_BUF_ADDR 0 -+#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF -+#define BF_PXP_PS_BUF_ADDR(v) (v) -+ -+#define HW_PXP_PS_UBUF (0x000000d0) -+ -+#define BP_PXP_PS_UBUF_ADDR 0 -+#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF -+#define BF_PXP_PS_UBUF_ADDR(v) (v) -+ -+#define HW_PXP_PS_VBUF (0x000000e0) -+ -+#define BP_PXP_PS_VBUF_ADDR 0 -+#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF -+#define BF_PXP_PS_VBUF_ADDR(v) (v) -+ -+#define HW_PXP_PS_PITCH (0x000000f0) -+ -+#define BP_PXP_PS_PITCH_RSVD 16 -+#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000 -+#define BF_PXP_PS_PITCH_RSVD(v) \ -+ (((v) << 16) & BM_PXP_PS_PITCH_RSVD) -+#define BP_PXP_PS_PITCH_PITCH 0 -+#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF -+#define BF_PXP_PS_PITCH_PITCH(v) \ -+ (((v) << 0) & BM_PXP_PS_PITCH_PITCH) -+ -+#define HW_PXP_PS_BACKGROUND (0x00000100) -+ -+#define BP_PXP_PS_BACKGROUND_RSVD 24 -+#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000 -+#define BF_PXP_PS_BACKGROUND_RSVD(v) \ -+ (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD) -+#define BP_PXP_PS_BACKGROUND_COLOR 0 -+#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF -+#define BF_PXP_PS_BACKGROUND_COLOR(v) \ -+ (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR) -+ -+#define HW_PXP_PS_SCALE (0x00000110) -+ -+#define BM_PXP_PS_SCALE_RSVD2 0x80000000 -+#define BP_PXP_PS_SCALE_YSCALE 16 -+#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000 -+#define BF_PXP_PS_SCALE_YSCALE(v) \ -+ (((v) << 16) & BM_PXP_PS_SCALE_YSCALE) -+#define BM_PXP_PS_SCALE_RSVD1 0x00008000 -+#define BP_PXP_PS_SCALE_XSCALE 0 -+#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF -+#define BF_PXP_PS_SCALE_XSCALE(v) \ -+ (((v) << 0) & BM_PXP_PS_SCALE_XSCALE) -+ -+#define HW_PXP_PS_OFFSET (0x00000120) -+ -+#define BP_PXP_PS_OFFSET_RSVD2 28 -+#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000 -+#define BF_PXP_PS_OFFSET_RSVD2(v) \ -+ (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2) -+#define BP_PXP_PS_OFFSET_YOFFSET 16 -+#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000 -+#define BF_PXP_PS_OFFSET_YOFFSET(v) \ -+ (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET) -+#define BP_PXP_PS_OFFSET_RSVD1 12 -+#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000 -+#define BF_PXP_PS_OFFSET_RSVD1(v) \ -+ (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1) -+#define BP_PXP_PS_OFFSET_XOFFSET 0 -+#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF -+#define BF_PXP_PS_OFFSET_XOFFSET(v) \ -+ (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET) -+ -+#define HW_PXP_PS_CLRKEYLOW (0x00000130) -+ -+#define BP_PXP_PS_CLRKEYLOW_RSVD1 24 -+#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000 -+#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \ -+ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1) -+#define BP_PXP_PS_CLRKEYLOW_PIXEL 0 -+#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF -+#define BF_PXP_PS_CLRKEYLOW_PIXEL(v) \ -+ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL) -+ -+#define HW_PXP_PS_CLRKEYHIGH (0x00000140) -+ -+#define BP_PXP_PS_CLRKEYHIGH_RSVD1 24 -+#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000 -+#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \ -+ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1) -+#define BP_PXP_PS_CLRKEYHIGH_PIXEL 0 -+#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF -+#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v) \ -+ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL) -+ -+#define HW_PXP_AS_CTRL (0x00000150) -+ -+#define BP_PXP_AS_CTRL_RSVD1 21 -+#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000 -+#define BF_PXP_AS_CTRL_RSVD1(v) \ -+ (((v) << 21) & BM_PXP_AS_CTRL_RSVD1) -+#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000 -+#define BP_PXP_AS_CTRL_ROP 16 -+#define BM_PXP_AS_CTRL_ROP 0x000F0000 -+#define BF_PXP_AS_CTRL_ROP(v) \ -+ (((v) << 16) & BM_PXP_AS_CTRL_ROP) -+#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0 -+#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1 -+#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2 -+#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3 -+#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4 -+#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5 -+#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6 -+#define BV_PXP_AS_CTRL_ROP__NOT 0x7 -+#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8 -+#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9 -+#define BV_PXP_AS_CTRL_ROP__XORAS 0xA -+#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB -+#define BP_PXP_AS_CTRL_ALPHA 8 -+#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00 -+#define BF_PXP_AS_CTRL_ALPHA(v) \ -+ (((v) << 8) & BM_PXP_AS_CTRL_ALPHA) -+#define BP_PXP_AS_CTRL_FORMAT 4 -+#define BM_PXP_AS_CTRL_FORMAT 0x000000F0 -+#define BF_PXP_AS_CTRL_FORMAT(v) \ -+ (((v) << 4) & BM_PXP_AS_CTRL_FORMAT) -+#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0 -+#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4 -+#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8 -+#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9 -+#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC -+#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD -+#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE -+#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008 -+#define BP_PXP_AS_CTRL_ALPHA_CTRL 1 -+#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006 -+#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \ -+ (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL) -+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0 -+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1 -+#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2 -+#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3 -+#define BM_PXP_AS_CTRL_RSVD0 0x00000001 -+ -+#define HW_PXP_AS_BUF (0x00000160) -+ -+#define BP_PXP_AS_BUF_ADDR 0 -+#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF -+#define BF_PXP_AS_BUF_ADDR(v) (v) -+ -+#define HW_PXP_AS_PITCH (0x00000170) -+ -+#define BP_PXP_AS_PITCH_RSVD 16 -+#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000 -+#define BF_PXP_AS_PITCH_RSVD(v) \ -+ (((v) << 16) & BM_PXP_AS_PITCH_RSVD) -+#define BP_PXP_AS_PITCH_PITCH 0 -+#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF -+#define BF_PXP_AS_PITCH_PITCH(v) \ -+ (((v) << 0) & BM_PXP_AS_PITCH_PITCH) -+ -+#define HW_PXP_AS_CLRKEYLOW (0x00000180) -+ -+#define BP_PXP_AS_CLRKEYLOW_RSVD1 24 -+#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000 -+#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \ -+ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1) -+#define BP_PXP_AS_CLRKEYLOW_PIXEL 0 -+#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF -+#define BF_PXP_AS_CLRKEYLOW_PIXEL(v) \ -+ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL) -+ -+#define HW_PXP_AS_CLRKEYHIGH (0x00000190) -+ -+#define BP_PXP_AS_CLRKEYHIGH_RSVD1 24 -+#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000 -+#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \ -+ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1) -+#define BP_PXP_AS_CLRKEYHIGH_PIXEL 0 -+#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF -+#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v) \ -+ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL) -+ -+#define HW_PXP_CSC1_COEF0 (0x000001a0) -+ -+#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000 -+#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000 -+#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000 -+#define BP_PXP_CSC1_COEF0_C0 18 -+#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000 -+#define BF_PXP_CSC1_COEF0_C0(v) \ -+ (((v) << 18) & BM_PXP_CSC1_COEF0_C0) -+#define BP_PXP_CSC1_COEF0_UV_OFFSET 9 -+#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00 -+#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \ -+ (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET) -+#define BP_PXP_CSC1_COEF0_Y_OFFSET 0 -+#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF -+#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \ -+ (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET) -+ -+#define HW_PXP_CSC1_COEF1 (0x000001b0) -+ -+#define BP_PXP_CSC1_COEF1_RSVD1 27 -+#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000 -+#define BF_PXP_CSC1_COEF1_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1) -+#define BP_PXP_CSC1_COEF1_C1 16 -+#define BM_PXP_CSC1_COEF1_C1 0x07FF0000 -+#define BF_PXP_CSC1_COEF1_C1(v) \ -+ (((v) << 16) & BM_PXP_CSC1_COEF1_C1) -+#define BP_PXP_CSC1_COEF1_RSVD0 11 -+#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800 -+#define BF_PXP_CSC1_COEF1_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0) -+#define BP_PXP_CSC1_COEF1_C4 0 -+#define BM_PXP_CSC1_COEF1_C4 0x000007FF -+#define BF_PXP_CSC1_COEF1_C4(v) \ -+ (((v) << 0) & BM_PXP_CSC1_COEF1_C4) -+ -+#define HW_PXP_CSC1_COEF2 (0x000001c0) -+ -+#define BP_PXP_CSC1_COEF2_RSVD1 27 -+#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000 -+#define BF_PXP_CSC1_COEF2_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1) -+#define BP_PXP_CSC1_COEF2_C2 16 -+#define BM_PXP_CSC1_COEF2_C2 0x07FF0000 -+#define BF_PXP_CSC1_COEF2_C2(v) \ -+ (((v) << 16) & BM_PXP_CSC1_COEF2_C2) -+#define BP_PXP_CSC1_COEF2_RSVD0 11 -+#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800 -+#define BF_PXP_CSC1_COEF2_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0) -+#define BP_PXP_CSC1_COEF2_C3 0 -+#define BM_PXP_CSC1_COEF2_C3 0x000007FF -+#define BF_PXP_CSC1_COEF2_C3(v) \ -+ (((v) << 0) & BM_PXP_CSC1_COEF2_C3) -+ -+#define HW_PXP_CSC2_CTRL (0x000001d0) -+ -+#define BP_PXP_CSC2_CTRL_RSVD 3 -+#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8 -+#define BF_PXP_CSC2_CTRL_RSVD(v) \ -+ (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD) -+#define BP_PXP_CSC2_CTRL_CSC_MODE 1 -+#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006 -+#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \ -+ (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE) -+#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0 -+#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1 -+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2 -+#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3 -+#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001 -+ -+#define HW_PXP_CSC2_COEF0 (0x000001e0) -+ -+#define BP_PXP_CSC2_COEF0_RSVD1 27 -+#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000 -+#define BF_PXP_CSC2_COEF0_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1) -+#define BP_PXP_CSC2_COEF0_A2 16 -+#define BM_PXP_CSC2_COEF0_A2 0x07FF0000 -+#define BF_PXP_CSC2_COEF0_A2(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF0_A2) -+#define BP_PXP_CSC2_COEF0_RSVD0 11 -+#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800 -+#define BF_PXP_CSC2_COEF0_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0) -+#define BP_PXP_CSC2_COEF0_A1 0 -+#define BM_PXP_CSC2_COEF0_A1 0x000007FF -+#define BF_PXP_CSC2_COEF0_A1(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF0_A1) -+ -+#define HW_PXP_CSC2_COEF1 (0x000001f0) -+ -+#define BP_PXP_CSC2_COEF1_RSVD1 27 -+#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000 -+#define BF_PXP_CSC2_COEF1_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1) -+#define BP_PXP_CSC2_COEF1_B1 16 -+#define BM_PXP_CSC2_COEF1_B1 0x07FF0000 -+#define BF_PXP_CSC2_COEF1_B1(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF1_B1) -+#define BP_PXP_CSC2_COEF1_RSVD0 11 -+#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800 -+#define BF_PXP_CSC2_COEF1_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0) -+#define BP_PXP_CSC2_COEF1_A3 0 -+#define BM_PXP_CSC2_COEF1_A3 0x000007FF -+#define BF_PXP_CSC2_COEF1_A3(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF1_A3) -+ -+#define HW_PXP_CSC2_COEF2 (0x00000200) -+ -+#define BP_PXP_CSC2_COEF2_RSVD1 27 -+#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000 -+#define BF_PXP_CSC2_COEF2_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1) -+#define BP_PXP_CSC2_COEF2_B3 16 -+#define BM_PXP_CSC2_COEF2_B3 0x07FF0000 -+#define BF_PXP_CSC2_COEF2_B3(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF2_B3) -+#define BP_PXP_CSC2_COEF2_RSVD0 11 -+#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800 -+#define BF_PXP_CSC2_COEF2_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0) -+#define BP_PXP_CSC2_COEF2_B2 0 -+#define BM_PXP_CSC2_COEF2_B2 0x000007FF -+#define BF_PXP_CSC2_COEF2_B2(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF2_B2) -+ -+#define HW_PXP_CSC2_COEF3 (0x00000210) -+ -+#define BP_PXP_CSC2_COEF3_RSVD1 27 -+#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000 -+#define BF_PXP_CSC2_COEF3_RSVD1(v) \ -+ (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1) -+#define BP_PXP_CSC2_COEF3_C2 16 -+#define BM_PXP_CSC2_COEF3_C2 0x07FF0000 -+#define BF_PXP_CSC2_COEF3_C2(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF3_C2) -+#define BP_PXP_CSC2_COEF3_RSVD0 11 -+#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800 -+#define BF_PXP_CSC2_COEF3_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0) -+#define BP_PXP_CSC2_COEF3_C1 0 -+#define BM_PXP_CSC2_COEF3_C1 0x000007FF -+#define BF_PXP_CSC2_COEF3_C1(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF3_C1) -+ -+#define HW_PXP_CSC2_COEF4 (0x00000220) -+ -+#define BP_PXP_CSC2_COEF4_RSVD1 25 -+#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000 -+#define BF_PXP_CSC2_COEF4_RSVD1(v) \ -+ (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1) -+#define BP_PXP_CSC2_COEF4_D1 16 -+#define BM_PXP_CSC2_COEF4_D1 0x01FF0000 -+#define BF_PXP_CSC2_COEF4_D1(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF4_D1) -+#define BP_PXP_CSC2_COEF4_RSVD0 11 -+#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800 -+#define BF_PXP_CSC2_COEF4_RSVD0(v) \ -+ (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0) -+#define BP_PXP_CSC2_COEF4_C3 0 -+#define BM_PXP_CSC2_COEF4_C3 0x000007FF -+#define BF_PXP_CSC2_COEF4_C3(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF4_C3) -+ -+#define HW_PXP_CSC2_COEF5 (0x00000230) -+ -+#define BP_PXP_CSC2_COEF5_RSVD1 25 -+#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000 -+#define BF_PXP_CSC2_COEF5_RSVD1(v) \ -+ (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1) -+#define BP_PXP_CSC2_COEF5_D3 16 -+#define BM_PXP_CSC2_COEF5_D3 0x01FF0000 -+#define BF_PXP_CSC2_COEF5_D3(v) \ -+ (((v) << 16) & BM_PXP_CSC2_COEF5_D3) -+#define BP_PXP_CSC2_COEF5_RSVD0 9 -+#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00 -+#define BF_PXP_CSC2_COEF5_RSVD0(v) \ -+ (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0) -+#define BP_PXP_CSC2_COEF5_D2 0 -+#define BM_PXP_CSC2_COEF5_D2 0x000001FF -+#define BF_PXP_CSC2_COEF5_D2(v) \ -+ (((v) << 0) & BM_PXP_CSC2_COEF5_D2) -+ -+#define HW_PXP_LUT_CTRL (0x00000240) -+ -+#define BM_PXP_LUT_CTRL_BYPASS 0x80000000 -+#define BP_PXP_LUT_CTRL_RSVD3 26 -+#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000 -+#define BF_PXP_LUT_CTRL_RSVD3(v) \ -+ (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3) -+#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24 -+#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000 -+#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \ -+ (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE) -+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0 -+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1 -+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2 -+#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3 -+#define BP_PXP_LUT_CTRL_RSVD2 18 -+#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000 -+#define BF_PXP_LUT_CTRL_RSVD2(v) \ -+ (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2) -+#define BP_PXP_LUT_CTRL_OUT_MODE 16 -+#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000 -+#define BF_PXP_LUT_CTRL_OUT_MODE(v) \ -+ (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE) -+#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0 -+#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1 -+#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2 -+#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3 -+#define BP_PXP_LUT_CTRL_RSVD1 11 -+#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800 -+#define BF_PXP_LUT_CTRL_RSVD1(v) \ -+ (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1) -+#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400 -+#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200 -+#define BM_PXP_LUT_CTRL_INVALID 0x00000100 -+#define BP_PXP_LUT_CTRL_RSVD0 1 -+#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE -+#define BF_PXP_LUT_CTRL_RSVD0(v) \ -+ (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0) -+#define BM_PXP_LUT_CTRL_DMA_START 0x00000001 -+ -+#define HW_PXP_LUT_ADDR (0x00000250) -+ -+#define BM_PXP_LUT_ADDR_RSVD2 0x80000000 -+#define BP_PXP_LUT_ADDR_NUM_BYTES 16 -+#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000 -+#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \ -+ (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES) -+#define BP_PXP_LUT_ADDR_RSVD1 14 -+#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000 -+#define BF_PXP_LUT_ADDR_RSVD1(v) \ -+ (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1) -+#define BP_PXP_LUT_ADDR_ADDR 0 -+#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF -+#define BF_PXP_LUT_ADDR_ADDR(v) \ -+ (((v) << 0) & BM_PXP_LUT_ADDR_ADDR) -+ -+#define HW_PXP_LUT_DATA (0x00000260) -+ -+#define BP_PXP_LUT_DATA_DATA 0 -+#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF -+#define BF_PXP_LUT_DATA_DATA(v) (v) -+ -+#define HW_PXP_LUT_EXTMEM (0x00000270) -+ -+#define BP_PXP_LUT_EXTMEM_ADDR 0 -+#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF -+#define BF_PXP_LUT_EXTMEM_ADDR(v) (v) -+ -+#define HW_PXP_CFA (0x00000280) -+ -+#define BP_PXP_CFA_DATA 0 -+#define BM_PXP_CFA_DATA 0xFFFFFFFF -+#define BF_PXP_CFA_DATA(v) (v) -+ -+#define HW_PXP_HIST_CTRL (0x00000290) -+ -+#define BP_PXP_HIST_CTRL_RSVD 6 -+#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0 -+#define BF_PXP_HIST_CTRL_RSVD(v) \ -+ (((v) << 6) & BM_PXP_HIST_CTRL_RSVD) -+#define BP_PXP_HIST_CTRL_PANEL_MODE 4 -+#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030 -+#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \ -+ (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE) -+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4 0x0 -+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8 0x1 -+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2 -+#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3 -+#define BP_PXP_HIST_CTRL_STATUS 0 -+#define BM_PXP_HIST_CTRL_STATUS 0x0000000F -+#define BF_PXP_HIST_CTRL_STATUS(v) \ -+ (((v) << 0) & BM_PXP_HIST_CTRL_STATUS) -+ -+#define HW_PXP_HIST2_PARAM (0x000002a0) -+ -+#define BP_PXP_HIST2_PARAM_RSVD 16 -+#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000 -+#define BF_PXP_HIST2_PARAM_RSVD(v) \ -+ (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD) -+#define BP_PXP_HIST2_PARAM_RSVD1 13 -+#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000 -+#define BF_PXP_HIST2_PARAM_RSVD1(v) \ -+ (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1) -+#define BP_PXP_HIST2_PARAM_VALUE1 8 -+#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00 -+#define BF_PXP_HIST2_PARAM_VALUE1(v) \ -+ (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1) -+#define BP_PXP_HIST2_PARAM_RSVD0 5 -+#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0 -+#define BF_PXP_HIST2_PARAM_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0) -+#define BP_PXP_HIST2_PARAM_VALUE0 0 -+#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F -+#define BF_PXP_HIST2_PARAM_VALUE0(v) \ -+ (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0) -+ -+#define HW_PXP_HIST4_PARAM (0x000002b0) -+ -+#define BP_PXP_HIST4_PARAM_RSVD3 29 -+#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000 -+#define BF_PXP_HIST4_PARAM_RSVD3(v) \ -+ (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3) -+#define BP_PXP_HIST4_PARAM_VALUE3 24 -+#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000 -+#define BF_PXP_HIST4_PARAM_VALUE3(v) \ -+ (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3) -+#define BP_PXP_HIST4_PARAM_RSVD2 21 -+#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000 -+#define BF_PXP_HIST4_PARAM_RSVD2(v) \ -+ (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2) -+#define BP_PXP_HIST4_PARAM_VALUE2 16 -+#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000 -+#define BF_PXP_HIST4_PARAM_VALUE2(v) \ -+ (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2) -+#define BP_PXP_HIST4_PARAM_RSVD1 13 -+#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000 -+#define BF_PXP_HIST4_PARAM_RSVD1(v) \ -+ (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1) -+#define BP_PXP_HIST4_PARAM_VALUE1 8 -+#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00 -+#define BF_PXP_HIST4_PARAM_VALUE1(v) \ -+ (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1) -+#define BP_PXP_HIST4_PARAM_RSVD0 5 -+#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0 -+#define BF_PXP_HIST4_PARAM_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0) -+#define BP_PXP_HIST4_PARAM_VALUE0 0 -+#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F -+#define BF_PXP_HIST4_PARAM_VALUE0(v) \ -+ (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0) -+ -+#define HW_PXP_HIST8_PARAM0 (0x000002c0) -+ -+#define BP_PXP_HIST8_PARAM0_RSVD3 29 -+#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000 -+#define BF_PXP_HIST8_PARAM0_RSVD3(v) \ -+ (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3) -+#define BP_PXP_HIST8_PARAM0_VALUE3 24 -+#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000 -+#define BF_PXP_HIST8_PARAM0_VALUE3(v) \ -+ (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3) -+#define BP_PXP_HIST8_PARAM0_RSVD2 21 -+#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000 -+#define BF_PXP_HIST8_PARAM0_RSVD2(v) \ -+ (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2) -+#define BP_PXP_HIST8_PARAM0_VALUE2 16 -+#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000 -+#define BF_PXP_HIST8_PARAM0_VALUE2(v) \ -+ (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2) -+#define BP_PXP_HIST8_PARAM0_RSVD1 13 -+#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000 -+#define BF_PXP_HIST8_PARAM0_RSVD1(v) \ -+ (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1) -+#define BP_PXP_HIST8_PARAM0_VALUE1 8 -+#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00 -+#define BF_PXP_HIST8_PARAM0_VALUE1(v) \ -+ (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1) -+#define BP_PXP_HIST8_PARAM0_RSVD0 5 -+#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0 -+#define BF_PXP_HIST8_PARAM0_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0) -+#define BP_PXP_HIST8_PARAM0_VALUE0 0 -+#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F -+#define BF_PXP_HIST8_PARAM0_VALUE0(v) \ -+ (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0) -+ -+#define HW_PXP_HIST8_PARAM1 (0x000002d0) -+ -+#define BP_PXP_HIST8_PARAM1_RSVD7 29 -+#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000 -+#define BF_PXP_HIST8_PARAM1_RSVD7(v) \ -+ (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7) -+#define BP_PXP_HIST8_PARAM1_VALUE7 24 -+#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000 -+#define BF_PXP_HIST8_PARAM1_VALUE7(v) \ -+ (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7) -+#define BP_PXP_HIST8_PARAM1_RSVD6 21 -+#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000 -+#define BF_PXP_HIST8_PARAM1_RSVD6(v) \ -+ (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6) -+#define BP_PXP_HIST8_PARAM1_VALUE6 16 -+#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000 -+#define BF_PXP_HIST8_PARAM1_VALUE6(v) \ -+ (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6) -+#define BP_PXP_HIST8_PARAM1_RSVD5 13 -+#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000 -+#define BF_PXP_HIST8_PARAM1_RSVD5(v) \ -+ (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5) -+#define BP_PXP_HIST8_PARAM1_VALUE5 8 -+#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00 -+#define BF_PXP_HIST8_PARAM1_VALUE5(v) \ -+ (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5) -+#define BP_PXP_HIST8_PARAM1_RSVD4 5 -+#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0 -+#define BF_PXP_HIST8_PARAM1_RSVD4(v) \ -+ (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4) -+#define BP_PXP_HIST8_PARAM1_VALUE4 0 -+#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F -+#define BF_PXP_HIST8_PARAM1_VALUE4(v) \ -+ (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4) -+ -+#define HW_PXP_HIST16_PARAM0 (0x000002e0) -+ -+#define BP_PXP_HIST16_PARAM0_RSVD3 29 -+#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000 -+#define BF_PXP_HIST16_PARAM0_RSVD3(v) \ -+ (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3) -+#define BP_PXP_HIST16_PARAM0_VALUE3 24 -+#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000 -+#define BF_PXP_HIST16_PARAM0_VALUE3(v) \ -+ (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3) -+#define BP_PXP_HIST16_PARAM0_RSVD2 21 -+#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000 -+#define BF_PXP_HIST16_PARAM0_RSVD2(v) \ -+ (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2) -+#define BP_PXP_HIST16_PARAM0_VALUE2 16 -+#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000 -+#define BF_PXP_HIST16_PARAM0_VALUE2(v) \ -+ (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2) -+#define BP_PXP_HIST16_PARAM0_RSVD1 13 -+#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000 -+#define BF_PXP_HIST16_PARAM0_RSVD1(v) \ -+ (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1) -+#define BP_PXP_HIST16_PARAM0_VALUE1 8 -+#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00 -+#define BF_PXP_HIST16_PARAM0_VALUE1(v) \ -+ (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1) -+#define BP_PXP_HIST16_PARAM0_RSVD0 5 -+#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0 -+#define BF_PXP_HIST16_PARAM0_RSVD0(v) \ -+ (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0) -+#define BP_PXP_HIST16_PARAM0_VALUE0 0 -+#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F -+#define BF_PXP_HIST16_PARAM0_VALUE0(v) \ -+ (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0) -+ -+#define HW_PXP_HIST16_PARAM1 (0x000002f0) -+ -+#define BP_PXP_HIST16_PARAM1_RSVD7 29 -+#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000 -+#define BF_PXP_HIST16_PARAM1_RSVD7(v) \ -+ (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7) -+#define BP_PXP_HIST16_PARAM1_VALUE7 24 -+#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000 -+#define BF_PXP_HIST16_PARAM1_VALUE7(v) \ -+ (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7) -+#define BP_PXP_HIST16_PARAM1_RSVD6 21 -+#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000 -+#define BF_PXP_HIST16_PARAM1_RSVD6(v) \ -+ (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6) -+#define BP_PXP_HIST16_PARAM1_VALUE6 16 -+#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000 -+#define BF_PXP_HIST16_PARAM1_VALUE6(v) \ -+ (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6) -+#define BP_PXP_HIST16_PARAM1_RSVD5 13 -+#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000 -+#define BF_PXP_HIST16_PARAM1_RSVD5(v) \ -+ (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5) -+#define BP_PXP_HIST16_PARAM1_VALUE5 8 -+#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00 -+#define BF_PXP_HIST16_PARAM1_VALUE5(v) \ -+ (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5) -+#define BP_PXP_HIST16_PARAM1_RSVD4 5 -+#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0 -+#define BF_PXP_HIST16_PARAM1_RSVD4(v) \ -+ (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4) -+#define BP_PXP_HIST16_PARAM1_VALUE4 0 -+#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F -+#define BF_PXP_HIST16_PARAM1_VALUE4(v) \ -+ (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4) -+ -+#define HW_PXP_HIST16_PARAM2 (0x00000300) -+ -+#define BP_PXP_HIST16_PARAM2_RSVD11 29 -+#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000 -+#define BF_PXP_HIST16_PARAM2_RSVD11(v) \ -+ (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11) -+#define BP_PXP_HIST16_PARAM2_VALUE11 24 -+#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000 -+#define BF_PXP_HIST16_PARAM2_VALUE11(v) \ -+ (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11) -+#define BP_PXP_HIST16_PARAM2_RSVD10 21 -+#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000 -+#define BF_PXP_HIST16_PARAM2_RSVD10(v) \ -+ (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10) -+#define BP_PXP_HIST16_PARAM2_VALUE10 16 -+#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000 -+#define BF_PXP_HIST16_PARAM2_VALUE10(v) \ -+ (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10) -+#define BP_PXP_HIST16_PARAM2_RSVD9 13 -+#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000 -+#define BF_PXP_HIST16_PARAM2_RSVD9(v) \ -+ (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9) -+#define BP_PXP_HIST16_PARAM2_VALUE9 8 -+#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00 -+#define BF_PXP_HIST16_PARAM2_VALUE9(v) \ -+ (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9) -+#define BP_PXP_HIST16_PARAM2_RSVD8 5 -+#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0 -+#define BF_PXP_HIST16_PARAM2_RSVD8(v) \ -+ (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8) -+#define BP_PXP_HIST16_PARAM2_VALUE8 0 -+#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F -+#define BF_PXP_HIST16_PARAM2_VALUE8(v) \ -+ (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8) -+ -+#define HW_PXP_HIST16_PARAM3 (0x00000310) -+ -+#define BP_PXP_HIST16_PARAM3_RSVD15 29 -+#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000 -+#define BF_PXP_HIST16_PARAM3_RSVD15(v) \ -+ (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15) -+#define BP_PXP_HIST16_PARAM3_VALUE15 24 -+#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000 -+#define BF_PXP_HIST16_PARAM3_VALUE15(v) \ -+ (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15) -+#define BP_PXP_HIST16_PARAM3_RSVD14 21 -+#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000 -+#define BF_PXP_HIST16_PARAM3_RSVD14(v) \ -+ (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14) -+#define BP_PXP_HIST16_PARAM3_VALUE14 16 -+#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000 -+#define BF_PXP_HIST16_PARAM3_VALUE14(v) \ -+ (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14) -+#define BP_PXP_HIST16_PARAM3_RSVD13 13 -+#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000 -+#define BF_PXP_HIST16_PARAM3_RSVD13(v) \ -+ (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13) -+#define BP_PXP_HIST16_PARAM3_VALUE13 8 -+#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00 -+#define BF_PXP_HIST16_PARAM3_VALUE13(v) \ -+ (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13) -+#define BP_PXP_HIST16_PARAM3_RSVD12 5 -+#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0 -+#define BF_PXP_HIST16_PARAM3_RSVD12(v) \ -+ (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12) -+#define BP_PXP_HIST16_PARAM3_VALUE12 0 -+#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F -+#define BF_PXP_HIST16_PARAM3_VALUE12(v) \ -+ (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12) -+ -+#define HW_PXP_POWER (0x00000320) -+ -+#define BP_PXP_POWER_CTRL 12 -+#define BM_PXP_POWER_CTRL 0xFFFFF000 -+#define BF_PXP_POWER_CTRL(v) \ -+ (((v) << 12) & BM_PXP_POWER_CTRL) -+#define BP_PXP_POWER_ROT_MEM_LP_STATE 9 -+#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00 -+#define BF_PXP_POWER_ROT_MEM_LP_STATE(v) \ -+ (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE) -+#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0 -+#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS 0x1 -+#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS 0x2 -+#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD 0x4 -+#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 6 -+#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0 -+#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v) \ -+ (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN) -+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS 0x1 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS 0x2 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD 0x4 -+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 3 -+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038 -+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v) \ -+ (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN) -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS 0x1 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS 0x2 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD 0x4 -+#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0 -+#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007 -+#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v) \ -+ (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0) -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS 0x1 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS 0x2 -+#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD 0x4 -+ -+#define HW_PXP_NEXT (0x00000400) -+ -+#define BP_PXP_NEXT_POINTER 2 -+#define BM_PXP_NEXT_POINTER 0xFFFFFFFC -+#define BF_PXP_NEXT_POINTER(v) \ -+ (((v) << 2) & BM_PXP_NEXT_POINTER) -+#define BM_PXP_NEXT_RSVD 0x00000002 -+#define BM_PXP_NEXT_ENABLED 0x00000001 -+ -+#define HW_PXP_DEBUGCTRL (0x00000410) -+ -+#define BP_PXP_DEBUGCTRL_RSVD 12 -+#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000 -+#define BF_PXP_DEBUGCTRL_RSVD(v) \ -+ (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD) -+#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8 -+#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00 -+#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \ -+ (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT) -+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0 -+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1 -+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2 -+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4 -+#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8 -+#define BP_PXP_DEBUGCTRL_SELECT 0 -+#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF -+#define BF_PXP_DEBUGCTRL_SELECT(v) \ -+ (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT) -+#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0 -+#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1 -+#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2 -+#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3 -+#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4 -+#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5 -+#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6 -+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7 -+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8 -+#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9 -+#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10 -+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11 -+#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12 -+#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13 -+#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14 -+ -+#define HW_PXP_DEBUG (0x00000420) -+ -+#define BP_PXP_DEBUG_DATA 0 -+#define BM_PXP_DEBUG_DATA 0xFFFFFFFF -+#define BF_PXP_DEBUG_DATA(v) (v) -+ -+#define HW_PXP_VERSION (0x00000430) -+ -+#define BP_PXP_VERSION_MAJOR 24 -+#define BM_PXP_VERSION_MAJOR 0xFF000000 -+#define BF_PXP_VERSION_MAJOR(v) \ -+ (((v) << 24) & BM_PXP_VERSION_MAJOR) -+#define BP_PXP_VERSION_MINOR 16 -+#define BM_PXP_VERSION_MINOR 0x00FF0000 -+#define BF_PXP_VERSION_MINOR(v) \ -+ (((v) << 16) & BM_PXP_VERSION_MINOR) -+#define BP_PXP_VERSION_STEP 0 -+#define BM_PXP_VERSION_STEP 0x0000FFFF -+#define BF_PXP_VERSION_STEP(v) \ -+ (((v) << 0) & BM_PXP_VERSION_STEP) -+#endif /* __ARCH_ARM___PXP_H */ -diff -Nur linux-3.14.22.orig/drivers/gpio/gpio-pca953x.c linux-3.14.22/drivers/gpio/gpio-pca953x.c ---- linux-3.14.22.orig/drivers/gpio/gpio-pca953x.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpio/gpio-pca953x.c 2014-10-22 14:55:52.050220001 -0500 -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #ifdef CONFIG_OF_GPIO - #include -@@ -741,6 +742,10 @@ - - mutex_init(&chip->i2c_lock); - -+ ret = device_reset(&client->dev); -+ if (ret == -ENODEV) -+ return -EPROBE_DEFER; -+ - /* initialize cached registers from their original values. - * we can't share this chip with another i2c master. - */ -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/drm_crtc_helper.c linux-3.14.22/drivers/gpu/drm/drm_crtc_helper.c ---- linux-3.14.22.orig/drivers/gpu/drm/drm_crtc_helper.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpu/drm/drm_crtc_helper.c 2014-10-22 14:55:52.050220001 -0500 -@@ -564,7 +564,7 @@ - * Caller must hold mode config lock. - * - * Setup a new configuration, provided by the upper layers (either an ioctl call -- * from userspace or internally e.g. from the fbdev suppport code) in @set, and -+ * from userspace or internally e.g. from the fbdev support code) in @set, and - * enable it. This is the main helper functions for drivers that implement - * kernel mode setting with the crtc helper functions and the assorted - * ->prepare(), ->modeset() and ->commit() helper callbacks. -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/drm_prime.c linux-3.14.22/drivers/gpu/drm/drm_prime.c ---- linux-3.14.22.orig/drivers/gpu/drm/drm_prime.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpu/drm/drm_prime.c 2014-10-22 14:55:52.050220001 -0500 -@@ -471,7 +471,7 @@ - get_dma_buf(dma_buf); - - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); -- if (IS_ERR_OR_NULL(sgt)) { -+ if (IS_ERR(sgt)) { - ret = PTR_ERR(sgt); - goto fail_detach; - } -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c linux-3.14.22/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c ---- linux-3.14.22.orig/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2014-10-22 14:55:52.050220001 -0500 -@@ -224,7 +224,7 @@ - get_dma_buf(dma_buf); - - sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); -- if (IS_ERR_OR_NULL(sgt)) { -+ if (IS_ERR(sgt)) { - ret = PTR_ERR(sgt); - goto err_buf_detach; - } -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/Kconfig linux-3.14.22/drivers/gpu/drm/Kconfig ---- linux-3.14.22.orig/drivers/gpu/drm/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpu/drm/Kconfig 2014-10-22 14:55:52.050220001 -0500 -@@ -166,6 +166,13 @@ - Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister - chipset. If M is selected the module will be called savage. - -+config DRM_VIVANTE -+ tristate "Vivante GCCore" -+ depends on DRM -+ help -+ Choose this option if you have a Vivante graphics card. -+ If M is selected, the module will be called vivante. -+ - source "drivers/gpu/drm/exynos/Kconfig" - - source "drivers/gpu/drm/vmwgfx/Kconfig" -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/Makefile linux-3.14.22/drivers/gpu/drm/Makefile ---- linux-3.14.22.orig/drivers/gpu/drm/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/gpu/drm/Makefile 2014-10-22 14:55:52.050220001 -0500 -@@ -1,3 +1,24 @@ -+############################################################################## -+# -+# Copyright (C) 2005 - 2013 by Vivante Corp. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the license, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not write to the Free Software -+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+# -+############################################################################## -+ -+ - # - # Makefile for the drm device driver. This driver provides support for the - # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -@@ -35,6 +56,7 @@ - obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o - obj-$(CONFIG_DRM_USB) += drm_usb.o - obj-$(CONFIG_DRM_TTM) += ttm/ -+obj-$(CONFIG_DRM_VIVANTE) += vivante/ - obj-$(CONFIG_DRM_TDFX) += tdfx/ - obj-$(CONFIG_DRM_R128) += r128/ - obj-$(CONFIG_DRM_RADEON)+= radeon/ -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/vivante/Makefile linux-3.14.22/drivers/gpu/drm/vivante/Makefile ---- linux-3.14.22.orig/drivers/gpu/drm/vivante/Makefile 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/gpu/drm/vivante/Makefile 2014-10-22 14:55:52.050220001 -0500 -@@ -0,0 +1,29 @@ -+############################################################################## -+# -+# Copyright (C) 2005 - 2013 by Vivante Corp. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the license, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not write to the Free Software -+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+# -+############################################################################## -+ -+ -+# -+# Makefile for the drm device driver. This driver provides support for the -+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -+ -+ccflags-y := -Iinclude/drm -+vivante-y := vivante_drv.o -+ -+obj-$(CONFIG_DRM_VIVANTE) += vivante.o -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/vivante/vivante_drv.c linux-3.14.22/drivers/gpu/drm/vivante/vivante_drv.c ---- linux-3.14.22.orig/drivers/gpu/drm/vivante/vivante_drv.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/gpu/drm/vivante/vivante_drv.c 2014-10-22 14:55:52.050220001 -0500 -@@ -0,0 +1,108 @@ -+/**************************************************************************** -+* -+* Copyright (C) 2005 - 2013 by Vivante Corp. -+* -+* This program is free software; you can redistribute it and/or modify -+* it under the terms of the GNU General Public License as published by -+* the Free Software Foundation; either version 2 of the license, or -+* (at your option) any later version. -+* -+* This program is distributed in the hope that it will be useful, -+* but WITHOUT ANY WARRANTY; without even the implied warranty of -+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+* GNU General Public License for more details. -+* -+* You should have received a copy of the GNU General Public License -+* along with this program; if not write to the Free Software -+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+* -+*****************************************************************************/ -+ -+ -+/* vivante_drv.c -- vivante driver -*- linux-c -*- -+ * -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: -+ * Rickard E. (Rik) Faith -+ * Daryll Strauss -+ * Gareth Hughes -+ */ -+ -+#include -+#include -+ -+#include "drmP.h" -+#include "vivante_drv.h" -+ -+#include "drm_pciids.h" -+ -+static char platformdevicename[] = "Vivante GCCore"; -+static struct platform_device *pplatformdev; -+ -+static const struct file_operations viv_driver_fops = { -+ .owner = THIS_MODULE, -+ .open = drm_open, -+ .release = drm_release, -+ .unlocked_ioctl = drm_ioctl, -+ .mmap = drm_mmap, -+ .poll = drm_poll, -+ .llseek = noop_llseek, -+}; -+ -+static struct drm_driver driver = { -+ .fops = &viv_driver_fops, -+ .name = DRIVER_NAME, -+ .desc = DRIVER_DESC, -+ .date = DRIVER_DATE, -+ .major = DRIVER_MAJOR, -+ .minor = DRIVER_MINOR, -+ .patchlevel = DRIVER_PATCHLEVEL, -+}; -+ -+static int __init vivante_init(void) -+{ -+ int retcode; -+ -+ pplatformdev = platform_device_register_simple(platformdevicename, -+ -1, NULL, 0); -+ if (pplatformdev == NULL) -+ printk(KERN_ERR"Platform device is null\n"); -+ -+ retcode = drm_platform_init(&driver, pplatformdev); -+ -+ return retcode; -+} -+ -+static void __exit vivante_exit(void) -+{ -+ if (pplatformdev) { -+ platform_device_unregister(pplatformdev); -+ pplatformdev = NULL; -+ } -+} -+ -+module_init(vivante_init); -+module_exit(vivante_exit); -+ -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_LICENSE("GPL and additional rights"); -diff -Nur linux-3.14.22.orig/drivers/gpu/drm/vivante/vivante_drv.h linux-3.14.22/drivers/gpu/drm/vivante/vivante_drv.h ---- linux-3.14.22.orig/drivers/gpu/drm/vivante/vivante_drv.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/gpu/drm/vivante/vivante_drv.h 2014-10-22 14:55:52.050220001 -0500 -@@ -0,0 +1,66 @@ -+/**************************************************************************** -+* -+* Copyright (C) 2005 - 2013 by Vivante Corp. -+* -+* This program is free software; you can redistribute it and/or modify -+* it under the terms of the GNU General Public License as published by -+* the Free Software Foundation; either version 2 of the license, or -+* (at your option) any later version. -+* -+* This program is distributed in the hope that it will be useful, -+* but WITHOUT ANY WARRANTY; without even the implied warranty of -+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+* GNU General Public License for more details. -+* -+* You should have received a copy of the GNU General Public License -+* along with this program; if not write to the Free Software -+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+* -+*****************************************************************************/ -+ -+ -+/* vivante_drv.h -- Vivante DRM template customization -*- linux-c -*- -+ * Created: Wed Feb 14 12:32:32 2012 by John Zhao -+ */ -+/* -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ * Authors: -+ * Gareth Hughes -+ */ -+ -+#ifndef __VIVANTE_DRV_H__ -+#define __VIVANTE_DRV_H__ -+ -+/* General customization: -+ */ -+ -+#define DRIVER_AUTHOR "Vivante Inc." -+ -+#define DRIVER_NAME "vivante" -+#define DRIVER_DESC "Vivante GCCore" -+#define DRIVER_DATE "20120216" -+ -+#define DRIVER_MAJOR 1 -+#define DRIVER_MINOR 0 -+#define DRIVER_PATCHLEVEL 0 -+ -+#endif -diff -Nur linux-3.14.22.orig/drivers/hwmon/Kconfig linux-3.14.22/drivers/hwmon/Kconfig ---- linux-3.14.22.orig/drivers/hwmon/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/hwmon/Kconfig 2014-10-22 14:55:52.050220001 -0500 -@@ -1584,4 +1584,19 @@ - - endif # ACPI - -+config SENSORS_MAG3110 -+ tristate "Freescale MAG3110 e-compass sensor" -+ depends on I2C && SYSFS -+ help -+ If you say yes here you get support for the Freescale MAG3110 -+ e-compass sensor. -+ This driver can also be built as a module. If so, the module -+ will be called mag3110. -+ -+config MXC_MMA8451 -+ tristate "MMA8451 device driver" -+ depends on I2C -+ depends on INPUT_POLLDEV -+ default y -+ - endif # HWMON -diff -Nur linux-3.14.22.orig/drivers/hwmon/mag3110.c linux-3.14.22/drivers/hwmon/mag3110.c ---- linux-3.14.22.orig/drivers/hwmon/mag3110.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/hwmon/mag3110.c 2014-10-22 14:55:52.054220001 -0500 -@@ -0,0 +1,611 @@ -+/* -+ * -+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MAG3110_DRV_NAME "mag3110" -+#define MAG3110_ID 0xC4 -+#define MAG3110_XYZ_DATA_LEN 6 -+#define MAG3110_STATUS_ZYXDR 0x08 -+ -+#define MAG3110_AC_MASK (0x01) -+#define MAG3110_AC_OFFSET 0 -+#define MAG3110_DR_MODE_MASK (0x7 << 5) -+#define MAG3110_DR_MODE_OFFSET 5 -+#define MAG3110_IRQ_USED 0 -+ -+#define POLL_INTERVAL_MAX 500 -+#define POLL_INTERVAL 100 -+#define INT_TIMEOUT 1000 -+#define DEFAULT_POSITION 2 -+/* register enum for mag3110 registers */ -+enum { -+ MAG3110_DR_STATUS = 0x00, -+ MAG3110_OUT_X_MSB, -+ MAG3110_OUT_X_LSB, -+ MAG3110_OUT_Y_MSB, -+ MAG3110_OUT_Y_LSB, -+ MAG3110_OUT_Z_MSB, -+ MAG3110_OUT_Z_LSB, -+ MAG3110_WHO_AM_I, -+ -+ MAG3110_OFF_X_MSB, -+ MAG3110_OFF_X_LSB, -+ MAG3110_OFF_Y_MSB, -+ MAG3110_OFF_Y_LSB, -+ MAG3110_OFF_Z_MSB, -+ MAG3110_OFF_Z_LSB, -+ -+ MAG3110_DIE_TEMP, -+ -+ MAG3110_CTRL_REG1 = 0x10, -+ MAG3110_CTRL_REG2, -+}; -+enum { -+ MAG_STANDBY, -+ MAG_ACTIVED -+}; -+struct mag3110_data { -+ struct i2c_client *client; -+ struct input_polled_dev *poll_dev; -+ struct device *hwmon_dev; -+ wait_queue_head_t waitq; -+ bool data_ready; -+ u8 ctl_reg1; -+ int active; -+ int position; -+}; -+static short MAGHAL[8][3][3] = { -+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, -+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, -+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, -+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, -+ -+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, -+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, -+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, -+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, -+}; -+ -+static struct mag3110_data *mag3110_pdata; -+/*! -+ * This function do one mag3110 register read. -+ */ -+static DEFINE_MUTEX(mag3110_lock); -+static int mag3110_adjust_position(short *x, short *y, short *z) -+{ -+ short rawdata[3], data[3]; -+ int i, j; -+ int position = mag3110_pdata->position; -+ if (position < 0 || position > 7) -+ position = 0; -+ rawdata[0] = *x; -+ rawdata[1] = *y; -+ rawdata[2] = *z; -+ for (i = 0; i < 3; i++) { -+ data[i] = 0; -+ for (j = 0; j < 3; j++) -+ data[i] += rawdata[j] * MAGHAL[position][i][j]; -+ } -+ *x = data[0]; -+ *y = data[1]; -+ *z = data[2]; -+ return 0; -+} -+ -+static int mag3110_read_reg(struct i2c_client *client, u8 reg) -+{ -+ return i2c_smbus_read_byte_data(client, reg); -+} -+ -+/*! -+ * This function do one mag3110 register write. -+ */ -+static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value) -+{ -+ int ret; -+ -+ ret = i2c_smbus_write_byte_data(client, reg, value); -+ if (ret < 0) -+ dev_err(&client->dev, "i2c write failed\n"); -+ return ret; -+} -+ -+/*! -+ * This function do multiple mag3110 registers read. -+ */ -+static int mag3110_read_block_data(struct i2c_client *client, u8 reg, -+ int count, u8 *addr) -+{ -+ if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) { -+ dev_err(&client->dev, "i2c block read failed\n"); -+ return -1; -+ } -+ -+ return count; -+} -+ -+/* -+ * Initialization function -+ */ -+static int mag3110_init_client(struct i2c_client *client) -+{ -+ int val, ret; -+ -+ /* enable automatic resets */ -+ val = 0x80; -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG2, val); -+ -+ /* set default data rate to 10HZ */ -+ val = mag3110_read_reg(client, MAG3110_CTRL_REG1); -+ val |= (0x0 << MAG3110_DR_MODE_OFFSET); -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, val); -+ -+ return ret; -+} -+ -+/*************************************************************** -+* -+* read sensor data from mag3110 -+* -+***************************************************************/ -+static int mag3110_read_data(short *x, short *y, short *z) -+{ -+ struct mag3110_data *data; -+ int retry = 3; -+ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; -+ int result; -+ if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY) -+ return -EINVAL; -+ -+ data = mag3110_pdata; -+#if MAG3110_IRQ_USED -+ if (!wait_event_interruptible_timeout -+ (data->waitq, data->data_ready != 0, -+ msecs_to_jiffies(INT_TIMEOUT))) { -+ dev_dbg(&data->client->dev, "interrupt not received\n"); -+ return -ETIME; -+ } -+#else -+ do { -+ msleep(1); -+ result = i2c_smbus_read_byte_data(data->client, -+ MAG3110_DR_STATUS); -+ retry--; -+ } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0); -+ /* Clear data_ready flag after data is read out */ -+ if (retry == 0) -+ return -EINVAL; -+#endif -+ -+ data->data_ready = 0; -+ -+ if (mag3110_read_block_data(data->client, -+ MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN, -+ tmp_data) < 0) -+ return -1; -+ -+ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; -+ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; -+ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; -+ -+ return 0; -+} -+ -+static void report_abs(void) -+{ -+ struct input_dev *idev; -+ short x, y, z; -+ -+ mutex_lock(&mag3110_lock); -+ if (mag3110_read_data(&x, &y, &z) != 0) -+ goto out; -+ mag3110_adjust_position(&x, &y, &z); -+ idev = mag3110_pdata->poll_dev->input; -+ input_report_abs(idev, ABS_X, x); -+ input_report_abs(idev, ABS_Y, y); -+ input_report_abs(idev, ABS_Z, z); -+ input_sync(idev); -+out: -+ mutex_unlock(&mag3110_lock); -+} -+ -+static void mag3110_dev_poll(struct input_polled_dev *dev) -+{ -+ report_abs(); -+} -+ -+#if MAG3110_IRQ_USED -+static irqreturn_t mag3110_irq_handler(int irq, void *dev_id) -+{ -+ mag3110_pdata->data_ready = 1; -+ wake_up_interruptible(&mag3110_pdata->waitq); -+ -+ return IRQ_HANDLED; -+} -+#endif -+static ssize_t mag3110_enable_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct i2c_client *client; -+ int val; -+ mutex_lock(&mag3110_lock); -+ client = mag3110_pdata->client; -+ val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK; -+ -+ mutex_unlock(&mag3110_lock); -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t mag3110_enable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client; -+ int reg, ret; -+ long enable; -+ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; -+ -+ ret = strict_strtol(buf, 10, &enable); -+ if (ret) { -+ dev_err(dev, "string to long error\n"); -+ return ret; -+ } -+ -+ mutex_lock(&mag3110_lock); -+ client = mag3110_pdata->client; -+ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1); -+ if (enable && mag3110_pdata->active == MAG_STANDBY) { -+ reg |= MAG3110_AC_MASK; -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); -+ if (!ret) -+ mag3110_pdata->active = MAG_ACTIVED; -+ } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) { -+ reg &= ~MAG3110_AC_MASK; -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); -+ if (!ret) -+ mag3110_pdata->active = MAG_STANDBY; -+ } -+ -+ if (mag3110_pdata->active == MAG_ACTIVED) { -+ msleep(100); -+ /* Read out MSB data to clear interrupt flag automatically */ -+ mag3110_read_block_data(client, MAG3110_OUT_X_MSB, -+ MAG3110_XYZ_DATA_LEN, tmp_data); -+ } -+ mutex_unlock(&mag3110_lock); -+ return count; -+} -+ -+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, -+ mag3110_enable_show, mag3110_enable_store); -+ -+static ssize_t mag3110_dr_mode_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct i2c_client *client; -+ int val; -+ -+ client = mag3110_pdata->client; -+ val = (mag3110_read_reg(client, MAG3110_CTRL_REG1) -+ & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET; -+ -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t mag3110_dr_mode_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client; -+ int reg, ret; -+ unsigned long val; -+ -+ /* This must be done when mag3110 is disabled */ -+ if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7)) -+ return -EINVAL; -+ -+ client = mag3110_pdata->client; -+ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) & -+ ~MAG3110_DR_MODE_MASK; -+ reg |= (val << MAG3110_DR_MODE_OFFSET); -+ /* MAG3110_CTRL_REG1 bit 5-7: data rate mode */ -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); -+ if (ret < 0) -+ return ret; -+ -+ return count; -+} -+ -+static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO, -+ mag3110_dr_mode_show, mag3110_dr_mode_store); -+ -+static ssize_t mag3110_position_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int val; -+ mutex_lock(&mag3110_lock); -+ val = mag3110_pdata->position; -+ mutex_unlock(&mag3110_lock); -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t mag3110_position_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ long position; -+ int ret; -+ ret = strict_strtol(buf, 10, &position); -+ if (ret) { -+ dev_err(dev, "string to long error\n"); -+ return ret; -+ } -+ -+ mutex_lock(&mag3110_lock); -+ mag3110_pdata->position = (int)position; -+ mutex_unlock(&mag3110_lock); -+ return count; -+} -+ -+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, -+ mag3110_position_show, mag3110_position_store); -+ -+static struct attribute *mag3110_attributes[] = { -+ &dev_attr_enable.attr, -+ &dev_attr_dr_mode.attr, -+ &dev_attr_position.attr, -+ NULL -+}; -+ -+static const struct attribute_group mag3110_attr_group = { -+ .attrs = mag3110_attributes, -+}; -+ -+static int mag3110_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct i2c_adapter *adapter; -+ struct input_dev *idev; -+ struct mag3110_data *data; -+ int ret = 0; -+ struct regulator *vdd, *vdd_io; -+ u32 pos = 0; -+ struct device_node *of_node = client->dev.of_node; -+ vdd = NULL; -+ vdd_io = NULL; -+ -+ vdd = devm_regulator_get(&client->dev, "vdd"); -+ if (!IS_ERR(vdd)) { -+ ret = regulator_enable(vdd); -+ if (ret) { -+ dev_err(&client->dev, "vdd set voltage error\n"); -+ return ret; -+ } -+ } -+ -+ vdd_io = devm_regulator_get(&client->dev, "vddio"); -+ if (!IS_ERR(vdd_io)) { -+ ret = regulator_enable(vdd_io); -+ if (ret) { -+ dev_err(&client->dev, "vddio set voltage error\n"); -+ return ret; -+ } -+ } -+ -+ adapter = to_i2c_adapter(client->dev.parent); -+ if (!i2c_check_functionality(adapter, -+ I2C_FUNC_SMBUS_BYTE | -+ I2C_FUNC_SMBUS_BYTE_DATA | -+ I2C_FUNC_SMBUS_I2C_BLOCK)) -+ return -EIO; -+ -+ dev_info(&client->dev, "check mag3110 chip ID\n"); -+ ret = mag3110_read_reg(client, MAG3110_WHO_AM_I); -+ -+ if (MAG3110_ID != ret) { -+ dev_err(&client->dev, -+ "read chip ID 0x%x is not equal to 0x%x!\n", ret, -+ MAG3110_ID); -+ return -EINVAL; -+ } -+ data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ data->client = client; -+ i2c_set_clientdata(client, data); -+ /* Init queue */ -+ init_waitqueue_head(&data->waitq); -+ -+ data->hwmon_dev = hwmon_device_register(&client->dev); -+ if (IS_ERR(data->hwmon_dev)) { -+ dev_err(&client->dev, "hwmon register failed!\n"); -+ ret = PTR_ERR(data->hwmon_dev); -+ goto error_rm_dev_sysfs; -+ } -+ -+ /*input poll device register */ -+ data->poll_dev = input_allocate_polled_device(); -+ if (!data->poll_dev) { -+ dev_err(&client->dev, "alloc poll device failed!\n"); -+ ret = -ENOMEM; -+ goto error_rm_hwmon_dev; -+ } -+ data->poll_dev->poll = mag3110_dev_poll; -+ data->poll_dev->poll_interval = POLL_INTERVAL; -+ data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX; -+ idev = data->poll_dev->input; -+ idev->name = MAG3110_DRV_NAME; -+ idev->id.bustype = BUS_I2C; -+ idev->evbit[0] = BIT_MASK(EV_ABS); -+ input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0); -+ input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0); -+ input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0); -+ ret = input_register_polled_device(data->poll_dev); -+ if (ret) { -+ dev_err(&client->dev, "register poll device failed!\n"); -+ goto error_free_poll_dev; -+ } -+ -+ /*create device group in sysfs as user interface */ -+ ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group); -+ if (ret) { -+ dev_err(&client->dev, "create device file failed!\n"); -+ ret = -EINVAL; -+ goto error_rm_poll_dev; -+ } -+ /* set irq type to edge rising */ -+#if MAG3110_IRQ_USED -+ ret = request_irq(client->irq, mag3110_irq_handler, -+ IRQF_TRIGGER_RISING, client->dev.driver->name, idev); -+ if (ret < 0) { -+ dev_err(&client->dev, "failed to register irq %d!\n", -+ client->irq); -+ goto error_rm_dev_sysfs; -+ } -+#endif -+ /* Initialize mag3110 chip */ -+ mag3110_init_client(client); -+ mag3110_pdata = data; -+ mag3110_pdata->active = MAG_STANDBY; -+ ret = of_property_read_u32(of_node, "position", &pos); -+ if (ret) -+ pos = DEFAULT_POSITION; -+ mag3110_pdata->position = (int)pos; -+ dev_info(&client->dev, "mag3110 is probed\n"); -+ return 0; -+error_rm_dev_sysfs: -+ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); -+error_rm_poll_dev: -+ input_unregister_polled_device(data->poll_dev); -+error_free_poll_dev: -+ input_free_polled_device(data->poll_dev); -+error_rm_hwmon_dev: -+ hwmon_device_unregister(data->hwmon_dev); -+ -+ kfree(data); -+ mag3110_pdata = NULL; -+ -+ return ret; -+} -+ -+static int mag3110_remove(struct i2c_client *client) -+{ -+ struct mag3110_data *data; -+ int ret; -+ -+ data = i2c_get_clientdata(client); -+ -+ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, -+ data->ctl_reg1 & ~MAG3110_AC_MASK); -+ -+ free_irq(client->irq, data); -+ input_unregister_polled_device(data->poll_dev); -+ input_free_polled_device(data->poll_dev); -+ hwmon_device_unregister(data->hwmon_dev); -+ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); -+ kfree(data); -+ mag3110_pdata = NULL; -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM -+static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg) -+{ -+ int ret = 0; -+ struct mag3110_data *data = i2c_get_clientdata(client); -+ if (data->active == MAG_ACTIVED) { -+ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, -+ data->ctl_reg1 & ~MAG3110_AC_MASK); -+ } -+ return ret; -+} -+ -+static int mag3110_resume(struct i2c_client *client) -+{ -+ int ret = 0; -+ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; -+ struct mag3110_data *data = i2c_get_clientdata(client); -+ if (data->active == MAG_ACTIVED) { -+ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, -+ data->ctl_reg1); -+ -+ if (data->ctl_reg1 & MAG3110_AC_MASK) { -+ /* Read out MSB data to clear interrupt -+ flag automatically */ -+ mag3110_read_block_data(client, MAG3110_OUT_X_MSB, -+ MAG3110_XYZ_DATA_LEN, tmp_data); -+ } -+ } -+ return ret; -+} -+ -+#else -+#define mag3110_suspend NULL -+#define mag3110_resume NULL -+#endif /* CONFIG_PM */ -+ -+static const struct i2c_device_id mag3110_id[] = { -+ {MAG3110_DRV_NAME, 0}, -+ {} -+}; -+ -+MODULE_DEVICE_TABLE(i2c, mag3110_id); -+static struct i2c_driver mag3110_driver = { -+ .driver = {.name = MAG3110_DRV_NAME, -+ .owner = THIS_MODULE,}, -+ .suspend = mag3110_suspend, -+ .resume = mag3110_resume, -+ .probe = mag3110_probe, -+ .remove = mag3110_remove, -+ .id_table = mag3110_id, -+}; -+ -+static int __init mag3110_init(void) -+{ -+ return i2c_add_driver(&mag3110_driver); -+} -+ -+static void __exit mag3110_exit(void) -+{ -+ i2c_del_driver(&mag3110_driver); -+} -+ -+module_init(mag3110_init); -+module_exit(mag3110_exit); -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/hwmon/Makefile linux-3.14.22/drivers/hwmon/Makefile ---- linux-3.14.22.orig/drivers/hwmon/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/hwmon/Makefile 2014-10-22 14:55:52.054220001 -0500 -@@ -142,6 +142,8 @@ - obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o - obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o - obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o -+obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o -+obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o - - obj-$(CONFIG_PMBUS) += pmbus/ - -diff -Nur linux-3.14.22.orig/drivers/hwmon/mxc_mma8451.c linux-3.14.22/drivers/hwmon/mxc_mma8451.c ---- linux-3.14.22.orig/drivers/hwmon/mxc_mma8451.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/hwmon/mxc_mma8451.c 2014-10-22 14:55:52.054220001 -0500 -@@ -0,0 +1,598 @@ -+/* -+ * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion -+ * Detection Sensor -+ * -+ * Copyright (C) 2010-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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MMA8451_I2C_ADDR 0x1C -+#define MMA8451_ID 0x1A -+#define MMA8452_ID 0x2A -+#define MMA8453_ID 0x3A -+ -+#define POLL_INTERVAL_MIN 1 -+#define POLL_INTERVAL_MAX 500 -+#define POLL_INTERVAL 100 /* msecs */ -+#define INPUT_FUZZ 32 -+#define INPUT_FLAT 32 -+#define MODE_CHANGE_DELAY_MS 100 -+ -+#define MMA8451_STATUS_ZYXDR 0x08 -+#define MMA8451_BUF_SIZE 7 -+#define DEFAULT_POSITION 0 -+ -+/* register enum for mma8451 registers */ -+enum { -+ MMA8451_STATUS = 0x00, -+ MMA8451_OUT_X_MSB, -+ MMA8451_OUT_X_LSB, -+ MMA8451_OUT_Y_MSB, -+ MMA8451_OUT_Y_LSB, -+ MMA8451_OUT_Z_MSB, -+ MMA8451_OUT_Z_LSB, -+ -+ MMA8451_F_SETUP = 0x09, -+ MMA8451_TRIG_CFG, -+ MMA8451_SYSMOD, -+ MMA8451_INT_SOURCE, -+ MMA8451_WHO_AM_I, -+ MMA8451_XYZ_DATA_CFG, -+ MMA8451_HP_FILTER_CUTOFF, -+ -+ MMA8451_PL_STATUS, -+ MMA8451_PL_CFG, -+ MMA8451_PL_COUNT, -+ MMA8451_PL_BF_ZCOMP, -+ MMA8451_P_L_THS_REG, -+ -+ MMA8451_FF_MT_CFG, -+ MMA8451_FF_MT_SRC, -+ MMA8451_FF_MT_THS, -+ MMA8451_FF_MT_COUNT, -+ -+ MMA8451_TRANSIENT_CFG = 0x1D, -+ MMA8451_TRANSIENT_SRC, -+ MMA8451_TRANSIENT_THS, -+ MMA8451_TRANSIENT_COUNT, -+ -+ MMA8451_PULSE_CFG, -+ MMA8451_PULSE_SRC, -+ MMA8451_PULSE_THSX, -+ MMA8451_PULSE_THSY, -+ MMA8451_PULSE_THSZ, -+ MMA8451_PULSE_TMLT, -+ MMA8451_PULSE_LTCY, -+ MMA8451_PULSE_WIND, -+ -+ MMA8451_ASLP_COUNT, -+ MMA8451_CTRL_REG1, -+ MMA8451_CTRL_REG2, -+ MMA8451_CTRL_REG3, -+ MMA8451_CTRL_REG4, -+ MMA8451_CTRL_REG5, -+ -+ MMA8451_OFF_X, -+ MMA8451_OFF_Y, -+ MMA8451_OFF_Z, -+ -+ MMA8451_REG_END, -+}; -+ -+/* The sensitivity is represented in counts/g. In 2g mode the -+sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512 -+counts/g and in 8g mode the sensitivity is 256 counts/g. -+ */ -+enum { -+ MODE_2G = 0, -+ MODE_4G, -+ MODE_8G, -+}; -+ -+enum { -+ MMA_STANDBY = 0, -+ MMA_ACTIVED, -+}; -+ -+/* mma8451 status */ -+struct mma8451_status { -+ u8 mode; -+ u8 ctl_reg1; -+ int active; -+ int position; -+}; -+ -+static struct mma8451_status mma_status; -+static struct input_polled_dev *mma8451_idev; -+static struct device *hwmon_dev; -+static struct i2c_client *mma8451_i2c_client; -+ -+static int senstive_mode = MODE_2G; -+static int ACCHAL[8][3][3] = { -+ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, -+ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, -+ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, -+ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, -+ -+ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, -+ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, -+ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, -+ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, -+}; -+ -+static DEFINE_MUTEX(mma8451_lock); -+static int mma8451_adjust_position(short *x, short *y, short *z) -+{ -+ short rawdata[3], data[3]; -+ int i, j; -+ int position = mma_status.position; -+ if (position < 0 || position > 7) -+ position = 0; -+ rawdata[0] = *x; -+ rawdata[1] = *y; -+ rawdata[2] = *z; -+ for (i = 0; i < 3; i++) { -+ data[i] = 0; -+ for (j = 0; j < 3; j++) -+ data[i] += rawdata[j] * ACCHAL[position][i][j]; -+ } -+ *x = data[0]; -+ *y = data[1]; -+ *z = data[2]; -+ return 0; -+} -+ -+static int mma8451_change_mode(struct i2c_client *client, int mode) -+{ -+ int result; -+ -+ mma_status.ctl_reg1 = 0; -+ result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0); -+ if (result < 0) -+ goto out; -+ mma_status.active = MMA_STANDBY; -+ -+ result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG, -+ mode); -+ if (result < 0) -+ goto out; -+ mdelay(MODE_CHANGE_DELAY_MS); -+ mma_status.mode = mode; -+ -+ return 0; -+out: -+ dev_err(&client->dev, "error when init mma8451:(%d)", result); -+ return result; -+} -+ -+static int mma8451_read_data(short *x, short *y, short *z) -+{ -+ u8 tmp_data[MMA8451_BUF_SIZE]; -+ int ret; -+ -+ ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client, -+ MMA8451_OUT_X_MSB, 7, tmp_data); -+ if (ret < MMA8451_BUF_SIZE) { -+ dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n"); -+ return -EIO; -+ } -+ -+ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; -+ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; -+ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; -+ return 0; -+} -+ -+static void report_abs(void) -+{ -+ short x, y, z; -+ int result; -+ int retry = 3; -+ -+ mutex_lock(&mma8451_lock); -+ if (mma_status.active == MMA_STANDBY) -+ goto out; -+ /* wait for the data ready */ -+ do { -+ result = i2c_smbus_read_byte_data(mma8451_i2c_client, -+ MMA8451_STATUS); -+ retry--; -+ msleep(1); -+ } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0); -+ if (retry == 0) -+ goto out; -+ if (mma8451_read_data(&x, &y, &z) != 0) -+ goto out; -+ mma8451_adjust_position(&x, &y, &z); -+ input_report_abs(mma8451_idev->input, ABS_X, x); -+ input_report_abs(mma8451_idev->input, ABS_Y, y); -+ input_report_abs(mma8451_idev->input, ABS_Z, z); -+ input_sync(mma8451_idev->input); -+out: -+ mutex_unlock(&mma8451_lock); -+} -+ -+static void mma8451_dev_poll(struct input_polled_dev *dev) -+{ -+ report_abs(); -+} -+ -+static ssize_t mma8451_enable_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct i2c_client *client; -+ u8 val; -+ int enable; -+ -+ mutex_lock(&mma8451_lock); -+ client = mma8451_i2c_client; -+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); -+ if ((val & 0x01) && mma_status.active == MMA_ACTIVED) -+ enable = 1; -+ else -+ enable = 0; -+ mutex_unlock(&mma8451_lock); -+ return sprintf(buf, "%d\n", enable); -+} -+ -+static ssize_t mma8451_enable_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client; -+ int ret; -+ unsigned long enable; -+ u8 val = 0; -+ -+ ret = strict_strtoul(buf, 10, &enable); -+ if (ret) { -+ dev_err(dev, "string transform error\n"); -+ return ret; -+ } -+ -+ mutex_lock(&mma8451_lock); -+ client = mma8451_i2c_client; -+ enable = (enable > 0) ? 1 : 0; -+ if (enable && mma_status.active == MMA_STANDBY) { -+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); -+ ret = -+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, -+ val | 0x01); -+ if (!ret) -+ mma_status.active = MMA_ACTIVED; -+ -+ } else if (enable == 0 && mma_status.active == MMA_ACTIVED) { -+ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); -+ ret = -+ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, -+ val & 0xFE); -+ if (!ret) -+ mma_status.active = MMA_STANDBY; -+ -+ } -+ mutex_unlock(&mma8451_lock); -+ return count; -+} -+ -+static ssize_t mma8451_position_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ int position = 0; -+ mutex_lock(&mma8451_lock); -+ position = mma_status.position; -+ mutex_unlock(&mma8451_lock); -+ return sprintf(buf, "%d\n", position); -+} -+ -+static ssize_t mma8451_position_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned long position; -+ int ret; -+ ret = strict_strtoul(buf, 10, &position); -+ if (ret) { -+ dev_err(dev, "string transform error\n"); -+ return ret; -+ } -+ -+ mutex_lock(&mma8451_lock); -+ mma_status.position = (int)position; -+ mutex_unlock(&mma8451_lock); -+ return count; -+} -+ -+static ssize_t mma8451_scalemode_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ int mode = 0; -+ mutex_lock(&mma8451_lock); -+ mode = (int)mma_status.mode; -+ mutex_unlock(&mma8451_lock); -+ -+ return sprintf(buf, "%d\n", mode); -+} -+ -+static ssize_t mma8451_scalemode_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned long mode; -+ int ret, active_save; -+ struct i2c_client *client = mma8451_i2c_client; -+ -+ ret = strict_strtoul(buf, 10, &mode); -+ if (ret) { -+ dev_err(dev, "string transform error\n"); -+ goto out; -+ } -+ -+ if (mode > MODE_8G) { -+ dev_warn(dev, "not supported mode\n"); -+ ret = count; -+ goto out; -+ } -+ -+ mutex_lock(&mma8451_lock); -+ if (mode == mma_status.mode) { -+ ret = count; -+ goto out_unlock; -+ } -+ -+ active_save = mma_status.active; -+ ret = mma8451_change_mode(client, mode); -+ if (ret) -+ goto out_unlock; -+ -+ if (active_save == MMA_ACTIVED) { -+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1); -+ -+ if (ret) -+ goto out_unlock; -+ mma_status.active = active_save; -+ } -+ -+out_unlock: -+ mutex_unlock(&mma8451_lock); -+out: -+ return ret; -+} -+ -+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, -+ mma8451_enable_show, mma8451_enable_store); -+static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, -+ mma8451_position_show, mma8451_position_store); -+static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, -+ mma8451_scalemode_show, mma8451_scalemode_store); -+ -+static struct attribute *mma8451_attributes[] = { -+ &dev_attr_enable.attr, -+ &dev_attr_position.attr, -+ &dev_attr_scalemode.attr, -+ NULL -+}; -+ -+static const struct attribute_group mma8451_attr_group = { -+ .attrs = mma8451_attributes, -+}; -+ -+static int mma8451_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ int result, client_id; -+ struct input_dev *idev; -+ struct i2c_adapter *adapter; -+ u32 pos; -+ struct device_node *of_node = client->dev.of_node; -+ struct regulator *vdd, *vdd_io; -+ -+ mma8451_i2c_client = client; -+ -+ vdd = devm_regulator_get(&client->dev, "vdd"); -+ if (!IS_ERR(vdd)) { -+ result = regulator_enable(vdd); -+ if (result) { -+ dev_err(&client->dev, "vdd set voltage error\n"); -+ return result; -+ } -+ } -+ -+ vdd_io = devm_regulator_get(&client->dev, "vddio"); -+ if (!IS_ERR(vdd_io)) { -+ result = regulator_enable(vdd_io); -+ if (result) { -+ dev_err(&client->dev, "vddio set voltage error\n"); -+ return result; -+ } -+ } -+ -+ adapter = to_i2c_adapter(client->dev.parent); -+ result = i2c_check_functionality(adapter, -+ I2C_FUNC_SMBUS_BYTE | -+ I2C_FUNC_SMBUS_BYTE_DATA); -+ if (!result) -+ goto err_out; -+ -+ client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I); -+ if (client_id != MMA8451_ID && client_id != MMA8452_ID -+ && client_id != MMA8453_ID) { -+ dev_err(&client->dev, -+ "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n", -+ result, MMA8451_ID, MMA8452_ID); -+ result = -EINVAL; -+ goto err_out; -+ } -+ -+ /* Initialize the MMA8451 chip */ -+ result = mma8451_change_mode(client, senstive_mode); -+ if (result) { -+ dev_err(&client->dev, -+ "error when init mma8451 chip:(%d)\n", result); -+ goto err_out; -+ } -+ -+ hwmon_dev = hwmon_device_register(&client->dev); -+ if (!hwmon_dev) { -+ result = -ENOMEM; -+ dev_err(&client->dev, "error when register hwmon device\n"); -+ goto err_out; -+ } -+ -+ mma8451_idev = input_allocate_polled_device(); -+ if (!mma8451_idev) { -+ result = -ENOMEM; -+ dev_err(&client->dev, "alloc poll device failed!\n"); -+ goto err_alloc_poll_device; -+ } -+ mma8451_idev->poll = mma8451_dev_poll; -+ mma8451_idev->poll_interval = POLL_INTERVAL; -+ mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN; -+ mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX; -+ idev = mma8451_idev->input; -+ idev->name = "mma845x"; -+ idev->id.bustype = BUS_I2C; -+ idev->evbit[0] = BIT_MASK(EV_ABS); -+ -+ input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); -+ input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); -+ input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); -+ -+ result = input_register_polled_device(mma8451_idev); -+ if (result) { -+ dev_err(&client->dev, "register poll device failed!\n"); -+ goto err_register_polled_device; -+ } -+ result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group); -+ if (result) { -+ dev_err(&client->dev, "create device file failed!\n"); -+ result = -EINVAL; -+ goto err_register_polled_device; -+ } -+ -+ result = of_property_read_u32(of_node, "position", &pos); -+ if (result) -+ pos = DEFAULT_POSITION; -+ mma_status.position = (int)pos; -+ -+ return 0; -+err_register_polled_device: -+ input_free_polled_device(mma8451_idev); -+err_alloc_poll_device: -+ hwmon_device_unregister(&client->dev); -+err_out: -+ return result; -+} -+ -+static int mma8451_stop_chip(struct i2c_client *client) -+{ -+ int ret = 0; -+ if (mma_status.active == MMA_ACTIVED) { -+ mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client, -+ MMA8451_CTRL_REG1); -+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, -+ mma_status.ctl_reg1 & 0xFE); -+ } -+ return ret; -+} -+ -+static int mma8451_remove(struct i2c_client *client) -+{ -+ int ret; -+ ret = mma8451_stop_chip(client); -+ hwmon_device_unregister(hwmon_dev); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int mma8451_suspend(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ -+ return mma8451_stop_chip(client); -+} -+ -+static int mma8451_resume(struct device *dev) -+{ -+ int ret = 0; -+ struct i2c_client *client = to_i2c_client(dev); -+ if (mma_status.active == MMA_ACTIVED) -+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, -+ mma_status.ctl_reg1); -+ return ret; -+ -+} -+#endif -+ -+static const struct i2c_device_id mma8451_id[] = { -+ {"mma8451", 0}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, mma8451_id); -+ -+static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume); -+static struct i2c_driver mma8451_driver = { -+ .driver = { -+ .name = "mma8451", -+ .owner = THIS_MODULE, -+ .pm = &mma8451_pm_ops, -+ }, -+ .probe = mma8451_probe, -+ .remove = mma8451_remove, -+ .id_table = mma8451_id, -+}; -+ -+static int __init mma8451_init(void) -+{ -+ /* register driver */ -+ int res; -+ -+ res = i2c_add_driver(&mma8451_driver); -+ if (res < 0) { -+ printk(KERN_INFO "add mma8451 i2c driver failed\n"); -+ return -ENODEV; -+ } -+ return res; -+} -+ -+static void __exit mma8451_exit(void) -+{ -+ i2c_del_driver(&mma8451_driver); -+} -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(mma8451_init); -+module_exit(mma8451_exit); -diff -Nur linux-3.14.22.orig/drivers/i2c/busses/i2c-imx.c linux-3.14.22/drivers/i2c/busses/i2c-imx.c ---- linux-3.14.22.orig/drivers/i2c/busses/i2c-imx.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/i2c/busses/i2c-imx.c 2014-10-22 14:55:52.054220001 -0500 -@@ -184,6 +184,9 @@ - int stopped; - unsigned int ifdr; /* IMX_I2C_IFDR */ - const struct imx_i2c_hwdata *hwdata; -+ -+ unsigned int cur_clk; -+ unsigned int bitrate; - }; - - static const struct imx_i2c_hwdata imx1_i2c_hwdata = { -@@ -305,6 +308,51 @@ - return 0; - } - -+static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) -+{ -+ struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; -+ unsigned ndivs = i2c_imx->hwdata->ndivs; -+ unsigned int i2c_clk_rate; -+ unsigned int div; -+ int i; -+ -+ /* Divider value calculation */ -+ i2c_clk_rate = clk_get_rate(i2c_imx->clk); -+ if (i2c_imx->cur_clk == i2c_clk_rate) -+ return; -+ else -+ i2c_imx->cur_clk = i2c_clk_rate; -+ -+ div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate; -+ if (div < i2c_clk_div[0].div) -+ i = 0; -+ else if (div > i2c_clk_div[ndivs - 1].div) -+ i = ndivs - 1; -+ else -+ for (i = 0; i2c_clk_div[i].div < div; i++) -+ ; -+ -+ /* Store divider value */ -+ i2c_imx->ifdr = imx_i2c_clk_div[i].val; -+ -+ /* -+ * There dummy delay is calculated. -+ * It should be about one I2C clock period long. -+ * This delay is used in I2C bus disable function -+ * to fix chip hardware bug. -+ */ -+ i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div -+ + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); -+ -+ /* dev_dbg() can't be used, because adapter is not yet registered */ -+#ifdef CONFIG_I2C_DEBUG_BUS -+ dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", -+ __func__, i2c_clk_rate, div); -+ dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", -+ __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); -+#endif -+} -+ - static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) - { - unsigned int temp = 0; -@@ -312,6 +360,7 @@ - - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - -+ i2c_imx_set_clk(i2c_imx); - result = clk_prepare_enable(i2c_imx->clk); - if (result) - return result; -@@ -367,45 +416,6 @@ - clk_disable_unprepare(i2c_imx->clk); - } - --static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, -- unsigned int rate) --{ -- struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; -- unsigned int i2c_clk_rate; -- unsigned int div; -- int i; -- -- /* Divider value calculation */ -- i2c_clk_rate = clk_get_rate(i2c_imx->clk); -- div = (i2c_clk_rate + rate - 1) / rate; -- if (div < i2c_clk_div[0].div) -- i = 0; -- else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) -- i = i2c_imx->hwdata->ndivs - 1; -- else -- for (i = 0; i2c_clk_div[i].div < div; i++); -- -- /* Store divider value */ -- i2c_imx->ifdr = i2c_clk_div[i].val; -- -- /* -- * There dummy delay is calculated. -- * It should be about one I2C clock period long. -- * This delay is used in I2C bus disable function -- * to fix chip hardware bug. -- */ -- i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div -- + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); -- -- /* dev_dbg() can't be used, because adapter is not yet registered */ --#ifdef CONFIG_I2C_DEBUG_BUS -- dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", -- __func__, i2c_clk_rate, div); -- dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", -- __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); --#endif --} -- - static irqreturn_t i2c_imx_isr(int irq, void *dev_id) - { - struct imx_i2c_struct *i2c_imx = dev_id; -@@ -600,7 +610,6 @@ - struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); - void __iomem *base; - int irq, ret; -- u32 bitrate; - - dev_dbg(&pdev->dev, "<%s>\n", __func__); - -@@ -664,12 +673,12 @@ - i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); - - /* Set up clock divider */ -- bitrate = IMX_I2C_BIT_RATE; -+ i2c_imx->bitrate = IMX_I2C_BIT_RATE; - ret = of_property_read_u32(pdev->dev.of_node, -- "clock-frequency", &bitrate); -+ "clock-frequency", &i2c_imx->bitrate); - if (ret < 0 && pdata && pdata->bitrate) -- bitrate = pdata->bitrate; -- i2c_imx_set_clk(i2c_imx, bitrate); -+ i2c_imx->bitrate = pdata->bitrate; -+ i2c_imx_set_clk(i2c_imx); - - /* Set up chip registers to defaults */ - imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, -diff -Nur linux-3.14.22.orig/drivers/input/keyboard/gpio_keys.c linux-3.14.22/drivers/input/keyboard/gpio_keys.c ---- linux-3.14.22.orig/drivers/input/keyboard/gpio_keys.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/input/keyboard/gpio_keys.c 2014-10-22 14:55:52.054220001 -0500 -@@ -3,6 +3,7 @@ - * - * Copyright 2005 Phil Blundell - * Copyright 2010, 2011 David Jander -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -473,6 +474,8 @@ - - isr = gpio_keys_gpio_isr; - irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; -+ if (bdata->button->wakeup) -+ irqflags |= IRQF_NO_SUSPEND; - - } else { - if (!button->irq) { -diff -Nur linux-3.14.22.orig/drivers/input/keyboard/imx_keypad.c linux-3.14.22/drivers/input/keyboard/imx_keypad.c ---- linux-3.14.22.orig/drivers/input/keyboard/imx_keypad.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/input/keyboard/imx_keypad.c 2014-10-22 14:55:52.054220001 -0500 -@@ -1,6 +1,7 @@ - /* - * Driver for the IMX keypad port. - * Copyright (C) 2009 Alberto Panizzo -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -548,6 +549,8 @@ - - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(kbd->irq); -+ else -+ pinctrl_pm_select_sleep_state(dev); - - return 0; - } -@@ -561,6 +564,8 @@ - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(kbd->irq); -+ else -+ pinctrl_pm_select_default_state(dev); - - mutex_lock(&input_dev->mutex); - -diff -Nur linux-3.14.22.orig/drivers/input/misc/mma8450.c linux-3.14.22/drivers/input/misc/mma8450.c ---- linux-3.14.22.orig/drivers/input/misc/mma8450.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/input/misc/mma8450.c 2014-10-22 14:55:52.054220001 -0500 -@@ -1,7 +1,7 @@ - /* - * Driver for Freescale's 3-Axis Accelerometer MMA8450 - * -- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. -+ * 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 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #define MMA8450_DRV_NAME "mma8450" - -@@ -51,11 +52,22 @@ - - #define MMA8450_CTRL_REG1 0x38 - #define MMA8450_CTRL_REG2 0x39 -+#define MMA8450_ID 0xC6 -+#define MMA8450_WHO_AM_I 0x0F -+ -+enum { -+ MODE_STANDBY = 0, -+ MODE_2G, -+ MODE_4G, -+ MODE_8G, -+}; - - /* mma8450 status */ - struct mma8450 { - struct i2c_client *client; - struct input_polled_dev *idev; -+ struct mutex mma8450_lock; -+ u8 mode; - }; - - static int mma8450_read(struct mma8450 *m, unsigned off) -@@ -112,16 +124,19 @@ - int ret; - u8 buf[6]; - -- ret = mma8450_read(m, MMA8450_STATUS); -- if (ret < 0) -- return; -+ mutex_lock(&m->mma8450_lock); - -- if (!(ret & MMA8450_STATUS_ZXYDR)) -+ ret = mma8450_read(m, MMA8450_STATUS); -+ if (ret < 0 || !(ret & MMA8450_STATUS_ZXYDR)) { -+ mutex_unlock(&m->mma8450_lock); - return; -+ } - - ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf)); -- if (ret < 0) -+ if (ret < 0) { -+ mutex_unlock(&m->mma8450_lock); - return; -+ } - - x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf); - y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf); -@@ -131,10 +146,12 @@ - input_report_abs(dev->input, ABS_Y, y); - input_report_abs(dev->input, ABS_Z, z); - input_sync(dev->input); -+ -+ mutex_unlock(&m->mma8450_lock); - } - - /* Initialize the MMA8450 chip */ --static void mma8450_open(struct input_polled_dev *dev) -+static s32 mma8450_open(struct input_polled_dev *dev) - { - struct mma8450 *m = dev->private; - int err; -@@ -142,18 +159,20 @@ - /* enable all events from X/Y/Z, no FIFO */ - err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07); - if (err) -- return; -+ return err; - - /* - * Sleep mode poll rate - 50Hz - * System output data rate - 400Hz -- * Full scale selection - Active, +/- 2G -+ * Standby mode - */ -- err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01); -- if (err < 0) -- return; -- -+ err = mma8450_write(m, MMA8450_CTRL_REG1, MODE_STANDBY); -+ if (err) -+ return err; -+ m->mode = MODE_STANDBY; - msleep(MODE_CHANGE_DELAY_MS); -+ -+ return 0; - } - - static void mma8450_close(struct input_polled_dev *dev) -@@ -164,6 +183,76 @@ - mma8450_write(m, MMA8450_CTRL_REG2, 0x01); - } - -+static ssize_t mma8450_scalemode_show(struct device *dev, -+ struct device_attribute *attr, -+ char *buf) -+{ -+ int mode = 0; -+ struct mma8450 *m; -+ struct i2c_client *client = to_i2c_client(dev); -+ -+ m = i2c_get_clientdata(client); -+ -+ mutex_lock(&m->mma8450_lock); -+ mode = (int)m->mode; -+ mutex_unlock(&m->mma8450_lock); -+ -+ return sprintf(buf, "%d\n", mode); -+} -+ -+static ssize_t mma8450_scalemode_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned long mode; -+ int ret; -+ struct mma8450 *m = NULL; -+ struct i2c_client *client = to_i2c_client(dev); -+ -+ ret = strict_strtoul(buf, 10, &mode); -+ if (ret) { -+ dev_err(dev, "string transform error\n"); -+ return ret; -+ } -+ -+ if (mode > MODE_8G) { -+ dev_warn(dev, "not supported mode %d\n", (int)mode); -+ return count; -+ } -+ -+ m = i2c_get_clientdata(client); -+ -+ mutex_lock(&m->mma8450_lock); -+ if (mode == m->mode) { -+ mutex_unlock(&m->mma8450_lock); -+ return count; -+ } -+ -+ ret = mma8450_write(m, MMA8450_CTRL_REG1, mode); -+ if (ret < 0) { -+ mutex_unlock(&m->mma8450_lock); -+ return ret; -+ } -+ -+ msleep(MODE_CHANGE_DELAY_MS); -+ m->mode = (u8)mode; -+ mutex_unlock(&m->mma8450_lock); -+ -+ return count; -+} -+ -+static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, -+ mma8450_scalemode_show, mma8450_scalemode_store); -+ -+static struct attribute *mma8450_attributes[] = { -+ &dev_attr_scalemode.attr, -+ NULL -+}; -+ -+static const struct attribute_group mma8450_attr_group = { -+ .attrs = mma8450_attributes, -+}; -+ - /* - * I2C init/probing/exit functions - */ -@@ -172,7 +261,25 @@ - { - struct input_polled_dev *idev; - struct mma8450 *m; -- int err; -+ int err, client_id; -+ struct i2c_adapter *adapter = NULL; -+ -+ adapter = to_i2c_adapter(c->dev.parent); -+ err = i2c_check_functionality(adapter, -+ I2C_FUNC_SMBUS_BYTE | -+ I2C_FUNC_SMBUS_BYTE_DATA); -+ if (!err) -+ goto err_out; -+ -+ client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I); -+ -+ if (MMA8450_ID != client_id) { -+ dev_err(&c->dev, -+ "read chip ID 0x%x is not equal to 0x%x!\n", client_id, -+ MMA8450_ID); -+ err = -EINVAL; -+ goto err_out; -+ } - - m = kzalloc(sizeof(struct mma8450), GFP_KERNEL); - idev = input_allocate_polled_device(); -@@ -183,6 +290,7 @@ - - m->client = c; - m->idev = idev; -+ i2c_set_clientdata(c, m); - - idev->private = m; - idev->input->name = MMA8450_DRV_NAME; -@@ -190,8 +298,6 @@ - idev->poll = mma8450_poll; - idev->poll_interval = POLL_INTERVAL; - idev->poll_interval_max = POLL_INTERVAL_MAX; -- idev->open = mma8450_open; -- idev->close = mma8450_close; - - __set_bit(EV_ABS, idev->input->evbit); - input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32); -@@ -206,11 +312,32 @@ - - i2c_set_clientdata(c, m); - -+ mutex_init(&m->mma8450_lock); -+ -+ err = mma8450_open(idev); -+ if (err) { -+ dev_err(&c->dev, "failed to initialize mma8450\n"); -+ goto err_unreg_dev; -+ } -+ -+ err = sysfs_create_group(&c->dev.kobj, &mma8450_attr_group); -+ if (err) { -+ dev_err(&c->dev, "create device file failed!\n"); -+ err = -EINVAL; -+ goto err_close; -+ } -+ - return 0; - -+err_close: -+ mma8450_close(idev); -+err_unreg_dev: -+ mutex_destroy(&m->mma8450_lock); -+ input_unregister_polled_device(idev); - err_free_mem: - input_free_polled_device(idev); - kfree(m); -+err_out: - return err; - } - -@@ -219,6 +346,9 @@ - struct mma8450 *m = i2c_get_clientdata(c); - struct input_polled_dev *idev = m->idev; - -+ sysfs_remove_group(&c->dev.kobj, &mma8450_attr_group); -+ mma8450_close(idev); -+ mutex_destroy(&m->mma8450_lock); - input_unregister_polled_device(idev); - input_free_polled_device(idev); - kfree(m); -diff -Nur linux-3.14.22.orig/drivers/input/sparse-keymap.c linux-3.14.22/drivers/input/sparse-keymap.c ---- linux-3.14.22.orig/drivers/input/sparse-keymap.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/input/sparse-keymap.c 2014-10-22 14:55:52.090220001 -0500 -@@ -236,7 +236,7 @@ - * in an input device that was set up by sparse_keymap_setup(). - * NOTE: It is safe to cal this function while input device is - * still registered (however the drivers should care not to try to -- * use freed keymap and thus have to shut off interrups/polling -+ * use freed keymap and thus have to shut off interrupts/polling - * before freeing the keymap). - */ - void sparse_keymap_free(struct input_dev *dev) -diff -Nur linux-3.14.22.orig/drivers/Kconfig linux-3.14.22/drivers/Kconfig ---- linux-3.14.22.orig/drivers/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/Kconfig 2014-10-22 14:55:52.094220001 -0500 -@@ -96,6 +96,8 @@ - - source "drivers/memstick/Kconfig" - -+source "drivers/mxc/Kconfig" -+ - source "drivers/leds/Kconfig" - - source "drivers/accessibility/Kconfig" -diff -Nur linux-3.14.22.orig/drivers/leds/leds-gpio.c linux-3.14.22/drivers/leds/leds-gpio.c ---- linux-3.14.22.orig/drivers/leds/leds-gpio.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/leds/leds-gpio.c 2014-10-22 14:55:52.094220001 -0500 -@@ -3,7 +3,7 @@ - * - * Copyright (C) 2007 8D Technologies inc. - * Raphael Assenat -- * Copyright (C) 2008 Freescale Semiconductor, Inc. -+ * Copyright (C) 2008, 2014 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -203,6 +203,8 @@ - else - led.default_state = LEDS_GPIO_DEFSTATE_OFF; - } -+ if (of_get_property(child, "retain-state-suspended", NULL)) -+ led.retain_state_suspended = 1; - - ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], - &pdev->dev, NULL); -diff -Nur linux-3.14.22.orig/drivers/leds/leds-pwm.c linux-3.14.22/drivers/leds/leds-pwm.c ---- linux-3.14.22.orig/drivers/leds/leds-pwm.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/leds/leds-pwm.c 2014-10-22 14:55:52.598220001 -0500 -@@ -70,6 +70,10 @@ - - duty *= brightness; - do_div(duty, max); -+ -+ if (led_dat->active_low) -+ duty = led_dat->period - duty; -+ - led_dat->duty = duty; - - if (led_dat->can_sleep) -@@ -93,55 +97,75 @@ - } - } - --static int led_pwm_create_of(struct platform_device *pdev, -- struct led_pwm_priv *priv) -+static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, -+ struct led_pwm *led, struct device_node *child) - { -- struct device_node *child; -+ struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; - int ret; - -- for_each_child_of_node(pdev->dev.of_node, child) { -- struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; -+ led_data->active_low = led->active_low; -+ led_data->period = led->pwm_period_ns; -+ led_data->cdev.name = led->name; -+ led_data->cdev.default_trigger = led->default_trigger; -+ led_data->cdev.brightness_set = led_pwm_set; -+ led_data->cdev.brightness = LED_OFF; -+ led_data->cdev.max_brightness = led->max_brightness; -+ led_data->cdev.flags = LED_CORE_SUSPENDRESUME; -+ -+ if (child) -+ led_data->pwm = devm_of_pwm_get(dev, child, NULL); -+ else -+ led_data->pwm = devm_pwm_get(dev, led->name); -+ if (IS_ERR(led_data->pwm)) { -+ ret = PTR_ERR(led_data->pwm); -+ dev_err(dev, "unable to request PWM for %s: %d\n", -+ led->name, ret); -+ return ret; -+ } - -- led_dat->cdev.name = of_get_property(child, "label", -- NULL) ? : child->name; -+ if (child) -+ led_data->period = pwm_get_period(led_data->pwm); - -- led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL); -- if (IS_ERR(led_dat->pwm)) { -- dev_err(&pdev->dev, "unable to request PWM for %s\n", -- led_dat->cdev.name); -- ret = PTR_ERR(led_dat->pwm); -- goto err; -- } -- /* Get the period from PWM core when n*/ -- led_dat->period = pwm_get_period(led_dat->pwm); -+ led_data->can_sleep = pwm_can_sleep(led_data->pwm); -+ if (led_data->can_sleep) -+ INIT_WORK(&led_data->work, led_pwm_work); - -- led_dat->cdev.default_trigger = of_get_property(child, -+ ret = led_classdev_register(dev, &led_data->cdev); -+ if (ret == 0) { -+ priv->num_leds++; -+ } else { -+ dev_err(dev, "failed to register PWM led for %s: %d\n", -+ led->name, ret); -+ } -+ -+ return ret; -+} -+ -+static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv) -+{ -+ struct device_node *child; -+ struct led_pwm led; -+ int ret = 0; -+ -+ memset(&led, 0, sizeof(led)); -+ -+ for_each_child_of_node(dev->of_node, child) { -+ led.name = of_get_property(child, "label", NULL) ? : -+ child->name; -+ -+ led.default_trigger = of_get_property(child, - "linux,default-trigger", NULL); -+ led.active_low = of_property_read_bool(child, "active-low"); - of_property_read_u32(child, "max-brightness", -- &led_dat->cdev.max_brightness); -+ &led.max_brightness); - -- led_dat->cdev.brightness_set = led_pwm_set; -- led_dat->cdev.brightness = LED_OFF; -- led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; -- -- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); -- if (led_dat->can_sleep) -- INIT_WORK(&led_dat->work, led_pwm_work); -- -- ret = led_classdev_register(&pdev->dev, &led_dat->cdev); -- if (ret < 0) { -- dev_err(&pdev->dev, "failed to register for %s\n", -- led_dat->cdev.name); -+ ret = led_pwm_add(dev, priv, &led, child); -+ if (ret) { - of_node_put(child); -- goto err; -+ break; - } -- priv->num_leds++; - } - -- return 0; --err: -- led_pwm_cleanup(priv); -- - return ret; - } - -@@ -167,51 +191,23 @@ - - if (pdata) { - for (i = 0; i < count; i++) { -- struct led_pwm *cur_led = &pdata->leds[i]; -- struct led_pwm_data *led_dat = &priv->leds[i]; -- -- led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name); -- if (IS_ERR(led_dat->pwm)) { -- ret = PTR_ERR(led_dat->pwm); -- dev_err(&pdev->dev, -- "unable to request PWM for %s\n", -- cur_led->name); -- goto err; -- } -- -- led_dat->cdev.name = cur_led->name; -- led_dat->cdev.default_trigger = cur_led->default_trigger; -- led_dat->active_low = cur_led->active_low; -- led_dat->period = cur_led->pwm_period_ns; -- led_dat->cdev.brightness_set = led_pwm_set; -- led_dat->cdev.brightness = LED_OFF; -- led_dat->cdev.max_brightness = cur_led->max_brightness; -- led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; -- -- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); -- if (led_dat->can_sleep) -- INIT_WORK(&led_dat->work, led_pwm_work); -- -- ret = led_classdev_register(&pdev->dev, &led_dat->cdev); -- if (ret < 0) -- goto err; -+ ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i], -+ NULL); -+ if (ret) -+ break; - } -- priv->num_leds = count; - } else { -- ret = led_pwm_create_of(pdev, priv); -- if (ret) -- return ret; -+ ret = led_pwm_create_of(&pdev->dev, priv); -+ } -+ -+ if (ret) { -+ led_pwm_cleanup(priv); -+ return ret; - } - - platform_set_drvdata(pdev, priv); - - return 0; -- --err: -- priv->num_leds = i; -- led_pwm_cleanup(priv); -- -- return ret; - } - - static int led_pwm_remove(struct platform_device *pdev) -diff -Nur linux-3.14.22.orig/drivers/mailbox/mailbox.c linux-3.14.22/drivers/mailbox/mailbox.c ---- linux-3.14.22.orig/drivers/mailbox/mailbox.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/mailbox/mailbox.c 2014-10-22 14:55:52.602220001 -0500 -@@ -0,0 +1,488 @@ -+/* -+ * Mailbox: Common code for Mailbox controllers and users -+ * -+ * Copyright (C) 2014 Linaro Ltd. -+ * Author: Jassi Brar -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define TXDONE_BY_IRQ (1 << 0) /* controller has remote RTR irq */ -+#define TXDONE_BY_POLL (1 << 1) /* controller can read status of last TX */ -+#define TXDONE_BY_ACK (1 << 2) /* S/W ACK recevied by Client ticks the TX */ -+ -+static LIST_HEAD(mbox_cons); -+static DEFINE_MUTEX(con_mutex); -+ -+static int _add_to_rbuf(struct mbox_chan *chan, void *mssg) -+{ -+ int idx; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&chan->lock, flags); -+ -+ /* See if there is any space left */ -+ if (chan->msg_count == MBOX_TX_QUEUE_LEN) { -+ spin_unlock_irqrestore(&chan->lock, flags); -+ return -ENOMEM; -+ } -+ -+ idx = chan->msg_free; -+ chan->msg_data[idx] = mssg; -+ chan->msg_count++; -+ -+ if (idx == MBOX_TX_QUEUE_LEN - 1) -+ chan->msg_free = 0; -+ else -+ chan->msg_free++; -+ -+ spin_unlock_irqrestore(&chan->lock, flags); -+ -+ return idx; -+} -+ -+static void _msg_submit(struct mbox_chan *chan) -+{ -+ unsigned count, idx; -+ unsigned long flags; -+ void *data; -+ int err; -+ -+ spin_lock_irqsave(&chan->lock, flags); -+ -+ if (!chan->msg_count || chan->active_req) { -+ spin_unlock_irqrestore(&chan->lock, flags); -+ return; -+ } -+ -+ count = chan->msg_count; -+ idx = chan->msg_free; -+ if (idx >= count) -+ idx -= count; -+ else -+ idx += MBOX_TX_QUEUE_LEN - count; -+ -+ data = chan->msg_data[idx]; -+ -+ /* Try to submit a message to the MBOX controller */ -+ err = chan->mbox->ops->send_data(chan, data); -+ if (!err) { -+ chan->active_req = data; -+ chan->msg_count--; -+ } -+ -+ spin_unlock_irqrestore(&chan->lock, flags); -+} -+ -+static void tx_tick(struct mbox_chan *chan, int r) -+{ -+ unsigned long flags; -+ void *mssg; -+ -+ spin_lock_irqsave(&chan->lock, flags); -+ mssg = chan->active_req; -+ chan->active_req = NULL; -+ spin_unlock_irqrestore(&chan->lock, flags); -+ -+ /* Submit next message */ -+ _msg_submit(chan); -+ -+ /* Notify the client */ -+ if (chan->cl->tx_block) -+ complete(&chan->tx_complete); -+ else if (mssg && chan->cl->tx_done) -+ chan->cl->tx_done(chan->cl, mssg, r); -+} -+ -+static void poll_txdone(unsigned long data) -+{ -+ struct mbox_controller *mbox = (struct mbox_controller *)data; -+ bool txdone, resched = false; -+ int i; -+ -+ for (i = 0; i < mbox->num_chans; i++) { -+ struct mbox_chan *chan = &mbox->chans[i]; -+ -+ if (chan->active_req && chan->cl) { -+ resched = true; -+ txdone = chan->mbox->ops->last_tx_done(chan); -+ if (txdone) -+ tx_tick(chan, 0); -+ } -+ } -+ -+ if (resched) -+ mod_timer(&mbox->poll, -+ jiffies + msecs_to_jiffies(mbox->period)); -+} -+ -+/** -+ * mbox_chan_received_data - A way for controller driver to push data -+ * received from remote to the upper layer. -+ * @chan: Pointer to the mailbox channel on which RX happened. -+ * @data: Client specific message typecasted as void * -+ * -+ * After startup and before shutdown any data received on the chan -+ * is passed on to the API via atomic mbox_chan_received_data(). -+ * The controller should ACK the RX only after this call returns. -+ */ -+void mbox_chan_received_data(struct mbox_chan *chan, void *mssg) -+{ -+ /* No buffering the received data */ -+ if (chan->cl->rx_callback) -+ chan->cl->rx_callback(chan->cl, mssg); -+} -+EXPORT_SYMBOL_GPL(mbox_chan_received_data); -+ -+/** -+ * mbox_chan_txdone - A way for controller driver to notify the -+ * framework that the last TX has completed. -+ * @chan: Pointer to the mailbox chan on which TX happened. -+ * @r: Status of last TX - OK or ERROR -+ * -+ * The controller that has IRQ for TX ACK calls this atomic API -+ * to tick the TX state machine. It works only if txdone_irq -+ * is set by the controller. -+ */ -+void mbox_chan_txdone(struct mbox_chan *chan, int r) -+{ -+ if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) { -+ pr_err("Controller can't run the TX ticker\n"); -+ return; -+ } -+ -+ tx_tick(chan, r); -+} -+EXPORT_SYMBOL_GPL(mbox_chan_txdone); -+ -+/** -+ * mbox_client_txdone - The way for a client to run the TX state machine. -+ * @chan: Mailbox channel assigned to this client. -+ * @r: Success status of last transmission. -+ * -+ * The client/protocol had received some 'ACK' packet and it notifies -+ * the API that the last packet was sent successfully. This only works -+ * if the controller can't sense TX-Done. -+ */ -+void mbox_client_txdone(struct mbox_chan *chan, int r) -+{ -+ if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) { -+ pr_err("Client can't run the TX ticker\n"); -+ return; -+ } -+ -+ tx_tick(chan, r); -+} -+EXPORT_SYMBOL_GPL(mbox_client_txdone); -+ -+/** -+ * mbox_client_peek_data - A way for client driver to pull data -+ * received from remote by the controller. -+ * @chan: Mailbox channel assigned to this client. -+ * -+ * A poke to controller driver for any received data. -+ * The data is actually passed onto client via the -+ * mbox_chan_received_data() -+ * The call can be made from atomic context, so the controller's -+ * implementation of peek_data() must not sleep. -+ * -+ * Return: True, if controller has, and is going to push after this, -+ * some data. -+ * False, if controller doesn't have any data to be read. -+ */ -+bool mbox_client_peek_data(struct mbox_chan *chan) -+{ -+ if (chan->mbox->ops->peek_data) -+ return chan->mbox->ops->peek_data(chan); -+ -+ return false; -+} -+EXPORT_SYMBOL_GPL(mbox_client_peek_data); -+ -+/** -+ * mbox_send_message - For client to submit a message to be -+ * sent to the remote. -+ * @chan: Mailbox channel assigned to this client. -+ * @mssg: Client specific message typecasted. -+ * -+ * For client to submit data to the controller destined for a remote -+ * processor. If the client had set 'tx_block', the call will return -+ * either when the remote receives the data or when 'tx_tout' millisecs -+ * run out. -+ * In non-blocking mode, the requests are buffered by the API and a -+ * non-negative token is returned for each queued request. If the request -+ * is not queued, a negative token is returned. Upon failure or successful -+ * TX, the API calls 'tx_done' from atomic context, from which the client -+ * could submit yet another request. -+ * In blocking mode, 'tx_done' is not called, effectively making the -+ * queue length 1. -+ * The pointer to message should be preserved until it is sent -+ * over the chan, i.e, tx_done() is made. -+ * This function could be called from atomic context as it simply -+ * queues the data and returns a token against the request. -+ * -+ * Return: Non-negative integer for successful submission (non-blocking mode) -+ * or transmission over chan (blocking mode). -+ * Negative value denotes failure. -+ */ -+int mbox_send_message(struct mbox_chan *chan, void *mssg) -+{ -+ int t; -+ -+ if (!chan || !chan->cl) -+ return -EINVAL; -+ -+ t = _add_to_rbuf(chan, mssg); -+ if (t < 0) { -+ pr_err("Try increasing MBOX_TX_QUEUE_LEN\n"); -+ return t; -+ } -+ -+ _msg_submit(chan); -+ -+ reinit_completion(&chan->tx_complete); -+ -+ if (chan->txdone_method == TXDONE_BY_POLL) -+ poll_txdone((unsigned long)chan->mbox); -+ -+ if (chan->cl->tx_block && chan->active_req) { -+ unsigned long wait; -+ int ret; -+ -+ if (!chan->cl->tx_tout) /* wait for ever */ -+ wait = msecs_to_jiffies(3600000); -+ else -+ wait = msecs_to_jiffies(chan->cl->tx_tout); -+ -+ ret = wait_for_completion_timeout(&chan->tx_complete, wait); -+ if (ret == 0) { -+ t = -EIO; -+ tx_tick(chan, -EIO); -+ } -+ } -+ -+ return t; -+} -+EXPORT_SYMBOL_GPL(mbox_send_message); -+ -+/** -+ * mbox_request_channel - Request a mailbox channel. -+ * @cl: Identity of the client requesting the channel. -+ * -+ * The Client specifies its requirements and capabilities while asking for -+ * a mailbox channel. It can't be called from atomic context. -+ * The channel is exclusively allocated and can't be used by another -+ * client before the owner calls mbox_free_channel. -+ * After assignment, any packet received on this channel will be -+ * handed over to the client via the 'rx_callback'. -+ * The framework holds reference to the client, so the mbox_client -+ * structure shouldn't be modified until the mbox_free_channel returns. -+ * -+ * Return: Pointer to the channel assigned to the client if successful. -+ * ERR_PTR for request failure. -+ */ -+struct mbox_chan *mbox_request_channel(struct mbox_client *cl) -+{ -+ struct device *dev = cl->dev; -+ struct mbox_controller *mbox; -+ struct of_phandle_args spec; -+ struct mbox_chan *chan; -+ unsigned long flags; -+ int count, i, ret; -+ -+ if (!dev || !dev->of_node) { -+ pr_err("%s: No owner device node\n", __func__); -+ return ERR_PTR(-ENODEV); -+ } -+ -+ count = of_property_count_strings(dev->of_node, "mbox-names"); -+ if (count < 0) { -+ pr_err("%s: mbox-names property of node '%s' missing\n", -+ __func__, dev->of_node->full_name); -+ return ERR_PTR(-ENODEV); -+ } -+ -+ mutex_lock(&con_mutex); -+ -+ ret = -ENODEV; -+ for (i = 0; i < count; i++) { -+ const char *s; -+ -+ if (of_property_read_string_index(dev->of_node, -+ "mbox-names", i, &s)) -+ continue; -+ -+ if (strcmp(cl->chan_name, s)) -+ continue; -+ -+ if (of_parse_phandle_with_args(dev->of_node, -+ "mbox", "#mbox-cells", i, &spec)) -+ continue; -+ -+ chan = NULL; -+ list_for_each_entry(mbox, &mbox_cons, node) -+ if (mbox->dev->of_node == spec.np) { -+ chan = mbox->of_xlate(mbox, &spec); -+ break; -+ } -+ -+ of_node_put(spec.np); -+ -+ if (!chan) -+ continue; -+ -+ ret = -EBUSY; -+ if (!chan->cl && try_module_get(mbox->dev->driver->owner)) -+ break; -+ } -+ -+ if (i == count) { -+ mutex_unlock(&con_mutex); -+ return ERR_PTR(ret); -+ } -+ -+ spin_lock_irqsave(&chan->lock, flags); -+ chan->msg_free = 0; -+ chan->msg_count = 0; -+ chan->active_req = NULL; -+ chan->cl = cl; -+ init_completion(&chan->tx_complete); -+ -+ if (chan->txdone_method == TXDONE_BY_POLL -+ && cl->knows_txdone) -+ chan->txdone_method |= TXDONE_BY_ACK; -+ spin_unlock_irqrestore(&chan->lock, flags); -+ -+ ret = chan->mbox->ops->startup(chan); -+ if (ret) { -+ pr_err("Unable to startup the chan (%d)\n", ret); -+ mbox_free_channel(chan); -+ chan = ERR_PTR(ret); -+ } -+ -+ mutex_unlock(&con_mutex); -+ return chan; -+} -+EXPORT_SYMBOL_GPL(mbox_request_channel); -+ -+/** -+ * mbox_free_channel - The client relinquishes control of a mailbox -+ * channel by this call. -+ * @chan: The mailbox channel to be freed. -+ */ -+void mbox_free_channel(struct mbox_chan *chan) -+{ -+ unsigned long flags; -+ -+ if (!chan || !chan->cl) -+ return; -+ -+ chan->mbox->ops->shutdown(chan); -+ -+ /* The queued TX requests are simply aborted, no callbacks are made */ -+ spin_lock_irqsave(&chan->lock, flags); -+ chan->cl = NULL; -+ chan->active_req = NULL; -+ if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK)) -+ chan->txdone_method = TXDONE_BY_POLL; -+ -+ module_put(chan->mbox->dev->driver->owner); -+ spin_unlock_irqrestore(&chan->lock, flags); -+} -+EXPORT_SYMBOL_GPL(mbox_free_channel); -+ -+static struct mbox_chan * -+of_mbox_index_xlate(struct mbox_controller *mbox, -+ const struct of_phandle_args *sp) -+{ -+ int ind = sp->args[0]; -+ -+ if (ind >= mbox->num_chans) -+ return NULL; -+ -+ return &mbox->chans[ind]; -+} -+ -+/** -+ * mbox_controller_register - Register the mailbox controller -+ * @mbox: Pointer to the mailbox controller. -+ * -+ * The controller driver registers its communication chans -+ */ -+int mbox_controller_register(struct mbox_controller *mbox) -+{ -+ int i, txdone; -+ -+ /* Sanity check */ -+ if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans) -+ return -EINVAL; -+ -+ if (mbox->txdone_irq) -+ txdone = TXDONE_BY_IRQ; -+ else if (mbox->txdone_poll) -+ txdone = TXDONE_BY_POLL; -+ else /* It has to be ACK then */ -+ txdone = TXDONE_BY_ACK; -+ -+ if (txdone == TXDONE_BY_POLL) { -+ mbox->poll.function = &poll_txdone; -+ mbox->poll.data = (unsigned long)mbox; -+ init_timer(&mbox->poll); -+ } -+ -+ for (i = 0; i < mbox->num_chans; i++) { -+ struct mbox_chan *chan = &mbox->chans[i]; -+ chan->cl = NULL; -+ chan->mbox = mbox; -+ chan->txdone_method = txdone; -+ spin_lock_init(&chan->lock); -+ } -+ -+ if (!mbox->of_xlate) -+ mbox->of_xlate = of_mbox_index_xlate; -+ -+ mutex_lock(&con_mutex); -+ list_add_tail(&mbox->node, &mbox_cons); -+ mutex_unlock(&con_mutex); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(mbox_controller_register); -+ -+/** -+ * mbox_controller_unregister - UnRegister the mailbox controller -+ * @mbox: Pointer to the mailbox controller. -+ */ -+void mbox_controller_unregister(struct mbox_controller *mbox) -+{ -+ int i; -+ -+ if (!mbox) -+ return; -+ -+ mutex_lock(&con_mutex); -+ -+ list_del(&mbox->node); -+ -+ for (i = 0; i < mbox->num_chans; i++) -+ mbox_free_channel(&mbox->chans[i]); -+ -+ if (mbox->txdone_poll) -+ del_timer_sync(&mbox->poll); -+ -+ mutex_unlock(&con_mutex); -+} -+EXPORT_SYMBOL_GPL(mbox_controller_unregister); -diff -Nur linux-3.14.22.orig/drivers/mailbox/Makefile linux-3.14.22/drivers/mailbox/Makefile ---- linux-3.14.22.orig/drivers/mailbox/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mailbox/Makefile 2014-10-22 14:55:52.602220001 -0500 -@@ -1,3 +1,7 @@ -+# Generic MAILBOX API -+ -+obj-$(CONFIG_MAILBOX) += mailbox.o -+ - obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o - - obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o -diff -Nur linux-3.14.22.orig/drivers/mailbox/pl320-ipc.c linux-3.14.22/drivers/mailbox/pl320-ipc.c ---- linux-3.14.22.orig/drivers/mailbox/pl320-ipc.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mailbox/pl320-ipc.c 2014-10-22 14:55:52.602220001 -0500 -@@ -26,7 +26,7 @@ - #include - #include - --#include -+#include - - #define IPCMxSOURCE(m) ((m) * 0x40) - #define IPCMxDSET(m) (((m) * 0x40) + 0x004) -diff -Nur linux-3.14.22.orig/drivers/Makefile linux-3.14.22/drivers/Makefile ---- linux-3.14.22.orig/drivers/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/Makefile 2014-10-22 14:55:52.602220001 -0500 -@@ -111,6 +111,7 @@ - obj-$(CONFIG_CPU_FREQ) += cpufreq/ - obj-$(CONFIG_CPU_IDLE) += cpuidle/ - obj-y += mmc/ -+obj-$(CONFIG_ARCH_MXC) += mxc/ - obj-$(CONFIG_MEMSTICK) += memstick/ - obj-y += leds/ - obj-$(CONFIG_INFINIBAND) += infiniband/ -diff -Nur linux-3.14.22.orig/drivers/media/platform/Kconfig linux-3.14.22/drivers/media/platform/Kconfig ---- linux-3.14.22.orig/drivers/media/platform/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/media/platform/Kconfig 2014-10-22 14:55:52.602220001 -0500 -@@ -115,6 +115,21 @@ - To compile this driver as a module, choose M here: the module - will be called s3c-camif. - -+config VIDEO_MXC_OUTPUT -+ tristate "MXC Video For Linux Video Output" -+ depends on VIDEO_DEV && ARCH_MXC && FB_MXC -+ select VIDEOBUF_DMA_CONTIG -+ ---help--- -+ This is the video4linux2 output driver based on MXC module. -+ -+config VIDEO_MXC_CAPTURE -+ tristate "MXC Video For Linux Video Capture" -+ depends on VIDEO_V4L2 && VIDEO_V4L2_INT_DEVICE -+ ---help--- -+ This is the video4linux2 capture driver based on i.MX video-in module. -+ -+source "drivers/media/platform/mxc/capture/Kconfig" -+source "drivers/media/platform/mxc/output/Kconfig" - source "drivers/media/platform/soc_camera/Kconfig" - source "drivers/media/platform/exynos4-is/Kconfig" - source "drivers/media/platform/s5p-tv/Kconfig" -diff -Nur linux-3.14.22.orig/drivers/media/platform/Makefile linux-3.14.22/drivers/media/platform/Makefile ---- linux-3.14.22.orig/drivers/media/platform/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/media/platform/Makefile 2014-10-22 14:55:52.602220001 -0500 -@@ -51,4 +51,7 @@ - - obj-$(CONFIG_ARCH_OMAP) += omap/ - -+obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/capture/ -+obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/ -+ - ccflags-y += -I$(srctree)/drivers/media/i2c -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/adv7180.c linux-3.14.22/drivers/media/platform/mxc/capture/adv7180.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/adv7180.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/adv7180.c 2014-10-22 14:55:52.606220001 -0500 -@@ -0,0 +1,1344 @@ -+/* -+ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file adv7180.c -+ * -+ * @brief Analog Device ADV7180 video decoder functions -+ * -+ * @ingroup Camera -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+ -+#define ADV7180_VOLTAGE_ANALOG 1800000 -+#define ADV7180_VOLTAGE_DIGITAL_CORE 1800000 -+#define ADV7180_VOLTAGE_DIGITAL_IO 3300000 -+#define ADV7180_VOLTAGE_PLL 1800000 -+ -+static struct regulator *dvddio_regulator; -+static struct regulator *dvdd_regulator; -+static struct regulator *avdd_regulator; -+static struct regulator *pvdd_regulator; -+static int pwn_gpio; -+ -+static int adv7180_probe(struct i2c_client *adapter, -+ const struct i2c_device_id *id); -+static int adv7180_detach(struct i2c_client *client); -+ -+static const struct i2c_device_id adv7180_id[] = { -+ {"adv7180", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, adv7180_id); -+ -+static struct i2c_driver adv7180_i2c_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "adv7180", -+ }, -+ .probe = adv7180_probe, -+ .remove = adv7180_detach, -+ .id_table = adv7180_id, -+}; -+ -+/*! -+ * Maintains the information on the current state of the sensor. -+ */ -+struct sensor { -+ struct sensor_data sen; -+ v4l2_std_id std_id; -+} adv7180_data; -+ -+ -+/*! List of input video formats supported. The video formats is corresponding -+ * with v4l2 id in video_fmt_t -+ */ -+typedef enum { -+ ADV7180_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ -+ ADV7180_PAL, /*!< (B, G, H, I, N)PAL video signal. */ -+ ADV7180_NOT_LOCKED, /*!< Not locked on a signal. */ -+} video_fmt_idx; -+ -+/*! Number of video standards supported (including 'not locked' signal). */ -+#define ADV7180_STD_MAX (ADV7180_PAL + 1) -+ -+/*! Video format structure. */ -+typedef struct { -+ int v4l2_id; /*!< Video for linux ID. */ -+ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ -+ u16 raw_width; /*!< Raw width. */ -+ u16 raw_height; /*!< Raw height. */ -+ u16 active_width; /*!< Active width. */ -+ u16 active_height; /*!< Active height. */ -+} video_fmt_t; -+ -+/*! Description of video formats supported. -+ * -+ * PAL: raw=720x625, active=720x576. -+ * NTSC: raw=720x525, active=720x480. -+ */ -+static video_fmt_t video_fmts[] = { -+ { /*! NTSC */ -+ .v4l2_id = V4L2_STD_NTSC, -+ .name = "NTSC", -+ .raw_width = 720, /* SENS_FRM_WIDTH */ -+ .raw_height = 525, /* SENS_FRM_HEIGHT */ -+ .active_width = 720, /* ACT_FRM_WIDTH plus 1 */ -+ .active_height = 480, /* ACT_FRM_WIDTH plus 1 */ -+ }, -+ { /*! (B, G, H, I, N) PAL */ -+ .v4l2_id = V4L2_STD_PAL, -+ .name = "PAL", -+ .raw_width = 720, -+ .raw_height = 625, -+ .active_width = 720, -+ .active_height = 576, -+ }, -+ { /*! Unlocked standard */ -+ .v4l2_id = V4L2_STD_ALL, -+ .name = "Autodetect", -+ .raw_width = 720, -+ .raw_height = 625, -+ .active_width = 720, -+ .active_height = 576, -+ }, -+}; -+ -+/*!* Standard index of ADV7180. */ -+static video_fmt_idx video_idx = ADV7180_PAL; -+ -+/*! @brief This mutex is used to provide mutual exclusion. -+ * -+ * Create a mutex that can be used to provide mutually exclusive -+ * read/write access to the globally accessible data structures -+ * and variables that were defined above. -+ */ -+static DEFINE_MUTEX(mutex); -+ -+#define IF_NAME "adv7180" -+#define ADV7180_INPUT_CTL 0x00 /* Input Control */ -+#define ADV7180_STATUS_1 0x10 /* Status #1 */ -+#define ADV7180_BRIGHTNESS 0x0a /* Brightness */ -+#define ADV7180_IDENT 0x11 /* IDENT */ -+#define ADV7180_VSYNC_FIELD_CTL_1 0x31 /* VSYNC Field Control #1 */ -+#define ADV7180_MANUAL_WIN_CTL 0x3d /* Manual Window Control */ -+#define ADV7180_SD_SATURATION_CB 0xe3 /* SD Saturation Cb */ -+#define ADV7180_SD_SATURATION_CR 0xe4 /* SD Saturation Cr */ -+#define ADV7180_PWR_MNG 0x0f /* Power Management */ -+ -+/* supported controls */ -+/* This hasn't been fully implemented yet. -+ * This is how it should work, though. */ -+static struct v4l2_queryctrl adv7180_qctrl[] = { -+ { -+ .id = V4L2_CID_BRIGHTNESS, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Brightness", -+ .minimum = 0, /* check this value */ -+ .maximum = 255, /* check this value */ -+ .step = 1, /* check this value */ -+ .default_value = 127, /* check this value */ -+ .flags = 0, -+ }, { -+ .id = V4L2_CID_SATURATION, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Saturation", -+ .minimum = 0, /* check this value */ -+ .maximum = 255, /* check this value */ -+ .step = 0x1, /* check this value */ -+ .default_value = 127, /* check this value */ -+ .flags = 0, -+ } -+}; -+ -+static inline void adv7180_power_down(int enable) -+{ -+ gpio_set_value_cansleep(pwn_gpio, !enable); -+ msleep(2); -+} -+ -+static int adv7180_regulator_enable(struct device *dev) -+{ -+ int ret = 0; -+ -+ dvddio_regulator = devm_regulator_get(dev, "DOVDD"); -+ -+ if (!IS_ERR(dvddio_regulator)) { -+ regulator_set_voltage(dvddio_regulator, -+ ADV7180_VOLTAGE_DIGITAL_IO, -+ ADV7180_VOLTAGE_DIGITAL_IO); -+ ret = regulator_enable(dvddio_regulator); -+ if (ret) { -+ dev_err(dev, "set io voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set io voltage ok\n"); -+ } -+ } else { -+ dev_warn(dev, "cannot get io voltage\n"); -+ } -+ -+ dvdd_regulator = devm_regulator_get(dev, "DVDD"); -+ if (!IS_ERR(dvdd_regulator)) { -+ regulator_set_voltage(dvdd_regulator, -+ ADV7180_VOLTAGE_DIGITAL_CORE, -+ ADV7180_VOLTAGE_DIGITAL_CORE); -+ ret = regulator_enable(dvdd_regulator); -+ if (ret) { -+ dev_err(dev, "set core voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set core voltage ok\n"); -+ } -+ } else { -+ dev_warn(dev, "cannot get core voltage\n"); -+ } -+ -+ avdd_regulator = devm_regulator_get(dev, "AVDD"); -+ if (!IS_ERR(avdd_regulator)) { -+ regulator_set_voltage(avdd_regulator, -+ ADV7180_VOLTAGE_ANALOG, -+ ADV7180_VOLTAGE_ANALOG); -+ ret = regulator_enable(avdd_regulator); -+ if (ret) { -+ dev_err(dev, "set analog voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set analog voltage ok\n"); -+ } -+ } else { -+ dev_warn(dev, "cannot get analog voltage\n"); -+ } -+ -+ pvdd_regulator = devm_regulator_get(dev, "PVDD"); -+ if (!IS_ERR(pvdd_regulator)) { -+ regulator_set_voltage(pvdd_regulator, -+ ADV7180_VOLTAGE_PLL, -+ ADV7180_VOLTAGE_PLL); -+ ret = regulator_enable(pvdd_regulator); -+ if (ret) { -+ dev_err(dev, "set pll voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set pll voltage ok\n"); -+ } -+ } else { -+ dev_warn(dev, "cannot get pll voltage\n"); -+ } -+ -+ return ret; -+} -+ -+ -+/*********************************************************************** -+ * I2C transfert. -+ ***********************************************************************/ -+ -+/*! Read one register from a ADV7180 i2c slave device. -+ * -+ * @param *reg register in the device we wish to access. -+ * -+ * @return 0 if success, an error code otherwise. -+ */ -+static inline int adv7180_read(u8 reg) -+{ -+ int val; -+ -+ val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg); -+ if (val < 0) { -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "%s:read reg error: reg=%2x\n", __func__, reg); -+ return -1; -+ } -+ return val; -+} -+ -+/*! Write one register of a ADV7180 i2c slave device. -+ * -+ * @param *reg register in the device we wish to access. -+ * -+ * @return 0 if success, an error code otherwise. -+ */ -+static int adv7180_write_reg(u8 reg, u8 val) -+{ -+ s32 ret; -+ -+ ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val); -+ if (ret < 0) { -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "%s:write reg error:reg=%2x,val=%2x\n", __func__, -+ reg, val); -+ return -1; -+ } -+ return 0; -+} -+ -+/*********************************************************************** -+ * mxc_v4l2_capture interface. -+ ***********************************************************************/ -+ -+/*! -+ * Return attributes of current video standard. -+ * Since this device autodetects the current standard, this function also -+ * sets the values that need to be changed if the standard changes. -+ * There is no set std equivalent function. -+ * -+ * @return None. -+ */ -+static void adv7180_get_std(v4l2_std_id *std) -+{ -+ int tmp; -+ int idx; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n"); -+ -+ /* Read the AD_RESULT to get the detect output video standard */ -+ tmp = adv7180_read(ADV7180_STATUS_1) & 0x70; -+ -+ mutex_lock(&mutex); -+ if (tmp == 0x40) { -+ /* PAL */ -+ *std = V4L2_STD_PAL; -+ idx = ADV7180_PAL; -+ } else if (tmp == 0) { -+ /*NTSC*/ -+ *std = V4L2_STD_NTSC; -+ idx = ADV7180_NTSC; -+ } else { -+ *std = V4L2_STD_ALL; -+ idx = ADV7180_NOT_LOCKED; -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "Got invalid video standard!\n"); -+ } -+ mutex_unlock(&mutex); -+ -+ /* This assumes autodetect which this device uses. */ -+ if (*std != adv7180_data.std_id) { -+ video_idx = idx; -+ adv7180_data.std_id = *std; -+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; -+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; -+ } -+} -+ -+/*********************************************************************** -+ * IOCTL Functions from v4l2_int_ioctl_desc. -+ ***********************************************************************/ -+ -+/*! -+ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num -+ * s: pointer to standard V4L2 device structure -+ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure -+ * -+ * Gets slave interface parameters. -+ * Calculates the required xclk value to support the requested -+ * clock parameters in p. This value is returned in the p -+ * parameter. -+ * -+ * vidioc_int_g_ifparm returns platform-specific information about the -+ * interface settings used by the sensor. -+ * -+ * Called on open. -+ */ -+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n"); -+ -+ if (s == NULL) { -+ pr_err(" ERROR!! no slave device set!\n"); -+ return -1; -+ } -+ -+ /* Initialize structure to 0s then set any non-0 values. */ -+ memset(p, 0, sizeof(*p)); -+ p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */ -+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; -+ p->u.bt656.nobt_hs_inv = 1; -+ p->u.bt656.bt_sync_correct = 1; -+ -+ /* ADV7180 has a dedicated clock so no clock settings needed. */ -+ -+ return 0; -+} -+ -+/*! -+ * Sets the camera power. -+ * -+ * s pointer to the camera device -+ * on if 1, power is to be turned on. 0 means power is to be turned off -+ * -+ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num -+ * @s: pointer to standard V4L2 device structure -+ * @on: power state to which device is to be set -+ * -+ * Sets devices power state to requrested state, if possible. -+ * This is called on open, close, suspend and resume. -+ */ -+static int ioctl_s_power(struct v4l2_int_device *s, int on) -+{ -+ struct sensor *sensor = s->priv; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n"); -+ -+ if (on && !sensor->sen.on) { -+ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0) -+ return -EIO; -+ -+ /* -+ * FIXME:Additional 400ms to wait the chip to be stable? -+ * This is a workaround for preview scrolling issue. -+ */ -+ msleep(400); -+ } else if (!on && sensor->sen.on) { -+ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0) -+ return -EIO; -+ } -+ -+ sensor->sen.on = on; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure -+ * -+ * Returns the sensor's video CAPTURE parameters. -+ */ -+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor *sensor = s->priv; -+ struct v4l2_captureparm *cparm = &a->parm.capture; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n"); -+ -+ switch (a->type) { -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); -+ memset(a, 0, sizeof(*a)); -+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cparm->capability = sensor->sen.streamcap.capability; -+ cparm->timeperframe = sensor->sen.streamcap.timeperframe; -+ cparm->capturemode = sensor->sen.streamcap.capturemode; -+ break; -+ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ break; -+ -+ default: -+ pr_debug("ioctl_g_parm:type is unknown %d\n", a->type); -+ break; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure -+ * -+ * Configures the sensor to use the input parameters, if possible. If -+ * not possible, reverts to the old parameters and returns the -+ * appropriate error code. -+ * -+ * This driver cannot change these settings. -+ */ -+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n"); -+ -+ switch (a->type) { -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ break; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap -+ * @s: pointer to standard V4L2 device structure -+ * @f: pointer to standard V4L2 v4l2_format structure -+ * -+ * Returns the sensor's current pixel format in the v4l2_format -+ * parameter. -+ */ -+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) -+{ -+ struct sensor *sensor = s->priv; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n"); -+ -+ switch (f->type) { -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" Returning size of %dx%d\n", -+ sensor->sen.pix.width, sensor->sen.pix.height); -+ f->fmt.pix = sensor->sen.pix; -+ break; -+ -+ case V4L2_BUF_TYPE_PRIVATE: { -+ v4l2_std_id std; -+ adv7180_get_std(&std); -+ f->fmt.pix.pixelformat = (u32)std; -+ } -+ break; -+ -+ default: -+ f->fmt.pix = sensor->sen.pix; -+ break; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure -+ * -+ * If the requested control is supported, returns the control information -+ * from the video_control[] array. Otherwise, returns -EINVAL if the -+ * control is not supported. -+ */ -+static int ioctl_queryctrl(struct v4l2_int_device *s, -+ struct v4l2_queryctrl *qc) -+{ -+ int i; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n"); -+ -+ for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++) -+ if (qc->id && qc->id == adv7180_qctrl[i].id) { -+ memcpy(qc, &(adv7180_qctrl[i]), -+ sizeof(*qc)); -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+/*! -+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure -+ * -+ * If the requested control is supported, returns the control's current -+ * value from the video_control[] array. Otherwise, returns -EINVAL -+ * if the control is not supported. -+ */ -+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int ret = 0; -+ int sat = 0; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n"); -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_BRIGHTNESS\n"); -+ adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS); -+ vc->value = adv7180_data.sen.brightness; -+ break; -+ case V4L2_CID_CONTRAST: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_CONTRAST\n"); -+ vc->value = adv7180_data.sen.contrast; -+ break; -+ case V4L2_CID_SATURATION: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_SATURATION\n"); -+ sat = adv7180_read(ADV7180_SD_SATURATION_CB); -+ adv7180_data.sen.saturation = sat; -+ vc->value = adv7180_data.sen.saturation; -+ break; -+ case V4L2_CID_HUE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_HUE\n"); -+ vc->value = adv7180_data.sen.hue; -+ break; -+ case V4L2_CID_AUTO_WHITE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_AUTO_WHITE_BALANCE\n"); -+ break; -+ case V4L2_CID_DO_WHITE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_DO_WHITE_BALANCE\n"); -+ break; -+ case V4L2_CID_RED_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_RED_BALANCE\n"); -+ vc->value = adv7180_data.sen.red; -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_BLUE_BALANCE\n"); -+ vc->value = adv7180_data.sen.blue; -+ break; -+ case V4L2_CID_GAMMA: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_GAMMA\n"); -+ break; -+ case V4L2_CID_EXPOSURE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_EXPOSURE\n"); -+ vc->value = adv7180_data.sen.ae_mode; -+ break; -+ case V4L2_CID_AUTOGAIN: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_AUTOGAIN\n"); -+ break; -+ case V4L2_CID_GAIN: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_GAIN\n"); -+ break; -+ case V4L2_CID_HFLIP: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_HFLIP\n"); -+ break; -+ case V4L2_CID_VFLIP: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_VFLIP\n"); -+ break; -+ default: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " Default case\n"); -+ vc->value = 0; -+ ret = -EPERM; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure -+ * -+ * If the requested control is supported, sets the control's current -+ * value in HW (and updates the video_control[] array). Otherwise, -+ * returns -EINVAL if the control is not supported. -+ */ -+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int retval = 0; -+ u8 tmp; -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n"); -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_BRIGHTNESS\n"); -+ tmp = vc->value; -+ adv7180_write_reg(ADV7180_BRIGHTNESS, tmp); -+ adv7180_data.sen.brightness = vc->value; -+ break; -+ case V4L2_CID_CONTRAST: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_CONTRAST\n"); -+ break; -+ case V4L2_CID_SATURATION: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_SATURATION\n"); -+ tmp = vc->value; -+ adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp); -+ adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp); -+ adv7180_data.sen.saturation = vc->value; -+ break; -+ case V4L2_CID_HUE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_HUE\n"); -+ break; -+ case V4L2_CID_AUTO_WHITE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_AUTO_WHITE_BALANCE\n"); -+ break; -+ case V4L2_CID_DO_WHITE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_DO_WHITE_BALANCE\n"); -+ break; -+ case V4L2_CID_RED_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_RED_BALANCE\n"); -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_BLUE_BALANCE\n"); -+ break; -+ case V4L2_CID_GAMMA: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_GAMMA\n"); -+ break; -+ case V4L2_CID_EXPOSURE: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_EXPOSURE\n"); -+ break; -+ case V4L2_CID_AUTOGAIN: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_AUTOGAIN\n"); -+ break; -+ case V4L2_CID_GAIN: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_GAIN\n"); -+ break; -+ case V4L2_CID_HFLIP: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_HFLIP\n"); -+ break; -+ case V4L2_CID_VFLIP: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " V4L2_CID_VFLIP\n"); -+ break; -+ default: -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ " Default case\n"); -+ retval = -EPERM; -+ break; -+ } -+ -+ return retval; -+} -+ -+/*! -+ * ioctl_enum_framesizes - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMESIZES ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_framesizes(struct v4l2_int_device *s, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index >= 1) -+ return -EINVAL; -+ -+ fsize->discrete.width = video_fmts[video_idx].active_width; -+ fsize->discrete.height = video_fmts[video_idx].active_height; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_chip_ident - V4L2 sensor interface handler for -+ * VIDIOC_DBG_G_CHIP_IDENT ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @id: pointer to int -+ * -+ * Return 0. -+ */ -+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) -+{ -+ ((struct v4l2_dbg_chip_ident *)id)->match.type = -+ V4L2_CHIP_MATCH_I2C_DRIVER; -+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, -+ "adv7180_decoder"); -+ ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT -+ * @s: pointer to standard V4L2 device structure -+ */ -+static int ioctl_init(struct v4l2_int_device *s) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n"); -+ return 0; -+} -+ -+/*! -+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Initialise the device when slave attaches to the master. -+ */ -+static int ioctl_dev_init(struct v4l2_int_device *s) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n"); -+ return 0; -+} -+ -+/*! -+ * This structure defines all the ioctls for this module. -+ */ -+static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = { -+ -+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init}, -+ -+ /*! -+ * Delinitialise the dev. at slave detach. -+ * The complement of ioctl_dev_init. -+ */ -+/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */ -+ -+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power}, -+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm}, -+/* {vidioc_int_g_needs_reset_num, -+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ -+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ -+ {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init}, -+ -+ /*! -+ * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. -+ */ -+/* {vidioc_int_enum_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */ -+ -+ /*! -+ * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. -+ * This ioctl is used to negotiate the image capture size and -+ * pixel format without actually making it take effect. -+ */ -+/* {vidioc_int_try_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ -+ -+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap}, -+ -+ /*! -+ * If the requested format is supported, configures the HW to use that -+ * format, returns error code if format not supported or HW can't be -+ * correctly configured. -+ */ -+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */ -+ -+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm}, -+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm}, -+ {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl}, -+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl}, -+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl}, -+ {vidioc_int_enum_framesizes_num, -+ (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, -+ {vidioc_int_g_chip_ident_num, -+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident}, -+}; -+ -+static struct v4l2_int_slave adv7180_slave = { -+ .ioctls = adv7180_ioctl_desc, -+ .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc), -+}; -+ -+static struct v4l2_int_device adv7180_int_device = { -+ .module = THIS_MODULE, -+ .name = "adv7180", -+ .type = v4l2_int_type_slave, -+ .u = { -+ .slave = &adv7180_slave, -+ }, -+}; -+ -+ -+/*********************************************************************** -+ * I2C client and driver. -+ ***********************************************************************/ -+ -+/*! ADV7180 Reset function. -+ * -+ * @return None. -+ */ -+static void adv7180_hard_reset(bool cvbs) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "In adv7180:adv7180_hard_reset\n"); -+ -+ if (cvbs) { -+ /* Set CVBS input on AIN1 */ -+ adv7180_write_reg(ADV7180_INPUT_CTL, 0x00); -+ } else { -+ /* -+ * Set YPbPr input on AIN1,4,5 and normal -+ * operations(autodection of all stds). -+ */ -+ adv7180_write_reg(ADV7180_INPUT_CTL, 0x09); -+ } -+ -+ /* Datasheet recommends */ -+ adv7180_write_reg(0x01, 0xc8); -+ adv7180_write_reg(0x02, 0x04); -+ adv7180_write_reg(0x03, 0x00); -+ adv7180_write_reg(0x04, 0x45); -+ adv7180_write_reg(0x05, 0x00); -+ adv7180_write_reg(0x06, 0x02); -+ adv7180_write_reg(0x07, 0x7F); -+ adv7180_write_reg(0x08, 0x80); -+ adv7180_write_reg(0x0A, 0x00); -+ adv7180_write_reg(0x0B, 0x00); -+ adv7180_write_reg(0x0C, 0x36); -+ adv7180_write_reg(0x0D, 0x7C); -+ adv7180_write_reg(0x0E, 0x00); -+ adv7180_write_reg(0x0F, 0x00); -+ adv7180_write_reg(0x13, 0x00); -+ adv7180_write_reg(0x14, 0x12); -+ adv7180_write_reg(0x15, 0x00); -+ adv7180_write_reg(0x16, 0x00); -+ adv7180_write_reg(0x17, 0x01); -+ adv7180_write_reg(0x18, 0x93); -+ adv7180_write_reg(0xF1, 0x19); -+ adv7180_write_reg(0x1A, 0x00); -+ adv7180_write_reg(0x1B, 0x00); -+ adv7180_write_reg(0x1C, 0x00); -+ adv7180_write_reg(0x1D, 0x40); -+ adv7180_write_reg(0x1E, 0x00); -+ adv7180_write_reg(0x1F, 0x00); -+ adv7180_write_reg(0x20, 0x00); -+ adv7180_write_reg(0x21, 0x00); -+ adv7180_write_reg(0x22, 0x00); -+ adv7180_write_reg(0x23, 0xC0); -+ adv7180_write_reg(0x24, 0x00); -+ adv7180_write_reg(0x25, 0x00); -+ adv7180_write_reg(0x26, 0x00); -+ adv7180_write_reg(0x27, 0x58); -+ adv7180_write_reg(0x28, 0x00); -+ adv7180_write_reg(0x29, 0x00); -+ adv7180_write_reg(0x2A, 0x00); -+ adv7180_write_reg(0x2B, 0xE1); -+ adv7180_write_reg(0x2C, 0xAE); -+ adv7180_write_reg(0x2D, 0xF4); -+ adv7180_write_reg(0x2E, 0x00); -+ adv7180_write_reg(0x2F, 0xF0); -+ adv7180_write_reg(0x30, 0x00); -+ adv7180_write_reg(0x31, 0x12); -+ adv7180_write_reg(0x32, 0x41); -+ adv7180_write_reg(0x33, 0x84); -+ adv7180_write_reg(0x34, 0x00); -+ adv7180_write_reg(0x35, 0x02); -+ adv7180_write_reg(0x36, 0x00); -+ adv7180_write_reg(0x37, 0x01); -+ adv7180_write_reg(0x38, 0x80); -+ adv7180_write_reg(0x39, 0xC0); -+ adv7180_write_reg(0x3A, 0x10); -+ adv7180_write_reg(0x3B, 0x05); -+ adv7180_write_reg(0x3C, 0x58); -+ adv7180_write_reg(0x3D, 0xB2); -+ adv7180_write_reg(0x3E, 0x64); -+ adv7180_write_reg(0x3F, 0xE4); -+ adv7180_write_reg(0x40, 0x90); -+ adv7180_write_reg(0x41, 0x01); -+ adv7180_write_reg(0x42, 0x7E); -+ adv7180_write_reg(0x43, 0xA4); -+ adv7180_write_reg(0x44, 0xFF); -+ adv7180_write_reg(0x45, 0xB6); -+ adv7180_write_reg(0x46, 0x12); -+ adv7180_write_reg(0x48, 0x00); -+ adv7180_write_reg(0x49, 0x00); -+ adv7180_write_reg(0x4A, 0x00); -+ adv7180_write_reg(0x4B, 0x00); -+ adv7180_write_reg(0x4C, 0x00); -+ adv7180_write_reg(0x4D, 0xEF); -+ adv7180_write_reg(0x4E, 0x08); -+ adv7180_write_reg(0x4F, 0x08); -+ adv7180_write_reg(0x50, 0x08); -+ adv7180_write_reg(0x51, 0x24); -+ adv7180_write_reg(0x52, 0x0B); -+ adv7180_write_reg(0x53, 0x4E); -+ adv7180_write_reg(0x54, 0x80); -+ adv7180_write_reg(0x55, 0x00); -+ adv7180_write_reg(0x56, 0x10); -+ adv7180_write_reg(0x57, 0x00); -+ adv7180_write_reg(0x58, 0x00); -+ adv7180_write_reg(0x59, 0x00); -+ adv7180_write_reg(0x5A, 0x00); -+ adv7180_write_reg(0x5B, 0x00); -+ adv7180_write_reg(0x5C, 0x00); -+ adv7180_write_reg(0x5D, 0x00); -+ adv7180_write_reg(0x5E, 0x00); -+ adv7180_write_reg(0x5F, 0x00); -+ adv7180_write_reg(0x60, 0x00); -+ adv7180_write_reg(0x61, 0x00); -+ adv7180_write_reg(0x62, 0x20); -+ adv7180_write_reg(0x63, 0x00); -+ adv7180_write_reg(0x64, 0x00); -+ adv7180_write_reg(0x65, 0x00); -+ adv7180_write_reg(0x66, 0x00); -+ adv7180_write_reg(0x67, 0x03); -+ adv7180_write_reg(0x68, 0x01); -+ adv7180_write_reg(0x69, 0x00); -+ adv7180_write_reg(0x6A, 0x00); -+ adv7180_write_reg(0x6B, 0xC0); -+ adv7180_write_reg(0x6C, 0x00); -+ adv7180_write_reg(0x6D, 0x00); -+ adv7180_write_reg(0x6E, 0x00); -+ adv7180_write_reg(0x6F, 0x00); -+ adv7180_write_reg(0x70, 0x00); -+ adv7180_write_reg(0x71, 0x00); -+ adv7180_write_reg(0x72, 0x00); -+ adv7180_write_reg(0x73, 0x10); -+ adv7180_write_reg(0x74, 0x04); -+ adv7180_write_reg(0x75, 0x01); -+ adv7180_write_reg(0x76, 0x00); -+ adv7180_write_reg(0x77, 0x3F); -+ adv7180_write_reg(0x78, 0xFF); -+ adv7180_write_reg(0x79, 0xFF); -+ adv7180_write_reg(0x7A, 0xFF); -+ adv7180_write_reg(0x7B, 0x1E); -+ adv7180_write_reg(0x7C, 0xC0); -+ adv7180_write_reg(0x7D, 0x00); -+ adv7180_write_reg(0x7E, 0x00); -+ adv7180_write_reg(0x7F, 0x00); -+ adv7180_write_reg(0x80, 0x00); -+ adv7180_write_reg(0x81, 0xC0); -+ adv7180_write_reg(0x82, 0x04); -+ adv7180_write_reg(0x83, 0x00); -+ adv7180_write_reg(0x84, 0x0C); -+ adv7180_write_reg(0x85, 0x02); -+ adv7180_write_reg(0x86, 0x03); -+ adv7180_write_reg(0x87, 0x63); -+ adv7180_write_reg(0x88, 0x5A); -+ adv7180_write_reg(0x89, 0x08); -+ adv7180_write_reg(0x8A, 0x10); -+ adv7180_write_reg(0x8B, 0x00); -+ adv7180_write_reg(0x8C, 0x40); -+ adv7180_write_reg(0x8D, 0x00); -+ adv7180_write_reg(0x8E, 0x40); -+ adv7180_write_reg(0x8F, 0x00); -+ adv7180_write_reg(0x90, 0x00); -+ adv7180_write_reg(0x91, 0x50); -+ adv7180_write_reg(0x92, 0x00); -+ adv7180_write_reg(0x93, 0x00); -+ adv7180_write_reg(0x94, 0x00); -+ adv7180_write_reg(0x95, 0x00); -+ adv7180_write_reg(0x96, 0x00); -+ adv7180_write_reg(0x97, 0xF0); -+ adv7180_write_reg(0x98, 0x00); -+ adv7180_write_reg(0x99, 0x00); -+ adv7180_write_reg(0x9A, 0x00); -+ adv7180_write_reg(0x9B, 0x00); -+ adv7180_write_reg(0x9C, 0x00); -+ adv7180_write_reg(0x9D, 0x00); -+ adv7180_write_reg(0x9E, 0x00); -+ adv7180_write_reg(0x9F, 0x00); -+ adv7180_write_reg(0xA0, 0x00); -+ adv7180_write_reg(0xA1, 0x00); -+ adv7180_write_reg(0xA2, 0x00); -+ adv7180_write_reg(0xA3, 0x00); -+ adv7180_write_reg(0xA4, 0x00); -+ adv7180_write_reg(0xA5, 0x00); -+ adv7180_write_reg(0xA6, 0x00); -+ adv7180_write_reg(0xA7, 0x00); -+ adv7180_write_reg(0xA8, 0x00); -+ adv7180_write_reg(0xA9, 0x00); -+ adv7180_write_reg(0xAA, 0x00); -+ adv7180_write_reg(0xAB, 0x00); -+ adv7180_write_reg(0xAC, 0x00); -+ adv7180_write_reg(0xAD, 0x00); -+ adv7180_write_reg(0xAE, 0x60); -+ adv7180_write_reg(0xAF, 0x00); -+ adv7180_write_reg(0xB0, 0x00); -+ adv7180_write_reg(0xB1, 0x60); -+ adv7180_write_reg(0xB2, 0x1C); -+ adv7180_write_reg(0xB3, 0x54); -+ adv7180_write_reg(0xB4, 0x00); -+ adv7180_write_reg(0xB5, 0x00); -+ adv7180_write_reg(0xB6, 0x00); -+ adv7180_write_reg(0xB7, 0x13); -+ adv7180_write_reg(0xB8, 0x03); -+ adv7180_write_reg(0xB9, 0x33); -+ adv7180_write_reg(0xBF, 0x02); -+ adv7180_write_reg(0xC0, 0x00); -+ adv7180_write_reg(0xC1, 0x00); -+ adv7180_write_reg(0xC2, 0x00); -+ adv7180_write_reg(0xC3, 0x00); -+ adv7180_write_reg(0xC4, 0x00); -+ adv7180_write_reg(0xC5, 0x81); -+ adv7180_write_reg(0xC6, 0x00); -+ adv7180_write_reg(0xC7, 0x00); -+ adv7180_write_reg(0xC8, 0x00); -+ adv7180_write_reg(0xC9, 0x04); -+ adv7180_write_reg(0xCC, 0x69); -+ adv7180_write_reg(0xCD, 0x00); -+ adv7180_write_reg(0xCE, 0x01); -+ adv7180_write_reg(0xCF, 0xB4); -+ adv7180_write_reg(0xD0, 0x00); -+ adv7180_write_reg(0xD1, 0x10); -+ adv7180_write_reg(0xD2, 0xFF); -+ adv7180_write_reg(0xD3, 0xFF); -+ adv7180_write_reg(0xD4, 0x7F); -+ adv7180_write_reg(0xD5, 0x7F); -+ adv7180_write_reg(0xD6, 0x3E); -+ adv7180_write_reg(0xD7, 0x08); -+ adv7180_write_reg(0xD8, 0x3C); -+ adv7180_write_reg(0xD9, 0x08); -+ adv7180_write_reg(0xDA, 0x3C); -+ adv7180_write_reg(0xDB, 0x9B); -+ adv7180_write_reg(0xDC, 0xAC); -+ adv7180_write_reg(0xDD, 0x4C); -+ adv7180_write_reg(0xDE, 0x00); -+ adv7180_write_reg(0xDF, 0x00); -+ adv7180_write_reg(0xE0, 0x14); -+ adv7180_write_reg(0xE1, 0x80); -+ adv7180_write_reg(0xE2, 0x80); -+ adv7180_write_reg(0xE3, 0x80); -+ adv7180_write_reg(0xE4, 0x80); -+ adv7180_write_reg(0xE5, 0x25); -+ adv7180_write_reg(0xE6, 0x44); -+ adv7180_write_reg(0xE7, 0x63); -+ adv7180_write_reg(0xE8, 0x65); -+ adv7180_write_reg(0xE9, 0x14); -+ adv7180_write_reg(0xEA, 0x63); -+ adv7180_write_reg(0xEB, 0x55); -+ adv7180_write_reg(0xEC, 0x55); -+ adv7180_write_reg(0xEE, 0x00); -+ adv7180_write_reg(0xEF, 0x4A); -+ adv7180_write_reg(0xF0, 0x44); -+ adv7180_write_reg(0xF1, 0x0C); -+ adv7180_write_reg(0xF2, 0x32); -+ adv7180_write_reg(0xF3, 0x00); -+ adv7180_write_reg(0xF4, 0x3F); -+ adv7180_write_reg(0xF5, 0xE0); -+ adv7180_write_reg(0xF6, 0x69); -+ adv7180_write_reg(0xF7, 0x10); -+ adv7180_write_reg(0xF8, 0x00); -+ adv7180_write_reg(0xF9, 0x03); -+ adv7180_write_reg(0xFA, 0xFA); -+ adv7180_write_reg(0xFB, 0x40); -+} -+ -+/*! ADV7180 I2C attach function. -+ * -+ * @param *adapter struct i2c_adapter *. -+ * -+ * @return Error code indicating success or failure. -+ */ -+ -+/*! -+ * ADV7180 I2C probe function. -+ * Function set in i2c_driver struct. -+ * Called by insmod. -+ * -+ * @param *adapter I2C adapter descriptor. -+ * -+ * @return Error code indicating success or failure. -+ */ -+static int adv7180_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ int rev_id; -+ int ret = 0; -+ u32 cvbs = true; -+ struct pinctrl *pinctrl; -+ struct device *dev = &client->dev; -+ -+ printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data); -+ -+ /* ov5640 pinctrl */ -+ pinctrl = devm_pinctrl_get_select_default(dev); -+ if (IS_ERR(pinctrl)) { -+ dev_err(dev, "setup pinctrl failed\n"); -+ return PTR_ERR(pinctrl); -+ } -+ -+ /* request power down pin */ -+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); -+ if (!gpio_is_valid(pwn_gpio)) { -+ dev_err(dev, "no sensor pwdn pin available\n"); -+ return -ENODEV; -+ } -+ ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, -+ "adv7180_pwdn"); -+ if (ret < 0) { -+ dev_err(dev, "no power pin available!\n"); -+ return ret; -+ } -+ -+ adv7180_regulator_enable(dev); -+ -+ adv7180_power_down(0); -+ -+ msleep(1); -+ -+ /* Set initial values for the sensor struct. */ -+ memset(&adv7180_data, 0, sizeof(adv7180_data)); -+ adv7180_data.sen.i2c_client = client; -+ adv7180_data.sen.streamcap.timeperframe.denominator = 30; -+ adv7180_data.sen.streamcap.timeperframe.numerator = 1; -+ adv7180_data.std_id = V4L2_STD_ALL; -+ video_idx = ADV7180_NOT_LOCKED; -+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; -+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; -+ adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */ -+ adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */ -+ adv7180_data.sen.on = true; -+ -+ adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk"); -+ if (IS_ERR(adv7180_data.sen.sensor_clk)) { -+ dev_err(dev, "get mclk failed\n"); -+ return PTR_ERR(adv7180_data.sen.sensor_clk); -+ } -+ -+ ret = of_property_read_u32(dev->of_node, "mclk", -+ &adv7180_data.sen.mclk); -+ if (ret) { -+ dev_err(dev, "mclk frequency is invalid\n"); -+ return ret; -+ } -+ -+ ret = of_property_read_u32( -+ dev->of_node, "mclk_source", -+ (u32 *) &(adv7180_data.sen.mclk_source)); -+ if (ret) { -+ dev_err(dev, "mclk_source invalid\n"); -+ return ret; -+ } -+ -+ ret = of_property_read_u32(dev->of_node, "csi_id", -+ &(adv7180_data.sen.csi)); -+ if (ret) { -+ dev_err(dev, "csi_id invalid\n"); -+ return ret; -+ } -+ -+ clk_prepare_enable(adv7180_data.sen.sensor_clk); -+ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "%s:adv7180 probe i2c address is 0x%02X\n", -+ __func__, adv7180_data.sen.i2c_client->addr); -+ -+ /*! Read the revision ID of the tvin chip */ -+ rev_id = adv7180_read(ADV7180_IDENT); -+ dev_dbg(dev, -+ "%s:Analog Device adv7%2X0 detected!\n", __func__, -+ rev_id); -+ -+ ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs)); -+ if (ret) { -+ dev_err(dev, "cvbs setting is not found\n"); -+ cvbs = true; -+ } -+ -+ /*! ADV7180 initialization. */ -+ adv7180_hard_reset(cvbs); -+ -+ pr_debug(" type is %d (expect %d)\n", -+ adv7180_int_device.type, v4l2_int_type_slave); -+ pr_debug(" num ioctls is %d\n", -+ adv7180_int_device.u.slave->num_ioctls); -+ -+ /* This function attaches this structure to the /dev/video0 device. -+ * The pointer in priv points to the adv7180_data structure here.*/ -+ adv7180_int_device.priv = &adv7180_data; -+ ret = v4l2_int_device_register(&adv7180_int_device); -+ -+ clk_disable_unprepare(adv7180_data.sen.sensor_clk); -+ -+ return ret; -+} -+ -+/*! -+ * ADV7180 I2C detach function. -+ * Called on rmmod. -+ * -+ * @param *client struct i2c_client*. -+ * -+ * @return Error code indicating success or failure. -+ */ -+static int adv7180_detach(struct i2c_client *client) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, -+ "%s:Removing %s video decoder @ 0x%02X from adapter %s\n", -+ __func__, IF_NAME, client->addr << 1, client->adapter->name); -+ -+ /* Power down via i2c */ -+ adv7180_write_reg(ADV7180_PWR_MNG, 0x24); -+ -+ if (dvddio_regulator) -+ regulator_disable(dvddio_regulator); -+ -+ if (dvdd_regulator) -+ regulator_disable(dvdd_regulator); -+ -+ if (avdd_regulator) -+ regulator_disable(avdd_regulator); -+ -+ if (pvdd_regulator) -+ regulator_disable(pvdd_regulator); -+ -+ v4l2_int_device_unregister(&adv7180_int_device); -+ -+ return 0; -+} -+ -+/*! -+ * ADV7180 init function. -+ * Called on insmod. -+ * -+ * @return Error code indicating success or failure. -+ */ -+static __init int adv7180_init(void) -+{ -+ u8 err = 0; -+ -+ pr_debug("In adv7180_init\n"); -+ -+ /* Tells the i2c driver what functions to call for this driver. */ -+ err = i2c_add_driver(&adv7180_i2c_driver); -+ if (err != 0) -+ pr_err("%s:driver registration failed, error=%d\n", -+ __func__, err); -+ -+ return err; -+} -+ -+/*! -+ * ADV7180 cleanup function. -+ * Called on rmmod. -+ * -+ * @return Error code indicating success or failure. -+ */ -+static void __exit adv7180_clean(void) -+{ -+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n"); -+ i2c_del_driver(&adv7180_i2c_driver); -+} -+ -+module_init(adv7180_init); -+module_exit(adv7180_clean); -+ -+MODULE_AUTHOR("Freescale Semiconductor"); -+MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/csi_v4l2_capture.c linux-3.14.22/drivers/media/platform/mxc/capture/csi_v4l2_capture.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 2014-10-22 14:55:52.610220001 -0500 -@@ -0,0 +1,2047 @@ -+/* -+ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file drivers/media/video/mxc/capture/csi_v4l2_capture.c -+ * This file is derived from mxc_v4l2_capture.c -+ * -+ * @brief Video For Linux 2 capture driver -+ * -+ * @ingroup MXC_V4L2_CAPTURE -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "fsl_csi.h" -+ -+static int video_nr = -1; -+static cam_data *g_cam; -+static int req_buf_number; -+ -+static int csi_v4l2_master_attach(struct v4l2_int_device *slave); -+static void csi_v4l2_master_detach(struct v4l2_int_device *slave); -+static u8 camera_power(cam_data *cam, bool cameraOn); -+struct v4l2_crop crop_current; -+struct v4l2_window win_current; -+ -+/*! Information about this driver. */ -+static struct v4l2_int_master csi_v4l2_master = { -+ .attach = csi_v4l2_master_attach, -+ .detach = csi_v4l2_master_detach, -+}; -+ -+static struct v4l2_int_device csi_v4l2_int_device = { -+ .module = THIS_MODULE, -+ .name = "csi_v4l2_cap", -+ .type = v4l2_int_type_master, -+ .u = { -+ .master = &csi_v4l2_master, -+ }, -+}; -+ -+static struct v4l2_queryctrl pxp_controls[] = { -+ { -+ .id = V4L2_CID_HFLIP, -+ .type = V4L2_CTRL_TYPE_BOOLEAN, -+ .name = "Horizontal Flip", -+ .minimum = 0, -+ .maximum = 1, -+ .step = 1, -+ .default_value = 0, -+ .flags = 0, -+ }, { -+ .id = V4L2_CID_VFLIP, -+ .type = V4L2_CTRL_TYPE_BOOLEAN, -+ .name = "Vertical Flip", -+ .minimum = 0, -+ .maximum = 1, -+ .step = 1, -+ .default_value = 0, -+ .flags = 0, -+ }, { -+ .id = V4L2_CID_PRIVATE_BASE, -+ .type = V4L2_CTRL_TYPE_INTEGER, -+ .name = "Rotation", -+ .minimum = 0, -+ .maximum = 270, -+ .step = 90, -+ .default_value = 0, -+ .flags = 0, -+ }, -+}; -+ -+/* Callback function triggered after PxP receives an EOF interrupt */ -+static void pxp_dma_done(void *arg) -+{ -+ struct pxp_tx_desc *tx_desc = to_tx_desc(arg); -+ struct dma_chan *chan = tx_desc->txd.chan; -+ struct pxp_channel *pxp_chan = to_pxp_channel(chan); -+ cam_data *cam = pxp_chan->client; -+ -+ /* This call will signal wait_for_completion_timeout() */ -+ complete(&cam->pxp_tx_cmpl); -+} -+ -+static bool chan_filter(struct dma_chan *chan, void *arg) -+{ -+ if (imx_dma_is_pxp(chan)) -+ return true; -+ else -+ return false; -+} -+ -+/* Function to request PXP DMA channel */ -+static int pxp_chan_init(cam_data *cam) -+{ -+ dma_cap_mask_t mask; -+ struct dma_chan *chan; -+ -+ /* Request a free channel */ -+ dma_cap_zero(mask); -+ dma_cap_set(DMA_SLAVE, mask); -+ dma_cap_set(DMA_PRIVATE, mask); -+ chan = dma_request_channel(mask, chan_filter, NULL); -+ if (!chan) { -+ pr_err("Unsuccessfully request channel!\n"); -+ return -EBUSY; -+ } -+ -+ cam->pxp_chan = to_pxp_channel(chan); -+ cam->pxp_chan->client = cam; -+ -+ init_completion(&cam->pxp_tx_cmpl); -+ -+ return 0; -+} -+ -+/* -+ * Function to call PxP DMA driver and send our new V4L2 buffer -+ * through the PxP. -+ * Note: This is a blocking call, so upon return the PxP tx should be complete. -+ */ -+static int pxp_process_update(cam_data *cam) -+{ -+ dma_cookie_t cookie; -+ struct scatterlist *sg = cam->sg; -+ struct dma_chan *dma_chan; -+ struct pxp_tx_desc *desc; -+ struct dma_async_tx_descriptor *txd; -+ struct pxp_config_data *pxp_conf = &cam->pxp_conf; -+ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; -+ int i, ret; -+ int length; -+ -+ pr_debug("Starting PxP Send Buffer\n"); -+ -+ /* First, check to see that we have acquired a PxP Channel object */ -+ if (cam->pxp_chan == NULL) { -+ /* -+ * PxP Channel has not yet been created and initialized, -+ * so let's go ahead and try -+ */ -+ ret = pxp_chan_init(cam); -+ if (ret) { -+ /* -+ * PxP channel init failed, and we can't use the -+ * PxP until the PxP DMA driver has loaded, so we abort -+ */ -+ pr_err("PxP chan init failed\n"); -+ return -ENODEV; -+ } -+ } -+ -+ /* -+ * Init completion, so that we can be properly informed of -+ * the completion of the PxP task when it is done. -+ */ -+ init_completion(&cam->pxp_tx_cmpl); -+ -+ dma_chan = &cam->pxp_chan->dma_chan; -+ -+ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2, -+ DMA_TO_DEVICE, -+ DMA_PREP_INTERRUPT, -+ NULL); -+ if (!txd) { -+ pr_err("Error preparing a DMA transaction descriptor.\n"); -+ return -EIO; -+ } -+ -+ txd->callback_param = txd; -+ txd->callback = pxp_dma_done; -+ -+ /* -+ * Configure PxP for processing of new v4l2 buf -+ */ -+ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_UYVY; -+ pxp_conf->s0_param.color_key = -1; -+ pxp_conf->s0_param.color_key_enable = false; -+ pxp_conf->s0_param.width = cam->v2f.fmt.pix.width; -+ pxp_conf->s0_param.height = cam->v2f.fmt.pix.height; -+ -+ pxp_conf->ol_param[0].combine_enable = false; -+ -+ proc_data->srect.top = 0; -+ proc_data->srect.left = 0; -+ proc_data->srect.width = pxp_conf->s0_param.width; -+ proc_data->srect.height = pxp_conf->s0_param.height; -+ -+ if (crop_current.c.top != 0) -+ proc_data->srect.top = crop_current.c.top; -+ if (crop_current.c.left != 0) -+ proc_data->srect.left = crop_current.c.left; -+ if (crop_current.c.width != 0) -+ proc_data->srect.width = crop_current.c.width; -+ if (crop_current.c.height != 0) -+ proc_data->srect.height = crop_current.c.height; -+ -+ proc_data->drect.left = 0; -+ proc_data->drect.top = 0; -+ proc_data->drect.width = proc_data->srect.width; -+ proc_data->drect.height = proc_data->srect.height; -+ -+ if (win_current.w.left != 0) -+ proc_data->drect.left = win_current.w.left; -+ if (win_current.w.top != 0) -+ proc_data->drect.top = win_current.w.top; -+ if (win_current.w.width != 0) -+ proc_data->drect.width = win_current.w.width; -+ if (win_current.w.height != 0) -+ proc_data->drect.height = win_current.w.height; -+ -+ pr_debug("srect l: %d, t: %d, w: %d, h: %d; " -+ "drect l: %d, t: %d, w: %d, h: %d\n", -+ proc_data->srect.left, proc_data->srect.top, -+ proc_data->srect.width, proc_data->srect.height, -+ proc_data->drect.left, proc_data->drect.top, -+ proc_data->drect.width, proc_data->drect.height); -+ -+ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565; -+ pxp_conf->out_param.width = proc_data->drect.width; -+ pxp_conf->out_param.height = proc_data->drect.height; -+ -+ if (cam->rotation % 180) -+ pxp_conf->out_param.stride = pxp_conf->out_param.height; -+ else -+ pxp_conf->out_param.stride = pxp_conf->out_param.width; -+ -+ desc = to_tx_desc(txd); -+ length = desc->len; -+ for (i = 0; i < length; i++) { -+ if (i == 0) {/* S0 */ -+ memcpy(&desc->proc_data, proc_data, -+ sizeof(struct pxp_proc_data)); -+ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]); -+ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param, -+ sizeof(struct pxp_layer_param)); -+ } else if (i == 1) { -+ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]); -+ memcpy(&desc->layer_param.out_param, -+ &pxp_conf->out_param, -+ sizeof(struct pxp_layer_param)); -+ } -+ -+ desc = desc->next; -+ } -+ -+ /* Submitting our TX starts the PxP processing task */ -+ cookie = txd->tx_submit(txd); -+ if (cookie < 0) { -+ pr_err("Error sending FB through PxP\n"); -+ return -EIO; -+ } -+ -+ cam->txd = txd; -+ -+ /* trigger PxP */ -+ dma_async_issue_pending(dma_chan); -+ -+ return 0; -+} -+ -+static int pxp_complete_update(cam_data *cam) -+{ -+ int ret; -+ /* -+ * Wait for completion event, which will be set -+ * through our TX callback function. -+ */ -+ ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10); -+ if (ret <= 0) { -+ pr_warning("PxP operation failed due to %s\n", -+ ret < 0 ? "user interrupt" : "timeout"); -+ dma_release_channel(&cam->pxp_chan->dma_chan); -+ cam->pxp_chan = NULL; -+ return ret ? : -ETIMEDOUT; -+ } -+ -+ dma_release_channel(&cam->pxp_chan->dma_chan); -+ cam->pxp_chan = NULL; -+ -+ pr_debug("TX completed\n"); -+ -+ return 0; -+} -+ -+/*! -+ * Camera V4l2 callback function. -+ * -+ * @param mask u32 -+ * @param dev void device structure -+ * -+ * @return none -+ */ -+static void camera_callback(u32 mask, void *dev) -+{ -+ struct mxc_v4l_frame *done_frame; -+ struct mxc_v4l_frame *ready_frame; -+ cam_data *cam; -+ -+ cam = (cam_data *) dev; -+ if (cam == NULL) -+ return; -+ -+ spin_lock(&cam->queue_int_lock); -+ spin_lock(&cam->dqueue_int_lock); -+ if (!list_empty(&cam->working_q)) { -+ done_frame = list_entry(cam->working_q.next, -+ struct mxc_v4l_frame, queue); -+ -+ if (done_frame->csi_buf_num != cam->ping_pong_csi) -+ goto next; -+ -+ if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { -+ done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; -+ done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; -+ -+ /* Added to the done queue */ -+ list_del(cam->working_q.next); -+ list_add_tail(&done_frame->queue, &cam->done_q); -+ cam->enc_counter++; -+ wake_up_interruptible(&cam->enc_queue); -+ } else { -+ pr_err("ERROR: v4l2 capture: %s: " -+ "buffer not queued\n", __func__); -+ } -+ } -+ -+next: -+ if (!list_empty(&cam->ready_q)) { -+ ready_frame = list_entry(cam->ready_q.next, -+ struct mxc_v4l_frame, queue); -+ list_del(cam->ready_q.next); -+ list_add_tail(&ready_frame->queue, &cam->working_q); -+ -+ __raw_writel(ready_frame->paddress, -+ cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : -+ CSI_CSIDMASA_FB2); -+ ready_frame->csi_buf_num = cam->ping_pong_csi; -+ } else { -+ __raw_writel(cam->dummy_frame.paddress, -+ cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : -+ CSI_CSIDMASA_FB2); -+ } -+ spin_unlock(&cam->dqueue_int_lock); -+ spin_unlock(&cam->queue_int_lock); -+ -+ return; -+} -+ -+/*! -+ * Make csi ready for capture image. -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 success -+ */ -+static int csi_cap_image(cam_data *cam) -+{ -+ unsigned int value; -+ -+ value = __raw_readl(CSI_CSICR3); -+ __raw_writel(value | BIT_FRMCNT_RST, CSI_CSICR3); -+ value = __raw_readl(CSI_CSISR); -+ __raw_writel(value, CSI_CSISR); -+ -+ return 0; -+} -+ -+/*************************************************************************** -+ * Functions for handling Frame buffers. -+ **************************************************************************/ -+ -+/*! -+ * Free frame buffers -+ * -+ * @param cam Structure cam_data * -+ * -+ * @return status 0 success. -+ */ -+static int csi_free_frame_buf(cam_data *cam) -+{ -+ int i; -+ -+ pr_debug("MVC: In %s\n", __func__); -+ -+ for (i = 0; i < FRAME_NUM; i++) { -+ if (cam->frame[i].vaddress != 0) { -+ dma_free_coherent(0, cam->frame[i].buffer.length, -+ cam->frame[i].vaddress, -+ cam->frame[i].paddress); -+ cam->frame[i].vaddress = 0; -+ } -+ } -+ -+ if (cam->dummy_frame.vaddress != 0) { -+ dma_free_coherent(0, cam->dummy_frame.buffer.length, -+ cam->dummy_frame.vaddress, -+ cam->dummy_frame.paddress); -+ cam->dummy_frame.vaddress = 0; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * Allocate frame buffers -+ * -+ * @param cam Structure cam_data * -+ * @param count int number of buffer need to allocated -+ * -+ * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. -+ */ -+static int csi_allocate_frame_buf(cam_data *cam, int count) -+{ -+ int i; -+ -+ pr_debug("In MVC:%s- size=%d\n", -+ __func__, cam->v2f.fmt.pix.sizeimage); -+ for (i = 0; i < count; i++) { -+ cam->frame[i].vaddress = dma_alloc_coherent(0, PAGE_ALIGN -+ (cam->v2f.fmt. -+ pix.sizeimage), -+ &cam->frame[i]. -+ paddress, -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->frame[i].vaddress == 0) { -+ pr_err("ERROR: v4l2 capture: " -+ "%s failed.\n", __func__); -+ csi_free_frame_buf(cam); -+ return -ENOBUFS; -+ } -+ cam->frame[i].buffer.index = i; -+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cam->frame[i].buffer.length = cam->v2f.fmt.pix.sizeimage; -+ cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; -+ cam->frame[i].buffer.m.offset = cam->frame[i].paddress; -+ cam->frame[i].index = i; -+ cam->frame[i].csi_buf_num = 0; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * Free frame buffers status -+ * -+ * @param cam Structure cam_data * -+ * -+ * @return none -+ */ -+static void csi_free_frames(cam_data *cam) -+{ -+ int i; -+ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ for (i = 0; i < FRAME_NUM; i++) -+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ -+ cam->enc_counter = 0; -+ INIT_LIST_HEAD(&cam->ready_q); -+ INIT_LIST_HEAD(&cam->working_q); -+ INIT_LIST_HEAD(&cam->done_q); -+ -+ return; -+} -+ -+/*! -+ * Return the buffer status -+ * -+ * @param cam Structure cam_data * -+ * @param buf Structure v4l2_buffer * -+ * -+ * @return status 0 success, EINVAL failed. -+ */ -+static int csi_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ if (buf->index < 0 || buf->index >= FRAME_NUM) { -+ pr_err("ERROR: v4l2 capture: %s buffers " -+ "not allocated\n", __func__); -+ return -EINVAL; -+ } -+ -+ memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); -+ -+ return 0; -+} -+ -+static int csi_v4l2_release_bufs(cam_data *cam) -+{ -+ pr_debug("In MVC:csi_v4l2_release_bufs\n"); -+ return 0; -+} -+ -+static int csi_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ pr_debug("In MVC:csi_v4l2_prepare_bufs\n"); -+ -+ if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < -+ cam->v2f.fmt.pix.sizeimage) { -+ pr_err("ERROR: v4l2 capture: csi_v4l2_prepare_bufs buffers " -+ "not allocated,index=%d, length=%d\n", buf->index, -+ buf->length); -+ return -EINVAL; -+ } -+ -+ cam->frame[buf->index].buffer.index = buf->index; -+ cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ cam->frame[buf->index].buffer.length = buf->length; -+ cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress -+ = buf->m.offset; -+ cam->frame[buf->index].buffer.type = buf->type; -+ cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; -+ cam->frame[buf->index].index = buf->index; -+ -+ return 0; -+} -+ -+/*! -+ * Indicates whether the palette is supported. -+ * -+ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_UYVY or V4L2_PIX_FMT_YUV420 -+ * -+ * @return 0 if failed -+ */ -+static inline int valid_mode(u32 palette) -+{ -+ return (palette == V4L2_PIX_FMT_RGB565) || -+ (palette == V4L2_PIX_FMT_YUYV) || -+ (palette == V4L2_PIX_FMT_UYVY) || (palette == V4L2_PIX_FMT_YUV420); -+} -+ -+/*! -+ * Start stream I/O -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int csi_streamon(cam_data *cam) -+{ -+ struct mxc_v4l_frame *frame; -+ unsigned long flags; -+ unsigned long val; -+ int timeout, timeout2; -+ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ if (NULL == cam) { -+ pr_err("ERROR: v4l2 capture: %s cam parameter is NULL\n", -+ __func__); -+ return -1; -+ } -+ cam->dummy_frame.vaddress = dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->dummy_frame.paddress, -+ GFP_DMA | GFP_KERNEL); -+ if (cam->dummy_frame.vaddress == 0) { -+ pr_err("ERROR: v4l2 capture: Allocate dummy frame " -+ "failed.\n"); -+ return -ENOBUFS; -+ } -+ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; -+ cam->dummy_frame.buffer.length = cam->v2f.fmt.pix.sizeimage; -+ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; -+ -+ spin_lock_irqsave(&cam->queue_int_lock, flags); -+ /* move the frame from readyq to workingq */ -+ if (list_empty(&cam->ready_q)) { -+ pr_err("ERROR: v4l2 capture: %s: " -+ "ready_q queue empty\n", __func__); -+ spin_unlock_irqrestore(&cam->queue_int_lock, flags); -+ return -1; -+ } -+ frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->ready_q.next); -+ list_add_tail(&frame->queue, &cam->working_q); -+ __raw_writel(frame->paddress, CSI_CSIDMASA_FB1); -+ frame->csi_buf_num = 1; -+ -+ if (list_empty(&cam->ready_q)) { -+ pr_err("ERROR: v4l2 capture: %s: " -+ "ready_q queue empty\n", __func__); -+ spin_unlock_irqrestore(&cam->queue_int_lock, flags); -+ return -1; -+ } -+ frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->ready_q.next); -+ list_add_tail(&frame->queue, &cam->working_q); -+ __raw_writel(frame->paddress, CSI_CSIDMASA_FB2); -+ frame->csi_buf_num = 2; -+ spin_unlock_irqrestore(&cam->queue_int_lock, flags); -+ -+ cam->capture_pid = current->pid; -+ cam->capture_on = true; -+ csi_cap_image(cam); -+ -+ local_irq_save(flags); -+ for (timeout = 1000000; timeout > 0; timeout--) { -+ if (__raw_readl(CSI_CSISR) & BIT_SOF_INT) { -+ val = __raw_readl(CSI_CSICR3); -+ __raw_writel(val | BIT_DMA_REFLASH_RFF, CSI_CSICR3); -+ for (timeout2 = 1000000; timeout2 > 0; timeout2--) { -+ if (__raw_readl(CSI_CSICR3) & -+ BIT_DMA_REFLASH_RFF) -+ cpu_relax(); -+ else -+ break; -+ } -+ if (timeout2 <= 0) { -+ pr_err("timeout when wait for reflash done.\n"); -+ local_irq_restore(flags); -+ return -ETIME; -+ } -+ -+ csi_dmareq_rff_enable(); -+ csi_enable_int(1); -+ break; -+ } else -+ cpu_relax(); -+ } -+ if (timeout <= 0) { -+ pr_err("timeout when wait for SOF\n"); -+ local_irq_restore(flags); -+ return -ETIME; -+ } -+ local_irq_restore(flags); -+ -+ return 0; -+} -+ -+/*! -+ * Stop stream I/O -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int csi_streamoff(cam_data *cam) -+{ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ if (cam->capture_on == false) -+ return 0; -+ -+ csi_dmareq_rff_disable(); -+ csi_disable_int(); -+ cam->capture_on = false; -+ -+ /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ -+ __raw_writel(0, CSI_CSIDMASA_FB1); -+ __raw_writel(0, CSI_CSIDMASA_FB2); -+ -+ csi_free_frames(cam); -+ csi_free_frame_buf(cam); -+ -+ return 0; -+} -+ -+/*! -+ * start the viewfinder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int start_preview(cam_data *cam) -+{ -+ unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base; -+ -+ __raw_writel(fb_addr, CSI_CSIDMASA_FB1); -+ __raw_writel(fb_addr, CSI_CSIDMASA_FB2); -+ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3); -+ -+ csi_enable_int(0); -+ -+ return 0; -+} -+ -+/*! -+ * shut down the viewfinder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int stop_preview(cam_data *cam) -+{ -+ csi_disable_int(); -+ -+ /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ -+ __raw_writel(0, CSI_CSIDMASA_FB1); -+ __raw_writel(0, CSI_CSIDMASA_FB2); -+ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3); -+ -+ return 0; -+} -+ -+/*************************************************************************** -+ * VIDIOC Functions. -+ **************************************************************************/ -+ -+/*! -+ * -+ * @param cam structure cam_data * -+ * -+ * @param f structure v4l2_format * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int csi_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) -+{ -+ int retval = 0; -+ -+ switch (f->type) { -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); -+ f->fmt.pix = cam->v2f.fmt.pix; -+ break; -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); -+ f->fmt.win = cam->win; -+ break; -+ default: -+ pr_debug(" type is invalid\n"); -+ retval = -EINVAL; -+ } -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ -+ return retval; -+} -+ -+/*! -+ * V4L2 - csi_v4l2_s_fmt function -+ * -+ * @param cam structure cam_data * -+ * -+ * @param f structure v4l2_format * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) -+{ -+ int retval = 0; -+ int size = 0; -+ int bytesperline = 0; -+ int *width, *height; -+ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ switch (f->type) { -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); -+ if (!valid_mode(f->fmt.pix.pixelformat)) { -+ pr_err("ERROR: v4l2 capture: %s: format " -+ "not supported\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* Handle case where size requested is larger than cuurent -+ * camera setting. */ -+ if ((f->fmt.pix.width > cam->crop_bounds.width) -+ || (f->fmt.pix.height > cam->crop_bounds.height)) { -+ /* Need the logic here, calling vidioc_s_param if -+ * camera can change. */ -+ pr_debug("csi_v4l2_s_fmt size changed\n"); -+ } -+ if (cam->rotation % 180) { -+ height = &f->fmt.pix.width; -+ width = &f->fmt.pix.height; -+ } else { -+ width = &f->fmt.pix.width; -+ height = &f->fmt.pix.height; -+ } -+ -+ if ((cam->crop_bounds.width / *width > 8) || -+ ((cam->crop_bounds.width / *width == 8) && -+ (cam->crop_bounds.width % *width))) { -+ *width = cam->crop_bounds.width / 8; -+ if (*width % 8) -+ *width += 8 - *width % 8; -+ pr_err("ERROR: v4l2 capture: width exceeds limit " -+ "resize to %d.\n", *width); -+ } -+ -+ if ((cam->crop_bounds.height / *height > 8) || -+ ((cam->crop_bounds.height / *height == 8) && -+ (cam->crop_bounds.height % *height))) { -+ *height = cam->crop_bounds.height / 8; -+ if (*height % 8) -+ *height += 8 - *height % 8; -+ pr_err("ERROR: v4l2 capture: height exceeds limit " -+ "resize to %d.\n", *height); -+ } -+ -+ switch (f->fmt.pix.pixelformat) { -+ case V4L2_PIX_FMT_RGB565: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ csi_init_format(V4L2_PIX_FMT_UYVY); -+ csi_set_16bit_imagpara(f->fmt.pix.width, -+ f->fmt.pix.height); -+ bytesperline = f->fmt.pix.width * 2; -+ break; -+ case V4L2_PIX_FMT_UYVY: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ csi_init_format(f->fmt.pix.pixelformat); -+ csi_set_16bit_imagpara(f->fmt.pix.width, -+ f->fmt.pix.height); -+ bytesperline = f->fmt.pix.width * 2; -+ break; -+ case V4L2_PIX_FMT_YUYV: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ csi_init_format(f->fmt.pix.pixelformat); -+ csi_set_16bit_imagpara(f->fmt.pix.width, -+ f->fmt.pix.height); -+ bytesperline = f->fmt.pix.width * 2; -+ break; -+ case V4L2_PIX_FMT_YUV420: -+ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; -+ csi_set_12bit_imagpara(f->fmt.pix.width, -+ f->fmt.pix.height); -+ bytesperline = f->fmt.pix.width; -+ break; -+ case V4L2_PIX_FMT_YUV422P: -+ case V4L2_PIX_FMT_RGB24: -+ case V4L2_PIX_FMT_BGR24: -+ case V4L2_PIX_FMT_BGR32: -+ case V4L2_PIX_FMT_RGB32: -+ case V4L2_PIX_FMT_NV12: -+ default: -+ pr_debug(" case not supported\n"); -+ break; -+ } -+ -+ if (f->fmt.pix.bytesperline < bytesperline) -+ f->fmt.pix.bytesperline = bytesperline; -+ else -+ bytesperline = f->fmt.pix.bytesperline; -+ -+ if (f->fmt.pix.sizeimage < size) -+ f->fmt.pix.sizeimage = size; -+ else -+ size = f->fmt.pix.sizeimage; -+ -+ cam->v2f.fmt.pix = f->fmt.pix; -+ -+ if (cam->v2f.fmt.pix.priv != 0) { -+ if (copy_from_user(&cam->offset, -+ (void *)cam->v2f.fmt.pix.priv, -+ sizeof(cam->offset))) { -+ retval = -EFAULT; -+ break; -+ } -+ } -+ break; -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); -+ cam->win = f->fmt.win; -+ win_current = f->fmt.win; -+ size = win_current.w.width * win_current.w.height * 2; -+ if (cam->v2f.fmt.pix.sizeimage < size) -+ cam->v2f.fmt.pix.sizeimage = size; -+ -+ break; -+ default: -+ retval = -EINVAL; -+ } -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ -+ return retval; -+} -+ -+/*! -+ * V4L2 - csi_v4l2_s_param function -+ * Allows setting of capturemode and frame rate. -+ * -+ * @param cam structure cam_data * -+ * @param parm structure v4l2_streamparm * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) -+{ -+ struct v4l2_ifparm ifparm; -+ struct v4l2_format cam_fmt; -+ struct v4l2_streamparm currentparm; -+ int err = 0; -+ -+ pr_debug("In %s\n", __func__); -+ -+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ pr_err(KERN_ERR "%s invalid type\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* Stop the viewfinder */ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ -+ /* First check that this device can support the changes requested. */ -+ err = vidioc_int_g_parm(cam->sensor, ¤tparm); -+ if (err) { -+ pr_err("%s: vidioc_int_g_parm returned an error %d\n", -+ __func__, err); -+ goto exit; -+ } -+ -+ pr_debug(" Current capabilities are %x\n", -+ currentparm.parm.capture.capability); -+ pr_debug(" Current capturemode is %d change to %d\n", -+ currentparm.parm.capture.capturemode, -+ parm->parm.capture.capturemode); -+ pr_debug(" Current framerate is %d change to %d\n", -+ currentparm.parm.capture.timeperframe.denominator, -+ parm->parm.capture.timeperframe.denominator); -+ -+ err = vidioc_int_s_parm(cam->sensor, parm); -+ if (err) { -+ pr_err("%s: vidioc_int_s_parm returned an error %d\n", -+ __func__, err); -+ goto exit; -+ } -+ -+ vidioc_int_g_ifparm(cam->sensor, &ifparm); -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); -+ pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", -+ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); -+ -+ cam->crop_bounds.top = cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = cam_fmt.fmt.pix.width; -+ cam->crop_bounds.height = cam_fmt.fmt.pix.height; -+ cam->crop_current.width = cam->crop_bounds.width; -+ cam->crop_current.height = cam->crop_bounds.height; -+ -+exit: -+ return err; -+} -+ -+static int pxp_set_cstate(cam_data *cam, struct v4l2_control *vc) -+{ -+ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; -+ -+ if (vc->id == V4L2_CID_HFLIP) { -+ proc_data->hflip = vc->value; -+ } else if (vc->id == V4L2_CID_VFLIP) { -+ proc_data->vflip = vc->value; -+ } else if (vc->id == V4L2_CID_PRIVATE_BASE) { -+ if (vc->value % 90) -+ return -ERANGE; -+ proc_data->rotate = vc->value; -+ cam->rotation = vc->value; -+ } -+ -+ return 0; -+} -+ -+static int pxp_get_cstate(cam_data *cam, struct v4l2_control *vc) -+{ -+ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; -+ -+ if (vc->id == V4L2_CID_HFLIP) -+ vc->value = proc_data->hflip; -+ else if (vc->id == V4L2_CID_VFLIP) -+ vc->value = proc_data->vflip; -+ else if (vc->id == V4L2_CID_PRIVATE_BASE) -+ vc->value = proc_data->rotate; -+ -+ return 0; -+} -+ -+ -+/*! -+ * Dequeue one V4L capture buffer -+ * -+ * @param cam structure cam_data * -+ * @param buf structure v4l2_buffer * -+ * -+ * @return status 0 success, EINVAL invalid frame number -+ * ETIME timeout, ERESTARTSYS interrupted by user -+ */ -+static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ int retval = 0; -+ struct mxc_v4l_frame *frame; -+ unsigned long lock_flags; -+ -+ if (!wait_event_interruptible_timeout(cam->enc_queue, -+ cam->enc_counter != 0, 10 * HZ)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " -+ "enc_counter %x\n", cam->enc_counter); -+ return -ETIME; -+ } else if (signal_pending(current)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " -+ "interrupt received\n"); -+ return -ERESTARTSYS; -+ } -+ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EBUSY; -+ -+ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); -+ -+ if (list_empty(&cam->done_q)) { -+ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); -+ up(&cam->busy_lock); -+ return -EINVAL; -+ } -+ -+ cam->enc_counter--; -+ -+ frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->done_q.next); -+ -+ if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { -+ frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; -+ } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " -+ "Buffer not filled.\n"); -+ frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; -+ retval = -EINVAL; -+ } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " -+ "Buffer not queued.\n"); -+ retval = -EINVAL; -+ } -+ -+ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); -+ -+ buf->bytesused = cam->v2f.fmt.pix.sizeimage; -+ buf->index = frame->index; -+ buf->flags = frame->buffer.flags; -+ buf->m = cam->frame[frame->index].buffer.m; -+ -+ /* -+ * Note: -+ * If want to do preview on LCD, use PxP CSC to convert from UYVY -+ * to RGB565; but for encoding, usually we don't use RGB format. -+ */ -+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { -+ sg_dma_address(&cam->sg[0]) = buf->m.offset; -+ sg_dma_address(&cam->sg[1]) = -+ cam->frame[req_buf_number].paddress; -+ retval = pxp_process_update(cam); -+ if (retval) { -+ pr_err("Unable to submit PxP update task.\n"); -+ return retval; -+ } -+ pxp_complete_update(cam); -+ if (cam->frame[buf->index].vaddress) -+ memcpy(cam->frame[buf->index].vaddress, -+ cam->frame[req_buf_number].vaddress, -+ cam->v2f.fmt.pix.sizeimage); -+ } -+ up(&cam->busy_lock); -+ -+ return retval; -+} -+ -+/*! -+ * V4L interface - open function -+ * -+ * @param file structure file * -+ * -+ * @return status 0 success, ENODEV invalid device instance, -+ * ENODEV timeout, ERESTARTSYS interrupted by user -+ */ -+static int csi_v4l_open(struct file *file) -+{ -+ struct v4l2_ifparm ifparm; -+ struct v4l2_format cam_fmt; -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ struct sensor_data *sensor; -+ int err = 0; -+ -+ pr_debug(" device name is %s\n", dev->name); -+ -+ if (!cam) { -+ pr_err("%s: Internal error, cam_data not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ if (!cam->sensor) { -+ pr_err("%s: Internal error, camera is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ sensor = cam->sensor->priv; -+ if (!sensor) { -+ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ down(&cam->busy_lock); -+ err = 0; -+ if (signal_pending(current)) -+ goto oops; -+ -+ if (cam->open_count++ == 0) { -+ wait_event_interruptible(cam->power_queue, -+ cam->low_power == false); -+ -+ cam->enc_counter = 0; -+ INIT_LIST_HEAD(&cam->ready_q); -+ INIT_LIST_HEAD(&cam->working_q); -+ INIT_LIST_HEAD(&cam->done_q); -+ -+ vidioc_int_g_ifparm(cam->sensor, &ifparm); -+ -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ clk_prepare_enable(sensor->sensor_clk); -+ vidioc_int_s_power(cam->sensor, 1); -+ vidioc_int_init(cam->sensor); -+ vidioc_int_dev_init(cam->sensor); -+ } -+ -+ file->private_data = dev; -+ -+oops: -+ up(&cam->busy_lock); -+ return err; -+} -+ -+/*! -+ * V4L interface - close function -+ * -+ * @param file struct file * -+ * -+ * @return 0 success -+ */ -+static int csi_v4l_close(struct file *file) -+{ -+ struct video_device *dev = video_devdata(file); -+ int err = 0; -+ cam_data *cam = video_get_drvdata(dev); -+ struct sensor_data *sensor; -+ -+ pr_debug("In MVC:%s\n", __func__); -+ -+ if (!cam) { -+ pr_err("%s: Internal error, cam_data not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ if (!cam->sensor) { -+ pr_err("%s: Internal error, camera is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ sensor = cam->sensor->priv; -+ if (!sensor) { -+ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ /* for the case somebody hit the ctrl C */ -+ if (cam->overlay_pid == current->pid) { -+ err = stop_preview(cam); -+ cam->overlay_on = false; -+ } -+ -+ if (--cam->open_count == 0) { -+ wait_event_interruptible(cam->power_queue, -+ cam->low_power == false); -+ file->private_data = NULL; -+ vidioc_int_s_power(cam->sensor, 0); -+ clk_disable_unprepare(sensor->sensor_clk); -+ } -+ -+ return err; -+} -+ -+/* -+ * V4L interface - read function -+ * -+ * @param file struct file * -+ * @param read buf char * -+ * @param count size_t -+ * @param ppos structure loff_t * -+ * -+ * @return bytes read -+ */ -+static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count, -+ loff_t *ppos) -+{ -+ int err = 0; -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EINTR; -+ -+ /* Stop the viewfinder */ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ if (cam->still_buf_vaddr == NULL) { -+ cam->still_buf_vaddr = dma_alloc_coherent(0, -+ PAGE_ALIGN -+ (cam->v2f.fmt. -+ pix.sizeimage), -+ &cam-> -+ still_buf[0], -+ GFP_DMA | GFP_KERNEL); -+ if (cam->still_buf_vaddr == NULL) { -+ pr_err("alloc dma memory failed\n"); -+ return -ENOMEM; -+ } -+ cam->still_counter = 0; -+ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB2); -+ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB1); -+ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, -+ CSI_CSICR3); -+ __raw_writel(__raw_readl(CSI_CSISR), CSI_CSISR); -+ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, -+ CSI_CSICR3); -+ csi_enable_int(1); -+ } -+ -+ wait_event_interruptible(cam->still_queue, cam->still_counter); -+ csi_disable_int(); -+ err = copy_to_user(buf, cam->still_buf_vaddr, -+ cam->v2f.fmt.pix.sizeimage); -+ -+ if (cam->still_buf_vaddr != NULL) { -+ dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ cam->still_buf_vaddr, cam->still_buf[0]); -+ cam->still_buf[0] = 0; -+ cam->still_buf_vaddr = NULL; -+ } -+ -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ -+ up(&cam->busy_lock); -+ if (err < 0) -+ return err; -+ -+ return cam->v2f.fmt.pix.sizeimage - err; -+} -+ -+/*! -+ * V4L interface - ioctl function -+ * -+ * @param file struct file* -+ * -+ * @param ioctlnr unsigned int -+ * -+ * @param arg void* -+ * -+ * @return 0 success, ENODEV for invalid device instance, -+ * -1 for other errors. -+ */ -+static long csi_v4l_do_ioctl(struct file *file, -+ unsigned int ioctlnr, void *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ int retval = 0; -+ unsigned long lock_flags; -+ -+ pr_debug("In MVC: %s, %x\n", __func__, ioctlnr); -+ wait_event_interruptible(cam->power_queue, cam->low_power == false); -+ /* make this _really_ smp-safe */ -+ if (ioctlnr != VIDIOC_DQBUF) -+ if (down_interruptible(&cam->busy_lock)) -+ return -EBUSY; -+ -+ switch (ioctlnr) { -+ /*! -+ * V4l2 VIDIOC_G_FMT ioctl -+ */ -+ case VIDIOC_G_FMT:{ -+ struct v4l2_format *gf = arg; -+ pr_debug(" case VIDIOC_G_FMT\n"); -+ retval = csi_v4l2_g_fmt(cam, gf); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_FMT ioctl -+ */ -+ case VIDIOC_S_FMT:{ -+ struct v4l2_format *sf = arg; -+ pr_debug(" case VIDIOC_S_FMT\n"); -+ retval = csi_v4l2_s_fmt(cam, sf); -+ vidioc_int_s_fmt_cap(cam->sensor, sf); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_OVERLAY ioctl -+ */ -+ case VIDIOC_OVERLAY:{ -+ int *on = arg; -+ pr_debug(" case VIDIOC_OVERLAY\n"); -+ if (*on) { -+ cam->overlay_on = true; -+ cam->overlay_pid = current->pid; -+ start_preview(cam); -+ } -+ if (!*on) { -+ stop_preview(cam); -+ cam->overlay_on = false; -+ } -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_G_FBUF ioctl -+ */ -+ case VIDIOC_G_FBUF:{ -+ struct v4l2_framebuffer *fb = arg; -+ *fb = cam->v4l2_fb; -+ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_FBUF ioctl -+ */ -+ case VIDIOC_S_FBUF:{ -+ struct v4l2_framebuffer *fb = arg; -+ cam->v4l2_fb = *fb; -+ break; -+ } -+ -+ case VIDIOC_G_PARM:{ -+ struct v4l2_streamparm *parm = arg; -+ pr_debug(" case VIDIOC_G_PARM\n"); -+ vidioc_int_g_parm(cam->sensor, parm); -+ break; -+ } -+ -+ case VIDIOC_S_PARM:{ -+ struct v4l2_streamparm *parm = arg; -+ pr_debug(" case VIDIOC_S_PARM\n"); -+ retval = csi_v4l2_s_param(cam, parm); -+ break; -+ } -+ -+ case VIDIOC_QUERYCAP:{ -+ struct v4l2_capability *cap = arg; -+ pr_debug(" case VIDIOC_QUERYCAP\n"); -+ strcpy(cap->driver, "csi_v4l2"); -+ cap->version = KERNEL_VERSION(0, 1, 11); -+ cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | -+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | -+ V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE; -+ cap->card[0] = '\0'; -+ cap->bus_info[0] = '\0'; -+ break; -+ } -+ -+ case VIDIOC_CROPCAP: -+ { -+ struct v4l2_cropcap *cap = arg; -+ -+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && -+ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { -+ retval = -EINVAL; -+ break; -+ } -+ cap->bounds = cam->crop_bounds; -+ cap->defrect = cam->crop_defrect; -+ break; -+ } -+ case VIDIOC_S_CROP: -+ { -+ struct v4l2_crop *crop = arg; -+ struct v4l2_rect *b = &cam->crop_bounds; -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ retval = -EINVAL; -+ break; -+ } -+ -+ crop->c.top = (crop->c.top < b->top) ? b->top -+ : crop->c.top; -+ if (crop->c.top > b->top + b->height) -+ crop->c.top = b->top + b->height - 1; -+ if (crop->c.height > b->top + b->height - crop->c.top) -+ crop->c.height = -+ b->top + b->height - crop->c.top; -+ -+ crop->c.left = (crop->c.left < b->left) ? b->left -+ : crop->c.left; -+ if (crop->c.left > b->left + b->width) -+ crop->c.left = b->left + b->width - 1; -+ if (crop->c.width > b->left - crop->c.left + b->width) -+ crop->c.width = -+ b->left - crop->c.left + b->width; -+ -+ crop->c.width -= crop->c.width % 8; -+ crop->c.height -= crop->c.height % 8; -+ -+ crop_current.c = crop->c; -+ -+ break; -+ } -+ case VIDIOC_G_CROP: -+ { -+ struct v4l2_crop *crop = arg; -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ retval = -EINVAL; -+ break; -+ } -+ crop->c = crop_current.c; -+ -+ break; -+ -+ } -+ case VIDIOC_REQBUFS: { -+ struct v4l2_requestbuffers *req = arg; -+ pr_debug(" case VIDIOC_REQBUFS\n"); -+ -+ if (req->count > FRAME_NUM) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " -+ "not enough buffers\n"); -+ req->count = FRAME_NUM; -+ } -+ -+ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " -+ "wrong buffer type\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ csi_streamoff(cam); -+ if (req->memory & V4L2_MEMORY_MMAP) { -+ csi_free_frame_buf(cam); -+ retval = csi_allocate_frame_buf(cam, req->count + 1); -+ req_buf_number = req->count; -+ } -+ break; -+ } -+ -+ case VIDIOC_QUERYBUF: { -+ struct v4l2_buffer *buf = arg; -+ int index = buf->index; -+ pr_debug(" case VIDIOC_QUERYBUF\n"); -+ -+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ retval = -EINVAL; -+ break; -+ } -+ -+ if (buf->memory & V4L2_MEMORY_MMAP) { -+ memset(buf, 0, sizeof(buf)); -+ buf->index = index; -+ } -+ -+ down(&cam->param_lock); -+ if (buf->memory & V4L2_MEMORY_USERPTR) { -+ csi_v4l2_release_bufs(cam); -+ retval = csi_v4l2_prepare_bufs(cam, buf); -+ } -+ if (buf->memory & V4L2_MEMORY_MMAP) -+ retval = csi_v4l2_buffer_status(cam, buf); -+ up(&cam->param_lock); -+ break; -+ } -+ -+ case VIDIOC_QBUF: { -+ struct v4l2_buffer *buf = arg; -+ int index = buf->index; -+ pr_debug(" case VIDIOC_QBUF\n"); -+ -+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); -+ cam->frame[index].buffer.m.offset = buf->m.offset; -+ if ((cam->frame[index].buffer.flags & 0x7) == -+ V4L2_BUF_FLAG_MAPPED) { -+ cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED; -+ list_add_tail(&cam->frame[index].queue, &cam->ready_q); -+ } else if (cam->frame[index].buffer.flags & -+ V4L2_BUF_FLAG_QUEUED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " -+ "buffer already queued\n"); -+ retval = -EINVAL; -+ } else if (cam->frame[index].buffer. -+ flags & V4L2_BUF_FLAG_DONE) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " -+ "overwrite done buffer.\n"); -+ cam->frame[index].buffer.flags &= -+ ~V4L2_BUF_FLAG_DONE; -+ cam->frame[index].buffer.flags |= -+ V4L2_BUF_FLAG_QUEUED; -+ retval = -EINVAL; -+ } -+ buf->flags = cam->frame[index].buffer.flags; -+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); -+ -+ break; -+ } -+ -+ case VIDIOC_DQBUF: { -+ struct v4l2_buffer *buf = arg; -+ pr_debug(" case VIDIOC_DQBUF\n"); -+ -+ retval = csi_v4l_dqueue(cam, buf); -+ -+ break; -+ } -+ -+ case VIDIOC_STREAMON: { -+ pr_debug(" case VIDIOC_STREAMON\n"); -+ retval = csi_streamon(cam); -+ break; -+ } -+ -+ case VIDIOC_STREAMOFF: { -+ pr_debug(" case VIDIOC_STREAMOFF\n"); -+ retval = csi_streamoff(cam); -+ break; -+ } -+ case VIDIOC_ENUM_FMT: { -+ struct v4l2_fmtdesc *fmt = arg; -+ if (cam->sensor) -+ retval = vidioc_int_enum_fmt_cap(cam->sensor, fmt); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_ENUM_FRAMESIZES: { -+ struct v4l2_frmsizeenum *fsize = arg; -+ if (cam->sensor) -+ retval = vidioc_int_enum_framesizes(cam->sensor, fsize); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_ENUM_FRAMEINTERVALS: { -+ struct v4l2_frmivalenum *fival = arg; -+ if (cam->sensor) -+ retval = vidioc_int_enum_frameintervals(cam->sensor, -+ fival); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_DBG_G_CHIP_IDENT: { -+ struct v4l2_dbg_chip_ident *p = arg; -+ p->ident = V4L2_IDENT_NONE; -+ p->revision = 0; -+ if (cam->sensor) -+ retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ -+ case VIDIOC_S_CTRL: -+ { -+ struct v4l2_control *vc = arg; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) -+ if (vc->id == pxp_controls[i].id) { -+ if (vc->value < pxp_controls[i].minimum || -+ vc->value > pxp_controls[i].maximum) { -+ retval = -ERANGE; -+ break; -+ } -+ retval = pxp_set_cstate(cam, vc); -+ break; -+ } -+ -+ if (i >= ARRAY_SIZE(pxp_controls)) -+ retval = -EINVAL; -+ break; -+ -+ } -+ case VIDIOC_G_CTRL: -+ { -+ struct v4l2_control *vc = arg; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) -+ if (vc->id == pxp_controls[i].id) { -+ retval = pxp_get_cstate(cam, vc); -+ break; -+ } -+ -+ if (i >= ARRAY_SIZE(pxp_controls)) -+ retval = -EINVAL; -+ break; -+ } -+ case VIDIOC_QUERYCTRL: -+ { -+ struct v4l2_queryctrl *qc = arg; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) -+ if (qc->id && qc->id == pxp_controls[i].id) { -+ memcpy(qc, &(pxp_controls[i]), sizeof(*qc)); -+ break; -+ } -+ -+ if (i >= ARRAY_SIZE(pxp_controls)) -+ retval = -EINVAL; -+ break; -+ } -+ case VIDIOC_G_STD: -+ case VIDIOC_G_OUTPUT: -+ case VIDIOC_S_OUTPUT: -+ case VIDIOC_ENUMSTD: -+ case VIDIOC_S_STD: -+ case VIDIOC_TRY_FMT: -+ case VIDIOC_ENUMINPUT: -+ case VIDIOC_G_INPUT: -+ case VIDIOC_S_INPUT: -+ case VIDIOC_G_TUNER: -+ case VIDIOC_S_TUNER: -+ case VIDIOC_G_FREQUENCY: -+ case VIDIOC_S_FREQUENCY: -+ case VIDIOC_ENUMOUTPUT: -+ default: -+ pr_debug(" case not supported\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ if (ioctlnr != VIDIOC_DQBUF) -+ up(&cam->busy_lock); -+ return retval; -+} -+ -+/* -+ * V4L interface - ioctl function -+ * -+ * @return None -+ */ -+static long csi_v4l_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return video_usercopy(file, cmd, arg, csi_v4l_do_ioctl); -+} -+ -+/*! -+ * V4L interface - mmap function -+ * -+ * @param file structure file * -+ * -+ * @param vma structure vm_area_struct * -+ * -+ * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error -+ */ -+static int csi_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct video_device *dev = video_devdata(file); -+ unsigned long size; -+ int res = 0; -+ cam_data *cam = video_get_drvdata(dev); -+ -+ pr_debug("%s\n", __func__); -+ pr_debug("\npgoff=0x%lx, start=0x%lx, end=0x%lx\n", -+ vma->vm_pgoff, vma->vm_start, vma->vm_end); -+ -+ /* make this _really_ smp-safe */ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EINTR; -+ -+ size = vma->vm_end - vma->vm_start; -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ if (remap_pfn_range(vma, vma->vm_start, -+ vma->vm_pgoff, size, vma->vm_page_prot)) { -+ pr_err("ERROR: v4l2 capture: %s : " -+ "remap_pfn_range failed\n", __func__); -+ res = -ENOBUFS; -+ goto csi_mmap_exit; -+ } -+ -+ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ -+ -+csi_mmap_exit: -+ up(&cam->busy_lock); -+ return res; -+} -+ -+/*! -+ * This structure defines the functions to be called in this driver. -+ */ -+static struct v4l2_file_operations csi_v4l_fops = { -+ .owner = THIS_MODULE, -+ .open = csi_v4l_open, -+ .release = csi_v4l_close, -+ .read = csi_v4l_read, -+ .ioctl = csi_v4l_ioctl, -+ .mmap = csi_mmap, -+}; -+ -+static struct video_device csi_v4l_template = { -+ .name = "Mx25 Camera", -+ .fops = &csi_v4l_fops, -+ .release = video_device_release, -+}; -+ -+/*! -+ * initialize cam_data structure -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static void init_camera_struct(cam_data *cam) -+{ -+ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; -+ pr_debug("In MVC: %s\n", __func__); -+ -+ proc_data->hflip = 0; -+ proc_data->vflip = 0; -+ proc_data->rotate = 0; -+ proc_data->bgcolor = 0; -+ -+ /* Default everything to 0 */ -+ memset(cam, 0, sizeof(cam_data)); -+ -+ sema_init(&cam->param_lock, 1); -+ sema_init(&cam->busy_lock, 1); -+ -+ cam->video_dev = video_device_alloc(); -+ if (cam->video_dev == NULL) -+ return; -+ -+ *(cam->video_dev) = csi_v4l_template; -+ -+ video_set_drvdata(cam->video_dev, cam); -+ cam->video_dev->minor = -1; -+ -+ init_waitqueue_head(&cam->enc_queue); -+ init_waitqueue_head(&cam->still_queue); -+ -+ cam->streamparm.parm.capture.capturemode = 0; -+ -+ cam->standard.index = 0; -+ cam->standard.id = V4L2_STD_UNKNOWN; -+ cam->standard.frameperiod.denominator = 30; -+ cam->standard.frameperiod.numerator = 1; -+ cam->standard.framelines = 480; -+ cam->standard_autodetect = true; -+ cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; -+ cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; -+ cam->overlay_on = false; -+ cam->capture_on = false; -+ cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; -+ -+ cam->v2f.fmt.pix.sizeimage = 480 * 640 * 2; -+ cam->v2f.fmt.pix.bytesperline = 640 * 2; -+ cam->v2f.fmt.pix.width = 640; -+ cam->v2f.fmt.pix.height = 480; -+ cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; -+ cam->win.w.width = 160; -+ cam->win.w.height = 160; -+ cam->win.w.left = 0; -+ cam->win.w.top = 0; -+ cam->still_counter = 0; -+ /* setup cropping */ -+ cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = 640; -+ cam->crop_bounds.top = 0; -+ cam->crop_bounds.height = 480; -+ cam->crop_current = cam->crop_defrect = cam->crop_bounds; -+ -+ cam->enc_callback = camera_callback; -+ csi_start_callback(cam); -+ init_waitqueue_head(&cam->power_queue); -+ spin_lock_init(&cam->queue_int_lock); -+ spin_lock_init(&cam->dqueue_int_lock); -+} -+ -+/*! -+ * camera_power function -+ * Turns Sensor power On/Off -+ * -+ * @param cam cam data struct -+ * @param cameraOn true to turn camera on, false to turn off power. -+ * -+ * @return status -+ */ -+static u8 camera_power(cam_data *cam, bool cameraOn) -+{ -+ pr_debug("In MVC: %s on=%d\n", __func__, cameraOn); -+ -+ if (cameraOn == true) { -+ vidioc_int_s_power(cam->sensor, 1); -+ } else { -+ vidioc_int_s_power(cam->sensor, 0); -+ } -+ return 0; -+} -+ -+static const struct of_device_id imx_csi_v4l2_dt_ids[] = { -+ { .compatible = "fsl,imx6sl-csi-v4l2", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, imx_csi_v4l2_dt_ids); -+ -+static int csi_v4l2_probe(struct platform_device *pdev) -+{ -+ struct scatterlist *sg; -+ u8 err = 0; -+ -+ /* Create g_cam and initialize it. */ -+ g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL); -+ if (g_cam == NULL) { -+ pr_err("ERROR: v4l2 capture: failed to register camera\n"); -+ err = -ENOMEM; -+ goto out; -+ } -+ memset(&crop_current, 0, sizeof(crop_current)); -+ memset(&win_current, 0, sizeof(win_current)); -+ init_camera_struct(g_cam); -+ platform_set_drvdata(pdev, (void *)g_cam); -+ -+ /* Set up the v4l2 device and register it */ -+ csi_v4l2_int_device.priv = g_cam; -+ /* This function contains a bug that won't let this be rmmod'd. */ -+ v4l2_int_device_register(&csi_v4l2_int_device); -+ -+ /* register v4l video device */ -+ if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr) -+ == -1) { -+ kfree(g_cam); -+ g_cam = NULL; -+ pr_err("ERROR: v4l2 capture: video_register_device failed\n"); -+ err = -ENODEV; -+ goto out; -+ } -+ pr_debug(" Video device registered: %s #%d\n", -+ g_cam->video_dev->name, g_cam->video_dev->minor); -+ -+ g_cam->pxp_chan = NULL; -+ /* Initialize Scatter-gather list containing 2 buffer addresses. */ -+ sg = g_cam->sg; -+ sg_init_table(sg, 2); -+ -+out: -+ return err; -+} -+ -+static int csi_v4l2_remove(struct platform_device *pdev) -+{ -+ if (g_cam->open_count) { -+ pr_err("ERROR: v4l2 capture:camera open " -+ "-- setting ops to NULL\n"); -+ } else { -+ pr_info("V4L2 freeing image input device\n"); -+ v4l2_int_device_unregister(&csi_v4l2_int_device); -+ csi_stop_callback(g_cam); -+ video_unregister_device(g_cam->video_dev); -+ platform_set_drvdata(pdev, NULL); -+ -+ kfree(g_cam); -+ g_cam = NULL; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * This function is called to put the sensor in a low power state. -+ * Refer to the document driver-model/driver.txt in the kernel source tree -+ * for more information. -+ * -+ * @param pdev the device structure used to give information on which I2C -+ * to suspend -+ * @param state the power state the device is entering -+ * -+ * @return The function returns 0 on success and -1 on failure. -+ */ -+static int csi_v4l2_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ cam_data *cam = platform_get_drvdata(pdev); -+ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ if (cam == NULL) -+ return -1; -+ -+ cam->low_power = true; -+ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ if (cam->capture_on == true || cam->overlay_on == true) -+ camera_power(cam, false); -+ -+ return 0; -+} -+ -+/*! -+ * This function is called to bring the sensor back from a low power state. -+ * Refer to the document driver-model/driver.txt in the kernel source tree -+ * for more information. -+ * -+ * @param pdev the device structure -+ * -+ * @return The function returns 0 on success and -1 on failure -+ */ -+static int csi_v4l2_resume(struct platform_device *pdev) -+{ -+ cam_data *cam = platform_get_drvdata(pdev); -+ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ if (cam == NULL) -+ return -1; -+ -+ cam->low_power = false; -+ wake_up_interruptible(&cam->power_queue); -+ if (cam->capture_on == true || cam->overlay_on == true) -+ camera_power(cam, true); -+ -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ -+ return 0; -+} -+ -+/*! -+ * This structure contains pointers to the power management callback functions. -+ */ -+static struct platform_driver csi_v4l2_driver = { -+ .driver = { -+ .name = "csi_v4l2", -+ .of_match_table = of_match_ptr(imx_csi_v4l2_dt_ids), -+ }, -+ .probe = csi_v4l2_probe, -+ .remove = csi_v4l2_remove, -+#ifdef CONFIG_PM -+ .suspend = csi_v4l2_suspend, -+ .resume = csi_v4l2_resume, -+#endif -+ .shutdown = NULL, -+}; -+ -+/*! -+ * Initializes the camera driver. -+ */ -+static int csi_v4l2_master_attach(struct v4l2_int_device *slave) -+{ -+ cam_data *cam = slave->u.slave->master->priv; -+ struct v4l2_format cam_fmt; -+ -+ pr_debug("In MVC: %s\n", __func__); -+ pr_debug(" slave.name = %s\n", slave->name); -+ pr_debug(" master.name = %s\n", slave->u.slave->master->name); -+ -+ cam->sensor = slave; -+ if (slave == NULL) { -+ pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); -+ return -1; -+ } -+ -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); -+ -+ /* Used to detect TV in (type 1) vs. camera (type 0) */ -+ cam->device_type = cam_fmt.fmt.pix.priv; -+ -+ cam->crop_bounds.top = cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = cam_fmt.fmt.pix.width; -+ cam->crop_bounds.height = cam_fmt.fmt.pix.height; -+ -+ /* This also is the max crop size for this device. */ -+ cam->crop_defrect.top = cam->crop_defrect.left = 0; -+ cam->crop_defrect.width = cam_fmt.fmt.pix.width; -+ cam->crop_defrect.height = cam_fmt.fmt.pix.height; -+ -+ /* At this point, this is also the current image size. */ -+ cam->crop_current.top = cam->crop_current.left = 0; -+ cam->crop_current.width = cam_fmt.fmt.pix.width; -+ cam->crop_current.height = cam_fmt.fmt.pix.height; -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ -+ return 0; -+} -+ -+/*! -+ * Disconnects the camera driver. -+ */ -+static void csi_v4l2_master_detach(struct v4l2_int_device *slave) -+{ -+ pr_debug("In MVC: %s\n", __func__); -+ -+ vidioc_int_dev_exit(slave); -+} -+ -+module_platform_driver(csi_v4l2_driver); -+ -+module_param(video_nr, int, 0444); -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("V4L2 capture driver for Mx25 based cameras"); -+MODULE_LICENSE("GPL"); -+MODULE_SUPPORTED_DEVICE("video"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/fsl_csi.c linux-3.14.22/drivers/media/platform/mxc/capture/fsl_csi.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/fsl_csi.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/fsl_csi.c 2014-10-22 14:55:52.614220001 -0500 -@@ -0,0 +1,302 @@ -+/* -+ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file fsl_csi.c, this file is derived from mx27_csi.c -+ * -+ * @brief mx25 CMOS Sensor interface functions -+ * -+ * @ingroup CSI -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mxc_v4l2_capture.h" -+#include "fsl_csi.h" -+ -+void __iomem *csi_regbase; -+EXPORT_SYMBOL(csi_regbase); -+static int irq_nr; -+static csi_irq_callback_t g_callback; -+static void *g_callback_data; -+ -+static irqreturn_t csi_irq_handler(int irq, void *data) -+{ -+ cam_data *cam = (cam_data *) data; -+ unsigned long status = __raw_readl(CSI_CSISR); -+ -+ __raw_writel(status, CSI_CSISR); -+ -+ if (status & BIT_HRESP_ERR_INT) -+ pr_warning("Hresponse error is detected.\n"); -+ -+ if (status & BIT_DMA_TSF_DONE_FB1) { -+ if (cam->capture_on) { -+ spin_lock(&cam->queue_int_lock); -+ cam->ping_pong_csi = 1; -+ spin_unlock(&cam->queue_int_lock); -+ cam->enc_callback(0, cam); -+ } else { -+ cam->still_counter++; -+ wake_up_interruptible(&cam->still_queue); -+ } -+ } -+ -+ if (status & BIT_DMA_TSF_DONE_FB2) { -+ if (cam->capture_on) { -+ spin_lock(&cam->queue_int_lock); -+ cam->ping_pong_csi = 2; -+ spin_unlock(&cam->queue_int_lock); -+ cam->enc_callback(0, cam); -+ } else { -+ cam->still_counter++; -+ wake_up_interruptible(&cam->still_queue); -+ } -+ } -+ -+ if (g_callback) -+ g_callback(g_callback_data, status); -+ -+ pr_debug("CSI status = 0x%08lX\n", status); -+ -+ return IRQ_HANDLED; -+} -+ -+static void csihw_reset_frame_count(void) -+{ -+ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, CSI_CSICR3); -+} -+ -+static void csihw_reset(void) -+{ -+ csihw_reset_frame_count(); -+ __raw_writel(CSICR1_RESET_VAL, CSI_CSICR1); -+ __raw_writel(CSICR2_RESET_VAL, CSI_CSICR2); -+ __raw_writel(CSICR3_RESET_VAL, CSI_CSICR3); -+} -+ -+/*! -+ * csi_init_interface -+ * Init csi interface -+ */ -+void csi_init_interface(void) -+{ -+ unsigned int val = 0; -+ unsigned int imag_para; -+ -+ val |= BIT_SOF_POL; -+ val |= BIT_REDGE; -+ val |= BIT_GCLK_MODE; -+ val |= BIT_HSYNC_POL; -+ val |= BIT_PACK_DIR; -+ val |= BIT_FCC; -+ val |= BIT_SWAP16_EN; -+ val |= 1 << SHIFT_MCLKDIV; -+ val |= BIT_MCLKEN; -+ __raw_writel(val, CSI_CSICR1); -+ -+ imag_para = (640 << 16) | 960; -+ __raw_writel(imag_para, CSI_CSIIMAG_PARA); -+ -+ val = 0x1010; -+ val |= BIT_DMA_REFLASH_RFF; -+ __raw_writel(val, CSI_CSICR3); -+} -+EXPORT_SYMBOL(csi_init_interface); -+ -+void csi_init_format(int fmt) -+{ -+ unsigned int val; -+ -+ val = __raw_readl(CSI_CSICR1); -+ if (fmt == V4L2_PIX_FMT_YUYV) { -+ val &= ~BIT_PACK_DIR; -+ val &= ~BIT_SWAP16_EN; -+ } else if (fmt == V4L2_PIX_FMT_UYVY) { -+ val |= BIT_PACK_DIR; -+ val |= BIT_SWAP16_EN; -+ } else -+ pr_warning("unsupported format, old format remains.\n"); -+ -+ __raw_writel(val, CSI_CSICR1); -+} -+EXPORT_SYMBOL(csi_init_format); -+ -+/*! -+ * csi_read_mclk_flag -+ * -+ * @return gcsi_mclk_source -+ */ -+int csi_read_mclk_flag(void) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(csi_read_mclk_flag); -+ -+void csi_start_callback(void *data) -+{ -+ cam_data *cam = (cam_data *) data; -+ -+ if (request_irq(irq_nr, csi_irq_handler, 0, "csi", cam) < 0) -+ pr_debug("CSI error: irq request fail\n"); -+ -+} -+EXPORT_SYMBOL(csi_start_callback); -+ -+void csi_stop_callback(void *data) -+{ -+ cam_data *cam = (cam_data *) data; -+ -+ free_irq(irq_nr, cam); -+} -+EXPORT_SYMBOL(csi_stop_callback); -+ -+void csi_enable_int(int arg) -+{ -+ unsigned long cr1 = __raw_readl(CSI_CSICR1); -+ -+ cr1 |= BIT_SOF_INTEN; -+ if (arg == 1) { -+ /* still capture needs DMA intterrupt */ -+ cr1 |= BIT_FB1_DMA_DONE_INTEN; -+ cr1 |= BIT_FB2_DMA_DONE_INTEN; -+ } -+ __raw_writel(cr1, CSI_CSICR1); -+} -+EXPORT_SYMBOL(csi_enable_int); -+ -+void csi_disable_int(void) -+{ -+ unsigned long cr1 = __raw_readl(CSI_CSICR1); -+ -+ cr1 &= ~BIT_SOF_INTEN; -+ cr1 &= ~BIT_FB1_DMA_DONE_INTEN; -+ cr1 &= ~BIT_FB2_DMA_DONE_INTEN; -+ __raw_writel(cr1, CSI_CSICR1); -+} -+EXPORT_SYMBOL(csi_disable_int); -+ -+void csi_set_16bit_imagpara(int width, int height) -+{ -+ int imag_para = 0; -+ unsigned long cr3 = __raw_readl(CSI_CSICR3); -+ -+ imag_para = (width << 16) | (height * 2); -+ __raw_writel(imag_para, CSI_CSIIMAG_PARA); -+ -+ /* reflash the embeded DMA controller */ -+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); -+} -+EXPORT_SYMBOL(csi_set_16bit_imagpara); -+ -+void csi_set_12bit_imagpara(int width, int height) -+{ -+ int imag_para = 0; -+ unsigned long cr3 = __raw_readl(CSI_CSICR3); -+ -+ imag_para = (width << 16) | (height * 3 / 2); -+ __raw_writel(imag_para, CSI_CSIIMAG_PARA); -+ -+ /* reflash the embeded DMA controller */ -+ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); -+} -+EXPORT_SYMBOL(csi_set_12bit_imagpara); -+ -+void csi_dmareq_rff_enable(void) -+{ -+ unsigned long cr3 = __raw_readl(CSI_CSICR3); -+ -+ cr3 |= BIT_DMA_REQ_EN_RFF; -+ cr3 |= BIT_HRESP_ERR_EN; -+ __raw_writel(cr3, CSI_CSICR3); -+} -+EXPORT_SYMBOL(csi_dmareq_rff_enable); -+ -+void csi_dmareq_rff_disable(void) -+{ -+ unsigned long cr3 = __raw_readl(CSI_CSICR3); -+ -+ cr3 &= ~BIT_DMA_REQ_EN_RFF; -+ cr3 &= ~BIT_HRESP_ERR_EN; -+ __raw_writel(cr3, CSI_CSICR3); -+} -+EXPORT_SYMBOL(csi_dmareq_rff_disable); -+ -+static const struct of_device_id fsl_csi_dt_ids[] = { -+ { .compatible = "fsl,imx6sl-csi", }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, fsl_csi_dt_ids); -+ -+static int csi_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "No csi irq found.\n"); -+ ret = -ENODEV; -+ goto err; -+ } -+ irq_nr = res->start; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "No csi base address found.\n"); -+ ret = -ENODEV; -+ goto err; -+ } -+ csi_regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); -+ if (!csi_regbase) { -+ dev_err(&pdev->dev, "ioremap failed with csi base\n"); -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ csihw_reset(); -+ csi_init_interface(); -+ csi_dmareq_rff_disable(); -+ -+err: -+ return ret; -+} -+ -+static int csi_remove(struct platform_device *pdev) -+{ -+ return 0; -+} -+ -+static struct platform_driver csi_driver = { -+ .driver = { -+ .name = "fsl_csi", -+ .of_match_table = of_match_ptr(fsl_csi_dt_ids), -+ }, -+ .probe = csi_probe, -+ .remove = csi_remove, -+}; -+ -+module_platform_driver(csi_driver); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("fsl CSI driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/fsl_csi.h linux-3.14.22/drivers/media/platform/mxc/capture/fsl_csi.h ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/fsl_csi.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/fsl_csi.h 2014-10-22 14:55:52.614220001 -0500 -@@ -0,0 +1,198 @@ -+/* -+ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file fsl_csi.h -+ * -+ * @brief mx25 CMOS Sensor interface functions -+ * -+ * @ingroup CSI -+ */ -+ -+#ifndef MX25_CSI_H -+#define MX25_CSI_H -+ -+#include -+ -+/* reset values */ -+#define CSICR1_RESET_VAL 0x40000800 -+#define CSICR2_RESET_VAL 0x0 -+#define CSICR3_RESET_VAL 0x0 -+ -+/* csi control reg 1 */ -+#define BIT_SWAP16_EN (0x1 << 31) -+#define BIT_EXT_VSYNC (0x1 << 30) -+#define BIT_EOF_INT_EN (0x1 << 29) -+#define BIT_PRP_IF_EN (0x1 << 28) -+#define BIT_CCIR_MODE (0x1 << 27) -+#define BIT_COF_INT_EN (0x1 << 26) -+#define BIT_SF_OR_INTEN (0x1 << 25) -+#define BIT_RF_OR_INTEN (0x1 << 24) -+#define BIT_SFF_DMA_DONE_INTEN (0x1 << 22) -+#define BIT_STATFF_INTEN (0x1 << 21) -+#define BIT_FB2_DMA_DONE_INTEN (0x1 << 20) -+#define BIT_FB1_DMA_DONE_INTEN (0x1 << 19) -+#define BIT_RXFF_INTEN (0x1 << 18) -+#define BIT_SOF_POL (0x1 << 17) -+#define BIT_SOF_INTEN (0x1 << 16) -+#define BIT_MCLKDIV (0xF << 12) -+#define BIT_HSYNC_POL (0x1 << 11) -+#define BIT_CCIR_EN (0x1 << 10) -+#define BIT_MCLKEN (0x1 << 9) -+#define BIT_FCC (0x1 << 8) -+#define BIT_PACK_DIR (0x1 << 7) -+#define BIT_CLR_STATFIFO (0x1 << 6) -+#define BIT_CLR_RXFIFO (0x1 << 5) -+#define BIT_GCLK_MODE (0x1 << 4) -+#define BIT_INV_DATA (0x1 << 3) -+#define BIT_INV_PCLK (0x1 << 2) -+#define BIT_REDGE (0x1 << 1) -+#define BIT_PIXEL_BIT (0x1 << 0) -+ -+#define SHIFT_MCLKDIV 12 -+ -+/* control reg 3 */ -+#define BIT_FRMCNT (0xFFFF << 16) -+#define BIT_FRMCNT_RST (0x1 << 15) -+#define BIT_DMA_REFLASH_RFF (0x1 << 14) -+#define BIT_DMA_REFLASH_SFF (0x1 << 13) -+#define BIT_DMA_REQ_EN_RFF (0x1 << 12) -+#define BIT_DMA_REQ_EN_SFF (0x1 << 11) -+#define BIT_STATFF_LEVEL (0x7 << 8) -+#define BIT_HRESP_ERR_EN (0x1 << 7) -+#define BIT_RXFF_LEVEL (0x7 << 4) -+#define BIT_TWO_8BIT_SENSOR (0x1 << 3) -+#define BIT_ZERO_PACK_EN (0x1 << 2) -+#define BIT_ECC_INT_EN (0x1 << 1) -+#define BIT_ECC_AUTO_EN (0x1 << 0) -+ -+#define SHIFT_FRMCNT 16 -+ -+/* csi status reg */ -+#define BIT_SFF_OR_INT (0x1 << 25) -+#define BIT_RFF_OR_INT (0x1 << 24) -+#define BIT_DMA_TSF_DONE_SFF (0x1 << 22) -+#define BIT_STATFF_INT (0x1 << 21) -+#define BIT_DMA_TSF_DONE_FB2 (0x1 << 20) -+#define BIT_DMA_TSF_DONE_FB1 (0x1 << 19) -+#define BIT_RXFF_INT (0x1 << 18) -+#define BIT_EOF_INT (0x1 << 17) -+#define BIT_SOF_INT (0x1 << 16) -+#define BIT_F2_INT (0x1 << 15) -+#define BIT_F1_INT (0x1 << 14) -+#define BIT_COF_INT (0x1 << 13) -+#define BIT_HRESP_ERR_INT (0x1 << 7) -+#define BIT_ECC_INT (0x1 << 1) -+#define BIT_DRDY (0x1 << 0) -+ -+#define CSI_MCLK_VF 1 -+#define CSI_MCLK_ENC 2 -+#define CSI_MCLK_RAW 4 -+#define CSI_MCLK_I2C 8 -+#endif -+ -+extern void __iomem *csi_regbase; -+#define CSI_CSICR1 (csi_regbase) -+#define CSI_CSICR2 (csi_regbase + 0x4) -+#define CSI_CSICR3 (csi_regbase + 0x8) -+#define CSI_STATFIFO (csi_regbase + 0xC) -+#define CSI_CSIRXFIFO (csi_regbase + 0x10) -+#define CSI_CSIRXCNT (csi_regbase + 0x14) -+#define CSI_CSISR (csi_regbase + 0x18) -+ -+#define CSI_CSIDBG (csi_regbase + 0x1C) -+#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20) -+#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24) -+#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28) -+#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C) -+#define CSI_CSIFBUF_PARA (csi_regbase + 0x30) -+#define CSI_CSIIMAG_PARA (csi_regbase + 0x34) -+ -+static inline void csi_clear_status(unsigned long status) -+{ -+ __raw_writel(status, CSI_CSISR); -+} -+ -+struct csi_signal_cfg_t { -+ unsigned data_width:3; -+ unsigned clk_mode:2; -+ unsigned ext_vsync:1; -+ unsigned Vsync_pol:1; -+ unsigned Hsync_pol:1; -+ unsigned pixclk_pol:1; -+ unsigned data_pol:1; -+ unsigned sens_clksrc:1; -+}; -+ -+struct csi_config_t { -+ /* control reg 1 */ -+ unsigned int swap16_en:1; -+ unsigned int ext_vsync:1; -+ unsigned int eof_int_en:1; -+ unsigned int prp_if_en:1; -+ unsigned int ccir_mode:1; -+ unsigned int cof_int_en:1; -+ unsigned int sf_or_inten:1; -+ unsigned int rf_or_inten:1; -+ unsigned int sff_dma_done_inten:1; -+ unsigned int statff_inten:1; -+ unsigned int fb2_dma_done_inten:1; -+ unsigned int fb1_dma_done_inten:1; -+ unsigned int rxff_inten:1; -+ unsigned int sof_pol:1; -+ unsigned int sof_inten:1; -+ unsigned int mclkdiv:4; -+ unsigned int hsync_pol:1; -+ unsigned int ccir_en:1; -+ unsigned int mclken:1; -+ unsigned int fcc:1; -+ unsigned int pack_dir:1; -+ unsigned int gclk_mode:1; -+ unsigned int inv_data:1; -+ unsigned int inv_pclk:1; -+ unsigned int redge:1; -+ unsigned int pixel_bit:1; -+ -+ /* control reg 3 */ -+ unsigned int frmcnt:16; -+ unsigned int frame_reset:1; -+ unsigned int dma_reflash_rff:1; -+ unsigned int dma_reflash_sff:1; -+ unsigned int dma_req_en_rff:1; -+ unsigned int dma_req_en_sff:1; -+ unsigned int statff_level:3; -+ unsigned int hresp_err_en:1; -+ unsigned int rxff_level:3; -+ unsigned int two_8bit_sensor:1; -+ unsigned int zero_pack_en:1; -+ unsigned int ecc_int_en:1; -+ unsigned int ecc_auto_en:1; -+ /* fifo counter */ -+ unsigned int rxcnt; -+}; -+ -+typedef void (*csi_irq_callback_t) (void *data, unsigned long status); -+ -+void csi_init_interface(void); -+void csi_init_format(int fmt); -+void csi_set_16bit_imagpara(int width, int height); -+void csi_set_12bit_imagpara(int width, int height); -+int csi_read_mclk_flag(void); -+void csi_start_callback(void *data); -+void csi_stop_callback(void *data); -+void csi_enable_int(int arg); -+void csi_disable_int(void); -+void csi_mclk_enable(void); -+void csi_mclk_disable(void); -+void csi_dmareq_rff_enable(void); -+void csi_dmareq_rff_disable(void); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 2014-10-22 14:55:52.614220001 -0500 -@@ -0,0 +1,546 @@ -+ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_bg_overlay_sdc_bg.c -+ * -+ * @brief IPU Use case for PRP-VF back-ground -+ * -+ * @ingroup IPU -+ */ -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+static int csi_buffer_num; -+static u32 bpp, csi_mem_bufsize = 3; -+static u32 out_format; -+static struct ipu_soc *disp_ipu; -+static u32 offset; -+ -+static void csi_buf_work_func(struct work_struct *work) -+{ -+ int err = 0; -+ cam_data *cam = -+ container_of(work, struct _cam_data, csi_work_struct); -+ -+ struct ipu_task task; -+ memset(&task, 0, sizeof(task)); -+ -+ if (csi_buffer_num) -+ task.input.paddr = cam->vf_bufs[0]; -+ else -+ task.input.paddr = cam->vf_bufs[1]; -+ task.input.width = cam->crop_current.width; -+ task.input.height = cam->crop_current.height; -+ task.input.format = IPU_PIX_FMT_UYVY; -+ -+ task.output.paddr = offset; -+ task.output.width = cam->overlay_fb->var.xres; -+ task.output.height = cam->overlay_fb->var.yres; -+ task.output.format = out_format; -+ task.output.rotate = cam->rotation; -+ task.output.crop.pos.x = cam->win.w.left; -+ task.output.crop.pos.y = cam->win.w.top; -+ if (cam->win.w.width > 1024 || cam->win.w.height > 1024) { -+ task.output.crop.w = cam->overlay_fb->var.xres; -+ task.output.crop.h = cam->overlay_fb->var.yres; -+ } else { -+ task.output.crop.w = cam->win.w.width; -+ task.output.crop.h = cam->win.w.height; -+ } -+again: -+ err = ipu_check_task(&task); -+ if (err != IPU_CHECK_OK) { -+ if (err > IPU_CHECK_ERR_MIN) { -+ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) { -+ task.input.crop.w -= 8; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) { -+ task.input.crop.h -= 8; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { -+ task.output.width -= 8; -+ task.output.crop.w = task.output.width; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { -+ task.output.height -= 8; -+ task.output.crop.h = task.output.height; -+ goto again; -+ } -+ printk(KERN_ERR "check ipu taks fail\n"); -+ return; -+ } -+ printk(KERN_ERR "check ipu taks fail\n"); -+ return; -+ } -+ err = ipu_queue_task(&task); -+ if (err < 0) -+ printk(KERN_ERR "queue ipu task error\n"); -+} -+ -+static void get_disp_ipu(cam_data *cam) -+{ -+ if (cam->output > 2) -+ disp_ipu = ipu_get_soc(1); /* using DISP4 */ -+ else -+ disp_ipu = ipu_get_soc(0); -+} -+ -+ -+/*! -+ * csi ENC callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t csi_enc_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = (cam_data *) dev_id; -+ -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num); -+ schedule_work(&cam->csi_work_struct); -+ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0; -+ return IRQ_HANDLED; -+} -+ -+static int csi_enc_setup(cam_data *cam) -+{ -+ ipu_channel_params_t params; -+ u32 pixel_fmt; -+ int err = 0, sensor_protocol = 0; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (!cam) { -+ printk(KERN_ERR "cam private is NULL\n"); -+ return -ENXIO; -+ } -+ -+ memset(¶ms, 0, sizeof(ipu_channel_params_t)); -+ params.csi_mem.csi = cam->csi; -+ -+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); -+ switch (sensor_protocol) { -+ case IPU_CSI_CLK_MODE_GATED_CLK: -+ case IPU_CSI_CLK_MODE_NONGATED_CLK: -+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: -+ params.csi_mem.interlaced = false; -+ break; -+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: -+ params.csi_mem.interlaced = true; -+ break; -+ default: -+ printk(KERN_ERR "sensor protocol unsupported\n"); -+ return -EINVAL; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ params.csi_mem.mipi_en = true; -+ params.csi_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ params.csi_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ } -+ csi_mem_bufsize = -+ cam->crop_current.width * cam->crop_current.height * 2; -+ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize); -+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[0], -+ (dma_addr_t *) & -+ cam->vf_bufs[0], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[0] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_2; -+ } -+ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize); -+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[1], -+ (dma_addr_t *) & -+ cam->vf_bufs[1], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[1] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_1; -+ } -+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); -+ -+ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); -+ if (err != 0) { -+ printk(KERN_ERR "ipu_init_channel %d\n", err); -+ goto out_1; -+ } -+ -+ pixel_fmt = IPU_PIX_FMT_UYVY; -+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ pixel_fmt, cam->crop_current.width, -+ cam->crop_current.height, -+ cam->crop_current.width, IPU_ROTATE_NONE, -+ cam->vf_bufs[0], cam->vf_bufs[1], 0, -+ cam->offset.u_offset, cam->offset.u_offset); -+ if (err != 0) { -+ printk(KERN_ERR "CSI_MEM output buffer\n"); -+ goto out_1; -+ } -+ err = ipu_enable_channel(cam->ipu, CSI_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); -+ goto out_1; -+ } -+ -+ csi_buffer_num = 0; -+ -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1); -+ return err; -+out_1: -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+out_2: -+ return err; -+} -+ -+/*! -+ * Enable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_enabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, -+ csi_enc_callback, 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n"); -+ return err; -+ } -+ -+ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func); -+ -+ err = csi_enc_setup(cam); -+ if (err != 0) { -+ printk(KERN_ERR "csi_enc_setup %d\n", err); -+ goto out1; -+ } -+ -+ return err; -+out1: -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+ return err; -+} -+ -+/*! -+ * bg_overlay_start - start the overlay task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int bg_overlay_start(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ if (!cam) { -+ printk(KERN_ERR "private is NULL\n"); -+ return -EIO; -+ } -+ -+ if (cam->overlay_active == true) { -+ pr_debug("already start.\n"); -+ return 0; -+ } -+ -+ get_disp_ipu(cam); -+ -+ out_format = cam->v4l2_fb.fmt.pixelformat; -+ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) { -+ bpp = 3, csi_mem_bufsize = 3; -+ pr_info("BGR24\n"); -+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) { -+ bpp = 2, csi_mem_bufsize = 2; -+ pr_info("RGB565\n"); -+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) { -+ bpp = 4, csi_mem_bufsize = 4; -+ pr_info("BGR32\n"); -+ } else { -+ printk(KERN_ERR -+ "unsupported fix format from the framebuffer.\n"); -+ return -EINVAL; -+ } -+ -+ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top + -+ csi_mem_bufsize * cam->win.w.left; -+ -+ if (cam->v4l2_fb.base == 0) -+ printk(KERN_ERR "invalid frame buffer address.\n"); -+ else -+ offset += (u32) cam->v4l2_fb.base; -+ -+ csi_mem_bufsize = cam->win.w.width * cam->win.w.height -+ * csi_mem_bufsize; -+ -+ err = csi_enc_enabling_tasks(cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error csi enc enable fail\n"); -+ return err; -+ } -+ -+ cam->overlay_active = true; -+ return err; -+} -+ -+/*! -+ * bg_overlay_stop - stop the overlay task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int bg_overlay_stop(void *private) -+{ -+ int err = 0; -+ cam_data *cam = (cam_data *) private; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (cam->overlay_active == false) -+ return 0; -+ -+ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); -+ -+ ipu_uninit_channel(cam->ipu, CSI_MEM); -+ -+ csi_buffer_num = 0; -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ flush_work(&cam->csi_work_struct); -+ cancel_work_sync(&cam->csi_work_struct); -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[0], -+ cam->rot_vf_bufs_vaddr[0], -+ cam->rot_vf_bufs[0]); -+ cam->rot_vf_bufs_vaddr[0] = NULL; -+ cam->rot_vf_bufs[0] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[1], -+ cam->rot_vf_bufs_vaddr[1], -+ cam->rot_vf_bufs[1]); -+ cam->rot_vf_bufs_vaddr[1] = NULL; -+ cam->rot_vf_bufs[1] = 0; -+ } -+ -+ cam->overlay_active = false; -+ return err; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int bg_overlay_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int bg_overlay_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select bg as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int bg_overlay_sdc_select(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ if (cam) { -+ cam->vf_start_sdc = bg_overlay_start; -+ cam->vf_stop_sdc = bg_overlay_stop; -+ cam->vf_enable_csi = bg_overlay_enable_csi; -+ cam->vf_disable_csi = bg_overlay_disable_csi; -+ cam->overlay_active = false; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(bg_overlay_sdc_select); -+ -+/*! -+ * function to de-select bg as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int bg_overlay_sdc_deselect(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ if (cam) { -+ cam->vf_start_sdc = NULL; -+ cam->vf_stop_sdc = NULL; -+ cam->vf_enable_csi = NULL; -+ cam->vf_disable_csi = NULL; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(bg_overlay_sdc_deselect); -+ -+/*! -+ * Init background overlay task. -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int bg_overlay_sdc_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit background overlay task. -+ * -+ * @return Error code indicating success or failure -+ */ -+void __exit bg_overlay_sdc_exit(void) -+{ -+} -+ -+module_init(bg_overlay_sdc_init); -+module_exit(bg_overlay_sdc_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_csi_enc.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_csi_enc.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_csi_enc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_csi_enc.c 2014-10-22 14:55:52.614220001 -0500 -@@ -0,0 +1,418 @@ -+/* -+ * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_csi_enc.c -+ * -+ * @brief CSI Use case for video capture -+ * -+ * @ingroup IPU -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+#ifdef CAMERA_DBG -+ #define CAMERA_TRACE(x) (printk)x -+#else -+ #define CAMERA_TRACE(x) -+#endif -+ -+/* -+ * Function definitions -+ */ -+ -+/*! -+ * csi ENC callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t csi_enc_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = (cam_data *) dev_id; -+ -+ if (cam->enc_callback == NULL) -+ return IRQ_HANDLED; -+ -+ cam->enc_callback(irq, dev_id); -+ return IRQ_HANDLED; -+} -+ -+/*! -+ * CSI ENC enable channel setup function -+ * -+ * @param cam struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_setup(cam_data *cam) -+{ -+ ipu_channel_params_t params; -+ u32 pixel_fmt; -+ int err = 0, sensor_protocol = 0; -+ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ CAMERA_TRACE("In csi_enc_setup\n"); -+ if (!cam) { -+ printk(KERN_ERR "cam private is NULL\n"); -+ return -ENXIO; -+ } -+ -+ memset(¶ms, 0, sizeof(ipu_channel_params_t)); -+ params.csi_mem.csi = cam->csi; -+ -+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); -+ switch (sensor_protocol) { -+ case IPU_CSI_CLK_MODE_GATED_CLK: -+ case IPU_CSI_CLK_MODE_NONGATED_CLK: -+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: -+ params.csi_mem.interlaced = false; -+ break; -+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: -+ params.csi_mem.interlaced = true; -+ break; -+ default: -+ printk(KERN_ERR "sensor protocol unsupported\n"); -+ return -EINVAL; -+ } -+ -+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) -+ pixel_fmt = IPU_PIX_FMT_YUV420P; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) -+ pixel_fmt = IPU_PIX_FMT_YVU420P; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) -+ pixel_fmt = IPU_PIX_FMT_YUV422P; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) -+ pixel_fmt = IPU_PIX_FMT_UYVY; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) -+ pixel_fmt = IPU_PIX_FMT_YUYV; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) -+ pixel_fmt = IPU_PIX_FMT_NV12; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) -+ pixel_fmt = IPU_PIX_FMT_BGR24; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) -+ pixel_fmt = IPU_PIX_FMT_RGB24; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) -+ pixel_fmt = IPU_PIX_FMT_RGB565; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) -+ pixel_fmt = IPU_PIX_FMT_BGR32; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) -+ pixel_fmt = IPU_PIX_FMT_RGB32; -+ else { -+ printk(KERN_ERR "format not supported\n"); -+ return -EINVAL; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ params.csi_mem.mipi_en = true; -+ params.csi_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ params.csi_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); -+ if (err != 0) { -+ printk(KERN_ERR "ipu_init_channel %d\n", err); -+ return err; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ pixel_fmt, cam->v2f.fmt.pix.width, -+ cam->v2f.fmt.pix.height, -+ cam->v2f.fmt.pix.bytesperline, -+ IPU_ROTATE_NONE, -+ dummy, dummy, 0, -+ cam->offset.u_offset, -+ cam->offset.v_offset); -+ if (err != 0) { -+ printk(KERN_ERR "CSI_MEM output buffer\n"); -+ return err; -+ } -+ err = ipu_enable_channel(cam->ipu, CSI_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); -+ return err; -+ } -+ -+ return err; -+} -+ -+/*! -+ * function to update physical buffer address for encorder IDMA channel -+ * -+ * @param eba physical buffer address for encorder IDMA channel -+ * @param buffer_num int buffer 0 or buffer 1 -+ * -+ * @return status -+ */ -+static int csi_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba, -+ int *buffer_num) -+{ -+ int err = 0; -+ -+ pr_debug("eba %x\n", eba); -+ err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ *buffer_num, eba); -+ if (err != 0) { -+ ipu_clear_buffer_ready(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ *buffer_num); -+ -+ err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ *buffer_num, eba); -+ if (err != 0) { -+ pr_err("ERROR: v4l2 capture: fail to update " -+ "buf%d\n", *buffer_num); -+ return err; -+ } -+ } -+ -+ ipu_select_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num); -+ -+ *buffer_num = (*buffer_num == 0) ? 1 : 0; -+ -+ return 0; -+} -+ -+/*! -+ * Enable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_enabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n"); -+ -+ cam->dummy_frame.vaddress = dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->dummy_frame.paddress, -+ GFP_DMA | GFP_KERNEL); -+ if (cam->dummy_frame.vaddress == 0) { -+ pr_err("ERROR: v4l2 capture: Allocate dummy frame " -+ "failed.\n"); -+ return -ENOBUFS; -+ } -+ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; -+ cam->dummy_frame.buffer.length = -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); -+ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, -+ csi_enc_callback, 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering rot irq\n"); -+ return err; -+ } -+ -+ err = csi_enc_setup(cam); -+ if (err != 0) { -+ printk(KERN_ERR "csi_enc_setup %d\n", err); -+ return err; -+ } -+ -+ return err; -+} -+ -+/*! -+ * Disable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+static int csi_enc_disabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); -+ -+ ipu_uninit_channel(cam->ipu, CSI_MEM); -+ -+ if (cam->dummy_frame.vaddress != 0) { -+ dma_free_coherent(0, cam->dummy_frame.buffer.length, -+ cam->dummy_frame.vaddress, -+ cam->dummy_frame.paddress); -+ cam->dummy_frame.vaddress = 0; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ return err; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select CSI ENC as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+int csi_enc_select(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ if (cam) { -+ cam->enc_update_eba = csi_enc_eba_update; -+ cam->enc_enable = csi_enc_enabling_tasks; -+ cam->enc_disable = csi_enc_disabling_tasks; -+ cam->enc_enable_csi = csi_enc_enable_csi; -+ cam->enc_disable_csi = csi_enc_disable_csi; -+ } else { -+ err = -EIO; -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(csi_enc_select); -+ -+/*! -+ * function to de-select CSI ENC as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+int csi_enc_deselect(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ if (cam) { -+ cam->enc_update_eba = NULL; -+ cam->enc_enable = NULL; -+ cam->enc_disable = NULL; -+ cam->enc_enable_csi = NULL; -+ cam->enc_disable_csi = NULL; -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(csi_enc_deselect); -+ -+/*! -+ * Init the Encorder channels -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int csi_enc_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit the Encorder channels -+ * -+ */ -+void __exit csi_enc_exit(void) -+{ -+} -+ -+module_init(csi_enc_init); -+module_exit(csi_enc_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("CSI ENC Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,634 @@ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+/* * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_foreground_sdc.c -+ * -+ * @brief IPU Use case for PRP-VF -+ * -+ * @ingroup IPU -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+#ifdef CAMERA_DBG -+ #define CAMERA_TRACE(x) (printk)x -+#else -+ #define CAMERA_TRACE(x) -+#endif -+ -+static int csi_buffer_num, buffer_num; -+static u32 csi_mem_bufsize; -+static struct ipu_soc *disp_ipu; -+static struct fb_info *fbi; -+static struct fb_var_screeninfo fbvar; -+static u32 vf_out_format; -+static void csi_buf_work_func(struct work_struct *work) -+{ -+ int err = 0; -+ cam_data *cam = -+ container_of(work, struct _cam_data, csi_work_struct); -+ -+ struct ipu_task task; -+ memset(&task, 0, sizeof(task)); -+ -+ if (csi_buffer_num) -+ task.input.paddr = cam->vf_bufs[0]; -+ else -+ task.input.paddr = cam->vf_bufs[1]; -+ task.input.width = cam->crop_current.width; -+ task.input.height = cam->crop_current.height; -+ task.input.format = IPU_PIX_FMT_NV12; -+ -+ if (buffer_num == 0) -+ task.output.paddr = fbi->fix.smem_start + -+ (fbi->fix.line_length * fbvar.yres); -+ else -+ task.output.paddr = fbi->fix.smem_start; -+ task.output.width = cam->win.w.width; -+ task.output.height = cam->win.w.height; -+ task.output.format = vf_out_format; -+ task.output.rotate = cam->rotation; -+again: -+ err = ipu_check_task(&task); -+ if (err != IPU_CHECK_OK) { -+ if (err > IPU_CHECK_ERR_MIN) { -+ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) { -+ task.input.crop.w -= 8; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) { -+ task.input.crop.h -= 8; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { -+ task.output.width -= 8; -+ task.output.crop.w = task.output.width; -+ goto again; -+ } -+ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { -+ task.output.height -= 8; -+ task.output.crop.h = task.output.height; -+ goto again; -+ } -+ printk(KERN_ERR "check ipu taks fail\n"); -+ return; -+ } -+ printk(KERN_ERR "check ipu taks fail\n"); -+ return; -+ } -+ err = ipu_queue_task(&task); -+ if (err < 0) -+ printk(KERN_ERR "queue ipu task error\n"); -+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num); -+ buffer_num = (buffer_num == 0) ? 1 : 0; -+} -+ -+static void get_disp_ipu(cam_data *cam) -+{ -+ if (cam->output > 2) -+ disp_ipu = ipu_get_soc(1); /* using DISP4 */ -+ else -+ disp_ipu = ipu_get_soc(0); -+} -+ -+/*! -+ * csi ENC callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t csi_enc_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = (cam_data *) dev_id; -+ -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num); -+ if ((cam->crop_current.width != cam->win.w.width) || -+ (cam->crop_current.height != cam->win.w.height) || -+ (vf_out_format != IPU_PIX_FMT_NV12) || -+ (cam->rotation >= IPU_ROTATE_VERT_FLIP)) -+ schedule_work(&cam->csi_work_struct); -+ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0; -+ return IRQ_HANDLED; -+} -+ -+static int csi_enc_setup(cam_data *cam) -+{ -+ ipu_channel_params_t params; -+ int err = 0, sensor_protocol = 0; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ CAMERA_TRACE("In csi_enc_setup\n"); -+ if (!cam) { -+ printk(KERN_ERR "cam private is NULL\n"); -+ return -ENXIO; -+ } -+ -+ memset(¶ms, 0, sizeof(ipu_channel_params_t)); -+ params.csi_mem.csi = cam->csi; -+ -+ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); -+ switch (sensor_protocol) { -+ case IPU_CSI_CLK_MODE_GATED_CLK: -+ case IPU_CSI_CLK_MODE_NONGATED_CLK: -+ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: -+ params.csi_mem.interlaced = false; -+ break; -+ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: -+ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: -+ params.csi_mem.interlaced = true; -+ break; -+ default: -+ printk(KERN_ERR "sensor protocol unsupported\n"); -+ return -EINVAL; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ params.csi_mem.mipi_en = true; -+ params.csi_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ params.csi_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } else { -+ params.csi_mem.mipi_en = false; -+ params.csi_mem.mipi_vc = 0; -+ params.csi_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ } -+ csi_mem_bufsize = cam->crop_current.width * -+ cam->crop_current.height * 3/2; -+ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize); -+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[0], -+ (dma_addr_t *) & -+ cam->vf_bufs[0], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[0] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_2; -+ } -+ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize); -+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[1], -+ (dma_addr_t *) & -+ cam->vf_bufs[1], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[1] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_1; -+ } -+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); -+ -+ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); -+ if (err != 0) { -+ printk(KERN_ERR "ipu_init_channel %d\n", err); -+ goto out_1; -+ } -+ -+ if ((cam->crop_current.width == cam->win.w.width) && -+ (cam->crop_current.height == cam->win.w.height) && -+ (vf_out_format == IPU_PIX_FMT_NV12) && -+ (cam->rotation < IPU_ROTATE_VERT_FLIP)) { -+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, -+ IPU_OUTPUT_BUFFER, -+ IPU_PIX_FMT_NV12, -+ cam->crop_current.width, -+ cam->crop_current.height, -+ cam->crop_current.width, IPU_ROTATE_NONE, -+ fbi->fix.smem_start + -+ (fbi->fix.line_length * fbvar.yres), -+ fbi->fix.smem_start, 0, -+ cam->offset.u_offset, cam->offset.u_offset); -+ } else { -+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, -+ IPU_OUTPUT_BUFFER, -+ IPU_PIX_FMT_NV12, -+ cam->crop_current.width, -+ cam->crop_current.height, -+ cam->crop_current.width, IPU_ROTATE_NONE, -+ cam->vf_bufs[0], cam->vf_bufs[1], 0, -+ cam->offset.u_offset, cam->offset.u_offset); -+ } -+ if (err != 0) { -+ printk(KERN_ERR "CSI_MEM output buffer\n"); -+ goto out_1; -+ } -+ err = ipu_enable_channel(cam->ipu, CSI_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); -+ goto out_1; -+ } -+ -+ csi_buffer_num = 0; -+ -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1); -+ return err; -+out_1: -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+out_2: -+ return err; -+} -+ -+/*! -+ * Enable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int csi_enc_enabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n"); -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, -+ csi_enc_callback, 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n"); -+ return err; -+ } -+ -+ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func); -+ -+ err = csi_enc_setup(cam); -+ if (err != 0) { -+ printk(KERN_ERR "csi_enc_setup %d\n", err); -+ goto out1; -+ } -+ -+ return err; -+out1: -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+ return err; -+} -+ -+/* -+ * Function definitions -+ */ -+ -+/*! -+ * foreground_start - start the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int foreground_start(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0, i = 0, screen_size; -+ char *base; -+ -+ if (!cam) { -+ printk(KERN_ERR "private is NULL\n"); -+ return -EIO; -+ } -+ -+ if (cam->overlay_active == true) { -+ pr_debug("already started.\n"); -+ return 0; -+ } -+ -+ get_disp_ipu(cam); -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ char *idstr = registered_fb[i]->fix.id; -+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || -+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { -+ fbi = registered_fb[i]; -+ break; -+ } -+ } -+ -+ if (fbi == NULL) { -+ printk(KERN_ERR "DISP FG fb not found\n"); -+ return -EPERM; -+ } -+ -+ fbvar = fbi->var; -+ -+ /* Store the overlay frame buffer's original std */ -+ cam->fb_origin_std = fbvar.nonstd; -+ -+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { -+ /* Use DP to do CSC so that we can get better performance */ -+ vf_out_format = IPU_PIX_FMT_NV12; -+ fbvar.nonstd = vf_out_format; -+ } else { -+ vf_out_format = IPU_PIX_FMT_RGB565; -+ fbvar.nonstd = 0; -+ } -+ -+ fbvar.bits_per_pixel = 16; -+ fbvar.xres = fbvar.xres_virtual = cam->win.w.width; -+ fbvar.yres = cam->win.w.height; -+ fbvar.yres_virtual = cam->win.w.height * 2; -+ fbvar.yoffset = 0; -+ fbvar.vmode &= ~FB_VMODE_YWRAP; -+ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG; -+ fbvar.activate |= FB_ACTIVATE_FORCE; -+ fb_set_var(fbi, &fbvar); -+ -+ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left, -+ cam->win.w.top); -+ -+ /* Fill black color for framebuffer */ -+ base = (char *) fbi->screen_base; -+ screen_size = fbi->var.xres * fbi->var.yres; -+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { -+ memset(base, 0, screen_size); -+ base += screen_size; -+ for (i = 0; i < screen_size / 2; i++, base++) -+ *base = 0x80; -+ } else { -+ for (i = 0; i < screen_size * 2; i++, base++) -+ *base = 0x00; -+ } -+ -+ console_lock(); -+ fb_blank(fbi, FB_BLANK_UNBLANK); -+ console_unlock(); -+ -+ /* correct display ch buffer address */ -+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, -+ 0, fbi->fix.smem_start + -+ (fbi->fix.line_length * fbvar.yres)); -+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, -+ 1, fbi->fix.smem_start); -+ -+ err = csi_enc_enabling_tasks(cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error csi enc enable fail\n"); -+ return err; -+ } -+ -+ cam->overlay_active = true; -+ return err; -+ -+} -+ -+/*! -+ * foreground_stop - stop the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int foreground_stop(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0, i = 0; -+ struct fb_info *fbi = NULL; -+ struct fb_var_screeninfo fbvar; -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (cam->overlay_active == false) -+ return 0; -+ -+ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); -+ -+ ipu_uninit_channel(cam->ipu, CSI_MEM); -+ -+ csi_buffer_num = 0; -+ buffer_num = 0; -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ char *idstr = registered_fb[i]->fix.id; -+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || -+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { -+ fbi = registered_fb[i]; -+ break; -+ } -+ } -+ -+ if (fbi == NULL) { -+ printk(KERN_ERR "DISP FG fb not found\n"); -+ return -EPERM; -+ } -+ -+ console_lock(); -+ fb_blank(fbi, FB_BLANK_POWERDOWN); -+ console_unlock(); -+ -+ /* Set the overlay frame buffer std to what it is used to be */ -+ fbvar = fbi->var; -+ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG; -+ fbvar.nonstd = cam->fb_origin_std; -+ fbvar.activate |= FB_ACTIVATE_FORCE; -+ fb_set_var(fbi, &fbvar); -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ flush_work(&cam->csi_work_struct); -+ cancel_work_sync(&cam->csi_work_struct); -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+ -+ cam->overlay_active = false; -+ return err; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int foreground_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int foreground_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select foreground as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int foreground_sdc_select(void *private) -+{ -+ cam_data *cam; -+ int err = 0; -+ if (private) { -+ cam = (cam_data *) private; -+ cam->vf_start_sdc = foreground_start; -+ cam->vf_stop_sdc = foreground_stop; -+ cam->vf_enable_csi = foreground_enable_csi; -+ cam->vf_disable_csi = foreground_disable_csi; -+ cam->overlay_active = false; -+ } else -+ err = -EIO; -+ -+ return err; -+} -+EXPORT_SYMBOL(foreground_sdc_select); -+ -+/*! -+ * function to de-select foreground as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return int -+ */ -+int foreground_sdc_deselect(void *private) -+{ -+ cam_data *cam; -+ -+ if (private) { -+ cam = (cam_data *) private; -+ cam->vf_start_sdc = NULL; -+ cam->vf_stop_sdc = NULL; -+ cam->vf_enable_csi = NULL; -+ cam->vf_disable_csi = NULL; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(foreground_sdc_deselect); -+ -+/*! -+ * Init viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int foreground_sdc_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+void __exit foreground_sdc_exit(void) -+{ -+} -+ -+module_init(foreground_sdc_init); -+module_exit(foreground_sdc_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP VF SDC Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_enc.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_enc.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_enc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_enc.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,595 @@ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_prp_enc.c -+ * -+ * @brief IPU Use case for PRP-ENC -+ * -+ * @ingroup IPU -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+#ifdef CAMERA_DBG -+ #define CAMERA_TRACE(x) (printk)x -+#else -+ #define CAMERA_TRACE(x) -+#endif -+ -+static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE; -+ -+/* -+ * Function definitions -+ */ -+ -+/*! -+ * IPU ENC callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t prp_enc_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = (cam_data *) dev_id; -+ -+ if (cam->enc_callback == NULL) -+ return IRQ_HANDLED; -+ -+ cam->enc_callback(irq, dev_id); -+ -+ return IRQ_HANDLED; -+} -+ -+/*! -+ * PrpENC enable channel setup function -+ * -+ * @param cam struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_enc_setup(cam_data *cam) -+{ -+ ipu_channel_params_t enc; -+ int err = 0; -+ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ CAMERA_TRACE("In prp_enc_setup\n"); -+ if (!cam) { -+ printk(KERN_ERR "cam private is NULL\n"); -+ return -ENXIO; -+ } -+ memset(&enc, 0, sizeof(ipu_channel_params_t)); -+ -+ ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width, -+ &enc.csi_prp_enc_mem.in_height, cam->csi); -+ -+ enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; -+ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width; -+ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height; -+ enc.csi_prp_enc_mem.csi = cam->csi; -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height; -+ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width; -+ } -+ -+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P; -+ pr_info("YUV420\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P; -+ pr_info("YVU420\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P; -+ pr_info("YUV422P\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV; -+ pr_info("YUYV\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY; -+ pr_info("UYVY\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12; -+ pr_info("NV12\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24; -+ pr_info("BGR24\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24; -+ pr_info("RGB24\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565; -+ pr_info("RGB565\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32; -+ pr_info("BGR32\n"); -+ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) { -+ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32; -+ pr_info("RGB32\n"); -+ } else { -+ printk(KERN_ERR "format not supported\n"); -+ return -EINVAL; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ enc.csi_prp_enc_mem.mipi_en = true; -+ enc.csi_prp_enc_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ enc.csi_prp_enc_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ enc.csi_prp_enc_mem.mipi_en = false; -+ enc.csi_prp_enc_mem.mipi_vc = 0; -+ enc.csi_prp_enc_mem.mipi_id = 0; -+ } -+ } else { -+ enc.csi_prp_enc_mem.mipi_en = false; -+ enc.csi_prp_enc_mem.mipi_vc = 0; -+ enc.csi_prp_enc_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc); -+ if (err != 0) { -+ printk(KERN_ERR "ipu_init_channel %d\n", err); -+ return err; -+ } -+ -+ grotation = cam->rotation; -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ if (cam->rot_enc_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->rot_enc_buf_size[0], -+ cam->rot_enc_bufs_vaddr[0], -+ cam->rot_enc_bufs[0]); -+ } -+ if (cam->rot_enc_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_enc_buf_size[1], -+ cam->rot_enc_bufs_vaddr[1], -+ cam->rot_enc_bufs[1]); -+ } -+ cam->rot_enc_buf_size[0] = -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); -+ cam->rot_enc_bufs_vaddr[0] = -+ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0], -+ &cam->rot_enc_bufs[0], -+ GFP_DMA | GFP_KERNEL); -+ if (!cam->rot_enc_bufs_vaddr[0]) { -+ printk(KERN_ERR "alloc enc_bufs0\n"); -+ return -ENOMEM; -+ } -+ cam->rot_enc_buf_size[1] = -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); -+ cam->rot_enc_bufs_vaddr[1] = -+ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1], -+ &cam->rot_enc_bufs[1], -+ GFP_DMA | GFP_KERNEL); -+ if (!cam->rot_enc_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_enc_buf_size[0], -+ cam->rot_enc_bufs_vaddr[0], -+ cam->rot_enc_bufs[0]); -+ cam->rot_enc_bufs_vaddr[0] = NULL; -+ cam->rot_enc_bufs[0] = 0; -+ printk(KERN_ERR "alloc enc_bufs1\n"); -+ return -ENOMEM; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ enc.csi_prp_enc_mem.out_pixel_fmt, -+ enc.csi_prp_enc_mem.out_width, -+ enc.csi_prp_enc_mem.out_height, -+ enc.csi_prp_enc_mem.out_width, -+ IPU_ROTATE_NONE, -+ cam->rot_enc_bufs[0], -+ cam->rot_enc_bufs[1], 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "CSI_PRP_ENC_MEM err\n"); -+ return err; -+ } -+ -+ err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL); -+ if (err != 0) { -+ printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n"); -+ return err; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, -+ IPU_INPUT_BUFFER, -+ enc.csi_prp_enc_mem.out_pixel_fmt, -+ enc.csi_prp_enc_mem.out_width, -+ enc.csi_prp_enc_mem.out_height, -+ enc.csi_prp_enc_mem.out_width, -+ cam->rotation, -+ cam->rot_enc_bufs[0], -+ cam->rot_enc_bufs[1], 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n"); -+ return err; -+ } -+ -+ err = -+ ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ enc.csi_prp_enc_mem.out_pixel_fmt, -+ enc.csi_prp_enc_mem.out_height, -+ enc.csi_prp_enc_mem.out_width, -+ cam->v2f.fmt.pix.bytesperline / -+ bytes_per_pixel(enc.csi_prp_enc_mem. -+ out_pixel_fmt), -+ IPU_ROTATE_NONE, -+ dummy, dummy, 0, -+ cam->offset.u_offset, -+ cam->offset.v_offset); -+ if (err != 0) { -+ printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n"); -+ return err; -+ } -+ -+ err = ipu_link_channels(cam->ipu, -+ CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); -+ if (err < 0) { -+ printk(KERN_ERR -+ "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n"); -+ return err; -+ } -+ -+ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); -+ return err; -+ } -+ err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n"); -+ return err; -+ } -+ -+ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, 0); -+ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, 1); -+ } else { -+ err = -+ ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ enc.csi_prp_enc_mem.out_pixel_fmt, -+ enc.csi_prp_enc_mem.out_width, -+ enc.csi_prp_enc_mem.out_height, -+ cam->v2f.fmt.pix.bytesperline / -+ bytes_per_pixel(enc.csi_prp_enc_mem. -+ out_pixel_fmt), -+ cam->rotation, -+ dummy, dummy, 0, -+ cam->offset.u_offset, -+ cam->offset.v_offset); -+ if (err != 0) { -+ printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n"); -+ return err; -+ } -+ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); -+ if (err < 0) { -+ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); -+ return err; -+ } -+ } -+ -+ return err; -+} -+ -+/*! -+ * function to update physical buffer address for encorder IDMA channel -+ * -+ * @param eba physical buffer address for encorder IDMA channel -+ * @param buffer_num int buffer 0 or buffer 1 -+ * -+ * @return status -+ */ -+static int prp_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba, -+ int *buffer_num) -+{ -+ int err = 0; -+ -+ pr_debug("eba %x\n", eba); -+ if (grotation >= IPU_ROTATE_90_RIGHT) { -+ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM, -+ IPU_OUTPUT_BUFFER, *buffer_num, -+ eba); -+ } else { -+ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, *buffer_num, -+ eba); -+ } -+ if (err != 0) { -+ if (grotation >= IPU_ROTATE_90_RIGHT) { -+ ipu_clear_buffer_ready(ipu, MEM_ROT_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ *buffer_num); -+ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ *buffer_num, -+ eba); -+ } else { -+ ipu_clear_buffer_ready(ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ *buffer_num); -+ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM, -+ IPU_OUTPUT_BUFFER, -+ *buffer_num, -+ eba); -+ } -+ -+ if (err != 0) { -+ pr_err("ERROR: v4l2 capture: fail to update " -+ "buf%d\n", *buffer_num); -+ return err; -+ } -+ } -+ -+ if (grotation >= IPU_ROTATE_90_RIGHT) { -+ ipu_select_buffer(ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER, -+ *buffer_num); -+ } else { -+ ipu_select_buffer(ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, -+ *buffer_num); -+ } -+ -+ *buffer_num = (*buffer_num == 0) ? 1 : 0; -+ return 0; -+} -+ -+/*! -+ * Enable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_enc_enabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n"); -+ -+ cam->dummy_frame.vaddress = dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->dummy_frame.paddress, -+ GFP_DMA | GFP_KERNEL); -+ if (cam->dummy_frame.vaddress == 0) { -+ pr_err("ERROR: v4l2 capture: Allocate dummy frame " -+ "failed.\n"); -+ return -ENOBUFS; -+ } -+ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; -+ cam->dummy_frame.buffer.length = -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); -+ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; -+ -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, -+ prp_enc_callback, 0, "Mxc Camera", cam); -+ } else { -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, -+ prp_enc_callback, 0, "Mxc Camera", cam); -+ } -+ if (err != 0) { -+ printk(KERN_ERR "Error registering rot irq\n"); -+ return err; -+ } -+ -+ err = prp_enc_setup(cam); -+ if (err != 0) { -+ printk(KERN_ERR "prp_enc_setup %d\n", err); -+ return err; -+ } -+ -+ return err; -+} -+ -+/*! -+ * Disable encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+static int prp_enc_disabling_tasks(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam); -+ ipu_unlink_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); -+ } -+ -+ err = ipu_disable_channel(cam->ipu, CSI_PRP_ENC_MEM, true); -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) -+ err |= ipu_disable_channel(cam->ipu, MEM_ROT_ENC_MEM, true); -+ -+ ipu_uninit_channel(cam->ipu, CSI_PRP_ENC_MEM); -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) -+ ipu_uninit_channel(cam->ipu, MEM_ROT_ENC_MEM); -+ -+ if (cam->dummy_frame.vaddress != 0) { -+ dma_free_coherent(0, cam->dummy_frame.buffer.length, -+ cam->dummy_frame.vaddress, -+ cam->dummy_frame.paddress); -+ cam->dummy_frame.vaddress = 0; -+ } -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ return err; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_enc_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_enc_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ if (cam->rotation < IPU_ROTATE_90_RIGHT) -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select PRP-ENC as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+int prp_enc_select(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ if (cam) { -+ cam->enc_update_eba = prp_enc_eba_update; -+ cam->enc_enable = prp_enc_enabling_tasks; -+ cam->enc_disable = prp_enc_disabling_tasks; -+ cam->enc_enable_csi = prp_enc_enable_csi; -+ cam->enc_disable_csi = prp_enc_disable_csi; -+ } else { -+ err = -EIO; -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(prp_enc_select); -+ -+/*! -+ * function to de-select PRP-ENC as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return int -+ */ -+int prp_enc_deselect(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ if (cam) { -+ cam->enc_update_eba = NULL; -+ cam->enc_enable = NULL; -+ cam->enc_disable = NULL; -+ cam->enc_enable_csi = NULL; -+ cam->enc_disable_csi = NULL; -+ if (cam->rot_enc_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->rot_enc_buf_size[0], -+ cam->rot_enc_bufs_vaddr[0], -+ cam->rot_enc_bufs[0]); -+ cam->rot_enc_bufs_vaddr[0] = NULL; -+ cam->rot_enc_bufs[0] = 0; -+ } -+ if (cam->rot_enc_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_enc_buf_size[1], -+ cam->rot_enc_bufs_vaddr[1], -+ cam->rot_enc_bufs[1]); -+ cam->rot_enc_bufs_vaddr[1] = NULL; -+ cam->rot_enc_bufs[1] = 0; -+ } -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(prp_enc_deselect); -+ -+/*! -+ * Init the Encorder channels -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int prp_enc_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit the Encorder channels -+ * -+ */ -+void __exit prp_enc_exit(void) -+{ -+} -+ -+module_init(prp_enc_init); -+module_exit(prp_enc_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP ENC Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_sw.h linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_sw.h ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_sw.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_sw.h 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,43 @@ -+/* -+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_prp_sw.h -+ * -+ * @brief This file contains the IPU PRP use case driver header. -+ * -+ * @ingroup IPU -+ */ -+ -+#ifndef _INCLUDE_IPU__PRP_SW_H_ -+#define _INCLUDE_IPU__PRP_SW_H_ -+ -+int csi_enc_select(void *private); -+int csi_enc_deselect(void *private); -+int prp_enc_select(void *private); -+int prp_enc_deselect(void *private); -+#ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+int prp_vf_sdc_select(void *private); -+int prp_vf_sdc_deselect(void *private); -+int prp_vf_sdc_select_bg(void *private); -+int prp_vf_sdc_deselect_bg(void *private); -+#else -+int foreground_sdc_select(void *private); -+int foreground_sdc_deselect(void *private); -+int bg_overlay_sdc_select(void *private); -+int bg_overlay_sdc_deselect(void *private); -+#endif -+int prp_still_select(void *private); -+int prp_still_deselect(void *private); -+ -+#endif -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,521 @@ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_prp_vf_sdc_bg.c -+ * -+ * @brief IPU Use case for PRP-VF back-ground -+ * -+ * @ingroup IPU -+ */ -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+static int buffer_num; -+static int buffer_ready; -+static struct ipu_soc *disp_ipu; -+ -+static void get_disp_ipu(cam_data *cam) -+{ -+ if (cam->output > 2) -+ disp_ipu = ipu_get_soc(1); /* using DISP4 */ -+ else -+ disp_ipu = ipu_get_soc(0); -+} -+ -+/* -+ * Function definitions -+ */ -+ -+/*! -+ * SDC V-Sync callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = dev_id; -+ if (buffer_ready > 0) { -+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, 0); -+ buffer_ready--; -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/*! -+ * VF EOF callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = dev_id; -+ pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num); -+ -+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_INPUT_BUFFER, buffer_num); -+ buffer_num = (buffer_num == 0) ? 1 : 0; -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, buffer_num); -+ buffer_ready++; -+ return IRQ_HANDLED; -+} -+ -+/*! -+ * prpvf_start - start the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int prpvf_start(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ ipu_channel_params_t vf; -+ u32 format; -+ u32 offset; -+ u32 bpp, size = 3; -+ int err = 0; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (!cam) { -+ printk(KERN_ERR "private is NULL\n"); -+ return -EIO; -+ } -+ -+ if (cam->overlay_active == true) { -+ pr_debug("already start.\n"); -+ return 0; -+ } -+ -+ get_disp_ipu(cam); -+ -+ format = cam->v4l2_fb.fmt.pixelformat; -+ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) { -+ bpp = 3, size = 3; -+ pr_info("BGR24\n"); -+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) { -+ bpp = 2, size = 2; -+ pr_info("RGB565\n"); -+ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) { -+ bpp = 4, size = 4; -+ pr_info("BGR32\n"); -+ } else { -+ printk(KERN_ERR -+ "unsupported fix format from the framebuffer.\n"); -+ return -EINVAL; -+ } -+ -+ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top + -+ size * cam->win.w.left; -+ -+ if (cam->v4l2_fb.base == 0) -+ printk(KERN_ERR "invalid frame buffer address.\n"); -+ else -+ offset += (u32) cam->v4l2_fb.base; -+ -+ memset(&vf, 0, sizeof(ipu_channel_params_t)); -+ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width, -+ &vf.csi_prp_vf_mem.in_height, cam->csi); -+ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; -+ vf.csi_prp_vf_mem.out_width = cam->win.w.width; -+ vf.csi_prp_vf_mem.out_height = cam->win.w.height; -+ vf.csi_prp_vf_mem.csi = cam->csi; -+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { -+ vf.csi_prp_vf_mem.out_width = cam->win.w.height; -+ vf.csi_prp_vf_mem.out_height = cam->win.w.width; -+ } -+ vf.csi_prp_vf_mem.out_pixel_fmt = format; -+ size = cam->win.w.width * cam->win.w.height * size; -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ vf.csi_prp_vf_mem.mipi_en = true; -+ vf.csi_prp_vf_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ vf.csi_prp_vf_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ vf.csi_prp_vf_mem.mipi_en = false; -+ vf.csi_prp_vf_mem.mipi_vc = 0; -+ vf.csi_prp_vf_mem.mipi_id = 0; -+ } -+ } else { -+ vf.csi_prp_vf_mem.mipi_en = false; -+ vf.csi_prp_vf_mem.mipi_vc = 0; -+ vf.csi_prp_vf_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); -+ if (err != 0) -+ goto out_4; -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); -+ } -+ cam->vf_bufs_size[0] = PAGE_ALIGN(size); -+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[0], -+ &cam->vf_bufs[0], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[0] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_3; -+ } -+ cam->vf_bufs_size[1] = PAGE_ALIGN(size); -+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[1], -+ &cam->vf_bufs[1], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[1] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_3; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ format, vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ IPU_ROTATE_NONE, -+ cam->vf_bufs[0], -+ cam->vf_bufs[1], -+ 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n"); -+ goto out_3; -+ } -+ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL); -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n"); -+ goto out_3; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_INPUT_BUFFER, -+ format, vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ cam->vf_rotation, -+ cam->vf_bufs[0], -+ cam->vf_bufs[1], -+ 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n"); -+ goto out_2; -+ } -+ -+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ format, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ cam->overlay_fb->var.xres * bpp, -+ IPU_ROTATE_NONE, -+ offset, 0, 0, 0, 0); -+ -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); -+ goto out_2; -+ } -+ } else { -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ format, -+ vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ cam->overlay_fb->var.xres * bpp, -+ IPU_ROTATE_NONE, -+ offset, 0, 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); -+ goto out_2; -+ } -+ } -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, -+ prpvf_vf_eof_callback, -+ 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR -+ "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n"); -+ goto out_2; -+ } -+ -+ ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END); -+ err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END, -+ prpvf_sdc_vsync_callback, -+ 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n"); -+ goto out_1; -+ } -+ -+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); -+ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM); -+ -+ buffer_num = 0; -+ buffer_ready = 0; -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0); -+ -+ cam->overlay_active = true; -+ return err; -+ -+out_1: -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL); -+out_2: -+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); -+out_3: -+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); -+out_4: -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[0], -+ cam->rot_vf_bufs_vaddr[0], -+ cam->rot_vf_bufs[0]); -+ cam->rot_vf_bufs_vaddr[0] = NULL; -+ cam->rot_vf_bufs[0] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[1], -+ cam->rot_vf_bufs_vaddr[1], -+ cam->rot_vf_bufs[1]); -+ cam->rot_vf_bufs_vaddr[1] = NULL; -+ cam->rot_vf_bufs[1] = 0; -+ } -+ return err; -+} -+ -+/*! -+ * prpvf_stop - stop the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int prpvf_stop(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (cam->overlay_active == false) -+ return 0; -+ -+ ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam); -+ -+ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true); -+ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true); -+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); -+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[0], -+ cam->rot_vf_bufs_vaddr[0], -+ cam->rot_vf_bufs[0]); -+ cam->rot_vf_bufs_vaddr[0] = NULL; -+ cam->rot_vf_bufs[0] = 0; -+ } -+ if (cam->rot_vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->rot_vf_buf_size[1], -+ cam->rot_vf_bufs_vaddr[1], -+ cam->rot_vf_bufs[1]); -+ cam->rot_vf_bufs_vaddr[1] = NULL; -+ cam->rot_vf_bufs[1] = 0; -+ } -+ -+ buffer_num = 0; -+ buffer_ready = 0; -+ cam->overlay_active = false; -+ return 0; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_vf_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_vf_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select PRP-VF as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int prp_vf_sdc_select_bg(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ if (cam) { -+ cam->vf_start_sdc = prpvf_start; -+ cam->vf_stop_sdc = prpvf_stop; -+ cam->vf_enable_csi = prp_vf_enable_csi; -+ cam->vf_disable_csi = prp_vf_disable_csi; -+ cam->overlay_active = false; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(prp_vf_sdc_select_bg); -+ -+/*! -+ * function to de-select PRP-VF as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int prp_vf_sdc_deselect_bg(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ if (cam) { -+ cam->vf_start_sdc = NULL; -+ cam->vf_stop_sdc = NULL; -+ cam->vf_enable_csi = NULL; -+ cam->vf_disable_csi = NULL; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(prp_vf_sdc_deselect_bg); -+ -+/*! -+ * Init viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int prp_vf_sdc_init_bg(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+void __exit prp_vf_sdc_exit_bg(void) -+{ -+} -+ -+module_init(prp_vf_sdc_init_bg); -+module_exit(prp_vf_sdc_exit_bg); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,582 @@ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+/* * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_prp_vf_sdc.c -+ * -+ * @brief IPU Use case for PRP-VF -+ * -+ * @ingroup IPU -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+static int buffer_num; -+static struct ipu_soc *disp_ipu; -+ -+static void get_disp_ipu(cam_data *cam) -+{ -+ if (cam->output > 2) -+ disp_ipu = ipu_get_soc(1); /* using DISP4 */ -+ else -+ disp_ipu = ipu_get_soc(0); -+} -+ -+static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = dev_id; -+ pr_debug("buffer_num %d\n", buffer_num); -+ -+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { -+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, -+ IPU_INPUT_BUFFER, buffer_num); -+ buffer_num = (buffer_num == 0) ? 1 : 0; -+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, buffer_num); -+ } else { -+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, -+ IPU_INPUT_BUFFER, buffer_num); -+ buffer_num = (buffer_num == 0) ? 1 : 0; -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, buffer_num); -+ } -+ return IRQ_HANDLED; -+} -+/* -+ * Function definitions -+ */ -+ -+/*! -+ * prpvf_start - start the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int prpvf_start(void *private) -+{ -+ struct fb_var_screeninfo fbvar; -+ struct fb_info *fbi = NULL; -+ cam_data *cam = (cam_data *) private; -+ ipu_channel_params_t vf; -+ u32 vf_out_format = 0; -+ u32 size = 2, temp = 0; -+ int err = 0, i = 0; -+ short *tmp, color; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (!cam) { -+ printk(KERN_ERR "private is NULL\n"); -+ return -EIO; -+ } -+ -+ if (cam->overlay_active == true) { -+ pr_debug("already started.\n"); -+ return 0; -+ } -+ -+ get_disp_ipu(cam); -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ char *idstr = registered_fb[i]->fix.id; -+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || -+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { -+ fbi = registered_fb[i]; -+ break; -+ } -+ } -+ -+ if (fbi == NULL) { -+ printk(KERN_ERR "DISP FG fb not found\n"); -+ return -EPERM; -+ } -+ -+ fbvar = fbi->var; -+ -+ /* Store the overlay frame buffer's original std */ -+ cam->fb_origin_std = fbvar.nonstd; -+ -+ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { -+ /* Use DP to do CSC so that we can get better performance */ -+ vf_out_format = IPU_PIX_FMT_UYVY; -+ fbvar.nonstd = vf_out_format; -+ color = 0x80; -+ } else { -+ vf_out_format = IPU_PIX_FMT_RGB565; -+ fbvar.nonstd = 0; -+ color = 0x0; -+ } -+ -+ fbvar.bits_per_pixel = 16; -+ fbvar.xres = fbvar.xres_virtual = cam->win.w.width; -+ fbvar.yres = cam->win.w.height; -+ fbvar.yres_virtual = cam->win.w.height * 2; -+ fbvar.yoffset = 0; -+ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG; -+ fbvar.activate |= FB_ACTIVATE_FORCE; -+ fb_set_var(fbi, &fbvar); -+ -+ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left, -+ cam->win.w.top); -+ -+ /* Fill black color for framebuffer */ -+ tmp = (short *) fbi->screen_base; -+ for (i = 0; i < (fbi->fix.line_length * fbi->var.yres)/2; -+ i++, tmp++) -+ *tmp = color; -+ -+ console_lock(); -+ fb_blank(fbi, FB_BLANK_UNBLANK); -+ console_unlock(); -+ -+ /* correct display ch buffer address */ -+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, -+ 0, fbi->fix.smem_start + -+ (fbi->fix.line_length * fbvar.yres)); -+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, -+ 1, fbi->fix.smem_start); -+ -+ memset(&vf, 0, sizeof(ipu_channel_params_t)); -+ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width, -+ &vf.csi_prp_vf_mem.in_height, cam->csi); -+ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; -+ vf.csi_prp_vf_mem.out_width = cam->win.w.width; -+ vf.csi_prp_vf_mem.out_height = cam->win.w.height; -+ vf.csi_prp_vf_mem.csi = cam->csi; -+ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { -+ vf.csi_prp_vf_mem.out_width = cam->win.w.height; -+ vf.csi_prp_vf_mem.out_height = cam->win.w.width; -+ } -+ vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format; -+ size = cam->win.w.width * cam->win.w.height * size; -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) { -+ vf.csi_prp_vf_mem.mipi_en = true; -+ vf.csi_prp_vf_mem.mipi_vc = -+ mipi_csi2_get_virtual_channel(mipi_csi2_info); -+ vf.csi_prp_vf_mem.mipi_id = -+ mipi_csi2_get_datatype(mipi_csi2_info); -+ -+ mipi_csi2_pixelclk_enable(mipi_csi2_info); -+ } else { -+ vf.csi_prp_vf_mem.mipi_en = false; -+ vf.csi_prp_vf_mem.mipi_vc = 0; -+ vf.csi_prp_vf_mem.mipi_id = 0; -+ } -+ } else { -+ vf.csi_prp_vf_mem.mipi_en = false; -+ vf.csi_prp_vf_mem.mipi_vc = 0; -+ vf.csi_prp_vf_mem.mipi_id = 0; -+ } -+ } -+#endif -+ -+ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); -+ if (err != 0) -+ goto out_5; -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ } -+ cam->vf_bufs_size[0] = PAGE_ALIGN(size); -+ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[0], -+ (dma_addr_t *) & -+ cam->vf_bufs[0], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[0] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_4; -+ } -+ cam->vf_bufs_size[1] = PAGE_ALIGN(size); -+ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, -+ cam->vf_bufs_size[1], -+ (dma_addr_t *) & -+ cam->vf_bufs[1], -+ GFP_DMA | -+ GFP_KERNEL); -+ if (cam->vf_bufs_vaddr[1] == NULL) { -+ printk(KERN_ERR "Error to allocate vf buffer\n"); -+ err = -ENOMEM; -+ goto out_3; -+ } -+ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); -+ -+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { -+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ vf_out_format, -+ vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ IPU_ROTATE_NONE, -+ cam->vf_bufs[0], cam->vf_bufs[1], -+ 0, 0, 0); -+ if (err != 0) -+ goto out_3; -+ -+ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL); -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n"); -+ goto out_3; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_INPUT_BUFFER, -+ vf_out_format, -+ vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ cam->vf_rotation, -+ cam->vf_bufs[0], -+ cam->vf_bufs[1], -+ 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n"); -+ goto out_2; -+ } -+ -+ if (cam->vf_rotation < IPU_ROTATE_90_RIGHT) { -+ temp = vf.csi_prp_vf_mem.out_width; -+ vf.csi_prp_vf_mem.out_width = -+ vf.csi_prp_vf_mem.out_height; -+ vf.csi_prp_vf_mem.out_height = temp; -+ } -+ -+ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ vf_out_format, -+ vf.csi_prp_vf_mem.out_height, -+ vf.csi_prp_vf_mem.out_width, -+ vf.csi_prp_vf_mem.out_height, -+ IPU_ROTATE_NONE, -+ fbi->fix.smem_start + -+ (fbi->fix.line_length * -+ fbi->var.yres), -+ fbi->fix.smem_start, 0, 0, 0); -+ -+ if (err != 0) { -+ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); -+ goto out_2; -+ } -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, -+ prpvf_rot_eof_callback, -+ 0, "Mxc Camera", cam); -+ if (err < 0) { -+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n"); -+ goto out_2; -+ } -+ -+ err = ipu_link_channels(cam->ipu, -+ CSI_PRP_VF_MEM, MEM_ROT_VF_MEM); -+ if (err < 0) { -+ printk(KERN_ERR -+ "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n"); -+ goto out_1; -+ } -+ -+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); -+ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM); -+ -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, 0); -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, 1); -+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, -+ IPU_OUTPUT_BUFFER, 0); -+ } else { -+ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, -+ vf_out_format, cam->win.w.width, -+ cam->win.w.height, -+ cam->win.w.width, -+ cam->vf_rotation, -+ fbi->fix.smem_start + -+ (fbi->fix.line_length * -+ fbi->var.yres), -+ fbi->fix.smem_start, 0, 0, 0); -+ if (err != 0) { -+ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n"); -+ goto out_4; -+ } -+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, -+ prpvf_rot_eof_callback, -+ 0, "Mxc Camera", cam); -+ if (err < 0) { -+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n"); -+ goto out_4; -+ } -+ -+ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); -+ -+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, -+ IPU_OUTPUT_BUFFER, 0); -+ } -+ -+ cam->overlay_active = true; -+ return err; -+ -+out_1: -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL); -+out_2: -+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) -+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); -+out_3: -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+out_4: -+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); -+out_5: -+ return err; -+} -+ -+/*! -+ * prpvf_stop - stop the vf task -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ */ -+static int prpvf_stop(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0, i = 0; -+ struct fb_info *fbi = NULL; -+ struct fb_var_screeninfo fbvar; -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ void *mipi_csi2_info; -+ int ipu_id; -+ int csi_id; -+#endif -+ -+ if (cam->overlay_active == false) -+ return 0; -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ char *idstr = registered_fb[i]->fix.id; -+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || -+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { -+ fbi = registered_fb[i]; -+ break; -+ } -+ } -+ -+ if (fbi == NULL) { -+ printk(KERN_ERR "DISP FG fb not found\n"); -+ return -EPERM; -+ } -+ -+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { -+ ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM); -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam); -+ } -+ buffer_num = 0; -+ -+ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true); -+ -+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { -+ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true); -+ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); -+ } -+ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); -+ -+ console_lock(); -+ fb_blank(fbi, FB_BLANK_POWERDOWN); -+ console_unlock(); -+ -+ /* Set the overlay frame buffer std to what it is used to be */ -+ fbvar = fbi->var; -+ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG; -+ fbvar.nonstd = cam->fb_origin_std; -+ fbvar.activate |= FB_ACTIVATE_FORCE; -+ fb_set_var(fbi, &fbvar); -+ -+#ifdef CONFIG_MXC_MIPI_CSI2 -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ if (mipi_csi2_info) { -+ if (mipi_csi2_get_status(mipi_csi2_info)) { -+ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); -+ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); -+ -+ if (cam->ipu == ipu_get_soc(ipu_id) -+ && cam->csi == csi_id) -+ mipi_csi2_pixelclk_disable(mipi_csi2_info); -+ } -+ } -+#endif -+ -+ if (cam->vf_bufs_vaddr[0]) { -+ dma_free_coherent(0, cam->vf_bufs_size[0], -+ cam->vf_bufs_vaddr[0], -+ (dma_addr_t) cam->vf_bufs[0]); -+ cam->vf_bufs_vaddr[0] = NULL; -+ cam->vf_bufs[0] = 0; -+ } -+ if (cam->vf_bufs_vaddr[1]) { -+ dma_free_coherent(0, cam->vf_bufs_size[1], -+ cam->vf_bufs_vaddr[1], -+ (dma_addr_t) cam->vf_bufs[1]); -+ cam->vf_bufs_vaddr[1] = NULL; -+ cam->vf_bufs[1] = 0; -+ } -+ -+ cam->overlay_active = false; -+ return err; -+} -+ -+/*! -+ * Enable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_vf_enable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ return ipu_enable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * Disable csi -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_vf_disable_csi(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ /* free csi eof irq firstly. -+ * when disable csi, wait for idmac eof. -+ * it requests eof irq again */ -+ if (cam->vf_rotation < IPU_ROTATE_VERT_FLIP) -+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam); -+ -+ return ipu_disable_csi(cam->ipu, cam->csi); -+} -+ -+/*! -+ * function to select PRP-VF as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return status -+ */ -+int prp_vf_sdc_select(void *private) -+{ -+ cam_data *cam; -+ int err = 0; -+ if (private) { -+ cam = (cam_data *) private; -+ cam->vf_start_sdc = prpvf_start; -+ cam->vf_stop_sdc = prpvf_stop; -+ cam->vf_enable_csi = prp_vf_enable_csi; -+ cam->vf_disable_csi = prp_vf_disable_csi; -+ cam->overlay_active = false; -+ } else -+ err = -EIO; -+ -+ return err; -+} -+EXPORT_SYMBOL(prp_vf_sdc_select); -+ -+/*! -+ * function to de-select PRP-VF as the working path -+ * -+ * @param private cam_data * mxc v4l2 main structure -+ * -+ * @return int -+ */ -+int prp_vf_sdc_deselect(void *private) -+{ -+ cam_data *cam; -+ -+ if (private) { -+ cam = (cam_data *) private; -+ cam->vf_start_sdc = NULL; -+ cam->vf_stop_sdc = NULL; -+ cam->vf_enable_csi = NULL; -+ cam->vf_disable_csi = NULL; -+ } -+ return 0; -+} -+EXPORT_SYMBOL(prp_vf_sdc_deselect); -+ -+/*! -+ * Init viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int prp_vf_sdc_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit viewfinder task. -+ * -+ * @return Error code indicating success or failure -+ */ -+void __exit prp_vf_sdc_exit(void) -+{ -+} -+ -+module_init(prp_vf_sdc_init); -+module_exit(prp_vf_sdc_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP VF SDC Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_still.c linux-3.14.22/drivers/media/platform/mxc/capture/ipu_still.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ipu_still.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ipu_still.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,268 @@ -+/* -+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file ipu_still.c -+ * -+ * @brief IPU Use case for still image capture -+ * -+ * @ingroup IPU -+ */ -+ -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+static int callback_eof_flag; -+#ifndef CONFIG_MXC_IPU_V1 -+static int buffer_num; -+#endif -+ -+#ifdef CONFIG_MXC_IPU_V1 -+static int callback_flag; -+/* -+ * Function definitions -+ */ -+/*! -+ * CSI EOF callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = devid; -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ callback_flag%2 ? 1 : 0); -+ if (callback_flag == 0) -+ ipu_enable_channel(cam->ipu, CSI_MEM); -+ -+ callback_flag++; -+ return IRQ_HANDLED; -+} -+#endif -+ -+/*! -+ * CSI callback function. -+ * -+ * @param irq int irq line -+ * @param dev_id void * device id -+ * -+ * @return status IRQ_HANDLED for handled -+ */ -+static irqreturn_t prp_still_callback(int irq, void *dev_id) -+{ -+ cam_data *cam = (cam_data *) dev_id; -+ -+ callback_eof_flag++; -+ if (callback_eof_flag < 5) { -+#ifndef CONFIG_MXC_IPU_V1 -+ buffer_num = (buffer_num == 0) ? 1 : 0; -+ ipu_select_buffer(cam->ipu, CSI_MEM, -+ IPU_OUTPUT_BUFFER, buffer_num); -+#endif -+ } else { -+ cam->still_counter++; -+ wake_up_interruptible(&cam->still_queue); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+/*! -+ * start csi->mem task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_still_start(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ u32 pixel_fmt; -+ int err; -+ ipu_channel_params_t params; -+ -+ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) -+ pixel_fmt = IPU_PIX_FMT_YUV420P; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) -+ pixel_fmt = IPU_PIX_FMT_NV12; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) -+ pixel_fmt = IPU_PIX_FMT_YUV422P; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) -+ pixel_fmt = IPU_PIX_FMT_UYVY; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) -+ pixel_fmt = IPU_PIX_FMT_YUYV; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) -+ pixel_fmt = IPU_PIX_FMT_BGR24; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) -+ pixel_fmt = IPU_PIX_FMT_RGB24; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) -+ pixel_fmt = IPU_PIX_FMT_RGB565; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) -+ pixel_fmt = IPU_PIX_FMT_BGR32; -+ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) -+ pixel_fmt = IPU_PIX_FMT_RGB32; -+ else { -+ printk(KERN_ERR "format not supported\n"); -+ return -EINVAL; -+ } -+ -+ memset(¶ms, 0, sizeof(params)); -+ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); -+ if (err != 0) -+ return err; -+ -+ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, -+ pixel_fmt, cam->v2f.fmt.pix.width, -+ cam->v2f.fmt.pix.height, -+ cam->v2f.fmt.pix.width, IPU_ROTATE_NONE, -+ cam->still_buf[0], cam->still_buf[1], 0, -+ 0, 0); -+ if (err != 0) -+ return err; -+ -+#ifdef CONFIG_MXC_IPU_V1 -+ ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF); -+ err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback, -+ 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering irq.\n"); -+ return err; -+ } -+ callback_flag = 0; -+ callback_eof_flag = 0; -+ ipu_clear_irq(IPU_IRQ_SENSOR_EOF); -+ err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback, -+ 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error IPU_IRQ_SENSOR_EOF\n"); -+ return err; -+ } -+#else -+ callback_eof_flag = 0; -+ buffer_num = 0; -+ -+ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); -+ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, -+ prp_still_callback, -+ 0, "Mxc Camera", cam); -+ if (err != 0) { -+ printk(KERN_ERR "Error registering irq.\n"); -+ return err; -+ } -+ -+ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); -+ ipu_enable_channel(cam->ipu, CSI_MEM); -+ ipu_enable_csi(cam->ipu, cam->csi); -+#endif -+ -+ return err; -+} -+ -+/*! -+ * stop csi->mem encoder task -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+static int prp_still_stop(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+#ifdef CONFIG_MXC_IPU_V1 -+ ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL); -+ ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam); -+#else -+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); -+#endif -+ -+ ipu_disable_csi(cam->ipu, cam->csi); -+ ipu_disable_channel(cam->ipu, CSI_MEM, true); -+ ipu_uninit_channel(cam->ipu, CSI_MEM); -+ -+ return err; -+} -+ -+/*! -+ * function to select CSI_MEM as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+int prp_still_select(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ -+ if (cam) { -+ cam->csi_start = prp_still_start; -+ cam->csi_stop = prp_still_stop; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL(prp_still_select); -+ -+/*! -+ * function to de-select CSI_MEM as the working path -+ * -+ * @param private struct cam_data * mxc capture instance -+ * -+ * @return status -+ */ -+int prp_still_deselect(void *private) -+{ -+ cam_data *cam = (cam_data *) private; -+ int err = 0; -+ -+ err = prp_still_stop(cam); -+ -+ if (cam) { -+ cam->csi_start = NULL; -+ cam->csi_stop = NULL; -+ } -+ -+ return err; -+} -+EXPORT_SYMBOL(prp_still_deselect); -+ -+/*! -+ * Init the Encorder channels -+ * -+ * @return Error code indicating success or failure -+ */ -+__init int prp_still_init(void) -+{ -+ return 0; -+} -+ -+/*! -+ * Deinit the Encorder channels -+ * -+ */ -+void __exit prp_still_exit(void) -+{ -+} -+ -+module_init(prp_still_init); -+module_exit(prp_still_exit); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("IPU PRP STILL IMAGE Driver"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/Kconfig linux-3.14.22/drivers/media/platform/mxc/capture/Kconfig ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/Kconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/Kconfig 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,86 @@ -+if VIDEO_MXC_CAPTURE -+ -+menu "MXC Camera/V4L2 PRP Features support" -+config VIDEO_MXC_IPU_CAMERA -+ bool -+ depends on VIDEO_MXC_CAPTURE && MXC_IPU -+ default y -+ -+config VIDEO_MXC_CSI_CAMERA -+ tristate "CSI camera support" -+ depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2 -+ ---help--- -+ This is the video4linux2 capture driver based on CSI module. -+ -+config MXC_CAMERA_OV5640 -+ tristate "OmniVision ov5640 camera support" -+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C -+ ---help--- -+ If you plan to use the ov5640 Camera with your MXC system, say Y here. -+ -+config MXC_CAMERA_OV5642 -+ tristate "OmniVision ov5642 camera support" -+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C -+ ---help--- -+ If you plan to use the ov5642 Camera with your MXC system, say Y here. -+ -+config MXC_CAMERA_OV5640_MIPI -+ tristate "OmniVision ov5640 camera support using mipi" -+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C -+ ---help--- -+ If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here. -+ -+config MXC_TVIN_ADV7180 -+ tristate "Analog Device adv7180 TV Decoder Input support" -+ depends on !VIDEO_MXC_EMMA_CAMERA && I2C -+ ---help--- -+ If you plan to use the adv7180 video decoder with your MXC system, say Y here. -+ -+choice -+ prompt "Select Overlay Rounting" -+ default MXC_IPU_DEVICE_QUEUE_SDC -+ depends on VIDEO_MXC_IPU_CAMERA && FB_MXC_SYNC_PANEL -+ -+config MXC_IPU_DEVICE_QUEUE_SDC -+ tristate "Queue ipu device for overlay library" -+ depends on VIDEO_MXC_IPU_CAMERA -+ ---help--- -+ Use case CSI->MEM->IPU DEVICE->SDC: -+ Images from sensor will be frist recieved in memory,then -+ queue to ipu device for processing if needed, and displaying -+ it on synchronous display with SDC use case. -+ -+config MXC_IPU_PRP_VF_SDC -+ bool "Pre-Processor VF SDC library" -+ depends on VIDEO_MXC_IPU_CAMERA -+ ---help--- -+ Use case PRP_VF_SDC: -+ Preprocessing image from smart sensor for viewfinder and -+ displaying it on synchronous display with SDC use case. -+ If SDC BG is selected, Rotation will not be supported. -+ CSI -> IC (PRP VF) -> MEM -+ MEM -> IC (ROT) -> MEM -+ MEM -> SDC (FG/BG) -+ -+endchoice -+ -+config MXC_IPU_PRP_ENC -+ tristate "Pre-processor Encoder library" -+ depends on VIDEO_MXC_IPU_CAMERA -+ default y -+ ---help--- -+ Use case PRP_ENC: -+ Preprocessing image from smart sensor for encoder. -+ CSI -> IC (PRP ENC) -> MEM -+ -+config MXC_IPU_CSI_ENC -+ tristate "IPU CSI Encoder library" -+ depends on VIDEO_MXC_IPU_CAMERA -+ default y -+ ---help--- -+ Use case IPU_CSI_ENC: -+ Get raw image with CSI from smart sensor for encoder. -+ CSI -> MEM -+endmenu -+ -+endif -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/Makefile linux-3.14.22/drivers/media/platform/mxc/capture/Makefile ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/Makefile 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/Makefile 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,21 @@ -+obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o -+ -+ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y) -+ obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc_v4l2_capture.o -+ obj-$(CONFIG_MXC_IPU_PRP_VF_SDC) += ipu_prp_vf_sdc.o ipu_prp_vf_sdc_bg.o -+ obj-$(CONFIG_MXC_IPU_DEVICE_QUEUE_SDC) += ipu_fg_overlay_sdc.o ipu_bg_overlay_sdc.o -+ obj-$(CONFIG_MXC_IPU_PRP_ENC) += ipu_prp_enc.o ipu_still.o -+ obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o -+endif -+ -+ov5640_camera-objs := ov5640.o -+obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o -+ -+ov5642_camera-objs := ov5642.o -+obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o -+ -+ov5640_camera_mipi-objs := ov5640_mipi.o -+obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o -+ -+adv7180_tvin-objs := adv7180.o -+obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c linux-3.14.22/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,3102 @@ -+/* -+ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @file drivers/media/video/mxc/capture/mxc_v4l2_capture.c -+ * -+ * @brief Mxc Video For Linux 2 driver -+ * -+ * @ingroup MXC_V4L2_CAPTURE -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+#include "ipu_prp_sw.h" -+ -+#define init_MUTEX(sem) sema_init(sem, 1) -+ -+static struct platform_device_id imx_v4l2_devtype[] = { -+ { -+ .name = "v4l2-capture-imx5", -+ .driver_data = IMX5_V4L2, -+ }, { -+ .name = "v4l2-capture-imx6", -+ .driver_data = IMX6_V4L2, -+ }, { -+ /* sentinel */ -+ } -+}; -+MODULE_DEVICE_TABLE(platform, imx_v4l2_devtype); -+ -+static const struct of_device_id mxc_v4l2_dt_ids[] = { -+ { -+ .compatible = "fsl,imx6q-v4l2-capture", -+ .data = &imx_v4l2_devtype[IMX6_V4L2], -+ }, { -+ /* sentinel */ -+ } -+}; -+MODULE_DEVICE_TABLE(of, mxc_v4l2_dt_ids); -+ -+static int video_nr = -1; -+ -+/*! This data is used for the output to the display. */ -+#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 6 -+#define MXC_V4L2_CAPTURE_NUM_INPUTS 2 -+static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = { -+ { -+ .index = 0, -+ .name = "DISP3 BG", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+ { -+ .index = 1, -+ .name = "DISP3 BG - DI1", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+ { -+ .index = 2, -+ .name = "DISP3 FG", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+ { -+ .index = 3, -+ .name = "DISP4 BG", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+ { -+ .index = 4, -+ .name = "DISP4 BG - DI1", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+ { -+ .index = 5, -+ .name = "DISP4 FG", -+ .type = V4L2_OUTPUT_TYPE_ANALOG, -+ .audioset = 0, -+ .modulator = 0, -+ .std = V4L2_STD_UNKNOWN, -+ }, -+}; -+ -+static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = { -+ { -+ .index = 0, -+ .name = "CSI IC MEM", -+ .type = V4L2_INPUT_TYPE_CAMERA, -+ .audioset = 0, -+ .tuner = 0, -+ .std = V4L2_STD_UNKNOWN, -+ .status = 0, -+ }, -+ { -+ .index = 1, -+ .name = "CSI MEM", -+ .type = V4L2_INPUT_TYPE_CAMERA, -+ .audioset = 0, -+ .tuner = 0, -+ .std = V4L2_STD_UNKNOWN, -+ .status = V4L2_IN_ST_NO_POWER, -+ }, -+}; -+ -+/*! List of TV input video formats supported. The video formats is corresponding -+ * to the v4l2_id in video_fmt_t. -+ * Currently, only PAL and NTSC is supported. Needs to be expanded in the -+ * future. -+ */ -+typedef enum { -+ TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ -+ TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */ -+ TV_NOT_LOCKED, /*!< Not locked on a signal. */ -+} video_fmt_idx; -+ -+/*! Number of video standards supported (including 'not locked' signal). */ -+#define TV_STD_MAX (TV_NOT_LOCKED + 1) -+ -+/*! Video format structure. */ -+typedef struct { -+ int v4l2_id; /*!< Video for linux ID. */ -+ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ -+ u16 raw_width; /*!< Raw width. */ -+ u16 raw_height; /*!< Raw height. */ -+ u16 active_width; /*!< Active width. */ -+ u16 active_height; /*!< Active height. */ -+ u16 active_top; /*!< Active top. */ -+ u16 active_left; /*!< Active left. */ -+} video_fmt_t; -+ -+/*! -+ * Description of video formats supported. -+ * -+ * PAL: raw=720x625, active=720x576. -+ * NTSC: raw=720x525, active=720x480. -+ */ -+static video_fmt_t video_fmts[] = { -+ { /*! NTSC */ -+ .v4l2_id = V4L2_STD_NTSC, -+ .name = "NTSC", -+ .raw_width = 720, /* SENS_FRM_WIDTH */ -+ .raw_height = 525, /* SENS_FRM_HEIGHT */ -+ .active_width = 720, /* ACT_FRM_WIDTH */ -+ .active_height = 480, /* ACT_FRM_HEIGHT */ -+ .active_top = 13, -+ .active_left = 0, -+ }, -+ { /*! (B, G, H, I, N) PAL */ -+ .v4l2_id = V4L2_STD_PAL, -+ .name = "PAL", -+ .raw_width = 720, -+ .raw_height = 625, -+ .active_width = 720, -+ .active_height = 576, -+ .active_top = 0, -+ .active_left = 0, -+ }, -+ { /*! Unlocked standard */ -+ .v4l2_id = V4L2_STD_ALL, -+ .name = "Autodetect", -+ .raw_width = 720, -+ .raw_height = 625, -+ .active_width = 720, -+ .active_height = 576, -+ .active_top = 0, -+ .active_left = 0, -+ }, -+}; -+ -+/*!* Standard index of TV. */ -+static video_fmt_idx video_index = TV_NOT_LOCKED; -+ -+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave); -+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave); -+static int start_preview(cam_data *cam); -+static int stop_preview(cam_data *cam); -+ -+/*! Information about this driver. */ -+static struct v4l2_int_master mxc_v4l2_master = { -+ .attach = mxc_v4l2_master_attach, -+ .detach = mxc_v4l2_master_detach, -+}; -+ -+/*************************************************************************** -+ * Functions for handling Frame buffers. -+ **************************************************************************/ -+ -+/*! -+ * Free frame buffers -+ * -+ * @param cam Structure cam_data * -+ * -+ * @return status 0 success. -+ */ -+static int mxc_free_frame_buf(cam_data *cam) -+{ -+ int i; -+ -+ pr_debug("MVC: In mxc_free_frame_buf\n"); -+ -+ for (i = 0; i < FRAME_NUM; i++) { -+ if (cam->frame[i].vaddress != 0) { -+ dma_free_coherent(0, cam->frame[i].buffer.length, -+ cam->frame[i].vaddress, -+ cam->frame[i].paddress); -+ cam->frame[i].vaddress = 0; -+ } -+ } -+ -+ return 0; -+} -+ -+/*! -+ * Allocate frame buffers -+ * -+ * @param cam Structure cam_data* -+ * @param count int number of buffer need to allocated -+ * -+ * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. -+ */ -+static int mxc_allocate_frame_buf(cam_data *cam, int count) -+{ -+ int i; -+ -+ pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n", -+ cam->v2f.fmt.pix.sizeimage); -+ -+ for (i = 0; i < count; i++) { -+ cam->frame[i].vaddress = -+ dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->frame[i].paddress, -+ GFP_DMA | GFP_KERNEL); -+ if (cam->frame[i].vaddress == 0) { -+ pr_err("ERROR: v4l2 capture: " -+ "mxc_allocate_frame_buf failed.\n"); -+ mxc_free_frame_buf(cam); -+ return -ENOBUFS; -+ } -+ cam->frame[i].buffer.index = i; -+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cam->frame[i].buffer.length = -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); -+ cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; -+ cam->frame[i].buffer.m.offset = cam->frame[i].paddress; -+ cam->frame[i].index = i; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * Free frame buffers status -+ * -+ * @param cam Structure cam_data * -+ * -+ * @return none -+ */ -+static void mxc_free_frames(cam_data *cam) -+{ -+ int i; -+ -+ pr_debug("In MVC:mxc_free_frames\n"); -+ -+ for (i = 0; i < FRAME_NUM; i++) -+ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ -+ cam->enc_counter = 0; -+ INIT_LIST_HEAD(&cam->ready_q); -+ INIT_LIST_HEAD(&cam->working_q); -+ INIT_LIST_HEAD(&cam->done_q); -+} -+ -+/*! -+ * Return the buffer status -+ * -+ * @param cam Structure cam_data * -+ * @param buf Structure v4l2_buffer * -+ * -+ * @return status 0 success, EINVAL failed. -+ */ -+static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ pr_debug("In MVC:mxc_v4l2_buffer_status\n"); -+ -+ if (buf->index < 0 || buf->index >= FRAME_NUM) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers " -+ "not allocated\n"); -+ return -EINVAL; -+ } -+ -+ memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); -+ return 0; -+} -+ -+static int mxc_v4l2_release_bufs(cam_data *cam) -+{ -+ pr_debug("In MVC:mxc_v4l2_release_bufs\n"); -+ return 0; -+} -+ -+static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ pr_debug("In MVC:mxc_v4l2_prepare_bufs\n"); -+ -+ if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers " -+ "not allocated,index=%d, length=%d\n", buf->index, -+ buf->length); -+ return -EINVAL; -+ } -+ -+ cam->frame[buf->index].buffer.index = buf->index; -+ cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; -+ cam->frame[buf->index].buffer.length = buf->length; -+ cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress -+ = buf->m.offset; -+ cam->frame[buf->index].buffer.type = buf->type; -+ cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; -+ cam->frame[buf->index].index = buf->index; -+ -+ return 0; -+} -+ -+/*************************************************************************** -+ * Functions for handling the video stream. -+ **************************************************************************/ -+ -+/*! -+ * Indicates whether the palette is supported. -+ * -+ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32 -+ * -+ * @return 0 if failed -+ */ -+static inline int valid_mode(u32 palette) -+{ -+ return ((palette == V4L2_PIX_FMT_RGB565) || -+ (palette == V4L2_PIX_FMT_BGR24) || -+ (palette == V4L2_PIX_FMT_RGB24) || -+ (palette == V4L2_PIX_FMT_BGR32) || -+ (palette == V4L2_PIX_FMT_RGB32) || -+ (palette == V4L2_PIX_FMT_YUV422P) || -+ (palette == V4L2_PIX_FMT_UYVY) || -+ (palette == V4L2_PIX_FMT_YUYV) || -+ (palette == V4L2_PIX_FMT_YUV420) || -+ (palette == V4L2_PIX_FMT_YVU420) || -+ (palette == V4L2_PIX_FMT_NV12)); -+} -+ -+/*! -+ * Start the encoder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int mxc_streamon(cam_data *cam) -+{ -+ struct mxc_v4l_frame *frame; -+ unsigned long lock_flags; -+ int err = 0; -+ -+ pr_debug("In MVC:mxc_streamon\n"); -+ -+ if (NULL == cam) { -+ pr_err("ERROR! cam parameter is NULL\n"); -+ return -1; -+ } -+ -+ if (cam->capture_on) { -+ pr_err("ERROR: v4l2 capture: Capture stream has been turned " -+ " on\n"); -+ return -1; -+ } -+ -+ if (list_empty(&cam->ready_q)) { -+ pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been " -+ "queued yet\n"); -+ return -EINVAL; -+ } -+ if (cam->enc_update_eba && -+ cam->ready_q.prev == cam->ready_q.next) { -+ pr_err("ERROR: v4l2 capture: mxc_streamon buffer need " -+ "ping pong at least two buffers\n"); -+ return -EINVAL; -+ } -+ -+ cam->capture_pid = current->pid; -+ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ if (cam->enc_enable) { -+ err = cam->enc_enable(cam); -+ if (err != 0) -+ return err; -+ } -+ -+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); -+ cam->ping_pong_csi = 0; -+ cam->local_buf_num = 0; -+ if (cam->enc_update_eba) { -+ frame = -+ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->ready_q.next); -+ list_add_tail(&frame->queue, &cam->working_q); -+ frame->ipu_buf_num = cam->ping_pong_csi; -+ err = cam->enc_update_eba(cam->ipu, frame->buffer.m.offset, -+ &cam->ping_pong_csi); -+ -+ frame = -+ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->ready_q.next); -+ list_add_tail(&frame->queue, &cam->working_q); -+ frame->ipu_buf_num = cam->ping_pong_csi; -+ err |= cam->enc_update_eba(cam->ipu, frame->buffer.m.offset, -+ &cam->ping_pong_csi); -+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); -+ } else { -+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); -+ return -EINVAL; -+ } -+ -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ -+ if (cam->enc_enable_csi) { -+ err = cam->enc_enable_csi(cam); -+ if (err != 0) -+ return err; -+ } -+ -+ cam->capture_on = true; -+ -+ return err; -+} -+ -+/*! -+ * Shut down the encoder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int mxc_streamoff(cam_data *cam) -+{ -+ int err = 0; -+ -+ pr_debug("In MVC:mxc_streamoff\n"); -+ -+ if (cam->capture_on == false) -+ return 0; -+ -+ /* For both CSI--MEM and CSI--IC--MEM -+ * 1. wait for idmac eof -+ * 2. disable csi first -+ * 3. disable idmac -+ * 4. disable smfc (CSI--MEM channel) -+ */ -+ if (mxc_capture_inputs[cam->current_input].name != NULL) { -+ if (cam->enc_disable_csi) { -+ err = cam->enc_disable_csi(cam); -+ if (err != 0) -+ return err; -+ } -+ if (cam->enc_disable) { -+ err = cam->enc_disable(cam); -+ if (err != 0) -+ return err; -+ } -+ } -+ -+ mxc_free_frames(cam); -+ mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER; -+ cam->capture_on = false; -+ return err; -+} -+ -+/*! -+ * Valid and adjust the overlay window size, position -+ * -+ * @param cam structure cam_data * -+ * @param win struct v4l2_window * -+ * -+ * @return 0 -+ */ -+static int verify_preview(cam_data *cam, struct v4l2_window *win) -+{ -+ int i = 0, width_bound = 0, height_bound = 0; -+ int *width, *height; -+ unsigned int ipu_ch = CHAN_NONE; -+ struct fb_info *bg_fbi = NULL, *fbi = NULL; -+ bool foregound_fb = false; -+ mm_segment_t old_fs; -+ -+ pr_debug("In MVC: verify_preview\n"); -+ -+ do { -+ fbi = (struct fb_info *)registered_fb[i]; -+ if (fbi == NULL) { -+ pr_err("ERROR: verify_preview frame buffer NULL.\n"); -+ return -1; -+ } -+ -+ /* Which DI supports 2 layers? */ -+ if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) && -+ (cam->output < 3)) || -+ ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) && -+ (cam->output >= 3))) { -+ if (fbi->fbops->fb_ioctl) { -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN, -+ (unsigned long)&ipu_ch); -+ set_fs(old_fs); -+ } -+ if (ipu_ch == MEM_BG_SYNC) { -+ bg_fbi = fbi; -+ pr_debug("Found background frame buffer.\n"); -+ } -+ } -+ -+ /* Found the frame buffer to preview on. */ -+ if (strcmp(fbi->fix.id, -+ mxc_capture_outputs[cam->output].name) == 0) { -+ if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) && -+ (cam->output < 3)) || -+ ((strcmp(fbi->fix.id, "DISP4 FG") == 0) && -+ (cam->output >= 3))) -+ foregound_fb = true; -+ -+ cam->overlay_fb = fbi; -+ break; -+ } -+ } while (++i < FB_MAX); -+ -+ if (foregound_fb) { -+ width_bound = bg_fbi->var.xres; -+ height_bound = bg_fbi->var.yres; -+ -+ if (win->w.width + win->w.left > bg_fbi->var.xres || -+ win->w.height + win->w.top > bg_fbi->var.yres) { -+ pr_err("ERROR: FG window position exceeds.\n"); -+ return -1; -+ } -+ } else { -+ /* 4 bytes alignment for BG */ -+ width_bound = cam->overlay_fb->var.xres; -+ height_bound = cam->overlay_fb->var.yres; -+ -+ if (cam->overlay_fb->var.bits_per_pixel == 24) -+ win->w.left -= win->w.left % 4; -+ else if (cam->overlay_fb->var.bits_per_pixel == 16) -+ win->w.left -= win->w.left % 2; -+ -+ if (win->w.width + win->w.left > cam->overlay_fb->var.xres) -+ win->w.width = cam->overlay_fb->var.xres - win->w.left; -+ if (win->w.height + win->w.top > cam->overlay_fb->var.yres) -+ win->w.height = cam->overlay_fb->var.yres - win->w.top; -+ } -+ -+ /* stride line limitation */ -+ win->w.height -= win->w.height % 8; -+ win->w.width -= win->w.width % 8; -+ -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ height = &win->w.width; -+ width = &win->w.height; -+ } else { -+ width = &win->w.width; -+ height = &win->w.height; -+ } -+ -+ if (*width == 0 || *height == 0) { -+ pr_err("ERROR: v4l2 capture: width or height" -+ " too small.\n"); -+ return -EINVAL; -+ } -+ -+ if ((cam->crop_bounds.width / *width > 8) || -+ ((cam->crop_bounds.width / *width == 8) && -+ (cam->crop_bounds.width % *width))) { -+ *width = cam->crop_bounds.width / 8; -+ if (*width % 8) -+ *width += 8 - *width % 8; -+ if (*width + win->w.left > width_bound) { -+ pr_err("ERROR: v4l2 capture: width exceeds " -+ "resize limit.\n"); -+ return -1; -+ } -+ pr_err("ERROR: v4l2 capture: width exceeds limit. " -+ "Resize to %d.\n", -+ *width); -+ } -+ -+ if ((cam->crop_bounds.height / *height > 8) || -+ ((cam->crop_bounds.height / *height == 8) && -+ (cam->crop_bounds.height % *height))) { -+ *height = cam->crop_bounds.height / 8; -+ if (*height % 8) -+ *height += 8 - *height % 8; -+ if (*height + win->w.top > height_bound) { -+ pr_err("ERROR: v4l2 capture: height exceeds " -+ "resize limit.\n"); -+ return -1; -+ } -+ pr_err("ERROR: v4l2 capture: height exceeds limit " -+ "resize to %d.\n", -+ *height); -+ } -+ -+ return 0; -+} -+ -+/*! -+ * start the viewfinder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int start_preview(cam_data *cam) -+{ -+ int err = 0; -+ -+ pr_debug("MVC: start_preview\n"); -+ -+ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) -+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+ err = prp_vf_sdc_select(cam); -+ #else -+ err = foreground_sdc_select(cam); -+ #endif -+ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) -+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+ err = prp_vf_sdc_select_bg(cam); -+ #else -+ err = bg_overlay_sdc_select(cam); -+ #endif -+ if (err != 0) -+ return err; -+ -+ if (cam->vf_start_sdc) { -+ err = cam->vf_start_sdc(cam); -+ if (err != 0) -+ return err; -+ } -+ -+ if (cam->vf_enable_csi) -+ err = cam->vf_enable_csi(cam); -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, -+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", -+ __func__, -+ cam->crop_bounds.width, cam->crop_bounds.height); -+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", -+ __func__, -+ cam->crop_defrect.width, cam->crop_defrect.height); -+ pr_debug("End of %s: crop_current widthxheight %d x %d\n", -+ __func__, -+ cam->crop_current.width, cam->crop_current.height); -+ -+ return err; -+} -+ -+/*! -+ * shut down the viewfinder job -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int stop_preview(cam_data *cam) -+{ -+ int err = 0; -+ -+ if (cam->vf_disable_csi) { -+ err = cam->vf_disable_csi(cam); -+ if (err != 0) -+ return err; -+ } -+ -+ if (cam->vf_stop_sdc) { -+ err = cam->vf_stop_sdc(cam); -+ if (err != 0) -+ return err; -+ } -+ -+ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) -+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+ err = prp_vf_sdc_deselect(cam); -+ #else -+ err = foreground_sdc_deselect(cam); -+ #endif -+ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) -+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+ err = prp_vf_sdc_deselect_bg(cam); -+ #else -+ err = bg_overlay_sdc_deselect(cam); -+ #endif -+ -+ return err; -+} -+ -+/*************************************************************************** -+ * VIDIOC Functions. -+ **************************************************************************/ -+ -+/*! -+ * V4L2 - mxc_v4l2_g_fmt function -+ * -+ * @param cam structure cam_data * -+ * -+ * @param f structure v4l2_format * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) -+{ -+ int retval = 0; -+ -+ pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type); -+ -+ switch (f->type) { -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); -+ f->fmt.pix = cam->v2f.fmt.pix; -+ break; -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); -+ f->fmt.win = cam->win; -+ break; -+ default: -+ pr_debug(" type is invalid\n"); -+ retval = -EINVAL; -+ } -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, -+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", -+ __func__, -+ cam->crop_bounds.width, cam->crop_bounds.height); -+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", -+ __func__, -+ cam->crop_defrect.width, cam->crop_defrect.height); -+ pr_debug("End of %s: crop_current widthxheight %d x %d\n", -+ __func__, -+ cam->crop_current.width, cam->crop_current.height); -+ -+ return retval; -+} -+ -+/*! -+ * V4L2 - mxc_v4l2_s_fmt function -+ * -+ * @param cam structure cam_data * -+ * -+ * @param f structure v4l2_format * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) -+{ -+ int retval = 0; -+ int size = 0; -+ int bytesperline = 0; -+ int *width, *height; -+ -+ pr_debug("In MVC: mxc_v4l2_s_fmt\n"); -+ -+ switch (f->type) { -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); -+ if (!valid_mode(f->fmt.pix.pixelformat)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format " -+ "not supported\n"); -+ return -EINVAL; -+ } -+ -+ /* -+ * Force the capture window resolution to be crop bounds -+ * for CSI MEM input mode. -+ */ -+ if (strcmp(mxc_capture_inputs[cam->current_input].name, -+ "CSI MEM") == 0) { -+ f->fmt.pix.width = cam->crop_current.width; -+ f->fmt.pix.height = cam->crop_current.height; -+ } -+ -+ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { -+ height = &f->fmt.pix.width; -+ width = &f->fmt.pix.height; -+ } else { -+ width = &f->fmt.pix.width; -+ height = &f->fmt.pix.height; -+ } -+ -+ /* stride line limitation */ -+ *width -= *width % 8; -+ *height -= *height % 8; -+ -+ if (*width == 0 || *height == 0) { -+ pr_err("ERROR: v4l2 capture: width or height" -+ " too small.\n"); -+ return -EINVAL; -+ } -+ -+ if ((cam->crop_current.width / *width > 8) || -+ ((cam->crop_current.width / *width == 8) && -+ (cam->crop_current.width % *width))) { -+ *width = cam->crop_current.width / 8; -+ if (*width % 8) -+ *width += 8 - *width % 8; -+ pr_err("ERROR: v4l2 capture: width exceeds limit " -+ "resize to %d.\n", -+ *width); -+ } -+ -+ if ((cam->crop_current.height / *height > 8) || -+ ((cam->crop_current.height / *height == 8) && -+ (cam->crop_current.height % *height))) { -+ *height = cam->crop_current.height / 8; -+ if (*height % 8) -+ *height += 8 - *height % 8; -+ pr_err("ERROR: v4l2 capture: height exceeds limit " -+ "resize to %d.\n", -+ *height); -+ } -+ -+ switch (f->fmt.pix.pixelformat) { -+ case V4L2_PIX_FMT_RGB565: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ bytesperline = f->fmt.pix.width * 2; -+ break; -+ case V4L2_PIX_FMT_BGR24: -+ size = f->fmt.pix.width * f->fmt.pix.height * 3; -+ bytesperline = f->fmt.pix.width * 3; -+ break; -+ case V4L2_PIX_FMT_RGB24: -+ size = f->fmt.pix.width * f->fmt.pix.height * 3; -+ bytesperline = f->fmt.pix.width * 3; -+ break; -+ case V4L2_PIX_FMT_BGR32: -+ size = f->fmt.pix.width * f->fmt.pix.height * 4; -+ bytesperline = f->fmt.pix.width * 4; -+ break; -+ case V4L2_PIX_FMT_RGB32: -+ size = f->fmt.pix.width * f->fmt.pix.height * 4; -+ bytesperline = f->fmt.pix.width * 4; -+ break; -+ case V4L2_PIX_FMT_YUV422P: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ bytesperline = f->fmt.pix.width; -+ break; -+ case V4L2_PIX_FMT_UYVY: -+ case V4L2_PIX_FMT_YUYV: -+ size = f->fmt.pix.width * f->fmt.pix.height * 2; -+ bytesperline = f->fmt.pix.width * 2; -+ break; -+ case V4L2_PIX_FMT_YUV420: -+ case V4L2_PIX_FMT_YVU420: -+ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; -+ bytesperline = f->fmt.pix.width; -+ break; -+ case V4L2_PIX_FMT_NV12: -+ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; -+ bytesperline = f->fmt.pix.width; -+ break; -+ default: -+ break; -+ } -+ -+ if (f->fmt.pix.bytesperline < bytesperline) -+ f->fmt.pix.bytesperline = bytesperline; -+ else -+ bytesperline = f->fmt.pix.bytesperline; -+ -+ if (f->fmt.pix.sizeimage < size) -+ f->fmt.pix.sizeimage = size; -+ else -+ size = f->fmt.pix.sizeimage; -+ -+ cam->v2f.fmt.pix = f->fmt.pix; -+ -+ if (cam->v2f.fmt.pix.priv != 0) { -+ if (copy_from_user(&cam->offset, -+ (void *)cam->v2f.fmt.pix.priv, -+ sizeof(cam->offset))) { -+ retval = -EFAULT; -+ break; -+ } -+ } -+ break; -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); -+ retval = verify_preview(cam, &f->fmt.win); -+ cam->win = f->fmt.win; -+ break; -+ default: -+ retval = -EINVAL; -+ } -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, -+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", -+ __func__, -+ cam->crop_bounds.width, cam->crop_bounds.height); -+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", -+ __func__, -+ cam->crop_defrect.width, cam->crop_defrect.height); -+ pr_debug("End of %s: crop_current widthxheight %d x %d\n", -+ __func__, -+ cam->crop_current.width, cam->crop_current.height); -+ -+ return retval; -+} -+ -+/*! -+ * get control param -+ * -+ * @param cam structure cam_data * -+ * -+ * @param c structure v4l2_control * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c) -+{ -+ int status = 0; -+ -+ pr_debug("In MVC:mxc_v4l2_g_ctrl\n"); -+ -+ /* probably don't need to store the values that can be retrieved, -+ * locally, but they are for now. */ -+ switch (c->id) { -+ case V4L2_CID_HFLIP: -+ /* This is handled in the ipu. */ -+ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP) -+ c->value = 1; -+ break; -+ case V4L2_CID_VFLIP: -+ /* This is handled in the ipu. */ -+ if (cam->rotation == IPU_ROTATE_VERT_FLIP) -+ c->value = 1; -+ break; -+ case V4L2_CID_MXC_ROT: -+ /* This is handled in the ipu. */ -+ c->value = cam->rotation; -+ break; -+ case V4L2_CID_BRIGHTNESS: -+ if (cam->sensor) { -+ c->value = cam->bright; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->bright = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_HUE: -+ if (cam->sensor) { -+ c->value = cam->hue; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->hue = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_CONTRAST: -+ if (cam->sensor) { -+ c->value = cam->contrast; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->contrast = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_SATURATION: -+ if (cam->sensor) { -+ c->value = cam->saturation; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->saturation = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_RED_BALANCE: -+ if (cam->sensor) { -+ c->value = cam->red; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->red = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ if (cam->sensor) { -+ c->value = cam->blue; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->blue = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ case V4L2_CID_BLACK_LEVEL: -+ if (cam->sensor) { -+ c->value = cam->ae_mode; -+ status = vidioc_int_g_ctrl(cam->sensor, c); -+ cam->ae_mode = c->value; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ status = -ENODEV; -+ } -+ break; -+ default: -+ pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n"); -+ } -+ -+ return status; -+} -+ -+/*! -+ * V4L2 - set_control function -+ * V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing. -+ * 0 for normal operation -+ * 1 for vertical flip -+ * 2 for horizontal flip -+ * 3 for horizontal and vertical flip -+ * 4 for 90 degree rotation -+ * @param cam structure cam_data * -+ * -+ * @param c structure v4l2_control * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) -+{ -+ int i, ret = 0; -+ int tmp_rotation = IPU_ROTATE_NONE; -+ struct sensor_data *sensor_data; -+ -+ pr_debug("In MVC:mxc_v4l2_s_ctrl\n"); -+ -+ switch (c->id) { -+ case V4L2_CID_HFLIP: -+ /* This is done by the IPU */ -+ if (c->value == 1) { -+ if ((cam->rotation != IPU_ROTATE_VERT_FLIP) && -+ (cam->rotation != IPU_ROTATE_180)) -+ cam->rotation = IPU_ROTATE_HORIZ_FLIP; -+ else -+ cam->rotation = IPU_ROTATE_180; -+ } else { -+ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP) -+ cam->rotation = IPU_ROTATE_NONE; -+ if (cam->rotation == IPU_ROTATE_180) -+ cam->rotation = IPU_ROTATE_VERT_FLIP; -+ } -+ break; -+ case V4L2_CID_VFLIP: -+ /* This is done by the IPU */ -+ if (c->value == 1) { -+ if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) && -+ (cam->rotation != IPU_ROTATE_180)) -+ cam->rotation = IPU_ROTATE_VERT_FLIP; -+ else -+ cam->rotation = IPU_ROTATE_180; -+ } else { -+ if (cam->rotation == IPU_ROTATE_VERT_FLIP) -+ cam->rotation = IPU_ROTATE_NONE; -+ if (cam->rotation == IPU_ROTATE_180) -+ cam->rotation = IPU_ROTATE_HORIZ_FLIP; -+ } -+ break; -+ case V4L2_CID_MXC_ROT: -+ case V4L2_CID_MXC_VF_ROT: -+ /* This is done by the IPU */ -+ switch (c->value) { -+ case V4L2_MXC_ROTATE_NONE: -+ tmp_rotation = IPU_ROTATE_NONE; -+ break; -+ case V4L2_MXC_ROTATE_VERT_FLIP: -+ tmp_rotation = IPU_ROTATE_VERT_FLIP; -+ break; -+ case V4L2_MXC_ROTATE_HORIZ_FLIP: -+ tmp_rotation = IPU_ROTATE_HORIZ_FLIP; -+ break; -+ case V4L2_MXC_ROTATE_180: -+ tmp_rotation = IPU_ROTATE_180; -+ break; -+ case V4L2_MXC_ROTATE_90_RIGHT: -+ tmp_rotation = IPU_ROTATE_90_RIGHT; -+ break; -+ case V4L2_MXC_ROTATE_90_RIGHT_VFLIP: -+ tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP; -+ break; -+ case V4L2_MXC_ROTATE_90_RIGHT_HFLIP: -+ tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP; -+ break; -+ case V4L2_MXC_ROTATE_90_LEFT: -+ tmp_rotation = IPU_ROTATE_90_LEFT; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC -+ if (c->id == V4L2_CID_MXC_VF_ROT) -+ cam->vf_rotation = tmp_rotation; -+ else -+ cam->rotation = tmp_rotation; -+ #else -+ cam->rotation = tmp_rotation; -+ #endif -+ -+ break; -+ case V4L2_CID_HUE: -+ if (cam->sensor) { -+ cam->hue = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_CONTRAST: -+ if (cam->sensor) { -+ cam->contrast = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_BRIGHTNESS: -+ if (cam->sensor) { -+ cam->bright = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_SATURATION: -+ if (cam->sensor) { -+ cam->saturation = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_RED_BALANCE: -+ if (cam->sensor) { -+ cam->red = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ if (cam->sensor) { -+ cam->blue = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_EXPOSURE: -+ if (cam->sensor) { -+ cam->ae_mode = c->value; -+ ret = vidioc_int_s_ctrl(cam->sensor, c); -+ } else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ ret = -ENODEV; -+ } -+ break; -+ case V4L2_CID_MXC_FLASH: -+#ifdef CONFIG_MXC_IPU_V1 -+ ipu_csi_flash_strobe(true); -+#endif -+ break; -+ case V4L2_CID_MXC_SWITCH_CAM: -+ if (cam->sensor == cam->all_sensors[c->value]) -+ break; -+ -+ /* power down other cameraes before enable new one */ -+ for (i = 0; i < cam->sensor_index; i++) { -+ if (i != c->value) { -+ vidioc_int_dev_exit(cam->all_sensors[i]); -+ vidioc_int_s_power(cam->all_sensors[i], 0); -+ if (cam->mclk_on[cam->mclk_source]) { -+ ipu_csi_enable_mclk_if(cam->ipu, -+ CSI_MCLK_I2C, -+ cam->mclk_source, -+ false, false); -+ cam->mclk_on[cam->mclk_source] = -+ false; -+ } -+ } -+ } -+ sensor_data = cam->all_sensors[c->value]->priv; -+ if (sensor_data->io_init) -+ sensor_data->io_init(); -+ cam->sensor = cam->all_sensors[c->value]; -+ cam->mclk_source = sensor_data->mclk_source; -+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, -+ cam->mclk_source, true, true); -+ cam->mclk_on[cam->mclk_source] = true; -+ vidioc_int_s_power(cam->sensor, 1); -+ vidioc_int_dev_init(cam->sensor); -+ break; -+ default: -+ pr_debug(" default case\n"); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * V4L2 - mxc_v4l2_s_param function -+ * Allows setting of capturemode and frame rate. -+ * -+ * @param cam structure cam_data * -+ * @param parm structure v4l2_streamparm * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) -+{ -+ struct v4l2_ifparm ifparm; -+ struct v4l2_format cam_fmt; -+ struct v4l2_streamparm currentparm; -+ ipu_csi_signal_cfg_t csi_param; -+ u32 current_fps, parm_fps; -+ int err = 0; -+ -+ pr_debug("In mxc_v4l2_s_param\n"); -+ -+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n"); -+ return -EINVAL; -+ } -+ -+ /* Stop the viewfinder */ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ -+ /* First check that this device can support the changes requested. */ -+ err = vidioc_int_g_parm(cam->sensor, ¤tparm); -+ if (err) { -+ pr_err("%s: vidioc_int_g_parm returned an error %d\n", -+ __func__, err); -+ goto exit; -+ } -+ -+ current_fps = currentparm.parm.capture.timeperframe.denominator -+ / currentparm.parm.capture.timeperframe.numerator; -+ parm_fps = parm->parm.capture.timeperframe.denominator -+ / parm->parm.capture.timeperframe.numerator; -+ -+ pr_debug(" Current capabilities are %x\n", -+ currentparm.parm.capture.capability); -+ pr_debug(" Current capturemode is %d change to %d\n", -+ currentparm.parm.capture.capturemode, -+ parm->parm.capture.capturemode); -+ pr_debug(" Current framerate is %d change to %d\n", -+ current_fps, parm_fps); -+ -+ /* This will change any camera settings needed. */ -+ err = vidioc_int_s_parm(cam->sensor, parm); -+ if (err) { -+ pr_err("%s: vidioc_int_s_parm returned an error %d\n", -+ __func__, err); -+ goto exit; -+ } -+ -+ /* If resolution changed, need to re-program the CSI */ -+ /* Get new values. */ -+ vidioc_int_g_ifparm(cam->sensor, &ifparm); -+ -+ csi_param.data_width = 0; -+ csi_param.clk_mode = 0; -+ csi_param.ext_vsync = 0; -+ csi_param.Vsync_pol = 0; -+ csi_param.Hsync_pol = 0; -+ csi_param.pixclk_pol = 0; -+ csi_param.data_pol = 0; -+ csi_param.sens_clksrc = 0; -+ csi_param.pack_tight = 0; -+ csi_param.force_eof = 0; -+ csi_param.data_en_pol = 0; -+ csi_param.data_fmt = 0; -+ csi_param.csi = cam->csi; -+ csi_param.mclk = 0; -+ -+ pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr); -+ if (ifparm.u.bt656.clock_curr == 0) -+ csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED; -+ else -+ csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK; -+ -+ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv; -+ -+ if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) { -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; -+ } else if (ifparm.u.bt656.mode -+ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) { -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_10; -+ } else { -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; -+ } -+ -+ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv; -+ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv; -+ csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct; -+ -+ /* if the capturemode changed, the size bounds will have changed. */ -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); -+ pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", -+ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); -+ -+ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat; -+ -+ cam->crop_bounds.top = cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = cam_fmt.fmt.pix.width; -+ cam->crop_bounds.height = cam_fmt.fmt.pix.height; -+ -+ /* -+ * Set the default current cropped resolution to be the same with -+ * the cropping boundary(except for tvin module). -+ */ -+ if (cam->device_type != 1) { -+ cam->crop_current.width = cam->crop_bounds.width; -+ cam->crop_current.height = cam->crop_bounds.height; -+ } -+ -+ /* This essentially loses the data at the left and bottom of the image -+ * giving a digital zoom image, if crop_current is less than the full -+ * size of the image. */ -+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, -+ cam->crop_current.height, cam->csi); -+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, -+ cam->crop_current.top, -+ cam->csi); -+ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width, -+ cam->crop_bounds.height, -+ cam_fmt.fmt.pix.pixelformat, csi_param); -+ -+ -+exit: -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ -+ return err; -+} -+ -+/*! -+ * V4L2 - mxc_v4l2_s_std function -+ * -+ * Sets the TV standard to be used. -+ * -+ * @param cam structure cam_data * -+ * @param parm structure v4l2_streamparm * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e) -+{ -+ pr_debug("In mxc_v4l2_s_std %Lx\n", e); -+ -+ if (e == V4L2_STD_PAL) { -+ pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL); -+ cam->standard.id = V4L2_STD_PAL; -+ video_index = TV_PAL; -+ } else if (e == V4L2_STD_NTSC) { -+ pr_debug(" Setting standard to NTSC %Lx\n", -+ V4L2_STD_NTSC); -+ /* Get rid of the white dot line in NTSC signal input */ -+ cam->standard.id = V4L2_STD_NTSC; -+ video_index = TV_NTSC; -+ } else { -+ cam->standard.id = V4L2_STD_ALL; -+ video_index = TV_NOT_LOCKED; -+ pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n", -+ e, V4L2_STD_PAL, V4L2_STD_NTSC); -+ } -+ -+ cam->standard.index = video_index; -+ strcpy(cam->standard.name, video_fmts[video_index].name); -+ cam->crop_bounds.width = video_fmts[video_index].raw_width; -+ cam->crop_bounds.height = video_fmts[video_index].raw_height; -+ cam->crop_current.width = video_fmts[video_index].active_width; -+ cam->crop_current.height = video_fmts[video_index].active_height; -+ cam->crop_current.top = video_fmts[video_index].active_top; -+ cam->crop_current.left = video_fmts[video_index].active_left; -+ -+ return 0; -+} -+ -+/*! -+ * V4L2 - mxc_v4l2_g_std function -+ * -+ * Gets the TV standard from the TV input device. -+ * -+ * @param cam structure cam_data * -+ * -+ * @param e structure v4l2_streamparm * -+ * -+ * @return status 0 success, EINVAL failed -+ */ -+static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e) -+{ -+ struct v4l2_format tv_fmt; -+ -+ pr_debug("In mxc_v4l2_g_std\n"); -+ -+ if (cam->device_type == 1) { -+ /* Use this function to get what the TV-In device detects the -+ * format to be. pixelformat is used to return the std value -+ * since the interface has no vidioc_g_std.*/ -+ tv_fmt.type = V4L2_BUF_TYPE_PRIVATE; -+ vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt); -+ -+ /* If the TV-in automatically detects the standard, then if it -+ * changes, the settings need to change. */ -+ if (cam->standard_autodetect) { -+ if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) { -+ pr_debug("MVC: mxc_v4l2_g_std: " -+ "Changing standard\n"); -+ mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat); -+ } -+ } -+ -+ *e = tv_fmt.fmt.pix.pixelformat; -+ } -+ -+ return 0; -+} -+ -+/*! -+ * Dequeue one V4L capture buffer -+ * -+ * @param cam structure cam_data * -+ * @param buf structure v4l2_buffer * -+ * -+ * @return status 0 success, EINVAL invalid frame number, -+ * ETIME timeout, ERESTARTSYS interrupted by user -+ */ -+static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) -+{ -+ int retval = 0; -+ struct mxc_v4l_frame *frame; -+ unsigned long lock_flags; -+ -+ pr_debug("In MVC:mxc_v4l_dqueue\n"); -+ -+ if (!wait_event_interruptible_timeout(cam->enc_queue, -+ cam->enc_counter != 0, 10 * HZ)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " -+ "enc_counter %x\n", -+ cam->enc_counter); -+ return -ETIME; -+ } else if (signal_pending(current)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " -+ "interrupt received\n"); -+ return -ERESTARTSYS; -+ } -+ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EBUSY; -+ -+ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); -+ cam->enc_counter--; -+ -+ frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); -+ list_del(cam->done_q.next); -+ if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { -+ frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; -+ } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " -+ "Buffer not filled.\n"); -+ frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; -+ retval = -EINVAL; -+ } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " -+ "Buffer not queued.\n"); -+ retval = -EINVAL; -+ } -+ -+ cam->frame[frame->index].buffer.field = cam->device_type ? -+ V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; -+ -+ buf->bytesused = cam->v2f.fmt.pix.sizeimage; -+ buf->index = frame->index; -+ buf->flags = frame->buffer.flags; -+ buf->m = cam->frame[frame->index].buffer.m; -+ buf->timestamp = cam->frame[frame->index].buffer.timestamp; -+ buf->field = cam->frame[frame->index].buffer.field; -+ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); -+ -+ up(&cam->busy_lock); -+ return retval; -+} -+ -+/*! -+ * V4L interface - open function -+ * -+ * @param file structure file * -+ * -+ * @return status 0 success, ENODEV invalid device instance, -+ * ENODEV timeout, ERESTARTSYS interrupted by user -+ */ -+static int mxc_v4l_open(struct file *file) -+{ -+ struct v4l2_ifparm ifparm; -+ struct v4l2_format cam_fmt; -+ ipu_csi_signal_cfg_t csi_param; -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ int err = 0; -+ struct sensor_data *sensor; -+ -+ pr_debug("\nIn MVC: mxc_v4l_open\n"); -+ pr_debug(" device name is %s\n", dev->name); -+ -+ if (!cam) { -+ pr_err("ERROR: v4l2 capture: Internal error, " -+ "cam_data not found!\n"); -+ return -EBADF; -+ } -+ -+ if (cam->sensor == NULL || -+ cam->sensor->type != v4l2_int_type_slave) { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ return -EAGAIN; -+ } -+ -+ sensor = cam->sensor->priv; -+ if (!sensor) { -+ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ down(&cam->busy_lock); -+ err = 0; -+ if (signal_pending(current)) -+ goto oops; -+ -+ if (cam->open_count++ == 0) { -+ wait_event_interruptible(cam->power_queue, -+ cam->low_power == false); -+ -+ if (strcmp(mxc_capture_inputs[cam->current_input].name, -+ "CSI MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) -+ err = csi_enc_select(cam); -+#endif -+ } else if (strcmp(mxc_capture_inputs[cam->current_input].name, -+ "CSI IC MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) -+ err = prp_enc_select(cam); -+#endif -+ } -+ -+ cam->enc_counter = 0; -+ INIT_LIST_HEAD(&cam->ready_q); -+ INIT_LIST_HEAD(&cam->working_q); -+ INIT_LIST_HEAD(&cam->done_q); -+ -+ vidioc_int_g_ifparm(cam->sensor, &ifparm); -+ -+ csi_param.sens_clksrc = 0; -+ -+ csi_param.clk_mode = 0; -+ csi_param.data_pol = 0; -+ csi_param.ext_vsync = 0; -+ -+ csi_param.pack_tight = 0; -+ csi_param.force_eof = 0; -+ csi_param.data_en_pol = 0; -+ -+ csi_param.mclk = ifparm.u.bt656.clock_curr; -+ -+ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv; -+ -+ if (ifparm.u.bt656.mode -+ == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; -+ else if (ifparm.u.bt656.mode -+ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_10; -+ else -+ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; -+ -+ -+ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv; -+ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv; -+ -+ csi_param.csi = cam->csi; -+ -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); -+ -+ /* Reset the sizes. Needed to prevent carryover of last -+ * operation.*/ -+ cam->crop_bounds.top = cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = cam_fmt.fmt.pix.width; -+ cam->crop_bounds.height = cam_fmt.fmt.pix.height; -+ -+ /* This also is the max crop size for this device. */ -+ cam->crop_defrect.top = cam->crop_defrect.left = 0; -+ cam->crop_defrect.width = cam_fmt.fmt.pix.width; -+ cam->crop_defrect.height = cam_fmt.fmt.pix.height; -+ -+ /* At this point, this is also the current image size. */ -+ cam->crop_current.top = cam->crop_current.left = 0; -+ cam->crop_current.width = cam_fmt.fmt.pix.width; -+ cam->crop_current.height = cam_fmt.fmt.pix.height; -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, -+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", -+ __func__, -+ cam->crop_bounds.width, cam->crop_bounds.height); -+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", -+ __func__, -+ cam->crop_defrect.width, cam->crop_defrect.height); -+ pr_debug("End of %s: crop_current widthxheight %d x %d\n", -+ __func__, -+ cam->crop_current.width, cam->crop_current.height); -+ -+ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat; -+ pr_debug("On Open: Input to ipu size is %d x %d\n", -+ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); -+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, -+ cam->crop_current.height, -+ cam->csi); -+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, -+ cam->crop_current.top, -+ cam->csi); -+ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width, -+ cam->crop_bounds.height, -+ cam_fmt.fmt.pix.pixelformat, -+ csi_param); -+ clk_prepare_enable(sensor->sensor_clk); -+ vidioc_int_s_power(cam->sensor, 1); -+ vidioc_int_init(cam->sensor); -+ vidioc_int_dev_init(cam->sensor); -+ } -+ -+ file->private_data = dev; -+ -+oops: -+ up(&cam->busy_lock); -+ return err; -+} -+ -+/*! -+ * V4L interface - close function -+ * -+ * @param file struct file * -+ * -+ * @return 0 success -+ */ -+static int mxc_v4l_close(struct file *file) -+{ -+ struct video_device *dev = video_devdata(file); -+ int err = 0; -+ cam_data *cam = video_get_drvdata(dev); -+ struct sensor_data *sensor; -+ pr_debug("In MVC:mxc_v4l_close\n"); -+ -+ if (!cam) { -+ pr_err("ERROR: v4l2 capture: Internal error, " -+ "cam_data not found!\n"); -+ return -EBADF; -+ } -+ -+ if (!cam->sensor) { -+ pr_err("%s: Internal error, camera is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ sensor = cam->sensor->priv; -+ if (!sensor) { -+ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); -+ return -EBADF; -+ } -+ -+ down(&cam->busy_lock); -+ -+ /* for the case somebody hit the ctrl C */ -+ if (cam->overlay_pid == current->pid && cam->overlay_on) { -+ err = stop_preview(cam); -+ cam->overlay_on = false; -+ } -+ if (cam->capture_pid == current->pid) { -+ err |= mxc_streamoff(cam); -+ wake_up_interruptible(&cam->enc_queue); -+ } -+ -+ if (--cam->open_count == 0) { -+ vidioc_int_s_power(cam->sensor, 0); -+ clk_disable_unprepare(sensor->sensor_clk); -+ wait_event_interruptible(cam->power_queue, -+ cam->low_power == false); -+ pr_debug("mxc_v4l_close: release resource\n"); -+ -+ if (strcmp(mxc_capture_inputs[cam->current_input].name, -+ "CSI MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) -+ err |= csi_enc_deselect(cam); -+#endif -+ } else if (strcmp(mxc_capture_inputs[cam->current_input].name, -+ "CSI IC MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) -+ err |= prp_enc_deselect(cam); -+#endif -+ } -+ -+ mxc_free_frame_buf(cam); -+ file->private_data = NULL; -+ -+ /* capture off */ -+ wake_up_interruptible(&cam->enc_queue); -+ mxc_free_frames(cam); -+ cam->enc_counter++; -+ } -+ -+ up(&cam->busy_lock); -+ -+ return err; -+} -+ -+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \ -+ defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \ -+ defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) -+/* -+ * V4L interface - read function -+ * -+ * @param file struct file * -+ * @param read buf char * -+ * @param count size_t -+ * @param ppos structure loff_t * -+ * -+ * @return bytes read -+ */ -+static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count, -+ loff_t *ppos) -+{ -+ int err = 0; -+ u8 *v_address[2]; -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EINTR; -+ -+ /* Stop the viewfinder */ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ -+ v_address[0] = dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->still_buf[0], -+ GFP_DMA | GFP_KERNEL); -+ -+ v_address[1] = dma_alloc_coherent(0, -+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), -+ &cam->still_buf[1], -+ GFP_DMA | GFP_KERNEL); -+ -+ if (!v_address[0] || !v_address[1]) { -+ err = -ENOBUFS; -+ goto exit0; -+ } -+ -+ err = prp_still_select(cam); -+ if (err != 0) { -+ err = -EIO; -+ goto exit0; -+ } -+ -+ cam->still_counter = 0; -+ err = cam->csi_start(cam); -+ if (err != 0) { -+ err = -EIO; -+ goto exit1; -+ } -+ -+ if (!wait_event_interruptible_timeout(cam->still_queue, -+ cam->still_counter != 0, -+ 10 * HZ)) { -+ pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n", -+ cam->still_counter); -+ err = -ETIME; -+ goto exit1; -+ } -+ err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage); -+ -+exit1: -+ prp_still_deselect(cam); -+ -+exit0: -+ if (v_address[0] != 0) -+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0], -+ cam->still_buf[0]); -+ if (v_address[1] != 0) -+ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1], -+ cam->still_buf[1]); -+ -+ cam->still_buf[0] = cam->still_buf[1] = 0; -+ -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ -+ up(&cam->busy_lock); -+ if (err < 0) -+ return err; -+ -+ return cam->v2f.fmt.pix.sizeimage - err; -+} -+#endif -+ -+/*! -+ * V4L interface - ioctl function -+ * -+ * @param file struct file* -+ * -+ * @param ioctlnr unsigned int -+ * -+ * @param arg void* -+ * -+ * @return 0 success, ENODEV for invalid device instance, -+ * -1 for other errors. -+ */ -+static long mxc_v4l_do_ioctl(struct file *file, -+ unsigned int ioctlnr, void *arg) -+{ -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ int retval = 0; -+ unsigned long lock_flags; -+ -+ pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr); -+ wait_event_interruptible(cam->power_queue, cam->low_power == false); -+ /* make this _really_ smp-safe */ -+ if (ioctlnr != VIDIOC_DQBUF) -+ if (down_interruptible(&cam->busy_lock)) -+ return -EBUSY; -+ -+ switch (ioctlnr) { -+ /*! -+ * V4l2 VIDIOC_QUERYCAP ioctl -+ */ -+ case VIDIOC_QUERYCAP: { -+ struct v4l2_capability *cap = arg; -+ pr_debug(" case VIDIOC_QUERYCAP\n"); -+ strcpy(cap->driver, "mxc_v4l2"); -+ cap->version = KERNEL_VERSION(0, 1, 11); -+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | -+ V4L2_CAP_VIDEO_OVERLAY | -+ V4L2_CAP_STREAMING | -+ V4L2_CAP_READWRITE; -+ cap->card[0] = '\0'; -+ cap->bus_info[0] = '\0'; -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_G_FMT ioctl -+ */ -+ case VIDIOC_G_FMT: { -+ struct v4l2_format *gf = arg; -+ pr_debug(" case VIDIOC_G_FMT\n"); -+ retval = mxc_v4l2_g_fmt(cam, gf); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_FMT ioctl -+ */ -+ case VIDIOC_S_FMT: { -+ struct v4l2_format *sf = arg; -+ pr_debug(" case VIDIOC_S_FMT\n"); -+ retval = mxc_v4l2_s_fmt(cam, sf); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_REQBUFS ioctl -+ */ -+ case VIDIOC_REQBUFS: { -+ struct v4l2_requestbuffers *req = arg; -+ pr_debug(" case VIDIOC_REQBUFS\n"); -+ -+ if (req->count > FRAME_NUM) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " -+ "not enough buffers\n"); -+ req->count = FRAME_NUM; -+ } -+ -+ if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " -+ "wrong buffer type\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ mxc_streamoff(cam); -+ if (req->memory & V4L2_MEMORY_MMAP) { -+ mxc_free_frame_buf(cam); -+ retval = mxc_allocate_frame_buf(cam, req->count); -+ } -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_QUERYBUF ioctl -+ */ -+ case VIDIOC_QUERYBUF: { -+ struct v4l2_buffer *buf = arg; -+ int index = buf->index; -+ pr_debug(" case VIDIOC_QUERYBUF\n"); -+ -+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { -+ pr_err("ERROR: v4l2 capture: " -+ "VIDIOC_QUERYBUFS: " -+ "wrong buffer type\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ if (buf->memory & V4L2_MEMORY_MMAP) { -+ memset(buf, 0, sizeof(buf)); -+ buf->index = index; -+ } -+ -+ down(&cam->param_lock); -+ if (buf->memory & V4L2_MEMORY_USERPTR) { -+ mxc_v4l2_release_bufs(cam); -+ retval = mxc_v4l2_prepare_bufs(cam, buf); -+ } -+ -+ if (buf->memory & V4L2_MEMORY_MMAP) -+ retval = mxc_v4l2_buffer_status(cam, buf); -+ up(&cam->param_lock); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_QBUF ioctl -+ */ -+ case VIDIOC_QBUF: { -+ struct v4l2_buffer *buf = arg; -+ int index = buf->index; -+ pr_debug(" case VIDIOC_QBUF\n"); -+ -+ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); -+ if ((cam->frame[index].buffer.flags & 0x7) == -+ V4L2_BUF_FLAG_MAPPED) { -+ cam->frame[index].buffer.flags |= -+ V4L2_BUF_FLAG_QUEUED; -+ list_add_tail(&cam->frame[index].queue, -+ &cam->ready_q); -+ } else if (cam->frame[index].buffer. -+ flags & V4L2_BUF_FLAG_QUEUED) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " -+ "buffer already queued\n"); -+ retval = -EINVAL; -+ } else if (cam->frame[index].buffer. -+ flags & V4L2_BUF_FLAG_DONE) { -+ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " -+ "overwrite done buffer.\n"); -+ cam->frame[index].buffer.flags &= -+ ~V4L2_BUF_FLAG_DONE; -+ cam->frame[index].buffer.flags |= -+ V4L2_BUF_FLAG_QUEUED; -+ retval = -EINVAL; -+ } -+ -+ buf->flags = cam->frame[index].buffer.flags; -+ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_DQBUF ioctl -+ */ -+ case VIDIOC_DQBUF: { -+ struct v4l2_buffer *buf = arg; -+ pr_debug(" case VIDIOC_DQBUF\n"); -+ -+ if ((cam->enc_counter == 0) && -+ (file->f_flags & O_NONBLOCK)) { -+ retval = -EAGAIN; -+ break; -+ } -+ -+ retval = mxc_v4l_dqueue(cam, buf); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_STREAMON ioctl -+ */ -+ case VIDIOC_STREAMON: { -+ pr_debug(" case VIDIOC_STREAMON\n"); -+ retval = mxc_streamon(cam); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_STREAMOFF ioctl -+ */ -+ case VIDIOC_STREAMOFF: { -+ pr_debug(" case VIDIOC_STREAMOFF\n"); -+ retval = mxc_streamoff(cam); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_G_CTRL ioctl -+ */ -+ case VIDIOC_G_CTRL: { -+ pr_debug(" case VIDIOC_G_CTRL\n"); -+ retval = mxc_v4l2_g_ctrl(cam, arg); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_CTRL ioctl -+ */ -+ case VIDIOC_S_CTRL: { -+ pr_debug(" case VIDIOC_S_CTRL\n"); -+ retval = mxc_v4l2_s_ctrl(cam, arg); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_CROPCAP ioctl -+ */ -+ case VIDIOC_CROPCAP: { -+ struct v4l2_cropcap *cap = arg; -+ pr_debug(" case VIDIOC_CROPCAP\n"); -+ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && -+ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { -+ retval = -EINVAL; -+ break; -+ } -+ cap->bounds = cam->crop_bounds; -+ cap->defrect = cam->crop_defrect; -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_G_CROP ioctl -+ */ -+ case VIDIOC_G_CROP: { -+ struct v4l2_crop *crop = arg; -+ pr_debug(" case VIDIOC_G_CROP\n"); -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && -+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { -+ retval = -EINVAL; -+ break; -+ } -+ crop->c = cam->crop_current; -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_CROP ioctl -+ */ -+ case VIDIOC_S_CROP: { -+ struct v4l2_crop *crop = arg; -+ struct v4l2_rect *b = &cam->crop_bounds; -+ pr_debug(" case VIDIOC_S_CROP\n"); -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && -+ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { -+ retval = -EINVAL; -+ break; -+ } -+ -+ crop->c.top = (crop->c.top < b->top) ? b->top -+ : crop->c.top; -+ if (crop->c.top > b->top + b->height) -+ crop->c.top = b->top + b->height - 1; -+ if (crop->c.height > b->top + b->height - crop->c.top) -+ crop->c.height = -+ b->top + b->height - crop->c.top; -+ -+ crop->c.left = (crop->c.left < b->left) ? b->left -+ : crop->c.left; -+ if (crop->c.left > b->left + b->width) -+ crop->c.left = b->left + b->width - 1; -+ if (crop->c.width > b->left - crop->c.left + b->width) -+ crop->c.width = -+ b->left - crop->c.left + b->width; -+ -+ crop->c.width -= crop->c.width % 8; -+ crop->c.left -= crop->c.left % 4; -+ cam->crop_current = crop->c; -+ -+ pr_debug(" Cropping Input to ipu size %d x %d\n", -+ cam->crop_current.width, -+ cam->crop_current.height); -+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, -+ cam->crop_current.height, -+ cam->csi); -+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, -+ cam->crop_current.top, -+ cam->csi); -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_OVERLAY ioctl -+ */ -+ case VIDIOC_OVERLAY: { -+ int *on = arg; -+ pr_debug(" VIDIOC_OVERLAY on=%d\n", *on); -+ if (*on) { -+ cam->overlay_on = true; -+ cam->overlay_pid = current->pid; -+ retval = start_preview(cam); -+ } -+ if (!*on) { -+ retval = stop_preview(cam); -+ cam->overlay_on = false; -+ } -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_G_FBUF ioctl -+ */ -+ case VIDIOC_G_FBUF: { -+ struct v4l2_framebuffer *fb = arg; -+ pr_debug(" case VIDIOC_G_FBUF\n"); -+ *fb = cam->v4l2_fb; -+ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; -+ break; -+ } -+ -+ /*! -+ * V4l2 VIDIOC_S_FBUF ioctl -+ */ -+ case VIDIOC_S_FBUF: { -+ struct v4l2_framebuffer *fb = arg; -+ pr_debug(" case VIDIOC_S_FBUF\n"); -+ cam->v4l2_fb = *fb; -+ break; -+ } -+ -+ case VIDIOC_G_PARM: { -+ struct v4l2_streamparm *parm = arg; -+ pr_debug(" case VIDIOC_G_PARM\n"); -+ if (cam->sensor) -+ retval = vidioc_int_g_parm(cam->sensor, parm); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ -+ case VIDIOC_S_PARM: { -+ struct v4l2_streamparm *parm = arg; -+ pr_debug(" case VIDIOC_S_PARM\n"); -+ if (cam->sensor) -+ retval = mxc_v4l2_s_param(cam, parm); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ -+ /* linux v4l2 bug, kernel c0485619 user c0405619 */ -+ case VIDIOC_ENUMSTD: { -+ struct v4l2_standard *e = arg; -+ pr_debug(" case VIDIOC_ENUMSTD\n"); -+ *e = cam->standard; -+ break; -+ } -+ -+ case VIDIOC_G_STD: { -+ v4l2_std_id *e = arg; -+ pr_debug(" case VIDIOC_G_STD\n"); -+ if (cam->sensor) -+ retval = mxc_v4l2_g_std(cam, e); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ -+ case VIDIOC_S_STD: { -+ v4l2_std_id *e = arg; -+ pr_debug(" case VIDIOC_S_STD\n"); -+ retval = mxc_v4l2_s_std(cam, *e); -+ -+ break; -+ } -+ -+ case VIDIOC_ENUMOUTPUT: { -+ struct v4l2_output *output = arg; -+ pr_debug(" case VIDIOC_ENUMOUTPUT\n"); -+ if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) { -+ retval = -EINVAL; -+ break; -+ } -+ *output = mxc_capture_outputs[output->index]; -+ -+ break; -+ } -+ case VIDIOC_G_OUTPUT: { -+ int *p_output_num = arg; -+ pr_debug(" case VIDIOC_G_OUTPUT\n"); -+ *p_output_num = cam->output; -+ break; -+ } -+ -+ case VIDIOC_S_OUTPUT: { -+ int *p_output_num = arg; -+ pr_debug(" case VIDIOC_S_OUTPUT\n"); -+ if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) { -+ retval = -EINVAL; -+ break; -+ } -+ cam->output = *p_output_num; -+ break; -+ } -+ -+ case VIDIOC_ENUMINPUT: { -+ struct v4l2_input *input = arg; -+ pr_debug(" case VIDIOC_ENUMINPUT\n"); -+ if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) { -+ retval = -EINVAL; -+ break; -+ } -+ *input = mxc_capture_inputs[input->index]; -+ break; -+ } -+ -+ case VIDIOC_G_INPUT: { -+ int *index = arg; -+ pr_debug(" case VIDIOC_G_INPUT\n"); -+ *index = cam->current_input; -+ break; -+ } -+ -+ case VIDIOC_S_INPUT: { -+ int *index = arg; -+ pr_debug(" case VIDIOC_S_INPUT\n"); -+ if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) { -+ retval = -EINVAL; -+ break; -+ } -+ -+ if (*index == cam->current_input) -+ break; -+ -+ if ((mxc_capture_inputs[cam->current_input].status & -+ V4L2_IN_ST_NO_POWER) == 0) { -+ retval = mxc_streamoff(cam); -+ if (retval) -+ break; -+ mxc_capture_inputs[cam->current_input].status |= -+ V4L2_IN_ST_NO_POWER; -+ } -+ -+ if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) -+ retval = csi_enc_select(cam); -+ if (retval) -+ break; -+#endif -+ } else if (strcmp(mxc_capture_inputs[*index].name, -+ "CSI IC MEM") == 0) { -+#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) -+ retval = prp_enc_select(cam); -+ if (retval) -+ break; -+#endif -+ } -+ -+ mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER; -+ cam->current_input = *index; -+ break; -+ } -+ case VIDIOC_ENUM_FMT: { -+ struct v4l2_fmtdesc *f = arg; -+ if (cam->sensor) -+ retval = vidioc_int_enum_fmt_cap(cam->sensor, f); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_ENUM_FRAMESIZES: { -+ struct v4l2_frmsizeenum *fsize = arg; -+ if (cam->sensor) -+ retval = vidioc_int_enum_framesizes(cam->sensor, fsize); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_DBG_G_CHIP_IDENT: { -+ struct v4l2_dbg_chip_ident *p = arg; -+ p->ident = V4L2_IDENT_NONE; -+ p->revision = 0; -+ if (cam->sensor) -+ retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); -+ else { -+ pr_err("ERROR: v4l2 capture: slave not found!\n"); -+ retval = -ENODEV; -+ } -+ break; -+ } -+ case VIDIOC_TRY_FMT: -+ case VIDIOC_QUERYCTRL: -+ case VIDIOC_G_TUNER: -+ case VIDIOC_S_TUNER: -+ case VIDIOC_G_FREQUENCY: -+ case VIDIOC_S_FREQUENCY: -+ default: -+ pr_debug(" case default or not supported\n"); -+ retval = -EINVAL; -+ break; -+ } -+ -+ if (ioctlnr != VIDIOC_DQBUF) -+ up(&cam->busy_lock); -+ return retval; -+} -+ -+/* -+ * V4L interface - ioctl function -+ * -+ * @return None -+ */ -+static long mxc_v4l_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ pr_debug("In MVC:mxc_v4l_ioctl\n"); -+ return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl); -+} -+ -+/*! -+ * V4L interface - mmap function -+ * -+ * @param file structure file * -+ * -+ * @param vma structure vm_area_struct * -+ * -+ * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error -+ */ -+static int mxc_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct video_device *dev = video_devdata(file); -+ unsigned long size; -+ int res = 0; -+ cam_data *cam = video_get_drvdata(dev); -+ -+ pr_debug("In MVC:mxc_mmap\n"); -+ pr_debug(" pgoff=0x%lx, start=0x%lx, end=0x%lx\n", -+ vma->vm_pgoff, vma->vm_start, vma->vm_end); -+ -+ /* make this _really_ smp-safe */ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EINTR; -+ -+ size = vma->vm_end - vma->vm_start; -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -+ -+ if (remap_pfn_range(vma, vma->vm_start, -+ vma->vm_pgoff, size, vma->vm_page_prot)) { -+ pr_err("ERROR: v4l2 capture: mxc_mmap: " -+ "remap_pfn_range failed\n"); -+ res = -ENOBUFS; -+ goto mxc_mmap_exit; -+ } -+ -+ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ -+ -+mxc_mmap_exit: -+ up(&cam->busy_lock); -+ return res; -+} -+ -+/*! -+ * V4L interface - poll function -+ * -+ * @param file structure file * -+ * -+ * @param wait structure poll_table_struct * -+ * -+ * @return status POLLIN | POLLRDNORM -+ */ -+static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait) -+{ -+ struct video_device *dev = video_devdata(file); -+ cam_data *cam = video_get_drvdata(dev); -+ wait_queue_head_t *queue = NULL; -+ int res = POLLIN | POLLRDNORM; -+ -+ pr_debug("In MVC:mxc_poll\n"); -+ -+ if (down_interruptible(&cam->busy_lock)) -+ return -EINTR; -+ -+ queue = &cam->enc_queue; -+ poll_wait(file, queue, wait); -+ -+ up(&cam->busy_lock); -+ -+ return res; -+} -+ -+/*! -+ * This structure defines the functions to be called in this driver. -+ */ -+static struct v4l2_file_operations mxc_v4l_fops = { -+ .owner = THIS_MODULE, -+ .open = mxc_v4l_open, -+ .release = mxc_v4l_close, -+ .read = mxc_v4l_read, -+ .ioctl = mxc_v4l_ioctl, -+ .mmap = mxc_mmap, -+ .poll = mxc_poll, -+}; -+ -+static struct video_device mxc_v4l_template = { -+ .name = "Mxc Camera", -+ .fops = &mxc_v4l_fops, -+ .release = video_device_release, -+}; -+ -+/*! -+ * This function can be used to release any platform data on closing. -+ */ -+static void camera_platform_release(struct device *device) -+{ -+} -+ -+/*! -+ * Camera V4l2 callback function. -+ * -+ * @param mask u32 -+ * -+ * @param dev void device structure -+ * -+ * @return status -+ */ -+static void camera_callback(u32 mask, void *dev) -+{ -+ struct mxc_v4l_frame *done_frame; -+ struct mxc_v4l_frame *ready_frame; -+ struct timeval cur_time; -+ -+ cam_data *cam = (cam_data *) dev; -+ if (cam == NULL) -+ return; -+ -+ pr_debug("In MVC:camera_callback\n"); -+ -+ spin_lock(&cam->queue_int_lock); -+ spin_lock(&cam->dqueue_int_lock); -+ if (!list_empty(&cam->working_q)) { -+ do_gettimeofday(&cur_time); -+ -+ done_frame = list_entry(cam->working_q.next, -+ struct mxc_v4l_frame, -+ queue); -+ -+ if (done_frame->ipu_buf_num != cam->local_buf_num) -+ goto next; -+ -+ /* -+ * Set the current time to done frame buffer's -+ * timestamp. Users can use this information to judge -+ * the frame's usage. -+ */ -+ done_frame->buffer.timestamp = cur_time; -+ -+ if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { -+ done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; -+ done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; -+ -+ /* Added to the done queue */ -+ list_del(cam->working_q.next); -+ list_add_tail(&done_frame->queue, &cam->done_q); -+ -+ /* Wake up the queue */ -+ cam->enc_counter++; -+ wake_up_interruptible(&cam->enc_queue); -+ } else -+ pr_err("ERROR: v4l2 capture: camera_callback: " -+ "buffer not queued\n"); -+ } -+ -+next: -+ if (!list_empty(&cam->ready_q)) { -+ ready_frame = list_entry(cam->ready_q.next, -+ struct mxc_v4l_frame, -+ queue); -+ if (cam->enc_update_eba) -+ if (cam->enc_update_eba(cam->ipu, -+ ready_frame->buffer.m.offset, -+ &cam->ping_pong_csi) == 0) { -+ list_del(cam->ready_q.next); -+ list_add_tail(&ready_frame->queue, -+ &cam->working_q); -+ ready_frame->ipu_buf_num = cam->local_buf_num; -+ } -+ } else { -+ if (cam->enc_update_eba) -+ cam->enc_update_eba( -+ cam->ipu, cam->dummy_frame.buffer.m.offset, -+ &cam->ping_pong_csi); -+ } -+ -+ cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0; -+ spin_unlock(&cam->dqueue_int_lock); -+ spin_unlock(&cam->queue_int_lock); -+ -+ return; -+} -+ -+/*! -+ * initialize cam_data structure -+ * -+ * @param cam structure cam_data * -+ * -+ * @return status 0 Success -+ */ -+static int init_camera_struct(cam_data *cam, struct platform_device *pdev) -+{ -+ const struct of_device_id *of_id = -+ of_match_device(mxc_v4l2_dt_ids, &pdev->dev); -+ struct device_node *np = pdev->dev.of_node; -+ int ipu_id, csi_id, mclk_source; -+ int ret = 0; -+ -+ pr_debug("In MVC: init_camera_struct\n"); -+ -+ ret = of_property_read_u32(np, "ipu_id", &ipu_id); -+ if (ret) { -+ dev_err(&pdev->dev, "ipu_id missing or invalid\n"); -+ return ret; -+ } -+ -+ ret = of_property_read_u32(np, "csi_id", &csi_id); -+ if (ret) { -+ dev_err(&pdev->dev, "csi_id missing or invalid\n"); -+ return ret; -+ } -+ -+ ret = of_property_read_u32(np, "mclk_source", &mclk_source); -+ if (ret) { -+ dev_err(&pdev->dev, "sensor mclk missing or invalid\n"); -+ return ret; -+ } -+ -+ /* Default everything to 0 */ -+ memset(cam, 0, sizeof(cam_data)); -+ -+ /* get devtype to distinguish if the cpu is imx5 or imx6 -+ * IMX5_V4L2 specify the cpu is imx5 -+ * IMX6_V4L2 specify the cpu is imx6q or imx6sdl -+ */ -+ if (of_id) -+ pdev->id_entry = of_id->data; -+ cam->devtype = pdev->id_entry->driver_data; -+ -+ cam->ipu = ipu_get_soc(ipu_id); -+ if (cam->ipu == NULL) { -+ pr_err("ERROR: v4l2 capture: failed to get ipu\n"); -+ return -EINVAL; -+ } else if (cam->ipu == ERR_PTR(-ENODEV)) { -+ pr_err("ERROR: v4l2 capture: get invalid ipu\n"); -+ return -ENODEV; -+ } -+ -+ init_MUTEX(&cam->param_lock); -+ init_MUTEX(&cam->busy_lock); -+ -+ cam->video_dev = video_device_alloc(); -+ if (cam->video_dev == NULL) -+ return -ENODEV; -+ -+ *(cam->video_dev) = mxc_v4l_template; -+ -+ video_set_drvdata(cam->video_dev, cam); -+ dev_set_drvdata(&pdev->dev, (void *)cam); -+ cam->video_dev->minor = -1; -+ -+ init_waitqueue_head(&cam->enc_queue); -+ init_waitqueue_head(&cam->still_queue); -+ -+ /* setup cropping */ -+ cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = 640; -+ cam->crop_bounds.top = 0; -+ cam->crop_bounds.height = 480; -+ cam->crop_current = cam->crop_defrect = cam->crop_bounds; -+ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, -+ cam->crop_current.height, cam->csi); -+ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, -+ cam->crop_current.top, cam->csi); -+ cam->streamparm.parm.capture.capturemode = 0; -+ -+ cam->standard.index = 0; -+ cam->standard.id = V4L2_STD_UNKNOWN; -+ cam->standard.frameperiod.denominator = 30; -+ cam->standard.frameperiod.numerator = 1; -+ cam->standard.framelines = 480; -+ cam->standard_autodetect = true; -+ cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; -+ cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; -+ cam->overlay_on = false; -+ cam->capture_on = false; -+ cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; -+ -+ cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2; -+ cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2; -+ cam->v2f.fmt.pix.width = 288; -+ cam->v2f.fmt.pix.height = 352; -+ cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; -+ cam->win.w.width = 160; -+ cam->win.w.height = 160; -+ cam->win.w.left = 0; -+ cam->win.w.top = 0; -+ -+ cam->ipu_id = ipu_id; -+ cam->csi = csi_id; -+ cam->mclk_source = mclk_source; -+ cam->mclk_on[cam->mclk_source] = false; -+ -+ cam->enc_callback = camera_callback; -+ init_waitqueue_head(&cam->power_queue); -+ spin_lock_init(&cam->queue_int_lock); -+ spin_lock_init(&cam->dqueue_int_lock); -+ -+ cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL); -+ cam->self->module = THIS_MODULE; -+ sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi); -+ cam->self->type = v4l2_int_type_master; -+ cam->self->u.master = &mxc_v4l2_master; -+ -+ return 0; -+} -+ -+static ssize_t show_streaming(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct video_device *video_dev = container_of(dev, -+ struct video_device, dev); -+ cam_data *cam = video_get_drvdata(video_dev); -+ -+ if (cam->capture_on) -+ return sprintf(buf, "stream on\n"); -+ else -+ return sprintf(buf, "stream off\n"); -+} -+static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL); -+ -+static ssize_t show_overlay(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct video_device *video_dev = container_of(dev, -+ struct video_device, dev); -+ cam_data *cam = video_get_drvdata(video_dev); -+ -+ if (cam->overlay_on) -+ return sprintf(buf, "overlay on\n"); -+ else -+ return sprintf(buf, "overlay off\n"); -+} -+static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL); -+ -+static ssize_t show_csi(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct video_device *video_dev = container_of(dev, -+ struct video_device, dev); -+ cam_data *cam = video_get_drvdata(video_dev); -+ -+ return sprintf(buf, "ipu%d_csi%d\n", cam->ipu_id, cam->csi); -+} -+static DEVICE_ATTR(fsl_csi_property, S_IRUGO, show_csi, NULL); -+ -+/*! -+ * This function is called to probe the devices if registered. -+ * -+ * @param pdev the device structure used to give information on which device -+ * to probe -+ * -+ * @return The function returns 0 on success and -1 on failure. -+ */ -+static int mxc_v4l2_probe(struct platform_device *pdev) -+{ -+ /* Create cam and initialize it. */ -+ cam_data *cam = kmalloc(sizeof(cam_data), GFP_KERNEL); -+ if (cam == NULL) { -+ pr_err("ERROR: v4l2 capture: failed to register camera\n"); -+ return -1; -+ } -+ -+ init_camera_struct(cam, pdev); -+ pdev->dev.release = camera_platform_release; -+ -+ /* Set up the v4l2 device and register it*/ -+ cam->self->priv = cam; -+ v4l2_int_device_register(cam->self); -+ -+ /* register v4l video device */ -+ if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr) -+ == -1) { -+ kfree(cam); -+ cam = NULL; -+ pr_err("ERROR: v4l2 capture: video_register_device failed\n"); -+ return -1; -+ } -+ pr_debug(" Video device registered: %s #%d\n", -+ cam->video_dev->name, cam->video_dev->minor); -+ -+ if (device_create_file(&cam->video_dev->dev, -+ &dev_attr_fsl_v4l2_capture_property)) -+ dev_err(&pdev->dev, "Error on creating sysfs file" -+ " for capture\n"); -+ -+ if (device_create_file(&cam->video_dev->dev, -+ &dev_attr_fsl_v4l2_overlay_property)) -+ dev_err(&pdev->dev, "Error on creating sysfs file" -+ " for overlay\n"); -+ -+ if (device_create_file(&cam->video_dev->dev, -+ &dev_attr_fsl_csi_property)) -+ dev_err(&pdev->dev, "Error on creating sysfs file" -+ " for csi number\n"); -+ -+ return 0; -+} -+ -+/*! -+ * This function is called to remove the devices when device unregistered. -+ * -+ * @param pdev the device structure used to give information on which device -+ * to remove -+ * -+ * @return The function returns 0 on success and -1 on failure. -+ */ -+static int mxc_v4l2_remove(struct platform_device *pdev) -+{ -+ cam_data *cam = (cam_data *)platform_get_drvdata(pdev); -+ if (cam->open_count) { -+ pr_err("ERROR: v4l2 capture:camera open " -+ "-- setting ops to NULL\n"); -+ return -EBUSY; -+ } else { -+ device_remove_file(&cam->video_dev->dev, -+ &dev_attr_fsl_v4l2_capture_property); -+ device_remove_file(&cam->video_dev->dev, -+ &dev_attr_fsl_v4l2_overlay_property); -+ device_remove_file(&cam->video_dev->dev, -+ &dev_attr_fsl_csi_property); -+ -+ pr_info("V4L2 freeing image input device\n"); -+ v4l2_int_device_unregister(cam->self); -+ video_unregister_device(cam->video_dev); -+ -+ mxc_free_frame_buf(cam); -+ kfree(cam); -+ } -+ -+ pr_info("V4L2 unregistering video\n"); -+ return 0; -+} -+ -+/*! -+ * This function is called to put the sensor in a low power state. -+ * Refer to the document driver-model/driver.txt in the kernel source tree -+ * for more information. -+ * -+ * @param pdev the device structure used to give information on which I2C -+ * to suspend -+ * @param state the power state the device is entering -+ * -+ * @return The function returns 0 on success and -1 on failure. -+ */ -+static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state) -+{ -+ cam_data *cam = platform_get_drvdata(pdev); -+ -+ pr_debug("In MVC:mxc_v4l2_suspend\n"); -+ -+ if (cam == NULL) -+ return -1; -+ -+ down(&cam->busy_lock); -+ -+ cam->low_power = true; -+ -+ if (cam->overlay_on == true) -+ stop_preview(cam); -+ if ((cam->capture_on == true) && cam->enc_disable) -+ cam->enc_disable(cam); -+ -+ if (cam->sensor && cam->open_count) { -+ if (cam->mclk_on[cam->mclk_source]) { -+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, -+ cam->mclk_source, -+ false, false); -+ cam->mclk_on[cam->mclk_source] = false; -+ } -+ vidioc_int_s_power(cam->sensor, 0); -+ } -+ -+ up(&cam->busy_lock); -+ -+ return 0; -+} -+ -+/*! -+ * This function is called to bring the sensor back from a low power state. -+ * Refer to the document driver-model/driver.txt in the kernel source tree -+ * for more information. -+ * -+ * @param pdev the device structure -+ * -+ * @return The function returns 0 on success and -1 on failure -+ */ -+static int mxc_v4l2_resume(struct platform_device *pdev) -+{ -+ cam_data *cam = platform_get_drvdata(pdev); -+ -+ pr_debug("In MVC:mxc_v4l2_resume\n"); -+ -+ if (cam == NULL) -+ return -1; -+ -+ down(&cam->busy_lock); -+ -+ cam->low_power = false; -+ wake_up_interruptible(&cam->power_queue); -+ -+ if (cam->sensor && cam->open_count) { -+ vidioc_int_s_power(cam->sensor, 1); -+ -+ if (!cam->mclk_on[cam->mclk_source]) { -+ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, -+ cam->mclk_source, -+ true, true); -+ cam->mclk_on[cam->mclk_source] = true; -+ } -+ } -+ -+ if (cam->overlay_on == true) -+ start_preview(cam); -+ if (cam->capture_on == true) -+ mxc_streamon(cam); -+ -+ up(&cam->busy_lock); -+ -+ return 0; -+} -+ -+/*! -+ * This structure contains pointers to the power management callback functions. -+ */ -+static struct platform_driver mxc_v4l2_driver = { -+ .driver = { -+ .name = "mxc_v4l2_capture", -+ .owner = THIS_MODULE, -+ .of_match_table = mxc_v4l2_dt_ids, -+ }, -+ .id_table = imx_v4l2_devtype, -+ .probe = mxc_v4l2_probe, -+ .remove = mxc_v4l2_remove, -+ .suspend = mxc_v4l2_suspend, -+ .resume = mxc_v4l2_resume, -+ .shutdown = NULL, -+}; -+ -+/*! -+ * Initializes the camera driver. -+ */ -+static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) -+{ -+ cam_data *cam = slave->u.slave->master->priv; -+ struct v4l2_format cam_fmt; -+ int i; -+ struct sensor_data *sdata = slave->priv; -+ -+ pr_debug("In MVC: mxc_v4l2_master_attach\n"); -+ pr_debug(" slave.name = %s\n", slave->name); -+ pr_debug(" master.name = %s\n", slave->u.slave->master->name); -+ -+ if (slave == NULL) { -+ pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); -+ return -1; -+ } -+ -+ if (sdata->csi != cam->csi) { -+ pr_debug("%s: csi doesn't match\n", __func__); -+ return -1; -+ } -+ -+ cam->sensor = slave; -+ -+ if (cam->sensor_index < MXC_SENSOR_NUM) { -+ cam->all_sensors[cam->sensor_index] = slave; -+ cam->sensor_index++; -+ } else { -+ pr_err("ERROR: v4l2 capture: slave number exceeds the maximum.\n"); -+ return -1; -+ } -+ -+ for (i = 0; i < cam->sensor_index; i++) { -+ vidioc_int_dev_exit(cam->all_sensors[i]); -+ vidioc_int_s_power(cam->all_sensors[i], 0); -+ } -+ -+ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -+ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); -+ -+ /* Used to detect TV in (type 1) vs. camera (type 0)*/ -+ cam->device_type = cam_fmt.fmt.pix.priv; -+ -+ /* Set the input size to the ipu for this device */ -+ cam->crop_bounds.top = cam->crop_bounds.left = 0; -+ cam->crop_bounds.width = cam_fmt.fmt.pix.width; -+ cam->crop_bounds.height = cam_fmt.fmt.pix.height; -+ -+ /* This also is the max crop size for this device. */ -+ cam->crop_defrect.top = cam->crop_defrect.left = 0; -+ cam->crop_defrect.width = cam_fmt.fmt.pix.width; -+ cam->crop_defrect.height = cam_fmt.fmt.pix.height; -+ -+ /* At this point, this is also the current image size. */ -+ cam->crop_current.top = cam->crop_current.left = 0; -+ cam->crop_current.width = cam_fmt.fmt.pix.width; -+ cam->crop_current.height = cam_fmt.fmt.pix.height; -+ -+ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", -+ __func__, -+ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); -+ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", -+ __func__, -+ cam->crop_bounds.width, cam->crop_bounds.height); -+ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", -+ __func__, -+ cam->crop_defrect.width, cam->crop_defrect.height); -+ pr_debug("End of %s: crop_current widthxheight %d x %d\n", -+ __func__, -+ cam->crop_current.width, cam->crop_current.height); -+ -+ return 0; -+} -+ -+/*! -+ * Disconnects the camera driver. -+ */ -+static void mxc_v4l2_master_detach(struct v4l2_int_device *slave) -+{ -+ unsigned int i; -+ cam_data *cam = slave->u.slave->master->priv; -+ -+ pr_debug("In MVC:mxc_v4l2_master_detach\n"); -+ -+ if (cam->sensor_index > 1) { -+ for (i = 0; i < cam->sensor_index; i++) { -+ if (cam->all_sensors[i] != slave) -+ continue; -+ /* Move all the sensors behind this -+ * sensor one step forward -+ */ -+ for (; i <= MXC_SENSOR_NUM - 2; i++) -+ cam->all_sensors[i] = cam->all_sensors[i+1]; -+ break; -+ } -+ /* Point current sensor to the last one */ -+ cam->sensor = cam->all_sensors[cam->sensor_index - 2]; -+ } else -+ cam->sensor = NULL; -+ -+ cam->sensor_index--; -+ vidioc_int_dev_exit(slave); -+} -+ -+/*! -+ * Entry point for the V4L2 -+ * -+ * @return Error code indicating success or failure -+ */ -+static __init int camera_init(void) -+{ -+ u8 err = 0; -+ -+ pr_debug("In MVC:camera_init\n"); -+ -+ /* Register the device driver structure. */ -+ err = platform_driver_register(&mxc_v4l2_driver); -+ if (err != 0) { -+ pr_err("ERROR: v4l2 capture:camera_init: " -+ "platform_driver_register failed.\n"); -+ return err; -+ } -+ -+ return err; -+} -+ -+/*! -+ * Exit and cleanup for the V4L2 -+ */ -+static void __exit camera_exit(void) -+{ -+ pr_debug("In MVC: camera_exit\n"); -+ -+ platform_driver_unregister(&mxc_v4l2_driver); -+} -+ -+module_init(camera_init); -+module_exit(camera_exit); -+ -+module_param(video_nr, int, 0444); -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras"); -+MODULE_LICENSE("GPL"); -+MODULE_SUPPORTED_DEVICE("video"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h linux-3.14.22/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 2014-10-22 14:55:52.618220001 -0500 -@@ -0,0 +1,260 @@ -+/* -+ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/*! -+ * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver -+ */ -+/*! -+ * @file mxc_v4l2_capture.h -+ * -+ * @brief mxc V4L2 capture device API Header file -+ * -+ * It include all the defines for frame operations, also three structure defines -+ * use case ops structure, common v4l2 driver structure and frame structure. -+ * -+ * @ingroup MXC_V4L2_CAPTURE -+ */ -+#ifndef __MXC_V4L2_CAPTURE_H__ -+#define __MXC_V4L2_CAPTURE_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+ -+#define FRAME_NUM 10 -+#define MXC_SENSOR_NUM 2 -+ -+enum imx_v4l2_devtype { -+ IMX5_V4L2, -+ IMX6_V4L2, -+}; -+ -+/*! -+ * v4l2 frame structure. -+ */ -+struct mxc_v4l_frame { -+ u32 paddress; -+ void *vaddress; -+ int count; -+ int width; -+ int height; -+ -+ struct v4l2_buffer buffer; -+ struct list_head queue; -+ int index; -+ union { -+ int ipu_buf_num; -+ int csi_buf_num; -+ }; -+}; -+ -+/* Only for old version. Will go away soon. */ -+typedef struct { -+ u8 clk_mode; -+ u8 ext_vsync; -+ u8 Vsync_pol; -+ u8 Hsync_pol; -+ u8 pixclk_pol; -+ u8 data_pol; -+ u8 data_width; -+ u8 pack_tight; -+ u8 force_eof; -+ u8 data_en_pol; -+ u16 width; -+ u16 height; -+ u32 pixel_fmt; -+ u32 mclk; -+ u16 active_width; -+ u16 active_height; -+} sensor_interface; -+ -+/* Sensor control function */ -+/* Only for old version. Will go away soon. */ -+struct camera_sensor { -+ void (*set_color) (int bright, int saturation, int red, int green, -+ int blue); -+ void (*get_color) (int *bright, int *saturation, int *red, int *green, -+ int *blue); -+ void (*set_ae_mode) (int ae_mode); -+ void (*get_ae_mode) (int *ae_mode); -+ sensor_interface *(*config) (int *frame_rate, int high_quality); -+ sensor_interface *(*reset) (void); -+ void (*get_std) (v4l2_std_id *std); -+ void (*set_std) (v4l2_std_id std); -+ unsigned int csi; -+}; -+ -+/*! -+ * common v4l2 driver structure. -+ */ -+typedef struct _cam_data { -+ struct video_device *video_dev; -+ int device_type; -+ -+ /* semaphore guard against SMP multithreading */ -+ struct semaphore busy_lock; -+ -+ int open_count; -+ -+ /* params lock for this camera */ -+ struct semaphore param_lock; -+ -+ /* Encoder */ -+ struct list_head ready_q; -+ struct list_head done_q; -+ struct list_head working_q; -+ int ping_pong_csi; -+ spinlock_t queue_int_lock; -+ spinlock_t dqueue_int_lock; -+ struct mxc_v4l_frame frame[FRAME_NUM]; -+ struct mxc_v4l_frame dummy_frame; -+ wait_queue_head_t enc_queue; -+ int enc_counter; -+ dma_addr_t rot_enc_bufs[2]; -+ void *rot_enc_bufs_vaddr[2]; -+ int rot_enc_buf_size[2]; -+ enum v4l2_buf_type type; -+ -+ /* still image capture */ -+ wait_queue_head_t still_queue; -+ int still_counter; -+ dma_addr_t still_buf[2]; -+ void *still_buf_vaddr; -+ -+ /* overlay */ -+ struct v4l2_window win; -+ struct v4l2_framebuffer v4l2_fb; -+ dma_addr_t vf_bufs[2]; -+ void *vf_bufs_vaddr[2]; -+ int vf_bufs_size[2]; -+ dma_addr_t rot_vf_bufs[2]; -+ void *rot_vf_bufs_vaddr[2]; -+ int rot_vf_buf_size[2]; -+ bool overlay_active; -+ int output; -+ struct fb_info *overlay_fb; -+ int fb_origin_std; -+ struct work_struct csi_work_struct; -+ -+ /* v4l2 format */ -+ struct v4l2_format v2f; -+ int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */ -+ int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */ -+ struct v4l2_mxc_offset offset; -+ -+ /* V4l2 control bit */ -+ int bright; -+ int hue; -+ int contrast; -+ int saturation; -+ int red; -+ int green; -+ int blue; -+ int ae_mode; -+ -+ /* standard */ -+ struct v4l2_streamparm streamparm; -+ struct v4l2_standard standard; -+ bool standard_autodetect; -+ -+ /* crop */ -+ struct v4l2_rect crop_bounds; -+ struct v4l2_rect crop_defrect; -+ struct v4l2_rect crop_current; -+ -+ int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, -+ int *bufferNum); -+ int (*enc_enable) (void *private); -+ int (*enc_disable) (void *private); -+ int (*enc_enable_csi) (void *private); -+ int (*enc_disable_csi) (void *private); -+ void (*enc_callback) (u32 mask, void *dev); -+ int (*vf_start_adc) (void *private); -+ int (*vf_stop_adc) (void *private); -+ int (*vf_start_sdc) (void *private); -+ int (*vf_stop_sdc) (void *private); -+ int (*vf_enable_csi) (void *private); -+ int (*vf_disable_csi) (void *private); -+ int (*csi_start) (void *private); -+ int (*csi_stop) (void *private); -+ -+ /* misc status flag */ -+ bool overlay_on; -+ bool capture_on; -+ int overlay_pid; -+ int capture_pid; -+ bool low_power; -+ wait_queue_head_t power_queue; -+ unsigned int ipu_id; -+ unsigned int csi; -+ u8 mclk_source; -+ bool mclk_on[2]; /* two mclk sources at most now */ -+ int current_input; -+ -+ int local_buf_num; -+ -+ /* camera sensor interface */ -+ struct camera_sensor *cam_sensor; /* old version */ -+ struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM]; -+ struct v4l2_int_device *sensor; -+ struct v4l2_int_device *self; -+ int sensor_index; -+ void *ipu; -+ enum imx_v4l2_devtype devtype; -+ -+ /* v4l2 buf elements related to PxP DMA */ -+ struct completion pxp_tx_cmpl; -+ struct pxp_channel *pxp_chan; -+ struct pxp_config_data pxp_conf; -+ struct dma_async_tx_descriptor *txd; -+ dma_cookie_t cookie; -+ struct scatterlist sg[2]; -+} cam_data; -+ -+struct sensor_data { -+ const struct ov5642_platform_data *platform_data; -+ struct v4l2_int_device *v4l2_int_device; -+ struct i2c_client *i2c_client; -+ struct v4l2_pix_format pix; -+ struct v4l2_captureparm streamcap; -+ bool on; -+ -+ /* control settings */ -+ int brightness; -+ int hue; -+ int contrast; -+ int saturation; -+ int red; -+ int green; -+ int blue; -+ int ae_mode; -+ -+ u32 mclk; -+ u8 mclk_source; -+ struct clk *sensor_clk; -+ int csi; -+ -+ void (*io_init)(void); -+}; -+ -+void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi); -+#endif /* __MXC_V4L2_CAPTURE_H__ */ -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5640.c linux-3.14.22/drivers/media/platform/mxc/capture/ov5640.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5640.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ov5640.c 2014-10-22 14:55:52.622220001 -0500 -@@ -0,0 +1,1951 @@ -+/* -+ * Copyright (C) 2012-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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.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 -+ -+#define OV5640_XCLK_MIN 6000000 -+#define OV5640_XCLK_MAX 24000000 -+ -+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A -+#define OV5640_CHIP_ID_LOW_BYTE 0x300B -+ -+enum ov5640_mode { -+ ov5640_mode_MIN = 0, -+ ov5640_mode_VGA_640_480 = 0, -+ ov5640_mode_QVGA_320_240 = 1, -+ ov5640_mode_NTSC_720_480 = 2, -+ ov5640_mode_PAL_720_576 = 3, -+ ov5640_mode_720P_1280_720 = 4, -+ ov5640_mode_1080P_1920_1080 = 5, -+ ov5640_mode_QSXGA_2592_1944 = 6, -+ ov5640_mode_QCIF_176_144 = 7, -+ ov5640_mode_XGA_1024_768 = 8, -+ ov5640_mode_MAX = 8 -+}; -+ -+enum ov5640_frame_rate { -+ ov5640_15_fps, -+ ov5640_30_fps -+}; -+ -+static int ov5640_framerates[] = { -+ [ov5640_15_fps] = 15, -+ [ov5640_30_fps] = 30, -+}; -+ -+struct reg_value { -+ u16 u16RegAddr; -+ u8 u8Val; -+ u8 u8Mask; -+ u32 u32Delay_ms; -+}; -+ -+struct ov5640_mode_info { -+ enum ov5640_mode mode; -+ u32 width; -+ u32 height; -+ struct reg_value *init_data_ptr; -+ u32 init_data_size; -+}; -+ -+/*! -+ * Maintains the information on the current state of the sesor. -+ */ -+static struct sensor_data ov5640_data; -+static int pwn_gpio, rst_gpio; -+static int prev_sysclk; -+static int AE_Target = 52, night_mode; -+static int prev_HTS; -+static int AE_high, AE_low; -+ -+static struct reg_value ov5640_global_init_setting[] = { -+ {0x3008, 0x42, 0, 0}, -+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0}, -+ {0x3034, 0x1a, 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, 0x7c, 0, 0}, -+ {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, -+ {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, -+ {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0}, -+ {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, -+ {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0}, -+ {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0}, -+ {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, -+ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, -+ {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0}, -+ {0x3008, 0x02, 0, 0}, -+}; -+ -+static struct reg_value ov5640_init_setting_30fps_VGA[] = { -+ {0x3008, 0x42, 0, 0}, -+ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0}, -+ {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 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, 0x34, 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, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 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, 0x22, 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}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_VGA_640_480[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_VGA_640_480[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = { -+ {0x3c07, 0x08, 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, 0x06, 0, 0}, -+ {0x3807, 0xd4, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = { -+ {0x3c07, 0x08, 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, 0x06, 0, 0}, -+ {0x3807, 0xd4, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_PAL_720_576[] = { -+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, -+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, -+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, -+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_PAL_720_576[] = { -+ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, -+ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, -+ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, -+ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_720P_1280_720[] = { -+ {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 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}, {0x3813, 0x04, 0, 0}, -+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0}, -+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0}, -+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0}, -+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0}, -+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, -+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, -+ {0x3503, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_720P_1280_720[] = { -+ {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 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}, {0x3813, 0x04, 0, 0}, -+ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0}, -+ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0}, -+ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0}, -+ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0}, -+ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, -+ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, -+ {0x3503, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = { -+ {0x3c07, 0x08, 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}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = { -+ {0x3c07, 0x08, 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, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, -+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0}, -+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = { -+ {0x3c07, 0x08, 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, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, -+ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0}, -+ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, -+ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, -+ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, -+ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, -+ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0}, -+ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+ -+static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = { -+ {0x3c07, 0x07, 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, 0xee, 0, 0}, -+ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0}, -+ {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, -+ {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0}, -+ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, -+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0}, -+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0}, -+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0}, -+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0}, -+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = { -+ {0x3c07, 0x07, 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}, -+ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0}, -+ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0}, -+ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0}, -+ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, -+ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0}, -+ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, -+ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, -+}; -+ -+static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = { -+ { -+ {ov5640_mode_VGA_640_480, 640, 480, -+ ov5640_setting_15fps_VGA_640_480, -+ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)}, -+ {ov5640_mode_QVGA_320_240, 320, 240, -+ ov5640_setting_15fps_QVGA_320_240, -+ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)}, -+ {ov5640_mode_NTSC_720_480, 720, 480, -+ ov5640_setting_15fps_NTSC_720_480, -+ ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)}, -+ {ov5640_mode_PAL_720_576, 720, 576, -+ ov5640_setting_15fps_PAL_720_576, -+ ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)}, -+ {ov5640_mode_720P_1280_720, 1280, 720, -+ ov5640_setting_15fps_720P_1280_720, -+ ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)}, -+ {ov5640_mode_1080P_1920_1080, 1920, 1080, -+ ov5640_setting_15fps_1080P_1920_1080, -+ ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)}, -+ {ov5640_mode_QSXGA_2592_1944, 2592, 1944, -+ ov5640_setting_15fps_QSXGA_2592_1944, -+ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)}, -+ {ov5640_mode_QCIF_176_144, 176, 144, -+ ov5640_setting_15fps_QCIF_176_144, -+ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)}, -+ {ov5640_mode_XGA_1024_768, 1024, 768, -+ ov5640_setting_15fps_XGA_1024_768, -+ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)}, -+ }, -+ { -+ {ov5640_mode_VGA_640_480, 640, 480, -+ ov5640_setting_30fps_VGA_640_480, -+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)}, -+ {ov5640_mode_QVGA_320_240, 320, 240, -+ ov5640_setting_30fps_QVGA_320_240, -+ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)}, -+ {ov5640_mode_NTSC_720_480, 720, 480, -+ ov5640_setting_30fps_NTSC_720_480, -+ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)}, -+ {ov5640_mode_PAL_720_576, 720, 576, -+ ov5640_setting_30fps_PAL_720_576, -+ ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)}, -+ {ov5640_mode_720P_1280_720, 1280, 720, -+ ov5640_setting_30fps_720P_1280_720, -+ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)}, -+ {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0}, -+ {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0}, -+ {ov5640_mode_QCIF_176_144, 176, 144, -+ ov5640_setting_30fps_QCIF_176_144, -+ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)}, -+ {ov5640_mode_XGA_1024_768, 1024, 768, -+ ov5640_setting_30fps_XGA_1024_768, -+ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)}, -+ }, -+}; -+ -+static struct regulator *io_regulator; -+static struct regulator *core_regulator; -+static struct regulator *analog_regulator; -+ -+static int ov5640_probe(struct i2c_client *adapter, -+ const struct i2c_device_id *device_id); -+static int ov5640_remove(struct i2c_client *client); -+ -+static s32 ov5640_read_reg(u16 reg, u8 *val); -+static s32 ov5640_write_reg(u16 reg, u8 val); -+ -+static const struct i2c_device_id ov5640_id[] = { -+ {"ov5640", 0}, -+ {"ov564x", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, ov5640_id); -+ -+static struct i2c_driver ov5640_i2c_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "ov5640", -+ }, -+ .probe = ov5640_probe, -+ .remove = ov5640_remove, -+ .id_table = ov5640_id, -+}; -+ -+static inline void ov5640_power_down(int enable) -+{ -+ gpio_set_value(pwn_gpio, enable); -+ -+ msleep(2); -+} -+ -+static inline void ov5640_reset(void) -+{ -+ /* camera reset */ -+ gpio_set_value(rst_gpio, 1); -+ -+ /* camera power down */ -+ gpio_set_value(pwn_gpio, 1); -+ msleep(5); -+ gpio_set_value(pwn_gpio, 0); -+ msleep(5); -+ gpio_set_value(rst_gpio, 0); -+ msleep(1); -+ gpio_set_value(rst_gpio, 1); -+ msleep(5); -+ gpio_set_value(pwn_gpio, 1); -+} -+ -+static int ov5640_regulator_enable(struct device *dev) -+{ -+ int ret = 0; -+ -+ io_regulator = devm_regulator_get(dev, "DOVDD"); -+ if (!IS_ERR(io_regulator)) { -+ regulator_set_voltage(io_regulator, -+ OV5640_VOLTAGE_DIGITAL_IO, -+ OV5640_VOLTAGE_DIGITAL_IO); -+ ret = regulator_enable(io_regulator); -+ if (ret) { -+ dev_err(dev, "set io voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set io voltage ok\n"); -+ } -+ } else { -+ io_regulator = NULL; -+ dev_warn(dev, "cannot get io voltage\n"); -+ } -+ -+ core_regulator = devm_regulator_get(dev, "DVDD"); -+ if (!IS_ERR(core_regulator)) { -+ regulator_set_voltage(core_regulator, -+ OV5640_VOLTAGE_DIGITAL_CORE, -+ OV5640_VOLTAGE_DIGITAL_CORE); -+ ret = regulator_enable(core_regulator); -+ if (ret) { -+ dev_err(dev, "set core voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set core voltage ok\n"); -+ } -+ } else { -+ core_regulator = NULL; -+ dev_warn(dev, "cannot get core voltage\n"); -+ } -+ -+ analog_regulator = devm_regulator_get(dev, "AVDD"); -+ if (!IS_ERR(analog_regulator)) { -+ regulator_set_voltage(analog_regulator, -+ OV5640_VOLTAGE_ANALOG, -+ OV5640_VOLTAGE_ANALOG); -+ ret = regulator_enable(analog_regulator); -+ if (ret) { -+ dev_err(dev, "set analog voltage failed\n"); -+ return ret; -+ } else { -+ dev_dbg(dev, "set analog voltage ok\n"); -+ } -+ } else { -+ analog_regulator = NULL; -+ dev_warn(dev, "cannot get analog voltage\n"); -+ } -+ -+ return ret; -+} -+ -+static s32 ov5640_write_reg(u16 reg, u8 val) -+{ -+ u8 au8Buf[3] = {0}; -+ -+ au8Buf[0] = reg >> 8; -+ au8Buf[1] = reg & 0xff; -+ au8Buf[2] = val; -+ -+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) { -+ pr_err("%s:write reg error:reg=%x,val=%x\n", -+ __func__, reg, val); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static s32 ov5640_read_reg(u16 reg, u8 *val) -+{ -+ u8 au8RegBuf[2] = {0}; -+ u8 u8RdVal = 0; -+ -+ au8RegBuf[0] = reg >> 8; -+ au8RegBuf[1] = reg & 0xff; -+ -+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) { -+ pr_err("%s:write reg error:reg=%x\n", -+ __func__, reg); -+ return -1; -+ } -+ -+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) { -+ pr_err("%s:read reg error:reg=%x,val=%x\n", -+ __func__, reg, u8RdVal); -+ return -1; -+ } -+ -+ *val = u8RdVal; -+ -+ return u8RdVal; -+} -+ -+static void ov5640_soft_reset(void) -+{ -+ /* sysclk from pad */ -+ ov5640_write_reg(0x3103, 0x11); -+ -+ /* software reset */ -+ ov5640_write_reg(0x3008, 0x82); -+ -+ /* delay at least 5ms */ -+ msleep(10); -+} -+ -+/* set sensor driver capability -+ * 0x302c[7:6] - strength -+ 00 - 1x -+ 01 - 2x -+ 10 - 3x -+ 11 - 4x -+ */ -+static int ov5640_driver_capability(int strength) -+{ -+ u8 temp = 0; -+ -+ if (strength > 4 || strength < 1) { -+ pr_err("The valid driver capability of ov5640 is 1x~4x\n"); -+ return -EINVAL; -+ } -+ -+ ov5640_read_reg(0x302c, &temp); -+ -+ temp &= ~0xc0; /* clear [7:6] */ -+ temp |= ((strength - 1) << 6); /* set [7:6] */ -+ -+ ov5640_write_reg(0x302c, temp); -+ -+ return 0; -+} -+ -+/* calculate sysclk */ -+static int ov5640_get_sysclk(void) -+{ -+ int xvclk = ov5640_data.mclk / 10000; -+ int sysclk; -+ int temp1, temp2; -+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv; -+ int sclk_rdiv_map[] = {1, 2, 4, 8}; -+ u8 regval = 0; -+ -+ temp1 = ov5640_read_reg(0x3034, ®val); -+ temp2 = temp1 & 0x0f; -+ if (temp2 == 8 || temp2 == 10) { -+ Bit_div2x = temp2 / 2; -+ } else { -+ pr_err("ov5640: unsupported bit mode %d\n", temp2); -+ return -1; -+ } -+ -+ temp1 = ov5640_read_reg(0x3035, ®val); -+ SysDiv = temp1 >> 4; -+ if (SysDiv == 0) -+ SysDiv = 16; -+ -+ temp1 = ov5640_read_reg(0x3036, ®val); -+ Multiplier = temp1; -+ temp1 = ov5640_read_reg(0x3037, ®val); -+ PreDiv = temp1 & 0x0f; -+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1; -+ -+ temp1 = ov5640_read_reg(0x3108, ®val); -+ 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; -+} -+ -+/* read HTS from register settings */ -+static int ov5640_get_HTS(void) -+{ -+ int HTS; -+ u8 temp = 0; -+ -+ HTS = ov5640_read_reg(0x380c, &temp); -+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp); -+ return HTS; -+} -+ -+/* read VTS from register settings */ -+static int ov5640_get_VTS(void) -+{ -+ int VTS; -+ u8 temp = 0; -+ -+ VTS = ov5640_read_reg(0x380e, &temp); -+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp); -+ -+ return VTS; -+} -+ -+/* write VTS to registers */ -+static int ov5640_set_VTS(int VTS) -+{ -+ int temp; -+ -+ temp = VTS & 0xff; -+ ov5640_write_reg(0x380f, temp); -+ -+ temp = VTS>>8; -+ ov5640_write_reg(0x380e, temp); -+ return 0; -+} -+ -+/* read shutter, in number of line period */ -+static int ov5640_get_shutter(void) -+{ -+ int shutter; -+ u8 regval; -+ -+ shutter = (ov5640_read_reg(0x03500, ®val) & 0x0f); -+ -+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, ®val); -+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, ®val)>>4); -+ -+ return shutter; -+} -+ -+/* write shutter, in number of line period */ -+static int ov5640_set_shutter(int shutter) -+{ -+ int temp; -+ -+ shutter = shutter & 0xffff; -+ temp = shutter & 0x0f; -+ temp = temp<<4; -+ ov5640_write_reg(0x3502, temp); -+ -+ temp = shutter & 0xfff; -+ temp = temp>>4; -+ ov5640_write_reg(0x3501, temp); -+ -+ temp = shutter>>12; -+ ov5640_write_reg(0x3500, temp); -+ -+ return 0; -+} -+ -+/* read gain, 16 = 1x */ -+static int ov5640_get_gain16(void) -+{ -+ int gain16; -+ u8 regval; -+ -+ gain16 = ov5640_read_reg(0x350a, ®val) & 0x03; -+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, ®val); -+ -+ return gain16; -+} -+ -+/* write gain, 16 = 1x */ -+static int ov5640_set_gain16(int gain16) -+{ -+ int temp; -+ -+ gain16 = gain16 & 0x3ff; -+ temp = gain16 & 0xff; -+ -+ ov5640_write_reg(0x350b, temp); -+ temp = gain16>>8; -+ -+ ov5640_write_reg(0x350a, temp); -+ return 0; -+} -+ -+/* get banding filter value */ -+static int ov5640_get_light_freq(void) -+{ -+ int temp, temp1, light_frequency; -+ u8 regval; -+ -+ temp = ov5640_read_reg(0x3c01, ®val); -+ if (temp & 0x80) { -+ /* manual */ -+ temp1 = ov5640_read_reg(0x3c00, ®val); -+ if (temp1 & 0x04) { -+ /* 50Hz */ -+ light_frequency = 50; -+ } else { -+ /* 60Hz */ -+ light_frequency = 60; -+ } -+ } else { -+ /* auto */ -+ temp1 = ov5640_read_reg(0x3c0c, ®val); -+ if (temp1 & 0x01) { -+ /* 50Hz */ -+ light_frequency = 50; -+ } else { -+ /* 60Hz */ -+ light_frequency = 60; -+ } -+ } -+ -+ return light_frequency; -+} -+ -+static void ov5640_set_bandingfilter(void) -+{ -+ int prev_VTS; -+ int band_step60, max_band60, band_step50, max_band50; -+ -+ /* read preview PCLK */ -+ prev_sysclk = ov5640_get_sysclk(); -+ -+ /* read preview HTS */ -+ prev_HTS = ov5640_get_HTS(); -+ -+ /* read preview VTS */ -+ prev_VTS = ov5640_get_VTS(); -+ -+ /* calculate banding filter */ -+ /* 60Hz */ -+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120; -+ ov5640_write_reg(0x3a0a, (band_step60 >> 8)); -+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff)); -+ -+ max_band60 = (int)((prev_VTS-4)/band_step60); -+ ov5640_write_reg(0x3a0d, max_band60); -+ -+ /* 50Hz */ -+ band_step50 = prev_sysclk * 100/prev_HTS; -+ ov5640_write_reg(0x3a08, (band_step50 >> 8)); -+ ov5640_write_reg(0x3a09, (band_step50 & 0xff)); -+ -+ max_band50 = (int)((prev_VTS-4)/band_step50); -+ ov5640_write_reg(0x3a0e, max_band50); -+} -+ -+/* stable in high */ -+static int ov5640_set_AE_target(int target) -+{ -+ int fast_high, fast_low; -+ -+ AE_low = target * 23 / 25; /* 0.92 */ -+ AE_high = target * 27 / 25; /* 1.08 */ -+ fast_high = AE_high << 1; -+ -+ if (fast_high > 255) -+ fast_high = 255; -+ fast_low = AE_low >> 1; -+ -+ ov5640_write_reg(0x3a0f, AE_high); -+ ov5640_write_reg(0x3a10, AE_low); -+ ov5640_write_reg(0x3a1b, AE_high); -+ ov5640_write_reg(0x3a1e, AE_low); -+ ov5640_write_reg(0x3a11, fast_high); -+ ov5640_write_reg(0x3a1f, fast_low); -+ -+ return 0; -+} -+ -+/* enable = 0 to turn off night mode -+ enable = 1 to turn on night mode */ -+static int ov5640_set_night_mode(int enable) -+{ -+ u8 mode; -+ -+ ov5640_read_reg(0x3a00, &mode); -+ -+ if (enable) { -+ /* night mode on */ -+ mode |= 0x04; -+ ov5640_write_reg(0x3a00, mode); -+ } else { -+ /* night mode off */ -+ mode &= 0xfb; -+ ov5640_write_reg(0x3a00, mode); -+ } -+ -+ return 0; -+} -+ -+/* enable = 0 to turn off AEC/AGC -+ enable = 1 to turn on AEC/AGC */ -+void ov5640_turn_on_AE_AG(int enable) -+{ -+ u8 ae_ag_ctrl; -+ -+ ov5640_read_reg(0x3503, &ae_ag_ctrl); -+ if (enable) { -+ /* turn on auto AE/AG */ -+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03); -+ } else { -+ /* turn off AE/AG */ -+ ae_ag_ctrl = ae_ag_ctrl | 0x03; -+ } -+ ov5640_write_reg(0x3503, ae_ag_ctrl); -+} -+ -+/* download ov5640 settings to sensor through i2c */ -+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize) -+{ -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int i, retval = 0; -+ -+ for (i = 0; i < ArySize; ++i, ++pModeSetting) { -+ Delay_ms = pModeSetting->u32Delay_ms; -+ RegAddr = pModeSetting->u16RegAddr; -+ Val = pModeSetting->u8Val; -+ Mask = pModeSetting->u8Mask; -+ -+ if (Mask) { -+ retval = ov5640_read_reg(RegAddr, &RegVal); -+ if (retval < 0) -+ goto err; -+ -+ RegVal &= ~(u8)Mask; -+ Val &= Mask; -+ Val |= RegVal; -+ } -+ -+ retval = ov5640_write_reg(RegAddr, Val); -+ if (retval < 0) -+ goto err; -+ -+ if (Delay_ms) -+ msleep(Delay_ms); -+ } -+err: -+ return retval; -+} -+ -+static int ov5640_init_mode(void) -+{ -+ struct reg_value *pModeSetting = NULL; -+ int ArySize = 0, retval = 0; -+ -+ ov5640_soft_reset(); -+ -+ pModeSetting = ov5640_global_init_setting; -+ ArySize = ARRAY_SIZE(ov5640_global_init_setting); -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ pModeSetting = ov5640_init_setting_30fps_VGA; -+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA); -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ /* change driver capability to 2x according to validation board. -+ * if the image is not stable, please increase the driver strength. -+ */ -+ ov5640_driver_capability(2); -+ ov5640_set_bandingfilter(); -+ ov5640_set_AE_target(AE_Target); -+ ov5640_set_night_mode(night_mode); -+ -+ /* skip 9 vysnc: start capture at 10th vsync */ -+ msleep(300); -+ -+ /* turn off night mode */ -+ night_mode = 0; -+ ov5640_data.pix.width = 640; -+ ov5640_data.pix.height = 480; -+err: -+ return retval; -+} -+ -+/* change to or back to subsampling mode set the mode directly -+ * image size below 1280 * 960 is subsampling mode */ -+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 ArySize = 0; -+ int retval = 0; -+ -+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) { -+ pr_err("Wrong ov5640 mode detected!\n"); -+ return -1; -+ } -+ -+ pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr; -+ ArySize = -+ ov5640_mode_info_data[frame_rate][mode].init_data_size; -+ -+ ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width; -+ ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height; -+ -+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || -+ pModeSetting == NULL || ArySize == 0) -+ return -EINVAL; -+ -+ /* set ov5640 to subsampling mode */ -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ -+ /* turn on AE AG for subsampling mode, in case the firmware didn't */ -+ ov5640_turn_on_AE_AG(1); -+ -+ /* calculate banding filter */ -+ ov5640_set_bandingfilter(); -+ -+ /* set AE target */ -+ ov5640_set_AE_target(AE_Target); -+ -+ /* update night mode setting */ -+ ov5640_set_night_mode(night_mode); -+ -+ /* skip 9 vysnc: start capture at 10th vsync */ -+ if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) { -+ pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n"); -+ /* 1/22.5 * 9*/ -+ msleep(400); -+ return retval; -+ } -+ -+ if (frame_rate == ov5640_15_fps) { -+ /* 1/15 * 9*/ -+ msleep(600); -+ } else if (frame_rate == ov5640_30_fps) { -+ /* 1/30 * 9*/ -+ msleep(300); -+ } -+ -+ return retval; -+} -+ -+/* change to scaling mode go through exposure calucation -+ * image size above 1280 * 960 is scaling mode */ -+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode) -+{ -+ int prev_shutter, prev_gain16, average; -+ int cap_shutter, cap_gain16; -+ int cap_sysclk, cap_HTS, cap_VTS; -+ int light_freq, cap_bandfilt, cap_maxband; -+ long cap_gain16_shutter; -+ u8 temp; -+ struct reg_value *pModeSetting = NULL; -+ s32 ArySize = 0; -+ int retval = 0; -+ -+ /* check if the input mode and frame rate is valid */ -+ pModeSetting = -+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; -+ ArySize = -+ ov5640_mode_info_data[frame_rate][mode].init_data_size; -+ -+ ov5640_data.pix.width = -+ ov5640_mode_info_data[frame_rate][mode].width; -+ ov5640_data.pix.height = -+ ov5640_mode_info_data[frame_rate][mode].height; -+ -+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || -+ pModeSetting == NULL || ArySize == 0) -+ return -EINVAL; -+ -+ /* read preview shutter */ -+ prev_shutter = ov5640_get_shutter(); -+ -+ /* read preview gain */ -+ prev_gain16 = ov5640_get_gain16(); -+ -+ /* get average */ -+ average = ov5640_read_reg(0x56a1, &temp); -+ -+ /* turn off night mode for capture */ -+ ov5640_set_night_mode(0); -+ -+ /* turn off overlay */ -+ ov5640_write_reg(0x3022, 0x06); -+ -+ /* Write capture setting */ -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ /* turn off AE AG when capture image. */ -+ ov5640_turn_on_AE_AG(0); -+ -+ /* read capture VTS */ -+ cap_VTS = ov5640_get_VTS(); -+ cap_HTS = ov5640_get_HTS(); -+ cap_sysclk = ov5640_get_sysclk(); -+ -+ /* calculate capture banding filter */ -+ light_freq = ov5640_get_light_freq(); -+ 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 > AE_low && average < AE_high) { -+ /* in stable range */ -+ cap_gain16_shutter = -+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk * -+ prev_HTS/cap_HTS * AE_Target / average; -+ } else { -+ cap_gain16_shutter = -+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk * -+ 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 =< max, cap_shutter = n/100 */ -+ cap_shutter = -+ ((int)(cap_gain16_shutter/16/cap_bandfilt)) -+ * cap_bandfilt; -+ cap_gain16 = cap_gain16_shutter / cap_shutter; -+ } -+ } -+ -+ /* write capture gain */ -+ ov5640_set_gain16(cap_gain16); -+ -+ /* write capture shutter */ -+ if (cap_shutter > (cap_VTS - 4)) { -+ cap_VTS = cap_shutter + 4; -+ ov5640_set_VTS(cap_VTS); -+ } -+ -+ ov5640_set_shutter(cap_shutter); -+ -+ /* skip 2 vysnc: start capture at 3rd vsync -+ * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2 -+ */ -+ pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n", -+ mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA"); -+ msleep(267); -+err: -+ return retval; -+} -+ -+static int ov5640_change_mode(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode) -+{ -+ int retval = 0; -+ -+ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) { -+ pr_err("Wrong ov5640 mode detected!\n"); -+ return -1; -+ } -+ -+ if (mode == ov5640_mode_1080P_1920_1080 || -+ mode == ov5640_mode_QSXGA_2592_1944) { -+ /* change to scaling mode go through exposure calucation -+ * image size above 1280 * 960 is scaling mode */ -+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode); -+ } else { -+ /* change back to subsampling modem download firmware directly -+ * image size below 1280 * 960 is subsampling mode */ -+ retval = ov5640_change_mode_direct(frame_rate, mode); -+ } -+ -+ return retval; -+} -+ -+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ -+ -+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) -+{ -+ if (s == NULL) { -+ pr_err(" ERROR!! no slave device set!\n"); -+ return -1; -+ } -+ -+ memset(p, 0, sizeof(*p)); -+ p->u.bt656.clock_curr = ov5640_data.mclk; -+ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk); -+ p->if_type = V4L2_IF_TYPE_BT656; -+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; -+ p->u.bt656.clock_min = OV5640_XCLK_MIN; -+ p->u.bt656.clock_max = OV5640_XCLK_MAX; -+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @on: indicates power mode (on or off) -+ * -+ * Turns the power on or off, depending on the value of on and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_power(struct v4l2_int_device *s, int on) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ if (on && !sensor->on) { -+ if (io_regulator) -+ if (regulator_enable(io_regulator) != 0) -+ return -EIO; -+ if (core_regulator) -+ if (regulator_enable(core_regulator) != 0) -+ return -EIO; -+ if (analog_regulator) -+ if (regulator_enable(analog_regulator) != 0) -+ return -EIO; -+ /* Make sure power on */ -+ ov5640_power_down(0); -+ } else if (!on && sensor->on) { -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ -+ ov5640_power_down(1); -+} -+ -+ sensor->on = on; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure -+ * -+ * Returns the sensor's video CAPTURE parameters. -+ */ -+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_captureparm *cparm = &a->parm.capture; -+ int ret = 0; -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ 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; -+ ret = 0; -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure -+ * -+ * Configures the sensor to use the input parameters, if possible. If -+ * not possible, reverts to the old parameters and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; -+ u32 tgt_fps; /* target frames per secound */ -+ enum ov5640_frame_rate frame_rate; -+ int ret = 0; -+ -+ /* Make sure power on */ -+ ov5640_power_down(0); -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ /* 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 { -+ pr_err(" The camera frame rate is not supported!\n"); -+ return -EINVAL; -+ } -+ -+ ret = ov5640_change_mode(frame_rate, -+ a->parm.capture.capturemode); -+ if (ret < 0) -+ return ret; -+ -+ sensor->streamcap.timeperframe = *timeperframe; -+ sensor->streamcap.capturemode = a->parm.capture.capturemode; -+ -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ pr_debug(" type is not " \ -+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", -+ a->type); -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap -+ * @s: pointer to standard V4L2 device structure -+ * @f: pointer to standard V4L2 v4l2_format structure -+ * -+ * Returns the sensor's current pixel format in the v4l2_format -+ * parameter. -+ */ -+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ f->fmt.pix = sensor->pix; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure -+ * -+ * If the requested control is supported, returns the control's current -+ * value from the video_control[] array. Otherwise, returns -EINVAL -+ * if the control is not supported. -+ */ -+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int ret = 0; -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ vc->value = ov5640_data.brightness; -+ break; -+ case V4L2_CID_HUE: -+ vc->value = ov5640_data.hue; -+ break; -+ case V4L2_CID_CONTRAST: -+ vc->value = ov5640_data.contrast; -+ break; -+ case V4L2_CID_SATURATION: -+ vc->value = ov5640_data.saturation; -+ break; -+ case V4L2_CID_RED_BALANCE: -+ vc->value = ov5640_data.red; -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ vc->value = ov5640_data.blue; -+ break; -+ case V4L2_CID_EXPOSURE: -+ vc->value = ov5640_data.ae_mode; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure -+ * -+ * If the requested control is supported, sets the control's current -+ * value in HW (and updates the video_control[] array). Otherwise, -+ * returns -EINVAL if the control is not supported. -+ */ -+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int retval = 0; -+ -+ pr_debug("In ov5640:ioctl_s_ctrl %d\n", -+ vc->id); -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ break; -+ case V4L2_CID_CONTRAST: -+ break; -+ case V4L2_CID_SATURATION: -+ break; -+ case V4L2_CID_HUE: -+ break; -+ case V4L2_CID_AUTO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_DO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_RED_BALANCE: -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ break; -+ case V4L2_CID_GAMMA: -+ break; -+ case V4L2_CID_EXPOSURE: -+ break; -+ case V4L2_CID_AUTOGAIN: -+ break; -+ case V4L2_CID_GAIN: -+ break; -+ case V4L2_CID_HFLIP: -+ break; -+ case V4L2_CID_VFLIP: -+ break; -+ default: -+ retval = -EPERM; -+ break; -+ } -+ -+ return retval; -+} -+ -+/*! -+ * ioctl_enum_framesizes - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMESIZES ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_framesizes(struct v4l2_int_device *s, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index > ov5640_mode_MAX) -+ return -EINVAL; -+ -+ fsize->pixel_format = ov5640_data.pix.pixelformat; -+ fsize->discrete.width = -+ max(ov5640_mode_info_data[0][fsize->index].width, -+ ov5640_mode_info_data[1][fsize->index].width); -+ fsize->discrete.height = -+ max(ov5640_mode_info_data[0][fsize->index].height, -+ ov5640_mode_info_data[1][fsize->index].height); -+ return 0; -+} -+ -+/*! -+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_frameintervals(struct v4l2_int_device *s, -+ struct v4l2_frmivalenum *fival) -+{ -+ int i, j, count; -+ -+ if (fival->index < 0 || fival->index > ov5640_mode_MAX) -+ return -EINVAL; -+ -+ if (fival->width == 0 || fival->height == 0 || -+ fival->pixel_format == 0) { -+ pr_warning("Please assign pixelformat, width and height.\n"); -+ return -EINVAL; -+ } -+ -+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; -+ fival->discrete.numerator = 1; -+ -+ count = 0; -+ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) { -+ for (j = 0; j < (ov5640_mode_MAX + 1); j++) { -+ if (fival->pixel_format == ov5640_data.pix.pixelformat -+ && fival->width == ov5640_mode_info_data[i][j].width -+ && fival->height == ov5640_mode_info_data[i][j].height -+ && ov5640_mode_info_data[i][j].init_data_ptr != NULL) { -+ count++; -+ } -+ if (fival->index == (count - 1)) { -+ fival->discrete.denominator = -+ ov5640_framerates[i]; -+ return 0; -+ } -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+/*! -+ * ioctl_g_chip_ident - V4L2 sensor interface handler for -+ * VIDIOC_DBG_G_CHIP_IDENT ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @id: pointer to int -+ * -+ * Return 0. -+ */ -+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) -+{ -+ ((struct v4l2_dbg_chip_ident *)id)->match.type = -+ V4L2_CHIP_MATCH_I2C_DRIVER; -+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera"); -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT -+ * @s: pointer to standard V4L2 device structure -+ */ -+static int ioctl_init(struct v4l2_int_device *s) -+{ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT -+ * @s: pointer to standard V4L2 device structure -+ * @fmt: pointer to standard V4L2 fmt description structure -+ * -+ * Return 0. -+ */ -+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, -+ struct v4l2_fmtdesc *fmt) -+{ -+ if (fmt->index > ov5640_mode_MAX) -+ return -EINVAL; -+ -+ fmt->pixelformat = ov5640_data.pix.pixelformat; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Initialise the device when slave attaches to the master. -+ */ -+static int ioctl_dev_init(struct v4l2_int_device *s) -+{ -+ struct sensor_data *sensor = s->priv; -+ u32 tgt_xclk; /* target xclk */ -+ u32 tgt_fps; /* target frames per secound */ -+ enum ov5640_frame_rate frame_rate; -+ int ret; -+ -+ ov5640_data.on = true; -+ -+ /* mclk */ -+ tgt_xclk = ov5640_data.mclk; -+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX); -+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN); -+ ov5640_data.mclk = tgt_xclk; -+ -+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); -+ clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk); -+ -+ /* Default camera frame rate is set in probe */ -+ tgt_fps = sensor->streamcap.timeperframe.denominator / -+ sensor->streamcap.timeperframe.numerator; -+ -+ if (tgt_fps == 15) -+ frame_rate = ov5640_15_fps; -+ else if (tgt_fps == 30) -+ frame_rate = ov5640_30_fps; -+ else -+ return -EINVAL; /* Only support 15fps or 30fps now. */ -+ -+ ret = ov5640_init_mode(); -+ return ret; -+} -+ -+/*! -+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Delinitialise the device when slave detaches to the master. -+ */ -+static int ioctl_dev_exit(struct v4l2_int_device *s) -+{ -+ return 0; -+} -+ -+/*! -+ * This structure defines all the ioctls for this module and links them to the -+ * enumeration. -+ */ -+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = { -+ { vidioc_int_dev_init_num, -+ (v4l2_int_ioctl_func *)ioctl_dev_init }, -+ { vidioc_int_dev_exit_num, -+ ioctl_dev_exit}, -+ { vidioc_int_s_power_num, -+ (v4l2_int_ioctl_func *)ioctl_s_power }, -+ { vidioc_int_g_ifparm_num, -+ (v4l2_int_ioctl_func *)ioctl_g_ifparm }, -+ { vidioc_int_init_num, -+ (v4l2_int_ioctl_func *)ioctl_init }, -+ { vidioc_int_enum_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, -+ { vidioc_int_g_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, -+ { vidioc_int_g_parm_num, -+ (v4l2_int_ioctl_func *)ioctl_g_parm }, -+ { vidioc_int_s_parm_num, -+ (v4l2_int_ioctl_func *)ioctl_s_parm }, -+ { vidioc_int_g_ctrl_num, -+ (v4l2_int_ioctl_func *)ioctl_g_ctrl }, -+ { vidioc_int_s_ctrl_num, -+ (v4l2_int_ioctl_func *)ioctl_s_ctrl }, -+ { vidioc_int_enum_framesizes_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes }, -+ { vidioc_int_enum_frameintervals_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals }, -+ { vidioc_int_g_chip_ident_num, -+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident }, -+}; -+ -+static struct v4l2_int_slave ov5640_slave = { -+ .ioctls = ov5640_ioctl_desc, -+ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc), -+}; -+ -+static struct v4l2_int_device ov5640_int_device = { -+ .module = THIS_MODULE, -+ .name = "ov5640", -+ .type = v4l2_int_type_slave, -+ .u = { -+ .slave = &ov5640_slave, -+ }, -+}; -+ -+/*! -+ * ov5640 I2C probe function -+ * -+ * @param adapter struct i2c_adapter * -+ * @return Error code indicating success or failure -+ */ -+static int ov5640_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct pinctrl *pinctrl; -+ struct device *dev = &client->dev; -+ int retval; -+ u8 chip_id_high, chip_id_low; -+ -+ /* ov5640 pinctrl */ -+ pinctrl = devm_pinctrl_get_select_default(dev); -+ if (IS_ERR(pinctrl)) { -+ dev_err(dev, "setup pinctrl failed\n"); -+ return PTR_ERR(pinctrl); -+ } -+ -+ /* request power down pin */ -+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); -+ if (!gpio_is_valid(pwn_gpio)) { -+ dev_err(dev, "no sensor pwdn pin available\n"); -+ return -ENODEV; -+ } -+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5640_pwdn"); -+ if (retval < 0) -+ return retval; -+ -+ /* request reset pin */ -+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); -+ if (!gpio_is_valid(rst_gpio)) { -+ dev_err(dev, "no sensor reset pin available\n"); -+ return -EINVAL; -+ } -+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5640_reset"); -+ if (retval < 0) -+ return retval; -+ -+ /* Set initial values for the sensor struct. */ -+ memset(&ov5640_data, 0, sizeof(ov5640_data)); -+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); -+ if (IS_ERR(ov5640_data.sensor_clk)) { -+ dev_err(dev, "get mclk failed\n"); -+ return PTR_ERR(ov5640_data.sensor_clk); -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk", -+ &ov5640_data.mclk); -+ if (retval) { -+ dev_err(dev, "mclk frequency is invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk_source", -+ (u32 *) &(ov5640_data.mclk_source)); -+ if (retval) { -+ dev_err(dev, "mclk_source invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "csi_id", -+ &(ov5640_data.csi)); -+ if (retval) { -+ dev_err(dev, "csi_id invalid\n"); -+ return retval; -+ } -+ -+ clk_prepare_enable(ov5640_data.sensor_clk); -+ -+ ov5640_data.io_init = ov5640_reset; -+ ov5640_data.i2c_client = client; -+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; -+ ov5640_data.pix.width = 640; -+ ov5640_data.pix.height = 480; -+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | -+ V4L2_CAP_TIMEPERFRAME; -+ ov5640_data.streamcap.capturemode = 0; -+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS; -+ ov5640_data.streamcap.timeperframe.numerator = 1; -+ -+ ov5640_regulator_enable(&client->dev); -+ -+ ov5640_reset(); -+ -+ ov5640_power_down(0); -+ -+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high); -+ if (retval < 0 || chip_id_high != 0x56) { -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ pr_warning("camera ov5640 is not found\n"); -+ return -ENODEV; -+ } -+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low); -+ if (retval < 0 || chip_id_low != 0x40) { -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ pr_warning("camera ov5640 is not found\n"); -+ return -ENODEV; -+ } -+ -+ ov5640_power_down(1); -+ -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ -+ ov5640_int_device.priv = &ov5640_data; -+ retval = v4l2_int_device_register(&ov5640_int_device); -+ -+ pr_info("camera ov5640 is found\n"); -+ return retval; -+} -+ -+/*! -+ * ov5640 I2C detach function -+ * -+ * @param client struct i2c_client * -+ * @return Error code indicating success or failure -+ */ -+static int ov5640_remove(struct i2c_client *client) -+{ -+ v4l2_int_device_unregister(&ov5640_int_device); -+ -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ -+ return 0; -+} -+ -+module_i2c_driver(ov5640_i2c_driver); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("OV5640 Camera Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.0"); -+MODULE_ALIAS("CSI"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5640_mipi.c linux-3.14.22/drivers/media/platform/mxc/capture/ov5640_mipi.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5640_mipi.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ov5640_mipi.c 2014-10-22 14:55:52.622220001 -0500 -@@ -0,0 +1,2104 @@ -+/* -+ * 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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.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 -+ -+#define OV5640_XCLK_MIN 6000000 -+#define OV5640_XCLK_MAX 24000000 -+ -+#define OV5640_CHIP_ID_HIGH_BYTE 0x300A -+#define OV5640_CHIP_ID_LOW_BYTE 0x300B -+ -+enum ov5640_mode { -+ ov5640_mode_MIN = 0, -+ ov5640_mode_VGA_640_480 = 0, -+ ov5640_mode_QVGA_320_240 = 1, -+ ov5640_mode_NTSC_720_480 = 2, -+ ov5640_mode_PAL_720_576 = 3, -+ ov5640_mode_720P_1280_720 = 4, -+ ov5640_mode_1080P_1920_1080 = 5, -+ ov5640_mode_QSXGA_2592_1944 = 6, -+ ov5640_mode_QCIF_176_144 = 7, -+ ov5640_mode_XGA_1024_768 = 8, -+ ov5640_mode_MAX = 8, -+ ov5640_mode_INIT = 0xff, /*only for sensor init*/ -+}; -+ -+enum ov5640_frame_rate { -+ ov5640_15_fps, -+ ov5640_30_fps -+}; -+ -+/* image size under 1280 * 960 are SUBSAMPLING -+ * image size upper 1280 * 960 are SCALING -+ */ -+enum ov5640_downsize_mode { -+ SUBSAMPLING, -+ SCALING, -+}; -+ -+struct reg_value { -+ u16 u16RegAddr; -+ u8 u8Val; -+ u8 u8Mask; -+ u32 u32Delay_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; -+}; -+ -+/*! -+ * Maintains the information on the current state of the sesor. -+ */ -+static struct sensor_data ov5640_data; -+static int pwn_gpio, rst_gpio; -+ -+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[2][ov5640_mode_MAX + 1] = { -+ { -+ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480, -+ ov5640_setting_15fps_VGA_640_480, -+ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)}, -+ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240, -+ ov5640_setting_15fps_QVGA_320_240, -+ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)}, -+ {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_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_15fps_QCIF_176_144, -+ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)}, -+ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768, -+ ov5640_setting_15fps_XGA_1024_768, -+ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)}, -+ }, -+ { -+ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480, -+ ov5640_setting_30fps_VGA_640_480, -+ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)}, -+ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240, -+ ov5640_setting_30fps_QVGA_320_240, -+ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)}, -+ {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_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}, -+ {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144, -+ ov5640_setting_30fps_QCIF_176_144, -+ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)}, -+ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768, -+ ov5640_setting_30fps_XGA_1024_768, -+ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)}, -+ }, -+}; -+ -+static struct regulator *io_regulator; -+static struct regulator *core_regulator; -+static struct regulator *analog_regulator; -+static struct regulator *gpo_regulator; -+ -+static int ov5640_probe(struct i2c_client *adapter, -+ const struct i2c_device_id *device_id); -+static int ov5640_remove(struct i2c_client *client); -+ -+static s32 ov5640_read_reg(u16 reg, u8 *val); -+static s32 ov5640_write_reg(u16 reg, u8 val); -+ -+static const struct i2c_device_id ov5640_id[] = { -+ {"ov5640_mipi", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, ov5640_id); -+ -+static struct i2c_driver ov5640_i2c_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "ov5640_mipi", -+ }, -+ .probe = ov5640_probe, -+ .remove = ov5640_remove, -+ .id_table = ov5640_id, -+}; -+ -+static void ov5640_standby(s32 enable) -+{ -+ if (enable) -+ gpio_set_value(pwn_gpio, 1); -+ else -+ gpio_set_value(pwn_gpio, 0); -+ -+ msleep(2); -+} -+ -+static void ov5640_reset(void) -+{ -+ /* camera reset */ -+ gpio_set_value(rst_gpio, 1); -+ -+ /* camera power dowmn */ -+ gpio_set_value(pwn_gpio, 1); -+ msleep(5); -+ -+ gpio_set_value(pwn_gpio, 0); -+ msleep(5); -+ -+ gpio_set_value(rst_gpio, 0); -+ msleep(1); -+ -+ gpio_set_value(rst_gpio, 1); -+ msleep(5); -+ -+ gpio_set_value(pwn_gpio, 1); -+} -+ -+static int ov5640_power_on(struct device *dev) -+{ -+ int ret = 0; -+ -+ io_regulator = devm_regulator_get(dev, "DOVDD"); -+ if (!IS_ERR(io_regulator)) { -+ regulator_set_voltage(io_regulator, -+ OV5640_VOLTAGE_DIGITAL_IO, -+ OV5640_VOLTAGE_DIGITAL_IO); -+ ret = regulator_enable(io_regulator); -+ if (ret) { -+ pr_err("%s:io set voltage error\n", __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:io set voltage ok\n", __func__); -+ } -+ } else { -+ pr_err("%s: cannot get io voltage error\n", __func__); -+ io_regulator = NULL; -+ } -+ -+ core_regulator = devm_regulator_get(dev, "DVDD"); -+ if (!IS_ERR(core_regulator)) { -+ regulator_set_voltage(core_regulator, -+ OV5640_VOLTAGE_DIGITAL_CORE, -+ OV5640_VOLTAGE_DIGITAL_CORE); -+ ret = regulator_enable(core_regulator); -+ if (ret) { -+ pr_err("%s:core set voltage error\n", __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:core set voltage ok\n", __func__); -+ } -+ } else { -+ core_regulator = NULL; -+ pr_err("%s: cannot get core voltage error\n", __func__); -+ } -+ -+ analog_regulator = devm_regulator_get(dev, "AVDD"); -+ if (!IS_ERR(analog_regulator)) { -+ regulator_set_voltage(analog_regulator, -+ OV5640_VOLTAGE_ANALOG, -+ OV5640_VOLTAGE_ANALOG); -+ ret = regulator_enable(analog_regulator); -+ if (ret) { -+ pr_err("%s:analog set voltage error\n", -+ __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:analog set voltage ok\n", __func__); -+ } -+ } else { -+ analog_regulator = NULL; -+ pr_err("%s: cannot get analog voltage error\n", __func__); -+ } -+ -+ return ret; -+} -+ -+static s32 ov5640_write_reg(u16 reg, u8 val) -+{ -+ u8 au8Buf[3] = {0}; -+ -+ au8Buf[0] = reg >> 8; -+ au8Buf[1] = reg & 0xff; -+ au8Buf[2] = val; -+ -+ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) { -+ pr_err("%s:write reg error:reg=%x,val=%x\n", -+ __func__, reg, val); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static s32 ov5640_read_reg(u16 reg, u8 *val) -+{ -+ u8 au8RegBuf[2] = {0}; -+ u8 u8RdVal = 0; -+ -+ au8RegBuf[0] = reg >> 8; -+ au8RegBuf[1] = reg & 0xff; -+ -+ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) { -+ pr_err("%s:write reg error:reg=%x\n", -+ __func__, reg); -+ return -1; -+ } -+ -+ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) { -+ pr_err("%s:read reg error:reg=%x,val=%x\n", -+ __func__, reg, u8RdVal); -+ return -1; -+ } -+ -+ *val = u8RdVal; -+ -+ return u8RdVal; -+} -+ -+static int prev_sysclk, prev_HTS; -+static int AE_low, AE_high, AE_Target = 52; -+ -+void OV5640_stream_on(void) -+{ -+ ov5640_write_reg(0x4202, 0x00); -+} -+ -+void OV5640_stream_off(void) -+{ -+ ov5640_write_reg(0x4202, 0x0f); -+} -+ -+ -+int OV5640_get_sysclk(void) -+{ -+ /* calculate sysclk */ -+ int xvclk = ov5640_data.mclk / 10000; -+ int temp1, temp2; -+ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv; -+ int Bit_div2x = 1, sclk_rdiv, sysclk; -+ u8 temp; -+ -+ int sclk_rdiv_map[] = {1, 2, 4, 8}; -+ -+ temp1 = ov5640_read_reg(0x3034, &temp); -+ temp2 = temp1 & 0x0f; -+ if (temp2 == 8 || temp2 == 10) -+ Bit_div2x = temp2 / 2; -+ -+ temp1 = ov5640_read_reg(0x3035, &temp); -+ SysDiv = temp1>>4; -+ if (SysDiv == 0) -+ SysDiv = 16; -+ -+ temp1 = ov5640_read_reg(0x3036, &temp); -+ Multiplier = temp1; -+ -+ temp1 = ov5640_read_reg(0x3037, &temp); -+ PreDiv = temp1 & 0x0f; -+ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1; -+ -+ temp1 = ov5640_read_reg(0x3108, &temp); -+ 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; -+} -+ -+void OV5640_set_night_mode(void) -+{ -+ /* read HTS from register settings */ -+ u8 mode; -+ -+ ov5640_read_reg(0x3a00, &mode); -+ mode &= 0xfb; -+ ov5640_write_reg(0x3a00, mode); -+} -+ -+int OV5640_get_HTS(void) -+{ -+ /* read HTS from register settings */ -+ int HTS; -+ u8 temp; -+ -+ HTS = ov5640_read_reg(0x380c, &temp); -+ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp); -+ -+ return HTS; -+} -+ -+int OV5640_get_VTS(void) -+{ -+ /* read VTS from register settings */ -+ int VTS; -+ u8 temp; -+ -+ /* total vertical size[15:8] high byte */ -+ VTS = ov5640_read_reg(0x380e, &temp); -+ -+ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp); -+ -+ return VTS; -+} -+ -+int OV5640_set_VTS(int VTS) -+{ -+ /* write VTS to registers */ -+ int temp; -+ -+ temp = VTS & 0xff; -+ ov5640_write_reg(0x380f, temp); -+ -+ temp = VTS>>8; -+ ov5640_write_reg(0x380e, temp); -+ -+ return 0; -+} -+ -+int OV5640_get_shutter(void) -+{ -+ /* read shutter, in number of line period */ -+ int shutter; -+ u8 temp; -+ -+ shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f); -+ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp); -+ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4); -+ -+ return shutter; -+} -+ -+int OV5640_set_shutter(int shutter) -+{ -+ /* write shutter, in number of line period */ -+ int temp; -+ -+ shutter = shutter & 0xffff; -+ -+ temp = shutter & 0x0f; -+ temp = temp<<4; -+ ov5640_write_reg(0x3502, temp); -+ -+ temp = shutter & 0xfff; -+ temp = temp>>4; -+ ov5640_write_reg(0x3501, temp); -+ -+ temp = shutter>>12; -+ ov5640_write_reg(0x3500, temp); -+ -+ return 0; -+} -+ -+int OV5640_get_gain16(void) -+{ -+ /* read gain, 16 = 1x */ -+ int gain16; -+ u8 temp; -+ -+ gain16 = ov5640_read_reg(0x350a, &temp) & 0x03; -+ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp); -+ -+ return gain16; -+} -+ -+int OV5640_set_gain16(int gain16) -+{ -+ /* write gain, 16 = 1x */ -+ u8 temp; -+ gain16 = gain16 & 0x3ff; -+ -+ temp = gain16 & 0xff; -+ ov5640_write_reg(0x350b, temp); -+ -+ temp = gain16>>8; -+ ov5640_write_reg(0x350a, temp); -+ -+ return 0; -+} -+ -+int OV5640_get_light_freq(void) -+{ -+ /* get banding filter value */ -+ int temp, temp1, light_freq = 0; -+ u8 tmp; -+ -+ temp = ov5640_read_reg(0x3c01, &tmp); -+ -+ if (temp & 0x80) { -+ /* manual */ -+ temp1 = ov5640_read_reg(0x3c00, &tmp); -+ if (temp1 & 0x04) { -+ /* 50Hz */ -+ light_freq = 50; -+ } else { -+ /* 60Hz */ -+ light_freq = 60; -+ } -+ } else { -+ /* auto */ -+ temp1 = ov5640_read_reg(0x3c0c, &tmp); -+ if (temp1 & 0x01) { -+ /* 50Hz */ -+ light_freq = 50; -+ } else { -+ /* 60Hz */ -+ } -+ } -+ return light_freq; -+} -+ -+void OV5640_set_bandingfilter(void) -+{ -+ int prev_VTS; -+ int band_step60, max_band60, band_step50, max_band50; -+ -+ /* read preview PCLK */ -+ prev_sysclk = OV5640_get_sysclk(); -+ /* read preview HTS */ -+ prev_HTS = OV5640_get_HTS(); -+ -+ /* read preview VTS */ -+ prev_VTS = OV5640_get_VTS(); -+ -+ /* calculate banding filter */ -+ /* 60Hz */ -+ band_step60 = prev_sysclk * 100/prev_HTS * 100/120; -+ ov5640_write_reg(0x3a0a, (band_step60 >> 8)); -+ ov5640_write_reg(0x3a0b, (band_step60 & 0xff)); -+ -+ max_band60 = (int)((prev_VTS-4)/band_step60); -+ ov5640_write_reg(0x3a0d, max_band60); -+ -+ /* 50Hz */ -+ band_step50 = prev_sysclk * 100/prev_HTS; -+ ov5640_write_reg(0x3a08, (band_step50 >> 8)); -+ ov5640_write_reg(0x3a09, (band_step50 & 0xff)); -+ -+ max_band50 = (int)((prev_VTS-4)/band_step50); -+ ov5640_write_reg(0x3a0e, max_band50); -+} -+ -+int OV5640_set_AE_target(int target) -+{ -+ /* stable in high */ -+ int fast_high, fast_low; -+ AE_low = target * 23 / 25; /* 0.92 */ -+ AE_high = target * 27 / 25; /* 1.08 */ -+ -+ fast_high = AE_high<<1; -+ if (fast_high > 255) -+ fast_high = 255; -+ -+ fast_low = AE_low >> 1; -+ -+ ov5640_write_reg(0x3a0f, AE_high); -+ ov5640_write_reg(0x3a10, AE_low); -+ ov5640_write_reg(0x3a1b, AE_high); -+ ov5640_write_reg(0x3a1e, AE_low); -+ ov5640_write_reg(0x3a11, fast_high); -+ ov5640_write_reg(0x3a1f, fast_low); -+ -+ return 0; -+} -+ -+void OV5640_turn_on_AE_AG(int enable) -+{ -+ u8 ae_ag_ctrl; -+ -+ ov5640_read_reg(0x3503, &ae_ag_ctrl); -+ if (enable) { -+ /* turn on auto AE/AG */ -+ ae_ag_ctrl = ae_ag_ctrl & ~(0x03); -+ } else { -+ /* turn off AE/AG */ -+ ae_ag_ctrl = ae_ag_ctrl | 0x03; -+ } -+ ov5640_write_reg(0x3503, ae_ag_ctrl); -+} -+ -+bool binning_on(void) -+{ -+ u8 temp; -+ ov5640_read_reg(0x3821, &temp); -+ temp &= 0xfe; -+ if (temp) -+ return true; -+ else -+ return false; -+} -+ -+static void ov5640_set_virtual_channel(int channel) -+{ -+ u8 channel_id; -+ -+ ov5640_read_reg(0x4814, &channel_id); -+ channel_id &= ~(3 << 6); -+ ov5640_write_reg(0x4814, channel_id | (channel << 6)); -+} -+ -+/* download ov5640 settings to sensor through i2c */ -+static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize) -+{ -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int i, retval = 0; -+ -+ for (i = 0; i < ArySize; ++i, ++pModeSetting) { -+ Delay_ms = pModeSetting->u32Delay_ms; -+ RegAddr = pModeSetting->u16RegAddr; -+ Val = pModeSetting->u8Val; -+ Mask = pModeSetting->u8Mask; -+ -+ if (Mask) { -+ retval = ov5640_read_reg(RegAddr, &RegVal); -+ if (retval < 0) -+ goto err; -+ -+ RegVal &= ~(u8)Mask; -+ Val &= Mask; -+ Val |= RegVal; -+ } -+ -+ retval = ov5640_write_reg(RegAddr, Val); -+ if (retval < 0) -+ goto err; -+ -+ if (Delay_ms) -+ msleep(Delay_ms); -+ } -+err: -+ return retval; -+} -+ -+/* sensor changes between scaling and subsampling -+ * go through exposure calcualtion -+ */ -+static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 ArySize = 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 retval = 0; -+ -+ /* check if the input mode and frame rate is valid */ -+ pModeSetting = -+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; -+ ArySize = -+ ov5640_mode_info_data[frame_rate][mode].init_data_size; -+ -+ ov5640_data.pix.width = -+ ov5640_mode_info_data[frame_rate][mode].width; -+ ov5640_data.pix.height = -+ ov5640_mode_info_data[frame_rate][mode].height; -+ -+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || -+ pModeSetting == NULL || ArySize == 0) -+ return -EINVAL; -+ -+ /* auto focus */ -+ /* OV5640_auto_focus();//if no af function, just skip it */ -+ -+ /* turn off AE/AG */ -+ OV5640_turn_on_AE_AG(0); -+ -+ /* read preview shutter */ -+ prev_shutter = OV5640_get_shutter(); -+ if ((binning_on()) && (mode != ov5640_mode_720P_1280_720) -+ && (mode != ov5640_mode_1080P_1920_1080)) -+ prev_shutter *= 2; -+ -+ /* read preview gain */ -+ prev_gain16 = OV5640_get_gain16(); -+ -+ /* get average */ -+ ov5640_read_reg(0x56a1, &average); -+ -+ /* turn off night mode for capture */ -+ OV5640_set_night_mode(); -+ -+ /* turn off overlay */ -+ /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */ -+ -+ OV5640_stream_off(); -+ -+ /* Write capture setting */ -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ /* read capture VTS */ -+ cap_VTS = OV5640_get_VTS(); -+ cap_HTS = OV5640_get_HTS(); -+ cap_sysclk = OV5640_get_sysclk(); -+ -+ /* calculate capture banding filter */ -+ light_freq = OV5640_get_light_freq(); -+ 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 > AE_low && average < AE_high) { -+ /* in stable range */ -+ cap_gain16_shutter = -+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk -+ * prev_HTS/cap_HTS * AE_Target / average; -+ } else { -+ cap_gain16_shutter = -+ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk -+ * 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 */ -+ OV5640_set_gain16(cap_gain16); -+ -+ /* write capture shutter */ -+ if (cap_shutter > (cap_VTS - 4)) { -+ cap_VTS = cap_shutter + 4; -+ OV5640_set_VTS(cap_VTS); -+ } -+ OV5640_set_shutter(cap_shutter); -+ -+ OV5640_stream_on(); -+ -+err: -+ return retval; -+} -+ -+/* if sensor changes inside scaling or subsampling -+ * change mode directly -+ * */ -+static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 ArySize = 0; -+ int retval = 0; -+ -+ /* check if the input mode and frame rate is valid */ -+ pModeSetting = -+ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; -+ ArySize = -+ ov5640_mode_info_data[frame_rate][mode].init_data_size; -+ -+ ov5640_data.pix.width = -+ ov5640_mode_info_data[frame_rate][mode].width; -+ ov5640_data.pix.height = -+ ov5640_mode_info_data[frame_rate][mode].height; -+ -+ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || -+ pModeSetting == NULL || ArySize == 0) -+ return -EINVAL; -+ -+ /* turn off AE/AG */ -+ OV5640_turn_on_AE_AG(0); -+ -+ OV5640_stream_off(); -+ -+ /* Write capture setting */ -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ OV5640_stream_on(); -+ -+ OV5640_turn_on_AE_AG(1); -+ -+err: -+ return retval; -+} -+ -+static int ov5640_init_mode(enum ov5640_frame_rate frame_rate, -+ enum ov5640_mode mode, enum ov5640_mode orig_mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 ArySize = 0; -+ int retval = 0; -+ void *mipi_csi2_info; -+ u32 mipi_reg, msec_wait4stable = 0; -+ enum ov5640_downsize_mode dn_mode, orig_dn_mode; -+ -+ if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) -+ && (mode != ov5640_mode_INIT)) { -+ pr_err("Wrong ov5640 mode detected!\n"); -+ return -1; -+ } -+ -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ /* initial mipi dphy */ -+ if (!mipi_csi2_info) { -+ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n", -+ __func__, __FILE__); -+ return -1; -+ } -+ -+ if (!mipi_csi2_get_status(mipi_csi2_info)) -+ mipi_csi2_enable(mipi_csi2_info); -+ -+ if (!mipi_csi2_get_status(mipi_csi2_info)) { -+ pr_err("Can not enable mipi csi2 driver!\n"); -+ return -1; -+ } -+ -+ mipi_csi2_set_lanes(mipi_csi2_info); -+ -+ /*Only reset MIPI CSI2 HW at sensor initialize*/ -+ if (mode == ov5640_mode_INIT) -+ mipi_csi2_reset(mipi_csi2_info); -+ -+ if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY) -+ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422); -+ else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565) -+ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565); -+ else -+ pr_err("currently this sensor format can not be supported!\n"); -+ -+ 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) { -+ pModeSetting = ov5640_init_setting_30fps_VGA; -+ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA); -+ -+ ov5640_data.pix.width = 640; -+ ov5640_data.pix.height = 480; -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ if (retval < 0) -+ goto err; -+ -+ pModeSetting = ov5640_setting_30fps_VGA_640_480; -+ ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480); -+ retval = ov5640_download_firmware(pModeSetting, ArySize); -+ } 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 */ -+ retval = ov5640_change_mode_exposure_calc(frame_rate, mode); -+ } else { -+ /* change inside subsampling or scaling -+ * download firmware directly */ -+ retval = ov5640_change_mode_direct(frame_rate, mode); -+ } -+ -+ if (retval < 0) -+ goto err; -+ -+ OV5640_set_AE_target(AE_Target); -+ OV5640_get_light_freq(); -+ OV5640_set_bandingfilter(); -+ ov5640_set_virtual_channel(ov5640_data.csi); -+ -+ /* add delay to wait for sensor stable */ -+ if (mode == ov5640_mode_QSXGA_2592_1944) { -+ /* dump the first two frames: 1/7.5*2 -+ * the frame rate of QSXGA is 7.5fps */ -+ msec_wait4stable = 267; -+ } else if (frame_rate == ov5640_15_fps) { -+ /* dump the first nine frames: 1/15*9 */ -+ msec_wait4stable = 600; -+ } else if (frame_rate == ov5640_30_fps) { -+ /* dump the first nine frames: 1/30*9 */ -+ msec_wait4stable = 300; -+ } -+ msleep(msec_wait4stable); -+ -+ if (mipi_csi2_info) { -+ unsigned int i; -+ -+ i = 0; -+ -+ /* wait for mipi sensor ready */ -+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); -+ while ((mipi_reg == 0x200) && (i < 10)) { -+ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); -+ i++; -+ msleep(10); -+ } -+ -+ if (i >= 10) { -+ pr_err("mipi csi2 can not receive sensor clk!\n"); -+ return -1; -+ } -+ -+ i = 0; -+ -+ /* wait for mipi stable */ -+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); -+ while ((mipi_reg != 0x0) && (i < 10)) { -+ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); -+ i++; -+ msleep(10); -+ } -+ -+ if (i >= 10) { -+ pr_err("mipi csi2 can not reveive data correctly!\n"); -+ return -1; -+ } -+ } -+err: -+ return retval; -+} -+ -+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ -+ -+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) -+{ -+ if (s == NULL) { -+ pr_err(" ERROR!! no slave device set!\n"); -+ return -1; -+ } -+ -+ memset(p, 0, sizeof(*p)); -+ p->u.bt656.clock_curr = ov5640_data.mclk; -+ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk); -+ p->if_type = V4L2_IF_TYPE_BT656; -+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; -+ p->u.bt656.clock_min = OV5640_XCLK_MIN; -+ p->u.bt656.clock_max = OV5640_XCLK_MAX; -+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @on: indicates power mode (on or off) -+ * -+ * Turns the power on or off, depending on the value of on and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_power(struct v4l2_int_device *s, int on) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ if (on && !sensor->on) { -+ if (io_regulator) -+ if (regulator_enable(io_regulator) != 0) -+ return -EIO; -+ if (core_regulator) -+ if (regulator_enable(core_regulator) != 0) -+ return -EIO; -+ if (gpo_regulator) -+ if (regulator_enable(gpo_regulator) != 0) -+ return -EIO; -+ if (analog_regulator) -+ if (regulator_enable(analog_regulator) != 0) -+ return -EIO; -+ /* Make sure power on */ -+ ov5640_standby(0); -+ } else if (!on && sensor->on) { -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ if (gpo_regulator) -+ regulator_disable(gpo_regulator); -+ -+ ov5640_standby(1); -+ } -+ -+ sensor->on = on; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure -+ * -+ * Returns the sensor's video CAPTURE parameters. -+ */ -+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_captureparm *cparm = &a->parm.capture; -+ int ret = 0; -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ 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; -+ ret = 0; -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure -+ * -+ * Configures the sensor to use the input parameters, if possible. If -+ * not possible, reverts to the old parameters and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; -+ u32 tgt_fps; /* target frames per secound */ -+ enum ov5640_frame_rate frame_rate; -+ enum ov5640_mode orig_mode; -+ int ret = 0; -+ -+ /* Make sure power on */ -+ ov5640_standby(0); -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ /* 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 { -+ pr_err(" The camera frame rate is not supported!\n"); -+ return -EINVAL; -+ } -+ -+ orig_mode = sensor->streamcap.capturemode; -+ ret = ov5640_init_mode(frame_rate, -+ (u32)a->parm.capture.capturemode, orig_mode); -+ if (ret < 0) -+ return ret; -+ -+ sensor->streamcap.timeperframe = *timeperframe; -+ sensor->streamcap.capturemode = -+ (u32)a->parm.capture.capturemode; -+ -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ pr_debug(" type is not " \ -+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", -+ a->type); -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap -+ * @s: pointer to standard V4L2 device structure -+ * @f: pointer to standard V4L2 v4l2_format structure -+ * -+ * Returns the sensor's current pixel format in the v4l2_format -+ * parameter. -+ */ -+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ f->fmt.pix = sensor->pix; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure -+ * -+ * If the requested control is supported, returns the control's current -+ * value from the video_control[] array. Otherwise, returns -EINVAL -+ * if the control is not supported. -+ */ -+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int ret = 0; -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ vc->value = ov5640_data.brightness; -+ break; -+ case V4L2_CID_HUE: -+ vc->value = ov5640_data.hue; -+ break; -+ case V4L2_CID_CONTRAST: -+ vc->value = ov5640_data.contrast; -+ break; -+ case V4L2_CID_SATURATION: -+ vc->value = ov5640_data.saturation; -+ break; -+ case V4L2_CID_RED_BALANCE: -+ vc->value = ov5640_data.red; -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ vc->value = ov5640_data.blue; -+ break; -+ case V4L2_CID_EXPOSURE: -+ vc->value = ov5640_data.ae_mode; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure -+ * -+ * If the requested control is supported, sets the control's current -+ * value in HW (and updates the video_control[] array). Otherwise, -+ * returns -EINVAL if the control is not supported. -+ */ -+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int retval = 0; -+ -+ pr_debug("In ov5640:ioctl_s_ctrl %d\n", -+ vc->id); -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ break; -+ case V4L2_CID_CONTRAST: -+ break; -+ case V4L2_CID_SATURATION: -+ break; -+ case V4L2_CID_HUE: -+ break; -+ case V4L2_CID_AUTO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_DO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_RED_BALANCE: -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ break; -+ case V4L2_CID_GAMMA: -+ break; -+ case V4L2_CID_EXPOSURE: -+ break; -+ case V4L2_CID_AUTOGAIN: -+ break; -+ case V4L2_CID_GAIN: -+ break; -+ case V4L2_CID_HFLIP: -+ break; -+ case V4L2_CID_VFLIP: -+ break; -+ default: -+ retval = -EPERM; -+ break; -+ } -+ -+ return retval; -+} -+ -+/*! -+ * ioctl_enum_framesizes - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMESIZES ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_framesizes(struct v4l2_int_device *s, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index > ov5640_mode_MAX) -+ return -EINVAL; -+ -+ fsize->pixel_format = ov5640_data.pix.pixelformat; -+ fsize->discrete.width = -+ max(ov5640_mode_info_data[0][fsize->index].width, -+ ov5640_mode_info_data[1][fsize->index].width); -+ fsize->discrete.height = -+ max(ov5640_mode_info_data[0][fsize->index].height, -+ ov5640_mode_info_data[1][fsize->index].height); -+ return 0; -+} -+ -+/*! -+ * ioctl_g_chip_ident - V4L2 sensor interface handler for -+ * VIDIOC_DBG_G_CHIP_IDENT ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @id: pointer to int -+ * -+ * Return 0. -+ */ -+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) -+{ -+ ((struct v4l2_dbg_chip_ident *)id)->match.type = -+ V4L2_CHIP_MATCH_I2C_DRIVER; -+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, -+ "ov5640_mipi_camera"); -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT -+ * @s: pointer to standard V4L2 device structure -+ */ -+static int ioctl_init(struct v4l2_int_device *s) -+{ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT -+ * @s: pointer to standard V4L2 device structure -+ * @fmt: pointer to standard V4L2 fmt description structure -+ * -+ * Return 0. -+ */ -+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, -+ struct v4l2_fmtdesc *fmt) -+{ -+ if (fmt->index > ov5640_mode_MAX) -+ return -EINVAL; -+ -+ fmt->pixelformat = ov5640_data.pix.pixelformat; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Initialise the device when slave attaches to the master. -+ */ -+static int ioctl_dev_init(struct v4l2_int_device *s) -+{ -+ struct sensor_data *sensor = s->priv; -+ u32 tgt_xclk; /* target xclk */ -+ u32 tgt_fps; /* target frames per secound */ -+ int ret; -+ enum ov5640_frame_rate frame_rate; -+ void *mipi_csi2_info; -+ -+ ov5640_data.on = true; -+ -+ /* mclk */ -+ tgt_xclk = ov5640_data.mclk; -+ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX); -+ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN); -+ ov5640_data.mclk = tgt_xclk; -+ -+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); -+ -+ /* Default camera frame rate is set in probe */ -+ tgt_fps = sensor->streamcap.timeperframe.denominator / -+ sensor->streamcap.timeperframe.numerator; -+ -+ if (tgt_fps == 15) -+ frame_rate = ov5640_15_fps; -+ else if (tgt_fps == 30) -+ frame_rate = ov5640_30_fps; -+ else -+ return -EINVAL; /* Only support 15fps or 30fps now. */ -+ -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ /* enable mipi csi2 */ -+ if (mipi_csi2_info) -+ mipi_csi2_enable(mipi_csi2_info); -+ else { -+ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n", -+ __func__, __FILE__); -+ return -EPERM; -+ } -+ -+ ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT); -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Delinitialise the device when slave detaches to the master. -+ */ -+static int ioctl_dev_exit(struct v4l2_int_device *s) -+{ -+ void *mipi_csi2_info; -+ -+ mipi_csi2_info = mipi_csi2_get_info(); -+ -+ /* disable mipi csi2 */ -+ if (mipi_csi2_info) -+ if (mipi_csi2_get_status(mipi_csi2_info)) -+ mipi_csi2_disable(mipi_csi2_info); -+ -+ return 0; -+} -+ -+/*! -+ * This structure defines all the ioctls for this module and links them to the -+ * enumeration. -+ */ -+static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = { -+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init}, -+ {vidioc_int_dev_exit_num, ioctl_dev_exit}, -+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power}, -+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm}, -+/* {vidioc_int_g_needs_reset_num, -+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ -+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ -+ {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init}, -+ {vidioc_int_enum_fmt_cap_num, -+ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, -+/* {vidioc_int_try_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ -+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, -+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */ -+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, -+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, -+/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */ -+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, -+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, -+ {vidioc_int_enum_framesizes_num, -+ (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, -+ {vidioc_int_g_chip_ident_num, -+ (v4l2_int_ioctl_func *) ioctl_g_chip_ident}, -+}; -+ -+static struct v4l2_int_slave ov5640_slave = { -+ .ioctls = ov5640_ioctl_desc, -+ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc), -+}; -+ -+static struct v4l2_int_device ov5640_int_device = { -+ .module = THIS_MODULE, -+ .name = "ov5640", -+ .type = v4l2_int_type_slave, -+ .u = { -+ .slave = &ov5640_slave, -+ }, -+}; -+ -+/*! -+ * ov5640 I2C probe function -+ * -+ * @param adapter struct i2c_adapter * -+ * @return Error code indicating success or failure -+ */ -+static int ov5640_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct device *dev = &client->dev; -+ int retval; -+ u8 chip_id_high, chip_id_low; -+ -+ /* request power down pin */ -+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); -+ if (!gpio_is_valid(pwn_gpio)) { -+ dev_warn(dev, "no sensor pwdn pin available"); -+ return -EINVAL; -+ } -+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5640_mipi_pwdn"); -+ if (retval < 0) -+ return retval; -+ -+ /* request reset pin */ -+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); -+ if (!gpio_is_valid(rst_gpio)) { -+ dev_warn(dev, "no sensor reset pin available"); -+ return -EINVAL; -+ } -+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5640_mipi_reset"); -+ if (retval < 0) -+ return retval; -+ -+ /* Set initial values for the sensor struct. */ -+ memset(&ov5640_data, 0, sizeof(ov5640_data)); -+ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); -+ if (IS_ERR(ov5640_data.sensor_clk)) { -+ /* assuming clock enabled by default */ -+ ov5640_data.sensor_clk = NULL; -+ dev_err(dev, "clock-frequency missing or invalid\n"); -+ return PTR_ERR(ov5640_data.sensor_clk); -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk", -+ &(ov5640_data.mclk)); -+ if (retval) { -+ dev_err(dev, "mclk missing or invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk_source", -+ (u32 *) &(ov5640_data.mclk_source)); -+ if (retval) { -+ dev_err(dev, "mclk_source missing or invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "csi_id", -+ &(ov5640_data.csi)); -+ if (retval) { -+ dev_err(dev, "csi id missing or invalid\n"); -+ return retval; -+ } -+ -+ clk_prepare_enable(ov5640_data.sensor_clk); -+ -+ ov5640_data.io_init = ov5640_reset; -+ ov5640_data.i2c_client = client; -+ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; -+ ov5640_data.pix.width = 640; -+ ov5640_data.pix.height = 480; -+ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | -+ V4L2_CAP_TIMEPERFRAME; -+ ov5640_data.streamcap.capturemode = 0; -+ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS; -+ ov5640_data.streamcap.timeperframe.numerator = 1; -+ -+ ov5640_power_on(dev); -+ -+ ov5640_reset(); -+ -+ ov5640_standby(0); -+ -+ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high); -+ if (retval < 0 || chip_id_high != 0x56) { -+ pr_warning("camera ov5640_mipi is not found\n"); -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ return -ENODEV; -+ } -+ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low); -+ if (retval < 0 || chip_id_low != 0x40) { -+ pr_warning("camera ov5640_mipi is not found\n"); -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ return -ENODEV; -+ } -+ -+ ov5640_standby(1); -+ -+ ov5640_int_device.priv = &ov5640_data; -+ retval = v4l2_int_device_register(&ov5640_int_device); -+ -+ clk_disable_unprepare(ov5640_data.sensor_clk); -+ -+ pr_info("camera ov5640_mipi is found\n"); -+ return retval; -+} -+ -+/*! -+ * ov5640 I2C detach function -+ * -+ * @param client struct i2c_client * -+ * @return Error code indicating success or failure -+ */ -+static int ov5640_remove(struct i2c_client *client) -+{ -+ v4l2_int_device_unregister(&ov5640_int_device); -+ -+ if (gpo_regulator) -+ regulator_disable(gpo_regulator); -+ -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ -+ return 0; -+} -+ -+/*! -+ * ov5640 init function -+ * Called by insmod ov5640_camera.ko. -+ * -+ * @return Error code indicating success or failure -+ */ -+static __init int ov5640_init(void) -+{ -+ u8 err; -+ -+ err = i2c_add_driver(&ov5640_i2c_driver); -+ if (err != 0) -+ pr_err("%s:driver registration failed, error=%d\n", -+ __func__, err); -+ -+ return err; -+} -+ -+/*! -+ * OV5640 cleanup function -+ * Called on rmmod ov5640_camera.ko -+ * -+ * @return Error code indicating success or failure -+ */ -+static void __exit ov5640_clean(void) -+{ -+ i2c_del_driver(&ov5640_i2c_driver); -+} -+ -+module_init(ov5640_init); -+module_exit(ov5640_clean); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("OV5640 MIPI Camera Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.0"); -+MODULE_ALIAS("CSI"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5642.c linux-3.14.22/drivers/media/platform/mxc/capture/ov5642.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/capture/ov5642.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/capture/ov5642.c 2014-10-22 14:55:52.626220001 -0500 -@@ -0,0 +1,4252 @@ -+/* -+ * Copyright (C) 2012-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. -+ -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mxc_v4l2_capture.h" -+ -+#define OV5642_VOLTAGE_ANALOG 2800000 -+#define OV5642_VOLTAGE_DIGITAL_CORE 1500000 -+#define OV5642_VOLTAGE_DIGITAL_IO 1800000 -+ -+#define MIN_FPS 15 -+#define MAX_FPS 30 -+#define DEFAULT_FPS 30 -+ -+#define OV5642_XCLK_MIN 6000000 -+#define OV5642_XCLK_MAX 24000000 -+ -+#define OV5642_CHIP_ID_HIGH_BYTE 0x300A -+#define OV5642_CHIP_ID_LOW_BYTE 0x300B -+ -+enum ov5642_mode { -+ ov5642_mode_MIN = 0, -+ ov5642_mode_VGA_640_480 = 0, -+ ov5642_mode_QVGA_320_240 = 1, -+ ov5642_mode_NTSC_720_480 = 2, -+ ov5642_mode_PAL_720_576 = 3, -+ ov5642_mode_720P_1280_720 = 4, -+ ov5642_mode_1080P_1920_1080 = 5, -+ ov5642_mode_QSXGA_2592_1944 = 6, -+ ov5642_mode_QCIF_176_144 = 7, -+ ov5642_mode_XGA_1024_768 = 8, -+ ov5642_mode_MAX = 8 -+}; -+ -+enum ov5642_frame_rate { -+ ov5642_15_fps, -+ ov5642_30_fps -+}; -+ -+static int ov5642_framerates[] = { -+ [ov5642_15_fps] = 15, -+ [ov5642_30_fps] = 30, -+}; -+ -+struct reg_value { -+ u16 u16RegAddr; -+ u8 u8Val; -+ u8 u8Mask; -+ u32 u32Delay_ms; -+}; -+ -+struct ov5642_mode_info { -+ enum ov5642_mode mode; -+ u32 width; -+ u32 height; -+ struct reg_value *init_data_ptr; -+ u32 init_data_size; -+}; -+ -+/*! -+ * Maintains the information on the current state of the sesor. -+ */ -+static struct sensor_data ov5642_data; -+static int pwn_gpio, rst_gpio; -+ -+static struct reg_value ov5642_rot_none_VGA[] = { -+ {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_vert_flip_VGA[] = { -+ {0x3818, 0x20, 0xbf, 0x00}, {0x3621, 0x20, 0xff, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_horiz_flip_VGA[] = { -+ {0x3818, 0x81, 0x00, 0x01}, {0x3621, 0xa7, 0x00, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_180_VGA[] = { -+ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00}, -+}; -+ -+ -+static struct reg_value ov5642_rot_none_FULL[] = { -+ {0x3818, 0xc0, 0x00, 0x00}, {0x3621, 0x09, 0x00, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_vert_flip_FULL[] = { -+ {0x3818, 0x20, 0xbf, 0x01}, {0x3621, 0x20, 0xff, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_horiz_flip_FULL[] = { -+ {0x3818, 0x80, 0x00, 0x01}, {0x3621, 0x29, 0x00, 0x00}, -+}; -+ -+static struct reg_value ov5642_rot_180_FULL[] = { -+ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00}, -+}; -+ -+ -+static struct reg_value ov5642_initial_setting[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c00, 0x04, 0, 0}, {0x3c01, 0x80, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, -+ {0x5182, 0x00, 0, 0}, {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, -+ {0x5001, 0xff, 0, 0}, {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, -+ {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, -+ {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, -+ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, -+ {0x380b, 0xe0, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, -+ {0x501f, 0x00, 0, 0}, {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, -+ {0x350b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x0b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 300}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_QCIF_176_144[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, -+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, -+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, -+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, -+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, -+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, -+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, -+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, -+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, -+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, -+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, -+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, -+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, -+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, -+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, -+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, -+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, -+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, -+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, -+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, -+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, -+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, -+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, -+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, -+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, -+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, -+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, -+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, -+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, -+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, -+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, -+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, -+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, -+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, -+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, -+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, -+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, -+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, -+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, -+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, -+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, -+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, -+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, -+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, -+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, -+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, -+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, -+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, -+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, -+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, -+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, -+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, -+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, -+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, -+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, -+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, -+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, -+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, -+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, -+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, -+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, -+ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, -+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, -+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, -+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, -+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, -+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, -+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, -+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, -+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, -+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, -+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, -+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, -+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, -+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, -+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, -+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, -+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, -+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, -+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, -+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, -+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, -+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, -+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, -+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, -+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, -+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, -+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, -+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, -+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, -+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, -+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, -+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, -+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, -+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, -+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, -+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, -+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, -+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, -+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, -+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, -+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, -+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, -+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, -+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, -+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, -+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, -+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, -+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, -+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, -+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, -+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, -+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, -+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, -+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, -+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, -+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, -+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, -+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, -+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, -+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, -+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0}, -+ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_QCIF_176_144[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x10, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, -+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, -+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, -+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, -+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, -+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, -+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, -+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, -+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, -+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, -+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, -+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, -+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, -+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, -+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, -+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, -+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, -+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, -+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, -+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, -+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, -+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, -+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, -+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, -+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, -+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, -+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, -+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, -+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, -+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, -+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, -+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, -+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, -+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, -+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, -+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, -+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, -+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, -+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, -+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, -+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, -+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, -+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, -+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, -+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, -+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, -+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, -+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, -+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, -+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, -+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, -+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, -+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, -+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, -+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, -+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, -+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, -+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, -+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, -+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, -+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, -+ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, -+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, -+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, -+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, -+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, -+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, -+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, -+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, -+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, -+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, -+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, -+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, -+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, -+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, -+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, -+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, -+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, -+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, -+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, -+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, -+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, -+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, -+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, -+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, -+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, -+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, -+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, -+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, -+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, -+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, -+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, -+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, -+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, -+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, -+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, -+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, -+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, -+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, -+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, -+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, -+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, -+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, -+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, -+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, -+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, -+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, -+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, -+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, -+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, -+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, -+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, -+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, -+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, -+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, -+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, -+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, -+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, -+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, -+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, -+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, -+ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0}, -+ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_QSXGA_2592_1944[] = { -+ {0x3503, 0x07, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, -+ {0x3002, 0x00, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, -+ {0x3005, 0xff, 0, 0}, {0x3006, 0xff, 0, 0}, {0x3007, 0x3f, 0, 0}, -+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3818, 0xc0, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3602, 0xe4, 0, 0}, {0x3612, 0xac, 0, 0}, {0x3613, 0x44, 0, 0}, -+ {0x3622, 0x60, 0, 0}, {0x3623, 0x22, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3705, 0xda, 0, 0}, {0x370a, 0x80, 0, 0}, {0x3801, 0x95, 0, 0}, -+ {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x20, 0, 0}, -+ {0x3806, 0x07, 0, 0}, {0x3807, 0x98, 0, 0}, {0x3808, 0x0a, 0, 0}, -+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, -+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3815, 0x44, 0, 0}, -+ {0x3824, 0x11, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, -+ {0x3a00, 0x78, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, -+ {0x5682, 0x0a, 0, 0}, {0x5683, 0x20, 0, 0}, {0x5686, 0x07, 0, 0}, -+ {0x5687, 0x98, 0, 0}, {0x5001, 0xff, 0, 0}, {0x589b, 0x00, 0, 0}, -+ {0x589a, 0xc0, 0, 0}, {0x4407, 0x04, 0, 0}, {0x3008, 0x02, 0, 0}, -+ {0x460b, 0x37, 0, 0}, {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, -+ {0x4713, 0x03, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x3815, 0x01, 0, 0}, -+ {0x501f, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0}, -+ {0x5002, 0xe0, 0, 0}, {0x530a, 0x01, 0, 0}, {0x530d, 0x10, 0, 0}, -+ {0x530c, 0x04, 0, 0}, {0x5312, 0x20, 0, 0}, {0x5282, 0x01, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x3012, 0x00, 0, 0}, -+}; -+ -+ -+static struct reg_value ov5642_setting_VGA_2_QVGA[] = { -+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, -+ {0x380b, 0xf0, 0, 0}, {0x3815, 0x04, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_QSXGA_2_VGA[] = { -+ {0x3503, 0x00, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, -+ {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, -+ {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x3818, 0xc1, 0, 0}, {0x3621, 0x87, 0, 0}, -+ {0x350c, 0x03, 0, 0}, {0x350d, 0xe8, 0, 0}, {0x3602, 0xfc, 0, 0}, -+ {0x3612, 0xff, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3622, 0x60, 0, 0}, -+ {0x3623, 0x01, 0, 0}, {0x3604, 0x48, 0, 0}, {0x3705, 0xdb, 0, 0}, -+ {0x370a, 0x81, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, -+ {0x3807, 0xc0, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, -+ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3810, 0x40, 0, 0}, {0x3815, 0x04, 0, 0}, {0x3824, 0x11, 0, 0}, -+ {0x3825, 0xb4, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, -+ {0x5001, 0xff, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x4407, 0x0c, 0, 0}, {0x3008, 0x02, 0, 0}, {0x460b, 0x37, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4713, 0x02, 0, 0}, -+ {0x471c, 0xd0, 0, 0}, {0x3815, 0x04, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x3002, 0x5c, 0, 0}, {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, -+ {0x530a, 0x01, 0, 0}, {0x530d, 0x0c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x5312, 0x40, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x3012, 0x02, 0, 0}, {0x3010, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_VGA_640_480[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_VGA_640_480[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+}; -+ -+ -+static struct reg_value ov5642_setting_30fps_XGA_1024_768[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, -+ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_XGA_1024_768[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, -+ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_QVGA_320_240[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3808, 0x01, 0, 0}, -+ {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_NTSC_720_480[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, -+ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x302c, 0x60, 0x60, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_PAL_720_576[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, -+ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, -+ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, -+ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, -+ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xd8, 0, 0}, -+ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, -+ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, -+ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, -+ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, -+ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0}, -+ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x5682, 0x04, 0, 0}, -+ {0x5683, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0}, -+ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, -+ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, -+ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, -+ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, -+ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, -+ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, -+ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, -+ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, -+ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, -+ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, -+ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, -+ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, -+ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, -+ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x302c, 0x60, 0x60, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_720P_1280_720[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, -+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, -+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, -+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, -+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, -+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, -+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, -+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, -+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, -+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, -+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, -+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, -+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, -+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, -+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, -+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, -+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, -+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, -+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, -+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, -+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, -+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, -+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, -+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0}, -+ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0}, -+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0}, -+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0}, -+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0}, -+ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0}, -+ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0}, -+ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0}, -+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0}, -+ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0}, -+ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0}, -+ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, -+ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, -+ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, {0x3010, 0x30, 0, 0}, -+ {0x3a08, 0x06, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x05, 0, 0}, -+ {0x3a0b, 0x50, 0, 0}, {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x07, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_30fps_720P_1280_720[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, -+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, -+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, -+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, -+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, -+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, -+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, -+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, -+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, -+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, -+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, -+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, -+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, -+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, -+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, -+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, -+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, -+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, -+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, -+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, -+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, -+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, -+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, -+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0}, -+ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0}, -+ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0}, -+ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0}, -+ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0}, -+ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0}, -+ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0}, -+ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0}, -+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0}, -+ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0}, -+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0}, -+ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0}, -+ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, -+ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, -+ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, -+ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_1080P_1920_1080[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, -+ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, -+ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, -+ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, -+ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, -+ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, -+ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, -+ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, -+ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, -+ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, -+ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, -+ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, -+ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, -+ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, -+ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, -+ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, -+ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, -+ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, -+ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, -+ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, -+ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, -+ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, -+ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, -+ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, -+ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, -+ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, -+ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, -+ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, -+ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, -+ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, -+ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, -+ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, -+ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, -+ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, -+ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, -+ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, -+ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, -+ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, -+ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, -+ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, -+ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, -+ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, -+ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, -+ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, -+ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, -+ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, -+ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, -+ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, -+ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, -+ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, -+ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, -+ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, -+ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, -+ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, -+ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, -+ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, -+ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, -+ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, -+ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, -+ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, -+ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, -+ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, -+ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, -+ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, -+ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, -+ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, -+ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, -+ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, -+ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, -+ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, -+ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, -+ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, -+ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, -+ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, -+ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, -+ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, -+ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, -+ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, -+ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, -+ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, -+ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, -+ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, -+ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, -+ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, -+ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, -+ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, -+ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, -+ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, -+ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, -+ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, -+ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, -+ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, -+ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, -+ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, -+ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, -+ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, -+ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, -+ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, -+ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, -+ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, -+ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, -+ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, -+ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, -+ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, -+ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, -+ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, -+ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, -+ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, -+ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, -+ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, -+ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, -+ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, -+ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, -+ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, -+ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, -+ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, -+ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, -+ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, -+ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, -+ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, -+ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, -+ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, -+ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, -+ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, -+ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, -+ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, -+ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, -+ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, -+ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, -+ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, -+ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, -+ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, -+ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, -+ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, -+ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, -+ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x07, 0, 0}, -+ {0x350c, 0x04, 0, 0}, {0x350d, 0x58, 0, 0}, {0x3801, 0x8a, 0, 0}, -+ {0x3803, 0x0a, 0, 0}, {0x3804, 0x07, 0, 0}, {0x3805, 0x80, 0, 0}, -+ {0x3806, 0x04, 0, 0}, {0x3807, 0x39, 0, 0}, {0x3808, 0x07, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, -+ {0x380c, 0x09, 0, 0}, {0x380d, 0xd6, 0, 0}, {0x380e, 0x04, 0, 0}, -+ {0x380f, 0x58, 0, 0}, {0x381c, 0x11, 0, 0}, {0x381d, 0xba, 0, 0}, -+ {0x381e, 0x04, 0, 0}, {0x381f, 0x48, 0, 0}, {0x3820, 0x04, 0, 0}, -+ {0x3821, 0x18, 0, 0}, {0x3a08, 0x14, 0, 0}, {0x3a09, 0xe0, 0, 0}, -+ {0x3a0a, 0x11, 0, 0}, {0x3a0b, 0x60, 0, 0}, {0x3a0d, 0x04, 0, 0}, -+ {0x3a0e, 0x03, 0, 0}, {0x5682, 0x07, 0, 0}, {0x5683, 0x60, 0, 0}, -+ {0x5686, 0x04, 0, 0}, {0x5687, 0x1c, 0, 0}, {0x5001, 0x7f, 0, 0}, -+ {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, {0x460c, 0x20, 0, 0}, -+ {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x471d, 0x05, 0, 0}, -+ {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, {0x501f, 0x00, 0, 0}, -+ {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0}, -+ {0x5002, 0xe0, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_QVGA_320_240[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, -+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, -+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, -+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, -+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, -+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, -+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, -+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, -+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, -+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, -+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, -+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, -+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, -+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, -+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, -+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, -+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, -+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, -+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, -+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, -+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, -+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, -+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, -+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, -+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, -+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, -+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, -+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, -+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, -+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, -+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, -+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, -+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, -+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, -+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, -+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, -+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, -+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, -+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, -+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, -+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, -+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, -+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, -+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, -+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, -+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, -+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, -+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, -+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, -+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, -+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, -+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, -+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, -+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, -+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, -+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, -+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, -+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, -+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, -+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, -+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, -+ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, -+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, -+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, -+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, -+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, -+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, -+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, -+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, -+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, -+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, -+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, -+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, -+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, -+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, -+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, -+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, -+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, -+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, -+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, -+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, -+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, -+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, -+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, -+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, -+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, -+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, -+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, -+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, -+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, -+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, -+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, -+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, -+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, -+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, -+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, -+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, -+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, -+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, -+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, -+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, -+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, -+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, -+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, -+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, -+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, -+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, -+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, -+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, -+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, -+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, -+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, -+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, -+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, -+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, -+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, -+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, -+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, -+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, -+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, -+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, -+ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, -+ {0x380b, 0xf0, 0, 0}, {0x3a00, 0x78, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_NTSC_720_480[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, -+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, -+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, -+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, -+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, -+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, -+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, -+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, -+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, -+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, -+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, -+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, -+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, -+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, -+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, -+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, -+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, -+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, -+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, -+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, -+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, -+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, -+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, -+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, -+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, -+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, -+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, -+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, -+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, -+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, -+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, -+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, -+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, -+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, -+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, -+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, -+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, -+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, -+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, -+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, -+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, -+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, -+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, -+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, -+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, -+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, -+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, -+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, -+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, -+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, -+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, -+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, -+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, -+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, -+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, -+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, -+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, -+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, -+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, -+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, -+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, -+ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, -+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, -+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, -+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, -+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, -+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, -+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, -+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, -+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, -+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, -+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, -+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, -+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, -+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, -+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, -+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, -+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, -+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, -+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, -+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, -+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, -+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, -+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, -+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, -+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, -+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, -+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, -+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, -+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, -+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, -+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, -+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, -+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, -+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, -+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, -+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, -+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, -+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, -+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, -+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, -+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, -+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, -+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, -+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, -+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, -+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, -+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, -+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, -+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, -+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, -+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, -+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, -+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, -+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, -+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, -+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, -+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, -+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, -+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, -+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, -+ {0x3824, 0x11, 0, 0}, {0x3825, 0xb4, 0, 0}, {0x3826, 0x00, 0, 0}, -+ {0x3827, 0x3d, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, -+ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0xd0, 0, 0}, {0x380A, 0x01, 0, 0}, {0x380B, 0xe0, 0, 0}, -+ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, -+ {0x3807, 0x55, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0x55, 0, 0}, -+ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+}; -+ -+static struct reg_value ov5642_setting_15fps_PAL_720_576[] = { -+ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, -+ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, -+ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, -+ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, -+ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, -+ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, -+ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, -+ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, -+ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, -+ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, -+ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, -+ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, -+ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, -+ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, -+ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, -+ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, -+ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, -+ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, -+ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, -+ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, -+ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, -+ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, -+ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, -+ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, -+ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, -+ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, -+ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, -+ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, -+ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, -+ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, -+ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, -+ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, -+ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, -+ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, -+ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, -+ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, -+ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, -+ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, -+ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, -+ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, -+ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, -+ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, -+ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, -+ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, -+ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, -+ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, -+ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, -+ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, -+ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, -+ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, -+ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, -+ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, -+ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, -+ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, -+ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, -+ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, -+ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, -+ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, -+ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, -+ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, -+ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, -+ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, -+ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, -+ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, -+ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, -+ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, -+ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, -+ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, -+ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, -+ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, -+ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, -+ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, -+ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, -+ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, -+ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, -+ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, -+ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, -+ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, -+ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, -+ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, -+ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, -+ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, -+ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, -+ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, -+ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, -+ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, -+ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, -+ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, -+ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, -+ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, -+ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, -+ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, -+ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, -+ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, -+ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, -+ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, -+ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, -+ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, -+ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, -+ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, -+ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, -+ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, -+ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, -+ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, -+ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, -+ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, -+ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, -+ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, -+ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, -+ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, -+ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, -+ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, -+ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, -+ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, -+ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, -+ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, -+ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, -+ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, -+ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, -+ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, -+ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, -+ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, -+ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, -+ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, -+ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, -+ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, -+ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, -+ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, -+ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, -+ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, -+ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, -+ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, -+ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, -+ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, -+ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, -+ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, -+ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, -+ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, -+ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, -+ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, -+ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, -+ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, -+ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, -+ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, -+ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, -+ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, -+ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, -+ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, -+ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, -+ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, -+ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, -+ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, -+ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, -+ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, -+ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, -+ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, -+ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, -+ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, -+ {0x3824, 0x11, 0, 0}, {0x3825, 0xdc, 0, 0}, {0x3826, 0x00, 0, 0}, -+ {0x3827, 0x08, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, -+ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0}, -+ {0x3809, 0xd0, 0, 0}, {0x380A, 0x02, 0, 0}, {0x380B, 0x40, 0, 0}, -+ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, -+ {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xc0, 0, 0}, -+ {0x5682, 0x04, 0, 0}, {0x5683, 0xb0, 0, 0}, -+}; -+ -+static struct ov5642_mode_info ov5642_mode_info_data[2][ov5642_mode_MAX + 1] = { -+ { -+ {ov5642_mode_VGA_640_480, 640, 480, -+ ov5642_setting_15fps_VGA_640_480, -+ ARRAY_SIZE(ov5642_setting_15fps_VGA_640_480)}, -+ {ov5642_mode_QVGA_320_240, 320, 240, -+ ov5642_setting_15fps_QVGA_320_240, -+ ARRAY_SIZE(ov5642_setting_15fps_QVGA_320_240)}, -+ {ov5642_mode_NTSC_720_480, 720, 480, -+ ov5642_setting_15fps_NTSC_720_480, -+ ARRAY_SIZE(ov5642_setting_15fps_NTSC_720_480)}, -+ {ov5642_mode_PAL_720_576, 720, 576, -+ ov5642_setting_15fps_PAL_720_576, -+ ARRAY_SIZE(ov5642_setting_15fps_PAL_720_576)}, -+ {ov5642_mode_720P_1280_720, 1280, 720, -+ ov5642_setting_15fps_720P_1280_720, -+ ARRAY_SIZE(ov5642_setting_15fps_720P_1280_720)}, -+ {ov5642_mode_1080P_1920_1080, 1920, 1080, -+ ov5642_setting_15fps_1080P_1920_1080, -+ ARRAY_SIZE(ov5642_setting_15fps_1080P_1920_1080)}, -+ {ov5642_mode_QSXGA_2592_1944, 2592, 1944, -+ ov5642_setting_15fps_QSXGA_2592_1944, -+ ARRAY_SIZE(ov5642_setting_15fps_QSXGA_2592_1944)}, -+ {ov5642_mode_QCIF_176_144, 176, 144, -+ ov5642_setting_15fps_QCIF_176_144, -+ ARRAY_SIZE(ov5642_setting_15fps_QCIF_176_144)}, -+ {ov5642_mode_XGA_1024_768, 1024, 768, -+ ov5642_setting_15fps_XGA_1024_768, -+ ARRAY_SIZE(ov5642_setting_15fps_XGA_1024_768)}, -+ }, -+ { -+ {ov5642_mode_VGA_640_480, 640, 480, -+ ov5642_setting_30fps_VGA_640_480, -+ ARRAY_SIZE(ov5642_setting_30fps_VGA_640_480)}, -+ {ov5642_mode_QVGA_320_240, 320, 240, -+ ov5642_setting_30fps_QVGA_320_240, -+ ARRAY_SIZE(ov5642_setting_30fps_QVGA_320_240)}, -+ {ov5642_mode_NTSC_720_480, 720, 480, -+ ov5642_setting_30fps_NTSC_720_480, -+ ARRAY_SIZE(ov5642_setting_30fps_NTSC_720_480)}, -+ {ov5642_mode_PAL_720_576, 720, 576, -+ ov5642_setting_30fps_PAL_720_576, -+ ARRAY_SIZE(ov5642_setting_30fps_PAL_720_576)}, -+ {ov5642_mode_720P_1280_720, 1280, 720, -+ ov5642_setting_30fps_720P_1280_720, -+ ARRAY_SIZE(ov5642_setting_30fps_720P_1280_720)}, -+ {ov5642_mode_1080P_1920_1080, 0, 0, NULL, 0}, -+ {ov5642_mode_QSXGA_2592_1944, 0, 0, NULL, 0}, -+ {ov5642_mode_QCIF_176_144, 176, 144, -+ ov5642_setting_30fps_QCIF_176_144, -+ ARRAY_SIZE(ov5642_setting_30fps_QCIF_176_144)}, -+ {ov5642_mode_XGA_1024_768, 1024, 768, -+ ov5642_setting_30fps_XGA_1024_768, -+ ARRAY_SIZE(ov5642_setting_30fps_XGA_1024_768)}, -+ }, -+}; -+ -+static struct regulator *io_regulator; -+static struct regulator *core_regulator; -+static struct regulator *analog_regulator; -+static struct regulator *gpo_regulator; -+ -+static int ov5642_probe(struct i2c_client *adapter, -+ const struct i2c_device_id *device_id); -+static int ov5642_remove(struct i2c_client *client); -+ -+static s32 ov5642_read_reg(u16 reg, u8 *val); -+static s32 ov5642_write_reg(u16 reg, u8 val); -+ -+static const struct i2c_device_id ov5642_id[] = { -+ {"ov5642", 0}, -+ {"ov564x", 0}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(i2c, ov5642_id); -+ -+static struct i2c_driver ov5642_i2c_driver = { -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "ov5642", -+ }, -+ .probe = ov5642_probe, -+ .remove = ov5642_remove, -+ .id_table = ov5642_id, -+}; -+ -+static void ov5642_standby(s32 enable) -+{ -+ if (enable) -+ gpio_set_value(pwn_gpio, 1); -+ else -+ gpio_set_value(pwn_gpio, 0); -+ -+ msleep(2); -+} -+ -+static void ov5642_reset(void) -+{ -+ /* camera reset */ -+ gpio_set_value(rst_gpio, 1); -+ -+ /* camera power down */ -+ gpio_set_value(pwn_gpio, 1); -+ msleep(5); -+ -+ gpio_set_value(pwn_gpio, 0); -+ msleep(5); -+ -+ gpio_set_value(rst_gpio, 0); -+ msleep(1); -+ -+ gpio_set_value(rst_gpio, 1); -+ msleep(5); -+ -+ gpio_set_value(pwn_gpio, 1); -+} -+ -+static int ov5642_power_on(struct device *dev) -+{ -+ int ret = 0; -+ -+ io_regulator = devm_regulator_get(dev, "DOVDD"); -+ if (!IS_ERR(io_regulator)) { -+ regulator_set_voltage(io_regulator, -+ OV5642_VOLTAGE_DIGITAL_IO, -+ OV5642_VOLTAGE_DIGITAL_IO); -+ ret = regulator_enable(io_regulator); -+ if (ret) { -+ pr_err("%s:io set voltage error\n", __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:io set voltage ok\n", __func__); -+ } -+ } else { -+ pr_err("%s: cannot get io voltage error\n", __func__); -+ io_regulator = NULL; -+ } -+ -+ core_regulator = devm_regulator_get(dev, "DVDD"); -+ if (!IS_ERR(core_regulator)) { -+ regulator_set_voltage(core_regulator, -+ OV5642_VOLTAGE_DIGITAL_CORE, -+ OV5642_VOLTAGE_DIGITAL_CORE); -+ ret = regulator_enable(core_regulator); -+ if (ret) { -+ pr_err("%s:core set voltage error\n", __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:core set voltage ok\n", __func__); -+ } -+ } else { -+ core_regulator = NULL; -+ pr_err("%s: cannot get core voltage error\n", __func__); -+ } -+ -+ analog_regulator = devm_regulator_get(dev, "AVDD"); -+ if (!IS_ERR(analog_regulator)) { -+ regulator_set_voltage(analog_regulator, -+ OV5642_VOLTAGE_ANALOG, -+ OV5642_VOLTAGE_ANALOG); -+ ret = regulator_enable(analog_regulator); -+ if (ret) { -+ pr_err("%s:analog set voltage error\n", -+ __func__); -+ return ret; -+ } else { -+ dev_dbg(dev, -+ "%s:analog set voltage ok\n", __func__); -+ } -+ } else { -+ analog_regulator = NULL; -+ pr_err("%s: cannot get analog voltage error\n", __func__); -+ } -+ -+ return ret; -+} -+ -+static s32 ov5642_write_reg(u16 reg, u8 val) -+{ -+ u8 au8Buf[3] = {0}; -+ -+ au8Buf[0] = reg >> 8; -+ au8Buf[1] = reg & 0xff; -+ au8Buf[2] = val; -+ -+ if (i2c_master_send(ov5642_data.i2c_client, au8Buf, 3) < 0) { -+ pr_err("%s:write reg error:reg=%x,val=%x\n", -+ __func__, reg, val); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static s32 ov5642_read_reg(u16 reg, u8 *val) -+{ -+ u8 au8RegBuf[2] = {0}; -+ u8 u8RdVal = 0; -+ -+ au8RegBuf[0] = reg >> 8; -+ au8RegBuf[1] = reg & 0xff; -+ -+ if (2 != i2c_master_send(ov5642_data.i2c_client, au8RegBuf, 2)) { -+ pr_err("%s:write reg error:reg=%x\n", -+ __func__, reg); -+ return -1; -+ } -+ -+ if (1 != i2c_master_recv(ov5642_data.i2c_client, &u8RdVal, 1)) { -+ pr_err("%s:read reg error:reg=%x,val=%x\n", -+ __func__, reg, u8RdVal); -+ return -1; -+ } -+ -+ *val = u8RdVal; -+ -+ return u8RdVal; -+} -+ -+static int ov5642_set_rot_mode(struct reg_value *rot_mode) -+{ -+ s32 i = 0; -+ s32 iModeSettingArySize = 2; -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int retval = 0; -+ for (i = 0; i < iModeSettingArySize; ++i, ++rot_mode) { -+ Delay_ms = rot_mode->u32Delay_ms; -+ RegAddr = rot_mode->u16RegAddr; -+ Val = rot_mode->u8Val; -+ Mask = rot_mode->u8Mask; -+ -+ if (Mask) { -+ retval = ov5642_read_reg(RegAddr, &RegVal); -+ if (retval < 0) { -+ pr_err("%s, read reg 0x%x failed\n", -+ __func__, RegAddr); -+ goto err; -+ } -+ -+ Val |= RegVal; -+ Val &= Mask; -+ } -+ -+ retval = ov5642_write_reg(RegAddr, Val); -+ if (retval < 0) { -+ pr_err("%s, write reg 0x%x failed\n", -+ __func__, RegAddr); -+ goto err; -+ } -+ -+ if (Delay_ms) -+ mdelay(Delay_ms); -+ } -+err: -+ return retval; -+} -+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate, -+ enum ov5642_mode mode); -+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate, -+ enum ov5642_mode mode); -+static int ov5642_change_mode(enum ov5642_frame_rate new_frame_rate, -+ enum ov5642_frame_rate old_frame_rate, -+ enum ov5642_mode new_mode, -+ enum ov5642_mode orig_mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 i = 0; -+ s32 iModeSettingArySize = 0; -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int retval = 0; -+ -+ if (new_mode > ov5642_mode_MAX || new_mode < ov5642_mode_MIN) { -+ pr_err("Wrong ov5642 mode detected!\n"); -+ return -1; -+ } -+ -+ if ((new_frame_rate == old_frame_rate) && -+ (new_mode == ov5642_mode_VGA_640_480) && -+ (orig_mode == ov5642_mode_QSXGA_2592_1944)) { -+ pModeSetting = ov5642_setting_QSXGA_2_VGA; -+ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_QSXGA_2_VGA); -+ ov5642_data.pix.width = 640; -+ ov5642_data.pix.height = 480; -+ } else if ((new_frame_rate == old_frame_rate) && -+ (new_mode == ov5642_mode_QVGA_320_240) && -+ (orig_mode == ov5642_mode_VGA_640_480)) { -+ pModeSetting = ov5642_setting_VGA_2_QVGA; -+ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_VGA_2_QVGA); -+ ov5642_data.pix.width = 320; -+ ov5642_data.pix.height = 240; -+ } else { -+ retval = ov5642_write_snapshot_para(new_frame_rate, new_mode); -+ goto err; -+ } -+ -+ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 || -+ pModeSetting == NULL || iModeSettingArySize == 0) -+ return -EINVAL; -+ -+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { -+ Delay_ms = pModeSetting->u32Delay_ms; -+ RegAddr = pModeSetting->u16RegAddr; -+ Val = pModeSetting->u8Val; -+ Mask = pModeSetting->u8Mask; -+ -+ if (Mask) { -+ retval = ov5642_read_reg(RegAddr, &RegVal); -+ if (retval < 0) { -+ pr_err("read reg error addr=0x%x", RegAddr); -+ goto err; -+ } -+ -+ RegVal &= ~(u8)Mask; -+ Val &= Mask; -+ Val |= RegVal; -+ } -+ -+ retval = ov5642_write_reg(RegAddr, Val); -+ if (retval < 0) { -+ pr_err("write reg error addr=0x%x", RegAddr); -+ goto err; -+ } -+ -+ if (Delay_ms) -+ msleep(Delay_ms); -+ } -+err: -+ return retval; -+} -+static int ov5642_init_mode(enum ov5642_frame_rate frame_rate, -+ enum ov5642_mode mode) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 i = 0; -+ s32 iModeSettingArySize = 0; -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int retval = 0; -+ -+ if (mode > ov5642_mode_MAX || mode < ov5642_mode_MIN) { -+ pr_err("Wrong ov5642 mode detected!\n"); -+ return -1; -+ } -+ -+ pModeSetting = ov5642_mode_info_data[frame_rate][mode].init_data_ptr; -+ iModeSettingArySize = -+ ov5642_mode_info_data[frame_rate][mode].init_data_size; -+ -+ ov5642_data.pix.width = ov5642_mode_info_data[frame_rate][mode].width; -+ ov5642_data.pix.height = ov5642_mode_info_data[frame_rate][mode].height; -+ -+ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 || -+ pModeSetting == NULL || iModeSettingArySize == 0) -+ return -EINVAL; -+ -+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { -+ Delay_ms = pModeSetting->u32Delay_ms; -+ RegAddr = pModeSetting->u16RegAddr; -+ Val = pModeSetting->u8Val; -+ Mask = pModeSetting->u8Mask; -+ -+ if (Mask) { -+ retval = ov5642_read_reg(RegAddr, &RegVal); -+ if (retval < 0) { -+ pr_err("read reg error addr=0x%x", RegAddr); -+ goto err; -+ } -+ -+ RegVal &= ~(u8)Mask; -+ Val &= Mask; -+ Val |= RegVal; -+ } -+ -+ retval = ov5642_write_reg(RegAddr, Val); -+ if (retval < 0) { -+ pr_err("write reg error addr=0x%x", RegAddr); -+ goto err; -+ } -+ -+ if (Delay_ms) -+ msleep(Delay_ms); -+ } -+err: -+ return retval; -+} -+ -+static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate, -+ enum ov5642_mode mode) -+{ -+ int ret = 0; -+ bool m_60Hz = false; -+ u16 cap_frame_rate = 50; -+ u16 g_prev_frame_rate = 225; -+ -+ u8 ev_low, ev_mid, ev_high; -+ u8 ret_l, ret_m, ret_h, gain, lines_10ms; -+ u16 ulcap_ev, icap_gain, prev_maxlines; -+ u32 ulcap_ev_gain, cap_maxlines, g_prev_ev; -+ -+ ov5642_write_reg(0x3503, 0x07); -+ -+ ret_h = ret_m = ret_l = 0; -+ g_prev_ev = 0; -+ ov5642_read_reg(0x3500, &ret_h); -+ ov5642_read_reg(0x3501, &ret_m); -+ ov5642_read_reg(0x3502, &ret_l); -+ g_prev_ev = (ret_h << 12) + (ret_m << 4) + (ret_l >> 4); -+ -+ ret_h = ret_m = ret_l = 0; -+ prev_maxlines = 0; -+ ov5642_read_reg(0x380e, &ret_h); -+ ov5642_read_reg(0x380f, &ret_l); -+ prev_maxlines = (ret_h << 8) + ret_l; -+ /*Read back AGC Gain for preview*/ -+ gain = 0; -+ ov5642_read_reg(0x350b, &gain); -+ -+ ret = ov5642_init_mode(frame_rate, mode); -+ if (ret < 0) -+ return ret; -+ -+ ret_h = ret_m = ret_l = 0; -+ ov5642_read_reg(0x380e, &ret_h); -+ ov5642_read_reg(0x380f, &ret_l); -+ cap_maxlines = (ret_h << 8) + ret_l; -+ if (m_60Hz == true) -+ lines_10ms = cap_frame_rate * cap_maxlines/12000; -+ else -+ lines_10ms = cap_frame_rate * cap_maxlines/10000; -+ -+ if (prev_maxlines == 0) -+ prev_maxlines = 1; -+ -+ ulcap_ev = (g_prev_ev*(cap_frame_rate)*(cap_maxlines))/ -+ (((prev_maxlines)*(g_prev_frame_rate))); -+ icap_gain = (gain & 0x0f) + 16; -+ if (gain & 0x10) -+ icap_gain = icap_gain << 1; -+ -+ if (gain & 0x20) -+ icap_gain = icap_gain << 1; -+ -+ if (gain & 0x40) -+ icap_gain = icap_gain << 1; -+ -+ if (gain & 0x80) -+ icap_gain = icap_gain << 1; -+ -+ ulcap_ev_gain = 2 * ulcap_ev * icap_gain; -+ -+ if (ulcap_ev_gain < cap_maxlines*16) { -+ ulcap_ev = ulcap_ev_gain/16; -+ if (ulcap_ev > lines_10ms) { -+ ulcap_ev /= lines_10ms; -+ ulcap_ev *= lines_10ms; -+ } -+ } else -+ ulcap_ev = cap_maxlines; -+ -+ if (ulcap_ev == 0) -+ ulcap_ev = 1; -+ -+ icap_gain = (ulcap_ev_gain*2/ulcap_ev + 1)/2; -+ ev_low = ((unsigned char)ulcap_ev)<<4; -+ ev_mid = (unsigned char)(ulcap_ev >> 4) & 0xff; -+ ev_high = (unsigned char)(ulcap_ev >> 12); -+ -+ gain = 0; -+ if (icap_gain > 31) { -+ gain |= 0x10; -+ icap_gain = icap_gain >> 1; -+ } -+ if (icap_gain > 31) { -+ gain |= 0x20; -+ icap_gain = icap_gain >> 1; -+ } -+ if (icap_gain > 31) { -+ gain |= 0x40; -+ icap_gain = icap_gain >> 1; -+ } -+ if (icap_gain > 31) { -+ gain |= 0x80; -+ icap_gain = icap_gain >> 1; -+ } -+ if (icap_gain > 16) -+ gain |= ((icap_gain - 16) & 0x0f); -+ -+ if (gain == 0x10) -+ gain = 0x11; -+ -+ ov5642_write_reg(0x350b, gain); -+ ov5642_write_reg(0x3502, ev_low); -+ ov5642_write_reg(0x3501, ev_mid); -+ ov5642_write_reg(0x3500, ev_high); -+ msleep(500); -+ -+ return ret ; -+} -+ -+ -+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ -+ -+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) -+{ -+ if (s == NULL) { -+ pr_err(" ERROR!! no slave device set!\n"); -+ return -1; -+ } -+ -+ memset(p, 0, sizeof(*p)); -+ p->u.bt656.clock_curr = ov5642_data.mclk; -+ pr_debug(" clock_curr=mclk=%d\n", ov5642_data.mclk); -+ p->if_type = V4L2_IF_TYPE_BT656; -+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; -+ p->u.bt656.clock_min = OV5642_XCLK_MIN; -+ p->u.bt656.clock_max = OV5642_XCLK_MAX; -+ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @on: indicates power mode (on or off) -+ * -+ * Turns the power on or off, depending on the value of on and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_power(struct v4l2_int_device *s, int on) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ if (on && !sensor->on) { -+ if (io_regulator) -+ if (regulator_enable(io_regulator) != 0) -+ return -EIO; -+ if (core_regulator) -+ if (regulator_enable(core_regulator) != 0) -+ return -EIO; -+ if (gpo_regulator) -+ if (regulator_enable(gpo_regulator) != 0) -+ return -EIO; -+ if (analog_regulator) -+ if (regulator_enable(analog_regulator) != 0) -+ return -EIO; -+ /* Make sure power on */ -+ ov5642_standby(0); -+ } else if (!on && sensor->on) { -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ if (gpo_regulator) -+ regulator_disable(gpo_regulator); -+ -+ ov5642_standby(1); -+ } -+ -+ sensor->on = on; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure -+ * -+ * Returns the sensor's video CAPTURE parameters. -+ */ -+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_captureparm *cparm = &a->parm.capture; -+ int ret = 0; -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ 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; -+ ret = 0; -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure -+ * -+ * Configures the sensor to use the input parameters, if possible. If -+ * not possible, reverts to the old parameters and returns the -+ * appropriate error code. -+ */ -+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) -+{ -+ struct sensor_data *sensor = s->priv; -+ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; -+ u32 tgt_fps, old_fps; /* target frames per secound */ -+ enum ov5642_frame_rate new_frame_rate, old_frame_rate; -+ int ret = 0; -+ -+ /* Make sure power on */ -+ ov5642_standby(0); -+ -+ switch (a->type) { -+ /* This is the only case currently handled. */ -+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: -+ /* 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) -+ new_frame_rate = ov5642_15_fps; -+ else if (tgt_fps == 30) -+ new_frame_rate = ov5642_30_fps; -+ else { -+ pr_err(" The camera frame rate is not supported!\n"); -+ return -EINVAL; -+ } -+ -+ if (sensor->streamcap.timeperframe.numerator != 0) -+ old_fps = sensor->streamcap.timeperframe.denominator / -+ sensor->streamcap.timeperframe.numerator; -+ else -+ old_fps = 30; -+ -+ if (old_fps == 15) -+ old_frame_rate = ov5642_15_fps; -+ else if (old_fps == 30) -+ old_frame_rate = ov5642_30_fps; -+ else { -+ pr_warning(" No valid frame rate set!\n"); -+ old_frame_rate = ov5642_30_fps; -+ } -+ -+ ret = ov5642_change_mode(new_frame_rate, old_frame_rate, -+ a->parm.capture.capturemode, -+ sensor->streamcap.capturemode); -+ if (ret < 0) -+ return ret; -+ -+ sensor->streamcap.timeperframe = *timeperframe; -+ sensor->streamcap.capturemode = -+ (u32)a->parm.capture.capturemode; -+ break; -+ -+ /* These are all the possible cases. */ -+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: -+ case V4L2_BUF_TYPE_VIDEO_OVERLAY: -+ case V4L2_BUF_TYPE_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_VBI_OUTPUT: -+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: -+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: -+ pr_debug(" type is not " \ -+ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", -+ a->type); -+ ret = -EINVAL; -+ break; -+ -+ default: -+ pr_debug(" type is unknown - %d\n", a->type); -+ ret = -EINVAL; -+ break; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap -+ * @s: pointer to standard V4L2 device structure -+ * @f: pointer to standard V4L2 v4l2_format structure -+ * -+ * Returns the sensor's current pixel format in the v4l2_format -+ * parameter. -+ */ -+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) -+{ -+ struct sensor_data *sensor = s->priv; -+ -+ f->fmt.pix = sensor->pix; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure -+ * -+ * If the requested control is supported, returns the control's current -+ * value from the video_control[] array. Otherwise, returns -EINVAL -+ * if the control is not supported. -+ */ -+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int ret = 0; -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ vc->value = ov5642_data.brightness; -+ break; -+ case V4L2_CID_HUE: -+ vc->value = ov5642_data.hue; -+ break; -+ case V4L2_CID_CONTRAST: -+ vc->value = ov5642_data.contrast; -+ break; -+ case V4L2_CID_SATURATION: -+ vc->value = ov5642_data.saturation; -+ break; -+ case V4L2_CID_RED_BALANCE: -+ vc->value = ov5642_data.red; -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ vc->value = ov5642_data.blue; -+ break; -+ case V4L2_CID_EXPOSURE: -+ vc->value = ov5642_data.ae_mode; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+/*! -+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure -+ * -+ * If the requested control is supported, sets the control's current -+ * value in HW (and updates the video_control[] array). Otherwise, -+ * returns -EINVAL if the control is not supported. -+ */ -+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) -+{ -+ int retval = 0; -+ struct sensor_data *sensor = s->priv; -+ __u32 captureMode = sensor->streamcap.capturemode; -+ struct reg_value *rot_mode = NULL; -+ -+ pr_debug("In ov5642:ioctl_s_ctrl %d\n", -+ vc->id); -+ -+ switch (vc->id) { -+ case V4L2_CID_BRIGHTNESS: -+ break; -+ case V4L2_CID_CONTRAST: -+ break; -+ case V4L2_CID_SATURATION: -+ break; -+ case V4L2_CID_HUE: -+ break; -+ case V4L2_CID_AUTO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_DO_WHITE_BALANCE: -+ break; -+ case V4L2_CID_RED_BALANCE: -+ break; -+ case V4L2_CID_BLUE_BALANCE: -+ break; -+ case V4L2_CID_GAMMA: -+ break; -+ case V4L2_CID_EXPOSURE: -+ break; -+ case V4L2_CID_AUTOGAIN: -+ break; -+ case V4L2_CID_GAIN: -+ break; -+ case V4L2_CID_HFLIP: -+ break; -+ case V4L2_CID_VFLIP: -+ break; -+ case V4L2_CID_MXC_ROT: -+ case V4L2_CID_MXC_VF_ROT: -+ switch (vc->value) { -+ case V4L2_MXC_ROTATE_NONE: -+ if (captureMode == ov5642_mode_QSXGA_2592_1944) -+ rot_mode = ov5642_rot_none_FULL; -+ else -+ rot_mode = ov5642_rot_none_VGA; -+ -+ if (ov5642_set_rot_mode(rot_mode)) -+ retval = -EPERM; -+ break; -+ case V4L2_MXC_ROTATE_VERT_FLIP: -+ if (captureMode == ov5642_mode_QSXGA_2592_1944) -+ rot_mode = ov5642_rot_vert_flip_FULL; -+ else -+ rot_mode = ov5642_rot_vert_flip_VGA ; -+ -+ if (ov5642_set_rot_mode(rot_mode)) -+ retval = -EPERM; -+ break; -+ case V4L2_MXC_ROTATE_HORIZ_FLIP: -+ if (captureMode == ov5642_mode_QSXGA_2592_1944) -+ rot_mode = ov5642_rot_horiz_flip_FULL; -+ else -+ rot_mode = ov5642_rot_horiz_flip_VGA; -+ -+ if (ov5642_set_rot_mode(rot_mode)) -+ retval = -EPERM; -+ break; -+ case V4L2_MXC_ROTATE_180: -+ if (captureMode == ov5642_mode_QSXGA_2592_1944) -+ rot_mode = ov5642_rot_180_FULL; -+ else -+ rot_mode = ov5642_rot_180_VGA; -+ -+ if (ov5642_set_rot_mode(rot_mode)) -+ retval = -EPERM; -+ break; -+ default: -+ retval = -EPERM; -+ break; -+ } -+ break; -+ default: -+ retval = -EPERM; -+ break; -+ } -+ -+ return retval; -+} -+ -+/*! -+ * ioctl_enum_framesizes - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMESIZES ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_framesizes(struct v4l2_int_device *s, -+ struct v4l2_frmsizeenum *fsize) -+{ -+ if (fsize->index > ov5642_mode_MAX) -+ return -EINVAL; -+ -+ fsize->pixel_format = ov5642_data.pix.pixelformat; -+ fsize->discrete.width = -+ max(ov5642_mode_info_data[0][fsize->index].width, -+ ov5642_mode_info_data[1][fsize->index].width); -+ fsize->discrete.height = -+ max(ov5642_mode_info_data[0][fsize->index].height, -+ ov5642_mode_info_data[1][fsize->index].height); -+ return 0; -+} -+ -+/*! -+ * ioctl_enum_frameintervals - V4L2 sensor interface handler for -+ * VIDIOC_ENUM_FRAMEINTERVALS ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure -+ * -+ * Return 0 if successful, otherwise -EINVAL. -+ */ -+static int ioctl_enum_frameintervals(struct v4l2_int_device *s, -+ struct v4l2_frmivalenum *fival) -+{ -+ int i, j, count; -+ -+ if (fival->index < 0 || fival->index > ov5642_mode_MAX) -+ return -EINVAL; -+ -+ if (fival->pixel_format == 0 || fival->width == 0 || -+ fival->height == 0) { -+ pr_warning("Please assign pixelformat, width and height.\n"); -+ return -EINVAL; -+ } -+ -+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; -+ fival->discrete.numerator = 1; -+ -+ count = 0; -+ for (i = 0; i < ARRAY_SIZE(ov5642_mode_info_data); i++) { -+ for (j = 0; j < (ov5642_mode_MAX + 1); j++) { -+ if (fival->pixel_format == ov5642_data.pix.pixelformat -+ && fival->width == ov5642_mode_info_data[i][j].width -+ && fival->height == ov5642_mode_info_data[i][j].height -+ && ov5642_mode_info_data[i][j].init_data_ptr != NULL) { -+ count++; -+ } -+ if (fival->index == (count - 1)) { -+ fival->discrete.denominator = -+ ov5642_framerates[i]; -+ return 0; -+ } -+ } -+ } -+ -+ return -EINVAL; -+} -+ -+/*! -+ * ioctl_g_chip_ident - V4L2 sensor interface handler for -+ * VIDIOC_DBG_G_CHIP_IDENT ioctl -+ * @s: pointer to standard V4L2 device structure -+ * @id: pointer to int -+ * -+ * Return 0. -+ */ -+static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) -+{ -+ ((struct v4l2_dbg_chip_ident *)id)->match.type = -+ V4L2_CHIP_MATCH_I2C_DRIVER; -+ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5642_camera"); -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT -+ * @s: pointer to standard V4L2 device structure -+ */ -+static int ioctl_init(struct v4l2_int_device *s) -+{ -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT -+ * @s: pointer to standard V4L2 device structure -+ * @fmt: pointer to standard V4L2 fmt description structure -+ * -+ * Return 0. -+ */ -+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, -+ struct v4l2_fmtdesc *fmt) -+{ -+ if (fmt->index > 0) /* only 1 pixelformat support so far */ -+ return -EINVAL; -+ -+ fmt->pixelformat = ov5642_data.pix.pixelformat; -+ -+ return 0; -+} -+ -+/*! -+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Initialise the device when slave attaches to the master. -+ */ -+static int ioctl_dev_init(struct v4l2_int_device *s) -+{ -+ struct reg_value *pModeSetting = NULL; -+ s32 i = 0; -+ s32 iModeSettingArySize = 0; -+ register u32 Delay_ms = 0; -+ register u16 RegAddr = 0; -+ register u8 Mask = 0; -+ register u8 Val = 0; -+ u8 RegVal = 0; -+ int retval = 0; -+ -+ struct sensor_data *sensor = s->priv; -+ u32 tgt_xclk; /* target xclk */ -+ u32 tgt_fps; /* target frames per secound */ -+ enum ov5642_frame_rate frame_rate; -+ -+ ov5642_data.on = true; -+ -+ /* mclk */ -+ tgt_xclk = ov5642_data.mclk; -+ tgt_xclk = min(tgt_xclk, (u32)OV5642_XCLK_MAX); -+ tgt_xclk = max(tgt_xclk, (u32)OV5642_XCLK_MIN); -+ ov5642_data.mclk = tgt_xclk; -+ -+ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); -+ -+ /* Default camera frame rate is set in probe */ -+ tgt_fps = sensor->streamcap.timeperframe.denominator / -+ sensor->streamcap.timeperframe.numerator; -+ -+ if (tgt_fps == 15) -+ frame_rate = ov5642_15_fps; -+ else if (tgt_fps == 30) -+ frame_rate = ov5642_30_fps; -+ else -+ return -EINVAL; /* Only support 15fps or 30fps now. */ -+ -+ pModeSetting = ov5642_initial_setting; -+ iModeSettingArySize = ARRAY_SIZE(ov5642_initial_setting); -+ -+ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { -+ Delay_ms = pModeSetting->u32Delay_ms; -+ RegAddr = pModeSetting->u16RegAddr; -+ Val = pModeSetting->u8Val; -+ Mask = pModeSetting->u8Mask; -+ if (Mask) { -+ retval = ov5642_read_reg(RegAddr, &RegVal); -+ if (retval < 0) -+ goto err; -+ -+ RegVal &= ~(u8)Mask; -+ Val &= Mask; -+ Val |= RegVal; -+ } -+ -+ retval = ov5642_write_reg(RegAddr, Val); -+ if (retval < 0) -+ goto err; -+ -+ if (Delay_ms) -+ msleep(Delay_ms); -+ } -+err: -+ return retval; -+} -+ -+/*! -+ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num -+ * @s: pointer to standard V4L2 device structure -+ * -+ * Delinitialise the device when slave detaches to the master. -+ */ -+static int ioctl_dev_exit(struct v4l2_int_device *s) -+{ -+ return 0; -+} -+ -+/*! -+ * This structure defines all the ioctls for this module and links them to the -+ * enumeration. -+ */ -+static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = { -+ { vidioc_int_dev_init_num, -+ (v4l2_int_ioctl_func *)ioctl_dev_init }, -+ { vidioc_int_dev_exit_num, ioctl_dev_exit}, -+ { vidioc_int_s_power_num, -+ (v4l2_int_ioctl_func *)ioctl_s_power }, -+ { vidioc_int_g_ifparm_num, -+ (v4l2_int_ioctl_func *)ioctl_g_ifparm }, -+/* { vidioc_int_g_needs_reset_num, -+ (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */ -+/* { vidioc_int_reset_num, -+ (v4l2_int_ioctl_func *)ioctl_reset }, */ -+ { vidioc_int_init_num, -+ (v4l2_int_ioctl_func *)ioctl_init }, -+ { vidioc_int_enum_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, -+/* { vidioc_int_try_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */ -+ { vidioc_int_g_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, -+/* { vidioc_int_s_fmt_cap_num, -+ (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */ -+ { vidioc_int_g_parm_num, -+ (v4l2_int_ioctl_func *)ioctl_g_parm }, -+ { vidioc_int_s_parm_num, -+ (v4l2_int_ioctl_func *)ioctl_s_parm }, -+/* { vidioc_int_queryctrl_num, -+ (v4l2_int_ioctl_func *)ioctl_queryctrl }, */ -+ { vidioc_int_g_ctrl_num, -+ (v4l2_int_ioctl_func *)ioctl_g_ctrl }, -+ { vidioc_int_s_ctrl_num, -+ (v4l2_int_ioctl_func *)ioctl_s_ctrl }, -+ { vidioc_int_enum_framesizes_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_framesizes }, -+ { vidioc_int_enum_frameintervals_num, -+ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals }, -+ { vidioc_int_g_chip_ident_num, -+ (v4l2_int_ioctl_func *)ioctl_g_chip_ident }, -+}; -+ -+static struct v4l2_int_slave ov5642_slave = { -+ .ioctls = ov5642_ioctl_desc, -+ .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc), -+}; -+ -+static struct v4l2_int_device ov5642_int_device = { -+ .module = THIS_MODULE, -+ .name = "ov5642", -+ .type = v4l2_int_type_slave, -+ .u = { -+ .slave = &ov5642_slave, -+ }, -+}; -+ -+/*! -+ * ov5642 I2C probe function -+ * -+ * @param adapter struct i2c_adapter * -+ * @return Error code indicating success or failure -+ */ -+static int ov5642_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct pinctrl *pinctrl; -+ struct device *dev = &client->dev; -+ int retval; -+ u8 chip_id_high, chip_id_low; -+ -+ /* ov5642 pinctrl */ -+ pinctrl = devm_pinctrl_get_select_default(dev); -+ if (IS_ERR(pinctrl)) { -+ dev_err(dev, "ov5642 setup pinctrl failed!"); -+ return PTR_ERR(pinctrl); -+ } -+ -+ /* request power down pin */ -+ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); -+ if (!gpio_is_valid(pwn_gpio)) { -+ dev_warn(dev, "no sensor pwdn pin available"); -+ return -EINVAL; -+ } -+ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5642_pwdn"); -+ if (retval < 0) -+ return retval; -+ -+ /* request reset pin */ -+ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); -+ if (!gpio_is_valid(rst_gpio)) { -+ dev_warn(dev, "no sensor reset pin available"); -+ return -EINVAL; -+ } -+ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, -+ "ov5642_reset"); -+ if (retval < 0) -+ return retval; -+ -+ /* Set initial values for the sensor struct. */ -+ memset(&ov5642_data, 0, sizeof(ov5642_data)); -+ ov5642_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); -+ if (IS_ERR(ov5642_data.sensor_clk)) { -+ /* assuming clock enabled by default */ -+ ov5642_data.sensor_clk = NULL; -+ dev_err(dev, "clock-frequency missing or invalid\n"); -+ return PTR_ERR(ov5642_data.sensor_clk); -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk", -+ (u32 *) &(ov5642_data.mclk)); -+ if (retval) { -+ dev_err(dev, "mclk missing or invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "mclk_source", -+ (u32 *) &(ov5642_data.mclk_source)); -+ if (retval) { -+ dev_err(dev, "mclk_source missing or invalid\n"); -+ return retval; -+ } -+ -+ retval = of_property_read_u32(dev->of_node, "csi_id", -+ &(ov5642_data.csi)); -+ if (retval) { -+ dev_err(dev, "csi_id missing or invalid\n"); -+ return retval; -+ } -+ -+ clk_prepare_enable(ov5642_data.sensor_clk); -+ -+ ov5642_data.io_init = ov5642_reset; -+ ov5642_data.i2c_client = client; -+ ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; -+ ov5642_data.pix.width = 640; -+ ov5642_data.pix.height = 480; -+ ov5642_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | -+ V4L2_CAP_TIMEPERFRAME; -+ ov5642_data.streamcap.capturemode = 0; -+ ov5642_data.streamcap.timeperframe.denominator = DEFAULT_FPS; -+ ov5642_data.streamcap.timeperframe.numerator = 1; -+ -+ ov5642_power_on(&client->dev); -+ -+ ov5642_reset(); -+ -+ ov5642_standby(0); -+ -+ retval = ov5642_read_reg(OV5642_CHIP_ID_HIGH_BYTE, &chip_id_high); -+ if (retval < 0 || chip_id_high != 0x56) { -+ pr_warning("camera ov5642 is not found\n"); -+ clk_disable_unprepare(ov5642_data.sensor_clk); -+ return -ENODEV; -+ } -+ retval = ov5642_read_reg(OV5642_CHIP_ID_LOW_BYTE, &chip_id_low); -+ if (retval < 0 || chip_id_low != 0x42) { -+ pr_warning("camera ov5642 is not found\n"); -+ clk_disable_unprepare(ov5642_data.sensor_clk); -+ return -ENODEV; -+ } -+ -+ ov5642_standby(1); -+ -+ ov5642_int_device.priv = &ov5642_data; -+ retval = v4l2_int_device_register(&ov5642_int_device); -+ -+ clk_disable_unprepare(ov5642_data.sensor_clk); -+ -+ pr_info("camera ov5642 is found\n"); -+ return retval; -+} -+ -+/*! -+ * ov5642 I2C detach function -+ * -+ * @param client struct i2c_client * -+ * @return Error code indicating success or failure -+ */ -+static int ov5642_remove(struct i2c_client *client) -+{ -+ v4l2_int_device_unregister(&ov5642_int_device); -+ -+ if (gpo_regulator) -+ regulator_disable(gpo_regulator); -+ -+ if (analog_regulator) -+ regulator_disable(analog_regulator); -+ -+ if (core_regulator) -+ regulator_disable(core_regulator); -+ -+ if (io_regulator) -+ regulator_disable(io_regulator); -+ -+ return 0; -+} -+ -+/*! -+ * ov5642 init function -+ * Called by insmod ov5642_camera.ko. -+ * -+ * @return Error code indicating success or failure -+ */ -+static __init int ov5642_init(void) -+{ -+ u8 err; -+ -+ err = i2c_add_driver(&ov5642_i2c_driver); -+ if (err != 0) -+ pr_err("%s:driver registration failed, error=%d\n", -+ __func__, err); -+ -+ return err; -+} -+ -+/*! -+ * OV5642 cleanup function -+ * Called on rmmod ov5642_camera.ko -+ * -+ * @return Error code indicating success or failure -+ */ -+static void __exit ov5642_clean(void) -+{ -+ i2c_del_driver(&ov5642_i2c_driver); -+} -+ -+module_init(ov5642_init); -+module_exit(ov5642_clean); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("OV5642 Camera Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.0"); -+MODULE_ALIAS("CSI"); -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/output/Kconfig linux-3.14.22/drivers/media/platform/mxc/output/Kconfig ---- linux-3.14.22.orig/drivers/media/platform/mxc/output/Kconfig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/output/Kconfig 2014-10-22 14:55:52.626220001 -0500 -@@ -0,0 +1,5 @@ -+config VIDEO_MXC_IPU_OUTPUT -+ tristate "IPU v4l2 output support" -+ depends on VIDEO_MXC_OUTPUT && MXC_IPU -+ ---help--- -+ This is the video4linux2 driver for IPU post processing video output. -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/output/Makefile linux-3.14.22/drivers/media/platform/mxc/output/Makefile ---- linux-3.14.22.orig/drivers/media/platform/mxc/output/Makefile 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/output/Makefile 2014-10-22 14:55:52.626220001 -0500 -@@ -0,0 +1 @@ -+obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc_vout.o -diff -Nur linux-3.14.22.orig/drivers/media/platform/mxc/output/mxc_vout.c linux-3.14.22/drivers/media/platform/mxc/output/mxc_vout.c ---- linux-3.14.22.orig/drivers/media/platform/mxc/output/mxc_vout.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/media/platform/mxc/output/mxc_vout.c 2014-10-22 14:55:52.626220001 -0500 -@@ -0,0 +1,2265 @@ -+/* -+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. -+ */ -+ -+/* -+ * The code contained herein is licensed under the GNU General Public -+ * License. You may obtain a copy of the GNU General Public License -+ * Version 2 or later at the following locations: -+ * -+ * http://www.opensource.org/licenses/gpl-license.html -+ * http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define UYVY_BLACK (0x00800080) -+#define RGB_BLACK (0x0) -+#define UV_BLACK (0x80) -+#define Y_BLACK (0x0) -+ -+#define MAX_FB_NUM 6 -+#define FB_BUFS 3 -+#define VDOA_FB_BUFS (FB_BUFS - 1) -+#define VALID_HEIGHT_1080P (1080) -+#define FRAME_HEIGHT_1080P (1088) -+#define FRAME_WIDTH_1080P (1920) -+#define CHECK_TILED_1080P_DISPLAY(vout) \ -+ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \ -+ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\ -+ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \ -+ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \ -+ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \ -+ (((vout)->task.input.crop.h == FRAME_HEIGHT_1080P) || \ -+ ((vout)->task.input.crop.h == VALID_HEIGHT_1080P)) && \ -+ ((vout)->task.output.width == FRAME_WIDTH_1080P) && \ -+ ((vout)->task.output.height == VALID_HEIGHT_1080P) && \ -+ ((vout)->task.output.crop.w == FRAME_WIDTH_1080P) && \ -+ ((vout)->task.output.crop.h == VALID_HEIGHT_1080P)) -+#define CHECK_TILED_1080P_STREAM(vout) \ -+ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \ -+ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\ -+ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \ -+ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \ -+ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \ -+ ((vout)->task.input.crop.h == FRAME_HEIGHT_1080P)) -+#define IS_PLANAR_PIXEL_FORMAT(format) \ -+ (format == IPU_PIX_FMT_NV12 || \ -+ format == IPU_PIX_FMT_YUV420P2 || \ -+ format == IPU_PIX_FMT_YUV420P || \ -+ format == IPU_PIX_FMT_YVU420P || \ -+ format == IPU_PIX_FMT_YUV422P || \ -+ format == IPU_PIX_FMT_YVU422P || \ -+ format == IPU_PIX_FMT_YUV444P) -+ -+#define NSEC_PER_FRAME_30FPS (33333333) -+ -+struct mxc_vout_fb { -+ char *name; -+ int ipu_id; -+ struct v4l2_rect crop_bounds; -+ unsigned int disp_fmt; -+ bool disp_support_csc; -+ bool disp_support_windows; -+}; -+ -+struct dma_mem { -+ void *vaddr; -+ dma_addr_t paddr; -+ size_t size; -+}; -+ -+struct mxc_vout_output { -+ int open_cnt; -+ struct fb_info *fbi; -+ unsigned long fb_smem_start; -+ unsigned long fb_smem_len; -+ struct video_device *vfd; -+ struct mutex mutex; -+ struct mutex task_lock; -+ enum v4l2_buf_type type; -+ -+ struct videobuf_queue vbq; -+ spinlock_t vbq_lock; -+ -+ struct list_head queue_list; -+ struct list_head active_list; -+ -+ struct v4l2_rect crop_bounds; -+ unsigned int disp_fmt; -+ struct mxcfb_pos win_pos; -+ bool disp_support_windows; -+ bool disp_support_csc; -+ -+ bool fmt_init; -+ bool release; -+ bool linear_bypass_pp; -+ bool vdoa_1080p; -+ bool tiled_bypass_pp; -+ struct v4l2_rect in_rect; -+ struct ipu_task task; -+ struct ipu_task vdoa_task; -+ struct dma_mem vdoa_work; -+ struct dma_mem vdoa_output[VDOA_FB_BUFS]; -+ -+ bool timer_stop; -+ struct hrtimer timer; -+ struct workqueue_struct *v4l_wq; -+ struct work_struct disp_work; -+ unsigned long frame_count; -+ unsigned long vdi_frame_cnt; -+ ktime_t start_ktime; -+ -+ int ctrl_rotate; -+ int ctrl_vflip; -+ int ctrl_hflip; -+ -+ dma_addr_t disp_bufs[FB_BUFS]; -+ -+ struct videobuf_buffer *pre1_vb; -+ struct videobuf_buffer *pre2_vb; -+}; -+ -+struct mxc_vout_dev { -+ struct device *dev; -+ struct v4l2_device v4l2_dev; -+ struct mxc_vout_output *out[MAX_FB_NUM]; -+ int out_num; -+}; -+ -+/* Driver Configuration macros */ -+#define VOUT_NAME "mxc_vout" -+ -+/* Variables configurable through module params*/ -+static int debug; -+static int vdi_rate_double; -+static int video_nr = 16; -+ -+/* Module parameters */ -+module_param(video_nr, int, S_IRUGO); -+MODULE_PARM_DESC(video_nr, "video device numbers"); -+module_param(debug, int, 0600); -+MODULE_PARM_DESC(debug, "Debug level (0-1)"); -+module_param(vdi_rate_double, int, 0600); -+MODULE_PARM_DESC(vdi_rate_double, "vdi frame rate double on/off"); -+ -+static const struct v4l2_fmtdesc mxc_formats[] = { -+ { -+ .description = "RGB565", -+ .pixelformat = V4L2_PIX_FMT_RGB565, -+ }, -+ { -+ .description = "BGR24", -+ .pixelformat = V4L2_PIX_FMT_BGR24, -+ }, -+ { -+ .description = "RGB24", -+ .pixelformat = V4L2_PIX_FMT_RGB24, -+ }, -+ { -+ .description = "RGB32", -+ .pixelformat = V4L2_PIX_FMT_RGB32, -+ }, -+ { -+ .description = "BGR32", -+ .pixelformat = V4L2_PIX_FMT_BGR32, -+ }, -+ { -+ .description = "NV12", -+ .pixelformat = V4L2_PIX_FMT_NV12, -+ }, -+ { -+ .description = "UYVY", -+ .pixelformat = V4L2_PIX_FMT_UYVY, -+ }, -+ { -+ .description = "YUYV", -+ .pixelformat = V4L2_PIX_FMT_YUYV, -+ }, -+ { -+ .description = "YUV422 planar", -+ .pixelformat = V4L2_PIX_FMT_YUV422P, -+ }, -+ { -+ .description = "YUV444", -+ .pixelformat = V4L2_PIX_FMT_YUV444, -+ }, -+ { -+ .description = "YUV420", -+ .pixelformat = V4L2_PIX_FMT_YUV420, -+ }, -+ { -+ .description = "YVU420", -+ .pixelformat = V4L2_PIX_FMT_YVU420, -+ }, -+ { -+ .description = "TILED NV12P", -+ .pixelformat = IPU_PIX_FMT_TILED_NV12, -+ }, -+ { -+ .description = "TILED NV12F", -+ .pixelformat = IPU_PIX_FMT_TILED_NV12F, -+ }, -+ { -+ .description = "YUV444 planar", -+ .pixelformat = IPU_PIX_FMT_YUV444P, -+ }, -+}; -+ -+#define NUM_MXC_VOUT_FORMATS (ARRAY_SIZE(mxc_formats)) -+ -+#define DEF_INPUT_WIDTH 320 -+#define DEF_INPUT_HEIGHT 240 -+ -+static int mxc_vidioc_streamoff(struct file *file, void *fh, -+ enum v4l2_buf_type i); -+ -+static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM]; -+static int config_disp_output(struct mxc_vout_output *vout); -+static void release_disp_output(struct mxc_vout_output *vout); -+ -+static unsigned int get_frame_size(struct mxc_vout_output *vout) -+{ -+ unsigned int size; -+ -+ if (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) -+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width, -+ vout->task.input.height); -+ else if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) { -+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width, -+ vout->task.input.height/2); -+ size *= 2; -+ } else -+ size = vout->task.input.width * vout->task.input.height * -+ fmt_to_bpp(vout->task.input.format)/8; -+ -+ return size; -+} -+ -+static void free_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf) -+{ -+ dma_free_coherent(vout->vbq.dev, buf->size, buf->vaddr, buf->paddr); -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "free dma size:0x%x, paddr:0x%x\n", -+ buf->size, buf->paddr); -+ memset(buf, 0, sizeof(*buf)); -+} -+ -+static int alloc_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf) -+{ -+ -+ buf->vaddr = dma_alloc_coherent(vout->vbq.dev, buf->size, &buf->paddr, -+ GFP_DMA | GFP_KERNEL); -+ if (!buf->vaddr) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "cannot get dma buf size:0x%x\n", buf->size); -+ return -ENOMEM; -+ } -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr); -+ return 0; -+} -+ -+static ipu_channel_t get_ipu_channel(struct fb_info *fbi) -+{ -+ ipu_channel_t ipu_ch = CHAN_NONE; -+ mm_segment_t old_fs; -+ -+ if (fbi->fbops->fb_ioctl) { -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN, -+ (unsigned long)&ipu_ch); -+ set_fs(old_fs); -+ } -+ -+ return ipu_ch; -+} -+ -+static unsigned int get_ipu_fmt(struct fb_info *fbi) -+{ -+ mm_segment_t old_fs; -+ unsigned int fb_fmt; -+ -+ if (fbi->fbops->fb_ioctl) { -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_DIFMT, -+ (unsigned long)&fb_fmt); -+ set_fs(old_fs); -+ } -+ -+ return fb_fmt; -+} -+ -+static void update_display_setting(void) -+{ -+ int i; -+ struct fb_info *fbi; -+ struct v4l2_rect bg_crop_bounds[2]; -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ fbi = registered_fb[i]; -+ -+ memset(&g_fb_setting[i], 0, sizeof(struct mxc_vout_fb)); -+ -+ if (!strncmp(fbi->fix.id, "DISP3", 5)) -+ g_fb_setting[i].ipu_id = 0; -+ else -+ g_fb_setting[i].ipu_id = 1; -+ -+ g_fb_setting[i].name = fbi->fix.id; -+ g_fb_setting[i].crop_bounds.left = 0; -+ g_fb_setting[i].crop_bounds.top = 0; -+ g_fb_setting[i].crop_bounds.width = fbi->var.xres; -+ g_fb_setting[i].crop_bounds.height = fbi->var.yres; -+ g_fb_setting[i].disp_fmt = get_ipu_fmt(fbi); -+ -+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) { -+ bg_crop_bounds[g_fb_setting[i].ipu_id] = -+ g_fb_setting[i].crop_bounds; -+ g_fb_setting[i].disp_support_csc = true; -+ } else if (get_ipu_channel(fbi) == MEM_FG_SYNC) { -+ g_fb_setting[i].disp_support_csc = true; -+ g_fb_setting[i].disp_support_windows = true; -+ } -+ } -+ -+ for (i = 0; i < num_registered_fb; i++) { -+ fbi = registered_fb[i]; -+ -+ if (get_ipu_channel(fbi) == MEM_FG_SYNC) -+ g_fb_setting[i].crop_bounds = -+ bg_crop_bounds[g_fb_setting[i].ipu_id]; -+ } -+} -+ -+/* called after g_fb_setting filled by update_display_setting */ -+static int update_setting_from_fbi(struct mxc_vout_output *vout, -+ struct fb_info *fbi) -+{ -+ int i; -+ bool found = false; -+ -+ for (i = 0; i < MAX_FB_NUM; i++) { -+ if (g_fb_setting[i].name) { -+ if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) { -+ vout->crop_bounds = g_fb_setting[i].crop_bounds; -+ vout->disp_fmt = g_fb_setting[i].disp_fmt; -+ vout->disp_support_csc = -+ g_fb_setting[i].disp_support_csc; -+ vout->disp_support_windows = -+ g_fb_setting[i].disp_support_windows; -+ found = true; -+ break; -+ } -+ } -+ } -+ -+ if (!found) { -+ v4l2_err(vout->vfd->v4l2_dev, "can not find output\n"); -+ return -EINVAL; -+ } -+ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name)); -+ -+ memset(&vout->task, 0, sizeof(struct ipu_task)); -+ -+ vout->task.input.width = DEF_INPUT_WIDTH; -+ vout->task.input.height = DEF_INPUT_HEIGHT; -+ vout->task.input.crop.pos.x = 0; -+ vout->task.input.crop.pos.y = 0; -+ vout->task.input.crop.w = DEF_INPUT_WIDTH; -+ vout->task.input.crop.h = DEF_INPUT_HEIGHT; -+ -+ vout->task.output.width = vout->crop_bounds.width; -+ vout->task.output.height = vout->crop_bounds.height; -+ vout->task.output.crop.pos.x = 0; -+ vout->task.output.crop.pos.y = 0; -+ vout->task.output.crop.w = vout->crop_bounds.width; -+ vout->task.output.crop.h = vout->crop_bounds.height; -+ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS) -+ vout->task.output.format = IPU_PIX_FMT_UYVY; -+ else -+ vout->task.output.format = IPU_PIX_FMT_RGB565; -+ -+ return 0; -+} -+ -+static inline unsigned long get_jiffies(struct timeval *t) -+{ -+ struct timeval cur; -+ -+ if (t->tv_usec >= 1000000) { -+ t->tv_sec += t->tv_usec / 1000000; -+ t->tv_usec = t->tv_usec % 1000000; -+ } -+ -+ do_gettimeofday(&cur); -+ if ((t->tv_sec < cur.tv_sec) -+ || ((t->tv_sec == cur.tv_sec) && (t->tv_usec < cur.tv_usec))) -+ return jiffies; -+ -+ if (t->tv_usec < cur.tv_usec) { -+ cur.tv_sec = t->tv_sec - cur.tv_sec - 1; -+ cur.tv_usec = t->tv_usec + 1000000 - cur.tv_usec; -+ } else { -+ cur.tv_sec = t->tv_sec - cur.tv_sec; -+ cur.tv_usec = t->tv_usec - cur.tv_usec; -+ } -+ -+ return jiffies + timeval_to_jiffies(&cur); -+} -+ -+static bool deinterlace_3_field(struct mxc_vout_output *vout) -+{ -+ return (vout->task.input.deinterlace.enable && -+ (vout->task.input.deinterlace.motion != HIGH_MOTION)); -+} -+ -+static int set_field_fmt(struct mxc_vout_output *vout, enum v4l2_field field) -+{ -+ struct ipu_deinterlace *deinterlace = &vout->task.input.deinterlace; -+ -+ switch (field) { -+ /* Images are in progressive format, not interlaced */ -+ case V4L2_FIELD_NONE: -+ case V4L2_FIELD_ANY: -+ deinterlace->enable = false; -+ deinterlace->field_fmt = 0; -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "Progressive frame.\n"); -+ break; -+ case V4L2_FIELD_INTERLACED_TB: -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "Enable deinterlace TB.\n"); -+ deinterlace->enable = true; -+ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_TOP; -+ break; -+ case V4L2_FIELD_INTERLACED_BT: -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "Enable deinterlace BT.\n"); -+ deinterlace->enable = true; -+ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; -+ break; -+ default: -+ v4l2_err(vout->vfd->v4l2_dev, -+ "field format:%d not supported yet!\n", field); -+ return -EINVAL; -+ } -+ -+ if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) { -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "tiled fmt enable deinterlace.\n"); -+ deinterlace->enable = true; -+ } -+ -+ if (deinterlace->enable && vdi_rate_double) -+ deinterlace->field_fmt |= IPU_DEINTERLACE_RATE_EN; -+ -+ return 0; -+} -+ -+static bool is_pp_bypass(struct mxc_vout_output *vout) -+{ -+ if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) || -+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format)) -+ return false; -+ if ((vout->task.input.width == vout->task.output.width) && -+ (vout->task.input.height == vout->task.output.height) && -+ (vout->task.input.crop.w == vout->task.output.crop.w) && -+ (vout->task.input.crop.h == vout->task.output.crop.h) && -+ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && -+ !vout->task.input.deinterlace.enable) { -+ if (vout->disp_support_csc) -+ return true; -+ else if (!need_csc(vout->task.input.format, vout->disp_fmt)) -+ return true; -+ /* -+ * input crop show to full output which can show based on -+ * xres_virtual/yres_virtual -+ */ -+ } else if ((vout->task.input.crop.w == vout->task.output.crop.w) && -+ (vout->task.output.crop.w == vout->task.output.width) && -+ (vout->task.input.crop.h == vout->task.output.crop.h) && -+ (vout->task.output.crop.h == -+ vout->task.output.height) && -+ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && -+ !vout->task.input.deinterlace.enable) { -+ if (vout->disp_support_csc) -+ return true; -+ else if (!need_csc(vout->task.input.format, vout->disp_fmt)) -+ return true; -+ } -+ return false; -+} -+ -+static void setup_buf_timer(struct mxc_vout_output *vout, -+ struct videobuf_buffer *vb) -+{ -+ ktime_t expiry_time, now; -+ -+ /* if timestamp is 0, then default to 30fps */ -+ if ((vb->ts.tv_sec == 0) && (vb->ts.tv_usec == 0)) -+ expiry_time = ktime_add_ns(vout->start_ktime, -+ NSEC_PER_FRAME_30FPS * vout->frame_count); -+ else -+ expiry_time = timeval_to_ktime(vb->ts); -+ -+ now = hrtimer_cb_get_time(&vout->timer); -+ if ((now.tv64 > expiry_time.tv64)) { -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "warning: timer timeout already expired.\n"); -+ expiry_time = now; -+ } -+ -+ hrtimer_start(&vout->timer, expiry_time, HRTIMER_MODE_ABS); -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "timer handler next " -+ "schedule: %lldnsecs\n", expiry_time.tv64); -+} -+ -+static int show_buf(struct mxc_vout_output *vout, int idx, -+ struct ipu_pos *ipos) -+{ -+ struct fb_info *fbi = vout->fbi; -+ struct fb_var_screeninfo var; -+ int ret; -+ u32 fb_base = 0; -+ -+ memcpy(&var, &fbi->var, sizeof(var)); -+ -+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) { -+ /* -+ * crack fb base -+ * NOTE: should not do other fb operation during v4l2 -+ */ -+ console_lock(); -+ fb_base = fbi->fix.smem_start; -+ fbi->fix.smem_start = vout->task.output.paddr; -+ fbi->var.yoffset = ipos->y + 1; -+ var.xoffset = ipos->x; -+ var.yoffset = ipos->y; -+ var.vmode |= FB_VMODE_YWRAP; -+ ret = fb_pan_display(fbi, &var); -+ fbi->fix.smem_start = fb_base; -+ console_unlock(); -+ } else { -+ console_lock(); -+ var.yoffset = idx * fbi->var.yres; -+ var.vmode &= ~FB_VMODE_YWRAP; -+ ret = fb_pan_display(fbi, &var); -+ console_unlock(); -+ } -+ -+ return ret; -+} -+ -+static void disp_work_func(struct work_struct *work) -+{ -+ struct mxc_vout_output *vout = -+ container_of(work, struct mxc_vout_output, disp_work); -+ struct videobuf_queue *q = &vout->vbq; -+ struct videobuf_buffer *vb, *vb_next = NULL; -+ unsigned long flags = 0; -+ struct ipu_pos ipos; -+ int ret = 0; -+ u32 in_fmt = 0; -+ u32 vdi_cnt = 0; -+ u32 vdi_frame; -+ u32 index = 0; -+ u32 ocrop_h = 0; -+ u32 o_height = 0; -+ u32 tiled_interlaced = 0; -+ bool tiled_fmt = false; -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n"); -+ -+ spin_lock_irqsave(q->irqlock, flags); -+ -+ if (list_empty(&vout->active_list)) { -+ v4l2_warn(vout->vfd->v4l2_dev, -+ "no entry in active_list, should not be here\n"); -+ spin_unlock_irqrestore(q->irqlock, flags); -+ return; -+ } -+ -+ vb = list_first_entry(&vout->active_list, -+ struct videobuf_buffer, queue); -+ ret = set_field_fmt(vout, vb->field); -+ if (ret < 0) { -+ spin_unlock_irqrestore(q->irqlock, flags); -+ return; -+ } -+ if (deinterlace_3_field(vout)) { -+ if (list_is_singular(&vout->active_list)) { -+ if (list_empty(&vout->queue_list)) { -+ vout->timer_stop = true; -+ spin_unlock_irqrestore(q->irqlock, flags); -+ v4l2_warn(vout->vfd->v4l2_dev, -+ "no enough entry for 3 fields " -+ "deinterlacer\n"); -+ return; -+ } -+ -+ /* -+ * We need to use the next vb even if it is -+ * not on the active list. -+ */ -+ vb_next = list_first_entry(&vout->queue_list, -+ struct videobuf_buffer, queue); -+ } else -+ vb_next = list_first_entry(vout->active_list.next, -+ struct videobuf_buffer, queue); -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "cur field_fmt:%d, next field_fmt:%d.\n", -+ vb->field, vb_next->field); -+ /* repeat the last field during field format changing */ -+ if ((vb->field != vb_next->field) && -+ (vb_next->field != V4L2_FIELD_NONE)) -+ vb_next = vb; -+ } -+ -+ spin_unlock_irqrestore(q->irqlock, flags); -+ -+vdi_frame_rate_double: -+ mutex_lock(&vout->task_lock); -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "v4l2 frame_cnt:%ld, vb_field:%d, fmt:%d\n", -+ vout->frame_count, vb->field, -+ vout->task.input.deinterlace.field_fmt); -+ if (vb->memory == V4L2_MEMORY_USERPTR) -+ vout->task.input.paddr = vb->baddr; -+ else -+ vout->task.input.paddr = videobuf_to_dma_contig(vb); -+ -+ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) -+ index = vout->vdi_frame_cnt % FB_BUFS; -+ else -+ index = vout->frame_count % FB_BUFS; -+ if (vout->linear_bypass_pp) { -+ vout->task.output.paddr = vout->task.input.paddr; -+ ipos.x = vout->task.input.crop.pos.x; -+ ipos.y = vout->task.input.crop.pos.y; -+ } else { -+ if (deinterlace_3_field(vout)) { -+ if (vb->memory == V4L2_MEMORY_USERPTR) -+ vout->task.input.paddr_n = vb_next->baddr; -+ else -+ vout->task.input.paddr_n = -+ videobuf_to_dma_contig(vb_next); -+ } -+ vout->task.output.paddr = vout->disp_bufs[index]; -+ if (vout->vdoa_1080p) { -+ o_height = vout->task.output.height; -+ ocrop_h = vout->task.output.crop.h; -+ vout->task.output.height = FRAME_HEIGHT_1080P; -+ vout->task.output.crop.h = FRAME_HEIGHT_1080P; -+ } -+ tiled_fmt = -+ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) || -+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format); -+ if (vout->tiled_bypass_pp) { -+ ipos.x = vout->task.input.crop.pos.x; -+ ipos.y = vout->task.input.crop.pos.y; -+ } else if (tiled_fmt) { -+ vout->vdoa_task.input.paddr = vout->task.input.paddr; -+ if (deinterlace_3_field(vout)) -+ vout->vdoa_task.input.paddr_n = -+ vout->task.input.paddr_n; -+ vout->vdoa_task.output.paddr = vout->vdoa_work.paddr; -+ ret = ipu_queue_task(&vout->vdoa_task); -+ if (ret < 0) { -+ mutex_unlock(&vout->task_lock); -+ goto err; -+ } -+ vout->task.input.paddr = vout->vdoa_task.output.paddr; -+ in_fmt = vout->task.input.format; -+ vout->task.input.format = vout->vdoa_task.output.format; -+ if (vout->task.input.deinterlace.enable) { -+ tiled_interlaced = 1; -+ vout->task.input.deinterlace.enable = 0; -+ } -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "tiled queue task\n"); -+ } -+ ret = ipu_queue_task(&vout->task); -+ if ((!vout->tiled_bypass_pp) && tiled_fmt) -+ vout->task.input.format = in_fmt; -+ if (tiled_interlaced) -+ vout->task.input.deinterlace.enable = 1; -+ if (ret < 0) { -+ mutex_unlock(&vout->task_lock); -+ goto err; -+ } -+ if (vout->vdoa_1080p) { -+ vout->task.output.crop.h = ocrop_h; -+ vout->task.output.height = o_height; -+ } -+ } -+ -+ mutex_unlock(&vout->task_lock); -+ -+ ret = show_buf(vout, index, &ipos); -+ if (ret < 0) -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "show buf with ret %d\n", ret); -+ -+ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) { -+ vdi_frame = vout->task.input.deinterlace.field_fmt -+ & IPU_DEINTERLACE_RATE_FRAME1; -+ if (vdi_frame) -+ vout->task.input.deinterlace.field_fmt &= -+ ~IPU_DEINTERLACE_RATE_FRAME1; -+ else -+ vout->task.input.deinterlace.field_fmt |= -+ IPU_DEINTERLACE_RATE_FRAME1; -+ vout->vdi_frame_cnt++; -+ vdi_cnt++; -+ if (vdi_cnt < IPU_DEINTERLACE_MAX_FRAME) -+ goto vdi_frame_rate_double; -+ } -+ spin_lock_irqsave(q->irqlock, flags); -+ -+ list_del(&vb->queue); -+ -+ /* -+ * The videobuf before the last one has been shown. Set -+ * VIDEOBUF_DONE state here to avoid tearing issue in ic bypass -+ * case, which makes sure a buffer being shown will not be -+ * dequeued to be overwritten. It also brings side-effect that -+ * the last 2 buffers can not be dequeued correctly, apps need -+ * to take care of it. -+ */ -+ if (vout->pre2_vb) { -+ vout->pre2_vb->state = VIDEOBUF_DONE; -+ wake_up_interruptible(&vout->pre2_vb->done); -+ vout->pre2_vb = NULL; -+ } -+ -+ if (vout->linear_bypass_pp) { -+ vout->pre2_vb = vout->pre1_vb; -+ vout->pre1_vb = vb; -+ } else { -+ if (vout->pre1_vb) { -+ vout->pre1_vb->state = VIDEOBUF_DONE; -+ wake_up_interruptible(&vout->pre1_vb->done); -+ vout->pre1_vb = NULL; -+ } -+ vb->state = VIDEOBUF_DONE; -+ wake_up_interruptible(&vb->done); -+ } -+ -+ vout->frame_count++; -+ -+ /* pick next queue buf to setup timer */ -+ if (list_empty(&vout->queue_list)) -+ vout->timer_stop = true; -+ else { -+ vb = list_first_entry(&vout->queue_list, -+ struct videobuf_buffer, queue); -+ setup_buf_timer(vout, vb); -+ } -+ -+ spin_unlock_irqrestore(q->irqlock, flags); -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work finish one frame\n"); -+ -+ return; -+err: -+ v4l2_err(vout->vfd->v4l2_dev, "display work fail ret = %d\n", ret); -+ vout->timer_stop = true; -+ vb->state = VIDEOBUF_ERROR; -+ return; -+} -+ -+static enum hrtimer_restart mxc_vout_timer_handler(struct hrtimer *timer) -+{ -+ struct mxc_vout_output *vout = container_of(timer, -+ struct mxc_vout_output, -+ timer); -+ struct videobuf_queue *q = &vout->vbq; -+ struct videobuf_buffer *vb; -+ unsigned long flags = 0; -+ -+ spin_lock_irqsave(q->irqlock, flags); -+ -+ /* -+ * put first queued entry into active, if previous entry did not -+ * finish, setup current entry's timer again. -+ */ -+ if (list_empty(&vout->queue_list)) { -+ spin_unlock_irqrestore(q->irqlock, flags); -+ return HRTIMER_NORESTART; -+ } -+ -+ /* move videobuf from queued list to active list */ -+ vb = list_first_entry(&vout->queue_list, -+ struct videobuf_buffer, queue); -+ list_del(&vb->queue); -+ list_add_tail(&vb->queue, &vout->active_list); -+ -+ if (queue_work(vout->v4l_wq, &vout->disp_work) == 0) { -+ v4l2_warn(vout->vfd->v4l2_dev, -+ "disp work was in queue already, queue buf again next time\n"); -+ list_del(&vb->queue); -+ list_add(&vb->queue, &vout->queue_list); -+ spin_unlock_irqrestore(q->irqlock, flags); -+ return HRTIMER_NORESTART; -+ } -+ -+ vb->state = VIDEOBUF_ACTIVE; -+ -+ spin_unlock_irqrestore(q->irqlock, flags); -+ -+ return HRTIMER_NORESTART; -+} -+ -+/* Video buffer call backs */ -+ -+/* -+ * Buffer setup function is called by videobuf layer when REQBUF ioctl is -+ * called. This is used to setup buffers and return size and count of -+ * buffers allocated. After the call to this buffer, videobuf layer will -+ * setup buffer queue depending on the size and count of buffers -+ */ -+static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, -+ unsigned int *size) -+{ -+ struct mxc_vout_output *vout = q->priv_data; -+ unsigned int frame_size; -+ -+ if (!vout) -+ return -EINVAL; -+ -+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) -+ return -EINVAL; -+ -+ frame_size = get_frame_size(vout); -+ *size = PAGE_ALIGN(frame_size); -+ -+ return 0; -+} -+ -+/* -+ * This function will be called when VIDIOC_QBUF ioctl is called. -+ * It prepare buffers before give out for the display. This function -+ * converts user space virtual address into physical address if userptr memory -+ * exchange mechanism is used. -+ */ -+static int mxc_vout_buffer_prepare(struct videobuf_queue *q, -+ struct videobuf_buffer *vb, -+ enum v4l2_field field) -+{ -+ vb->state = VIDEOBUF_PREPARED; -+ return 0; -+} -+ -+/* -+ * Buffer queue funtion will be called from the videobuf layer when _QBUF -+ * ioctl is called. It is used to enqueue buffer, which is ready to be -+ * displayed. -+ * This function is protected by q->irqlock. -+ */ -+static void mxc_vout_buffer_queue(struct videobuf_queue *q, -+ struct videobuf_buffer *vb) -+{ -+ struct mxc_vout_output *vout = q->priv_data; -+ struct videobuf_buffer *active_vb; -+ -+ list_add_tail(&vb->queue, &vout->queue_list); -+ vb->state = VIDEOBUF_QUEUED; -+ -+ if (vout->timer_stop) { -+ if (deinterlace_3_field(vout) && -+ !list_empty(&vout->active_list)) { -+ active_vb = list_first_entry(&vout->active_list, -+ struct videobuf_buffer, queue); -+ setup_buf_timer(vout, active_vb); -+ } else { -+ setup_buf_timer(vout, vb); -+ } -+ vout->timer_stop = false; -+ } -+} -+ -+/* -+ * Buffer release function is called from videobuf layer to release buffer -+ * which are already allocated -+ */ -+static void mxc_vout_buffer_release(struct videobuf_queue *q, -+ struct videobuf_buffer *vb) -+{ -+ vb->state = VIDEOBUF_NEEDS_INIT; -+} -+ -+static int mxc_vout_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ int ret; -+ struct mxc_vout_output *vout = file->private_data; -+ -+ if (!vout) -+ return -ENODEV; -+ -+ ret = videobuf_mmap_mapper(&vout->vbq, vma); -+ if (ret < 0) -+ v4l2_err(vout->vfd->v4l2_dev, -+ "offset invalid [offset=0x%lx]\n", -+ (vma->vm_pgoff << PAGE_SHIFT)); -+ -+ return ret; -+} -+ -+static int mxc_vout_release(struct file *file) -+{ -+ unsigned int ret = 0; -+ struct videobuf_queue *q; -+ struct mxc_vout_output *vout = file->private_data; -+ -+ if (!vout) -+ return 0; -+ -+ if (--vout->open_cnt == 0) { -+ q = &vout->vbq; -+ if (q->streaming) -+ mxc_vidioc_streamoff(file, vout, vout->type); -+ else { -+ release_disp_output(vout); -+ videobuf_queue_cancel(q); -+ } -+ destroy_workqueue(vout->v4l_wq); -+ ret = videobuf_mmap_free(q); -+ } -+ -+ return ret; -+} -+ -+static int mxc_vout_open(struct file *file) -+{ -+ struct mxc_vout_output *vout = NULL; -+ int ret = 0; -+ -+ vout = video_drvdata(file); -+ -+ if (vout == NULL) -+ return -ENODEV; -+ -+ if (vout->open_cnt++ == 0) { -+ vout->ctrl_rotate = 0; -+ vout->ctrl_vflip = 0; -+ vout->ctrl_hflip = 0; -+ update_display_setting(); -+ ret = update_setting_from_fbi(vout, vout->fbi); -+ if (ret < 0) -+ goto err; -+ -+ vout->v4l_wq = create_singlethread_workqueue("v4l2q"); -+ if (!vout->v4l_wq) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "Could not create work queue\n"); -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ INIT_WORK(&vout->disp_work, disp_work_func); -+ -+ INIT_LIST_HEAD(&vout->queue_list); -+ INIT_LIST_HEAD(&vout->active_list); -+ -+ vout->fmt_init = false; -+ vout->frame_count = 0; -+ vout->vdi_frame_cnt = 0; -+ -+ vout->win_pos.x = 0; -+ vout->win_pos.y = 0; -+ vout->release = true; -+ } -+ -+ file->private_data = vout; -+ -+err: -+ return ret; -+} -+ -+/* -+ * V4L2 ioctls -+ */ -+static int mxc_vidioc_querycap(struct file *file, void *fh, -+ struct v4l2_capability *cap) -+{ -+ struct mxc_vout_output *vout = fh; -+ -+ strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); -+ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); -+ cap->bus_info[0] = '\0'; -+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; -+ -+ return 0; -+} -+ -+static int mxc_vidioc_enum_fmt_vid_out(struct file *file, void *fh, -+ struct v4l2_fmtdesc *fmt) -+{ -+ if (fmt->index >= NUM_MXC_VOUT_FORMATS) -+ return -EINVAL; -+ -+ strlcpy(fmt->description, mxc_formats[fmt->index].description, -+ sizeof(fmt->description)); -+ fmt->pixelformat = mxc_formats[fmt->index].pixelformat; -+ -+ return 0; -+} -+ -+static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh, -+ struct v4l2_format *f) -+{ -+ struct mxc_vout_output *vout = fh; -+ struct v4l2_rect rect; -+ -+ f->fmt.pix.width = vout->task.input.width; -+ f->fmt.pix.height = vout->task.input.height; -+ f->fmt.pix.pixelformat = vout->task.input.format; -+ f->fmt.pix.sizeimage = get_frame_size(vout); -+ -+ if (f->fmt.pix.priv) { -+ rect.left = vout->task.input.crop.pos.x; -+ rect.top = vout->task.input.crop.pos.y; -+ rect.width = vout->task.input.crop.w; -+ rect.height = vout->task.input.crop.h; -+ if (copy_to_user((void __user *)f->fmt.pix.priv, -+ &rect, sizeof(rect))) -+ return -EFAULT; -+ } -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "frame_size:0x%x, pix_fmt:0x%x\n", -+ f->fmt.pix.sizeimage, -+ vout->task.input.format); -+ -+ return 0; -+} -+ -+static inline int ipu_try_task(struct mxc_vout_output *vout) -+{ -+ int ret; -+ struct ipu_task *task = &vout->task; -+ -+again: -+ ret = ipu_check_task(task); -+ if (ret != IPU_CHECK_OK) { -+ if (ret > IPU_CHECK_ERR_MIN) { -+ if (ret == IPU_CHECK_ERR_SPLIT_INPUTW_OVER || -+ ret == IPU_CHECK_ERR_W_DOWNSIZE_OVER) { -+ task->input.crop.w -= 8; -+ goto again; -+ } -+ if (ret == IPU_CHECK_ERR_SPLIT_INPUTH_OVER || -+ ret == IPU_CHECK_ERR_H_DOWNSIZE_OVER) { -+ task->input.crop.h -= 8; -+ goto again; -+ } -+ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { -+ if (vout->disp_support_windows) { -+ task->output.width -= 8; -+ task->output.crop.w = -+ task->output.width; -+ } else -+ task->output.crop.w -= 8; -+ goto again; -+ } -+ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { -+ if (vout->disp_support_windows) { -+ task->output.height -= 8; -+ task->output.crop.h = -+ task->output.height; -+ } else -+ task->output.crop.h -= 8; -+ goto again; -+ } -+ ret = -EINVAL; -+ } -+ } else -+ ret = 0; -+ -+ return ret; -+} -+ -+static inline int vdoaipu_try_task(struct mxc_vout_output *vout) -+{ -+ int ret; -+ int is_1080p_stream; -+ size_t size; -+ struct ipu_task *ipu_task = &vout->task; -+ struct ipu_crop *icrop = &ipu_task->input.crop; -+ struct ipu_task *vdoa_task = &vout->vdoa_task; -+ u32 deinterlace = 0; -+ u32 in_fmt; -+ -+ if (vout->task.input.deinterlace.enable) -+ deinterlace = 1; -+ -+ memset(vdoa_task, 0, sizeof(*vdoa_task)); -+ vdoa_task->output.format = IPU_PIX_FMT_NV12; -+ memcpy(&vdoa_task->input, &ipu_task->input, -+ sizeof(ipu_task->input)); -+ if ((icrop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) || -+ (icrop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) { -+ vdoa_task->input.crop.w = -+ ALIGN(icrop->w, IPU_PIX_FMT_TILED_NV12_MBALIGN); -+ vdoa_task->input.crop.h = -+ ALIGN(icrop->h, IPU_PIX_FMT_TILED_NV12_MBALIGN); -+ } -+ vdoa_task->output.width = vdoa_task->input.crop.w; -+ vdoa_task->output.height = vdoa_task->input.crop.h; -+ vdoa_task->output.crop.w = vdoa_task->input.crop.w; -+ vdoa_task->output.crop.h = vdoa_task->input.crop.h; -+ -+ size = PAGE_ALIGN(vdoa_task->input.crop.w * -+ vdoa_task->input.crop.h * -+ fmt_to_bpp(vdoa_task->output.format)/8); -+ if (size > vout->vdoa_work.size) { -+ if (vout->vdoa_work.vaddr) -+ free_dma_buf(vout, &vout->vdoa_work); -+ vout->vdoa_work.size = size; -+ ret = alloc_dma_buf(vout, &vout->vdoa_work); -+ if (ret < 0) -+ return ret; -+ } -+ ret = ipu_check_task(vdoa_task); -+ if (ret != IPU_CHECK_OK) -+ return -EINVAL; -+ -+ is_1080p_stream = CHECK_TILED_1080P_STREAM(vout); -+ if (is_1080p_stream) -+ ipu_task->input.crop.h = VALID_HEIGHT_1080P; -+ in_fmt = ipu_task->input.format; -+ ipu_task->input.format = vdoa_task->output.format; -+ ipu_task->input.height = vdoa_task->output.height; -+ ipu_task->input.width = vdoa_task->output.width; -+ if (deinterlace) -+ ipu_task->input.deinterlace.enable = 0; -+ ret = ipu_try_task(vout); -+ if (deinterlace) -+ ipu_task->input.deinterlace.enable = 1; -+ ipu_task->input.format = in_fmt; -+ -+ return ret; -+} -+ -+static int mxc_vout_try_task(struct mxc_vout_output *vout) -+{ -+ int ret = 0; -+ struct ipu_output *output = &vout->task.output; -+ struct ipu_input *input = &vout->task.input; -+ struct ipu_crop *crop = &input->crop; -+ u32 o_height = 0; -+ u32 ocrop_h = 0; -+ bool tiled_fmt = false; -+ bool tiled_need_pp = false; -+ -+ vout->vdoa_1080p = CHECK_TILED_1080P_DISPLAY(vout); -+ if (vout->vdoa_1080p) { -+ input->crop.h = FRAME_HEIGHT_1080P; -+ o_height = output->height; -+ ocrop_h = output->crop.h; -+ output->height = FRAME_HEIGHT_1080P; -+ output->crop.h = FRAME_HEIGHT_1080P; -+ } -+ -+ if ((IPU_PIX_FMT_TILED_NV12 == input->format) || -+ (IPU_PIX_FMT_TILED_NV12F == input->format)) { -+ if ((input->width % IPU_PIX_FMT_TILED_NV12_MBALIGN) || -+ (input->height % IPU_PIX_FMT_TILED_NV12_MBALIGN) || -+ (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN) || -+ (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN)) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "ERR: tiled fmt needs 16 pixel align.\n"); -+ return -EINVAL; -+ } -+ if ((crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) || -+ (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) -+ tiled_need_pp = true; -+ } else { -+ crop->w -= crop->w % 8; -+ crop->h -= crop->h % 8; -+ } -+ /* assume task.output already set by S_CROP */ -+ vout->linear_bypass_pp = is_pp_bypass(vout); -+ if (vout->linear_bypass_pp) { -+ v4l2_info(vout->vfd->v4l2_dev, "Bypass IC.\n"); -+ output->format = input->format; -+ } else { -+ /* if need CSC, choose IPU-DP or IPU_IC do it */ -+ if (vout->disp_support_csc) { -+ if (colorspaceofpixel(input->format) == YUV_CS) -+ output->format = IPU_PIX_FMT_UYVY; -+ else -+ output->format = IPU_PIX_FMT_RGB565; -+ } else { -+ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS) -+ output->format = IPU_PIX_FMT_UYVY; -+ else -+ output->format = IPU_PIX_FMT_RGB565; -+ } -+ -+ vout->tiled_bypass_pp = false; -+ if ((IPU_PIX_FMT_TILED_NV12 == input->format) || -+ (IPU_PIX_FMT_TILED_NV12F == input->format)) { -+ /* check resize/rotate/flip, or csc task */ -+ if (!(tiled_need_pp || -+ (IPU_ROTATE_NONE != output->rotate) || -+ (input->crop.w != output->crop.w) || -+ (input->crop.h != output->crop.h) || -+ (!vout->disp_support_csc && -+ (colorspaceofpixel(vout->disp_fmt) == RGB_CS))) -+ ) { -+ /* IC bypass */ -+ output->format = IPU_PIX_FMT_NV12; -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "tiled bypass pp\n"); -+ vout->tiled_bypass_pp = true; -+ } -+ tiled_fmt = true; -+ } -+ -+ if ((!vout->tiled_bypass_pp) && tiled_fmt) -+ ret = vdoaipu_try_task(vout); -+ else -+ ret = ipu_try_task(vout); -+ } -+ -+ if (vout->vdoa_1080p) { -+ output->height = o_height; -+ output->crop.h = ocrop_h; -+ } -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "icrop.w:%u, icrop.h:%u, iw:%u, ih:%u," -+ "ocrop.w:%u, ocrop.h:%u, ow:%u, oh:%u\n", -+ input->crop.w, input->crop.h, -+ input->width, input->height, -+ output->crop.w, output->crop.h, -+ output->width, output->height); -+ return ret; -+} -+ -+static int mxc_vout_try_format(struct mxc_vout_output *vout, -+ struct v4l2_format *f) -+{ -+ int ret = 0; -+ struct v4l2_rect rect; -+ -+ if ((f->fmt.pix.field != V4L2_FIELD_NONE) && -+ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "progressive tiled fmt should used V4L2_FIELD_NONE!\n"); -+ return -EINVAL; -+ } -+ -+ if (f->fmt.pix.priv && copy_from_user(&rect, -+ (void __user *)f->fmt.pix.priv, sizeof(rect))) -+ return -EFAULT; -+ -+ vout->task.input.width = f->fmt.pix.width; -+ vout->task.input.height = f->fmt.pix.height; -+ vout->task.input.format = f->fmt.pix.pixelformat; -+ -+ ret = set_field_fmt(vout, f->fmt.pix.field); -+ if (ret < 0) -+ return ret; -+ -+ if (f->fmt.pix.priv) { -+ vout->task.input.crop.pos.x = rect.left; -+ vout->task.input.crop.pos.y = rect.top; -+ vout->task.input.crop.w = rect.width; -+ vout->task.input.crop.h = rect.height; -+ } else { -+ vout->task.input.crop.pos.x = 0; -+ vout->task.input.crop.pos.y = 0; -+ vout->task.input.crop.w = f->fmt.pix.width; -+ vout->task.input.crop.h = f->fmt.pix.height; -+ } -+ memcpy(&vout->in_rect, &vout->task.input.crop, sizeof(vout->in_rect)); -+ -+ ret = mxc_vout_try_task(vout); -+ if (!ret) { -+ if (f->fmt.pix.priv) { -+ rect.width = vout->task.input.crop.w; -+ rect.height = vout->task.input.crop.h; -+ if (copy_to_user((void __user *)f->fmt.pix.priv, -+ &rect, sizeof(rect))) -+ ret = -EFAULT; -+ } else { -+ f->fmt.pix.width = vout->task.input.crop.w; -+ f->fmt.pix.height = vout->task.input.crop.h; -+ } -+ } -+ -+ return ret; -+} -+ -+static bool mxc_vout_need_fb_reconfig(struct mxc_vout_output *vout, -+ struct mxc_vout_output *pre_vout) -+{ -+ if (!vout->vbq.streaming) -+ return false; -+ -+ if (vout->tiled_bypass_pp) -+ return true; -+ -+ if (vout->linear_bypass_pp != pre_vout->linear_bypass_pp) -+ return true; -+ -+ /* cropped output resolution or format are changed */ -+ if (vout->task.output.format != pre_vout->task.output.format || -+ vout->task.output.crop.w != pre_vout->task.output.crop.w || -+ vout->task.output.crop.h != pre_vout->task.output.crop.h) -+ return true; -+ -+ /* overlay: window position or resolution are changed */ -+ if (vout->disp_support_windows && -+ (vout->win_pos.x != pre_vout->win_pos.x || -+ vout->win_pos.y != pre_vout->win_pos.y || -+ vout->task.output.width != pre_vout->task.output.width || -+ vout->task.output.height != pre_vout->task.output.height)) -+ return true; -+ -+ /* background: cropped position is changed */ -+ if (!vout->disp_support_windows && -+ (vout->task.output.crop.pos.x != -+ pre_vout->task.output.crop.pos.x || -+ vout->task.output.crop.pos.y != -+ pre_vout->task.output.crop.pos.y)) -+ return true; -+ -+ return false; -+} -+ -+static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh, -+ struct v4l2_format *f) -+{ -+ struct mxc_vout_output *vout = fh; -+ int ret = 0; -+ -+ if (vout->vbq.streaming) -+ return -EBUSY; -+ -+ mutex_lock(&vout->task_lock); -+ ret = mxc_vout_try_format(vout, f); -+ if (ret >= 0) -+ vout->fmt_init = true; -+ mutex_unlock(&vout->task_lock); -+ -+ return ret; -+} -+ -+static int mxc_vidioc_cropcap(struct file *file, void *fh, -+ struct v4l2_cropcap *cropcap) -+{ -+ struct mxc_vout_output *vout = fh; -+ -+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) -+ return -EINVAL; -+ -+ cropcap->bounds = vout->crop_bounds; -+ cropcap->defrect = vout->crop_bounds; -+ -+ return 0; -+} -+ -+static int mxc_vidioc_g_crop(struct file *file, void *fh, -+ struct v4l2_crop *crop) -+{ -+ struct mxc_vout_output *vout = fh; -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) -+ return -EINVAL; -+ -+ if (vout->disp_support_windows) { -+ crop->c.left = vout->win_pos.x; -+ crop->c.top = vout->win_pos.y; -+ crop->c.width = vout->task.output.width; -+ crop->c.height = vout->task.output.height; -+ } else { -+ if (vout->task.output.crop.w && vout->task.output.crop.h) { -+ crop->c.left = vout->task.output.crop.pos.x; -+ crop->c.top = vout->task.output.crop.pos.y; -+ crop->c.width = vout->task.output.crop.w; -+ crop->c.height = vout->task.output.crop.h; -+ } else { -+ crop->c.left = 0; -+ crop->c.top = 0; -+ crop->c.width = vout->task.output.width; -+ crop->c.height = vout->task.output.height; -+ } -+ } -+ -+ return 0; -+} -+ -+static int mxc_vidioc_s_crop(struct file *file, void *fh, -+ const struct v4l2_crop *crop) -+{ -+ struct mxc_vout_output *vout = fh, *pre_vout; -+ struct v4l2_rect *b = &vout->crop_bounds; -+ struct v4l2_crop fix_up_crop; -+ int ret = 0; -+ -+ memcpy(&fix_up_crop, crop, sizeof(*crop)); -+ -+ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) -+ return -EINVAL; -+ -+ if (crop->c.width < 0 || crop->c.height < 0) -+ return -EINVAL; -+ -+ if (crop->c.width == 0) -+ fix_up_crop.c.width = b->width - b->left; -+ if (crop->c.height == 0) -+ fix_up_crop.c.height = b->height - b->top; -+ -+ if (crop->c.top < b->top) -+ fix_up_crop.c.top = b->top; -+ if (crop->c.top >= b->top + b->height) -+ fix_up_crop.c.top = b->top + b->height - 1; -+ if (crop->c.height > b->top - crop->c.top + b->height) -+ fix_up_crop.c.height = -+ b->top - fix_up_crop.c.top + b->height; -+ -+ if (crop->c.left < b->left) -+ fix_up_crop.c.left = b->left; -+ if (crop->c.left >= b->left + b->width) -+ fix_up_crop.c.left = b->left + b->width - 1; -+ if (crop->c.width > b->left - crop->c.left + b->width) -+ fix_up_crop.c.width = -+ b->left - fix_up_crop.c.left + b->width; -+ -+ /* stride line limitation */ -+ fix_up_crop.c.height -= fix_up_crop.c.height % 8; -+ fix_up_crop.c.width -= fix_up_crop.c.width % 8; -+ if ((fix_up_crop.c.width <= 0) || (fix_up_crop.c.height <= 0) || -+ ((fix_up_crop.c.left + fix_up_crop.c.width) > -+ (b->left + b->width)) || -+ ((fix_up_crop.c.top + fix_up_crop.c.height) > -+ (b->top + b->height))) { -+ v4l2_err(vout->vfd->v4l2_dev, "s_crop err: %d, %d, %d, %d", -+ fix_up_crop.c.left, fix_up_crop.c.top, -+ fix_up_crop.c.width, fix_up_crop.c.height); -+ return -EINVAL; -+ } -+ -+ /* the same setting, return */ -+ if (vout->disp_support_windows) { -+ if ((vout->win_pos.x == fix_up_crop.c.left) && -+ (vout->win_pos.y == fix_up_crop.c.top) && -+ (vout->task.output.crop.w == fix_up_crop.c.width) && -+ (vout->task.output.crop.h == fix_up_crop.c.height)) -+ return 0; -+ } else { -+ if ((vout->task.output.crop.pos.x == fix_up_crop.c.left) && -+ (vout->task.output.crop.pos.y == fix_up_crop.c.top) && -+ (vout->task.output.crop.w == fix_up_crop.c.width) && -+ (vout->task.output.crop.h == fix_up_crop.c.height)) -+ return 0; -+ } -+ -+ pre_vout = vmalloc(sizeof(*pre_vout)); -+ if (!pre_vout) -+ return -ENOMEM; -+ -+ /* wait current work finish */ -+ if (vout->vbq.streaming) -+ flush_workqueue(vout->v4l_wq); -+ -+ mutex_lock(&vout->task_lock); -+ -+ memcpy(pre_vout, vout, sizeof(*vout)); -+ -+ if (vout->disp_support_windows) { -+ vout->task.output.crop.pos.x = 0; -+ vout->task.output.crop.pos.y = 0; -+ vout->win_pos.x = fix_up_crop.c.left; -+ vout->win_pos.y = fix_up_crop.c.top; -+ vout->task.output.width = fix_up_crop.c.width; -+ vout->task.output.height = fix_up_crop.c.height; -+ } else { -+ vout->task.output.crop.pos.x = fix_up_crop.c.left; -+ vout->task.output.crop.pos.y = fix_up_crop.c.top; -+ } -+ -+ vout->task.output.crop.w = fix_up_crop.c.width; -+ vout->task.output.crop.h = fix_up_crop.c.height; -+ -+ /* -+ * must S_CROP before S_FMT, for fist time S_CROP, will not check -+ * ipu task, it will check in S_FMT, after S_FMT, S_CROP should -+ * check ipu task too. -+ */ -+ if (vout->fmt_init) { -+ memcpy(&vout->task.input.crop, &vout->in_rect, -+ sizeof(vout->in_rect)); -+ ret = mxc_vout_try_task(vout); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "vout check task failed\n"); -+ memcpy(vout, pre_vout, sizeof(*vout)); -+ goto done; -+ } -+ -+ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) { -+ ret = config_disp_output(vout); -+ if (ret < 0) -+ v4l2_err(vout->vfd->v4l2_dev, -+ "Config display output failed\n"); -+ } -+ } -+ -+done: -+ vfree(pre_vout); -+ mutex_unlock(&vout->task_lock); -+ -+ return ret; -+} -+ -+static int mxc_vidioc_queryctrl(struct file *file, void *fh, -+ struct v4l2_queryctrl *ctrl) -+{ -+ int ret = 0; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_ROTATE: -+ ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0); -+ break; -+ case V4L2_CID_VFLIP: -+ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); -+ break; -+ case V4L2_CID_HFLIP: -+ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); -+ break; -+ case V4L2_CID_MXC_MOTION: -+ ret = v4l2_ctrl_query_fill(ctrl, 0, 2, 1, 0); -+ break; -+ default: -+ ctrl->name[0] = '\0'; -+ ret = -EINVAL; -+ } -+ return ret; -+} -+ -+static int mxc_vidioc_g_ctrl(struct file *file, void *fh, -+ struct v4l2_control *ctrl) -+{ -+ int ret = 0; -+ struct mxc_vout_output *vout = fh; -+ -+ switch (ctrl->id) { -+ case V4L2_CID_ROTATE: -+ ctrl->value = vout->ctrl_rotate; -+ break; -+ case V4L2_CID_VFLIP: -+ ctrl->value = vout->ctrl_vflip; -+ break; -+ case V4L2_CID_HFLIP: -+ ctrl->value = vout->ctrl_hflip; -+ break; -+ case V4L2_CID_MXC_MOTION: -+ if (vout->task.input.deinterlace.enable) -+ ctrl->value = vout->task.input.deinterlace.motion; -+ else -+ ctrl->value = 0; -+ break; -+ default: -+ ret = -EINVAL; -+ } -+ return ret; -+} -+ -+static void setup_task_rotation(struct mxc_vout_output *vout) -+{ -+ if (vout->ctrl_rotate == 0) { -+ if (vout->ctrl_vflip && vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_180; -+ else if (vout->ctrl_vflip) -+ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP; -+ else if (vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP; -+ else -+ vout->task.output.rotate = IPU_ROTATE_NONE; -+ } else if (vout->ctrl_rotate == 90) { -+ if (vout->ctrl_vflip && vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_90_LEFT; -+ else if (vout->ctrl_vflip) -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP; -+ else if (vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP; -+ else -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT; -+ } else if (vout->ctrl_rotate == 180) { -+ if (vout->ctrl_vflip && vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_NONE; -+ else if (vout->ctrl_vflip) -+ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP; -+ else if (vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP; -+ else -+ vout->task.output.rotate = IPU_ROTATE_180; -+ } else if (vout->ctrl_rotate == 270) { -+ if (vout->ctrl_vflip && vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT; -+ else if (vout->ctrl_vflip) -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP; -+ else if (vout->ctrl_hflip) -+ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP; -+ else -+ vout->task.output.rotate = IPU_ROTATE_90_LEFT; -+ } -+} -+ -+static int mxc_vidioc_s_ctrl(struct file *file, void *fh, -+ struct v4l2_control *ctrl) -+{ -+ int ret = 0; -+ struct mxc_vout_output *vout = fh, *pre_vout; -+ -+ pre_vout = vmalloc(sizeof(*pre_vout)); -+ if (!pre_vout) -+ return -ENOMEM; -+ -+ /* wait current work finish */ -+ if (vout->vbq.streaming) -+ flush_workqueue(vout->v4l_wq); -+ -+ mutex_lock(&vout->task_lock); -+ -+ memcpy(pre_vout, vout, sizeof(*vout)); -+ -+ switch (ctrl->id) { -+ case V4L2_CID_ROTATE: -+ { -+ vout->ctrl_rotate = (ctrl->value/90) * 90; -+ if (vout->ctrl_rotate > 270) -+ vout->ctrl_rotate = 270; -+ setup_task_rotation(vout); -+ break; -+ } -+ case V4L2_CID_VFLIP: -+ { -+ vout->ctrl_vflip = ctrl->value; -+ setup_task_rotation(vout); -+ break; -+ } -+ case V4L2_CID_HFLIP: -+ { -+ vout->ctrl_hflip = ctrl->value; -+ setup_task_rotation(vout); -+ break; -+ } -+ case V4L2_CID_MXC_MOTION: -+ { -+ vout->task.input.deinterlace.motion = ctrl->value; -+ break; -+ } -+ default: -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ if (vout->fmt_init) { -+ memcpy(&vout->task.input.crop, &vout->in_rect, -+ sizeof(vout->in_rect)); -+ ret = mxc_vout_try_task(vout); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "vout check task failed\n"); -+ memcpy(vout, pre_vout, sizeof(*vout)); -+ goto done; -+ } -+ -+ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) { -+ ret = config_disp_output(vout); -+ if (ret < 0) -+ v4l2_err(vout->vfd->v4l2_dev, -+ "Config display output failed\n"); -+ } -+ } -+ -+done: -+ vfree(pre_vout); -+ mutex_unlock(&vout->task_lock); -+ -+ return ret; -+} -+ -+static int mxc_vidioc_reqbufs(struct file *file, void *fh, -+ struct v4l2_requestbuffers *req) -+{ -+ int ret = 0; -+ struct mxc_vout_output *vout = fh; -+ struct videobuf_queue *q = &vout->vbq; -+ -+ if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) -+ return -EINVAL; -+ -+ /* should not be here after streaming, videobuf_reqbufs will control */ -+ mutex_lock(&vout->task_lock); -+ -+ ret = videobuf_reqbufs(q, req); -+ -+ mutex_unlock(&vout->task_lock); -+ return ret; -+} -+ -+static int mxc_vidioc_querybuf(struct file *file, void *fh, -+ struct v4l2_buffer *b) -+{ -+ int ret; -+ struct mxc_vout_output *vout = fh; -+ -+ ret = videobuf_querybuf(&vout->vbq, b); -+ if (!ret) { -+ /* return physical address */ -+ struct videobuf_buffer *vb = vout->vbq.bufs[b->index]; -+ if (b->flags & V4L2_BUF_FLAG_MAPPED) -+ b->m.offset = videobuf_to_dma_contig(vb); -+ } -+ -+ return ret; -+} -+ -+static int mxc_vidioc_qbuf(struct file *file, void *fh, -+ struct v4l2_buffer *buffer) -+{ -+ struct mxc_vout_output *vout = fh; -+ -+ return videobuf_qbuf(&vout->vbq, buffer); -+} -+ -+static int mxc_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) -+{ -+ struct mxc_vout_output *vout = fh; -+ -+ if (!vout->vbq.streaming) -+ return -EINVAL; -+ -+ if (file->f_flags & O_NONBLOCK) -+ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 1); -+ else -+ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 0); -+} -+ -+static int set_window_position(struct mxc_vout_output *vout, -+ struct mxcfb_pos *pos) -+{ -+ struct fb_info *fbi = vout->fbi; -+ mm_segment_t old_fs; -+ int ret = 0; -+ -+ if (vout->disp_support_windows) { -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ ret = fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS, -+ (unsigned long)pos); -+ set_fs(old_fs); -+ } -+ -+ return ret; -+} -+ -+static int config_disp_output(struct mxc_vout_output *vout) -+{ -+ struct dma_mem *buf = NULL; -+ struct fb_info *fbi = vout->fbi; -+ struct fb_var_screeninfo var; -+ struct mxcfb_pos pos; -+ int i, fb_num, ret; -+ u32 fb_base; -+ u32 size; -+ u32 display_buf_size; -+ u32 *pixel = NULL; -+ u32 color; -+ int j; -+ -+ memcpy(&var, &fbi->var, sizeof(var)); -+ fb_base = fbi->fix.smem_start; -+ -+ var.xres = vout->task.output.width; -+ var.yres = vout->task.output.height; -+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) { -+ fb_num = 1; -+ /* input crop */ -+ if (vout->task.input.width > vout->task.output.width) -+ var.xres_virtual = vout->task.input.width; -+ else -+ var.xres_virtual = var.xres; -+ if (vout->task.input.height > vout->task.output.height) -+ var.yres_virtual = vout->task.input.height; -+ else -+ var.yres_virtual = var.yres; -+ var.rotate = vout->task.output.rotate; -+ var.vmode |= FB_VMODE_YWRAP; -+ } else { -+ fb_num = FB_BUFS; -+ var.xres_virtual = var.xres; -+ var.yres_virtual = fb_num * var.yres; -+ var.vmode &= ~FB_VMODE_YWRAP; -+ } -+ var.bits_per_pixel = fmt_to_bpp(vout->task.output.format); -+ var.nonstd = vout->task.output.format; -+ -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "set display fb to %d %d\n", -+ var.xres, var.yres); -+ -+ /* -+ * To setup the overlay fb from scratch without -+ * the last time overlay fb position or resolution's -+ * impact, we take the following steps: -+ * - blank fb -+ * - set fb position to the starting point -+ * - reconfigure fb -+ * - set fb position to a specific point -+ * - unblank fb -+ * This procedure applies to non-overlay fbs as well. -+ */ -+ console_lock(); -+ fbi->flags |= FBINFO_MISC_USEREVENT; -+ fb_blank(fbi, FB_BLANK_POWERDOWN); -+ fbi->flags &= ~FBINFO_MISC_USEREVENT; -+ console_unlock(); -+ -+ pos.x = 0; -+ pos.y = 0; -+ ret = set_window_position(vout, &pos); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position " -+ "to starting point\n"); -+ return ret; -+ } -+ -+ /* Init display channel through fb API */ -+ var.yoffset = 0; -+ var.activate |= FB_ACTIVATE_FORCE; -+ console_lock(); -+ fbi->flags |= FBINFO_MISC_USEREVENT; -+ ret = fb_set_var(fbi, &var); -+ fbi->flags &= ~FBINFO_MISC_USEREVENT; -+ console_unlock(); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "ERR:%s fb_set_var ret:%d\n", __func__, ret); -+ return ret; -+ } -+ -+ ret = set_window_position(vout, &vout->win_pos); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position\n"); -+ return ret; -+ } -+ -+ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) -+ display_buf_size = fbi->fix.line_length * fbi->var.yres_virtual; -+ else -+ display_buf_size = fbi->fix.line_length * fbi->var.yres; -+ for (i = 0; i < fb_num; i++) -+ vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size; -+ if (vout->tiled_bypass_pp) { -+ size = PAGE_ALIGN(vout->task.input.crop.w * -+ vout->task.input.crop.h * -+ fmt_to_bpp(vout->task.output.format)/8); -+ if (size > vout->vdoa_output[0].size) { -+ for (i = 0; i < VDOA_FB_BUFS; i++) { -+ buf = &vout->vdoa_output[i]; -+ if (buf->vaddr) -+ free_dma_buf(vout, buf); -+ buf->size = size; -+ ret = alloc_dma_buf(vout, buf); -+ if (ret < 0) -+ goto err; -+ } -+ } -+ for (i = fb_num; i < (fb_num + VDOA_FB_BUFS); i++) -+ vout->disp_bufs[i] = -+ vout->vdoa_output[i - fb_num].paddr; -+ } -+ vout->fb_smem_len = fbi->fix.smem_len; -+ vout->fb_smem_start = fbi->fix.smem_start; -+ if (fb_base != fbi->fix.smem_start) { -+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, -+ "realloc fb mem size:0x%x@0x%lx,old paddr @0x%x\n", -+ fbi->fix.smem_len, fbi->fix.smem_start, fb_base); -+ } -+ -+ /* fill black when video config changed */ -+ color = colorspaceofpixel(vout->task.output.format) == YUV_CS ? -+ UYVY_BLACK : RGB_BLACK; -+ if (IS_PLANAR_PIXEL_FORMAT(vout->task.output.format)) { -+ size = display_buf_size * 8 / -+ fmt_to_bpp(vout->task.output.format); -+ memset(fbi->screen_base, Y_BLACK, size); -+ memset(fbi->screen_base + size, UV_BLACK, -+ display_buf_size - size); -+ } else { -+ pixel = (u32 *)fbi->screen_base; -+ for (i = 0; i < (display_buf_size >> 2); i++) -+ *pixel++ = color; -+ } -+ console_lock(); -+ fbi->flags |= FBINFO_MISC_USEREVENT; -+ ret = fb_blank(fbi, FB_BLANK_UNBLANK); -+ fbi->flags &= ~FBINFO_MISC_USEREVENT; -+ console_unlock(); -+ vout->release = false; -+ -+ return ret; -+err: -+ for (j = i - 1; j >= 0; j--) { -+ buf = &vout->vdoa_output[j]; -+ if (buf->vaddr) -+ free_dma_buf(vout, buf); -+ } -+ return ret; -+} -+ -+static inline void wait_for_vsync(struct mxc_vout_output *vout) -+{ -+ struct fb_info *fbi = vout->fbi; -+ mm_segment_t old_fs; -+ -+ if (fbi->fbops->fb_ioctl) { -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC, -+ (unsigned long)NULL); -+ set_fs(old_fs); -+ } -+ -+ return; -+} -+ -+static void release_disp_output(struct mxc_vout_output *vout) -+{ -+ struct fb_info *fbi = vout->fbi; -+ struct mxcfb_pos pos; -+ -+ if (vout->release) -+ return; -+ console_lock(); -+ fbi->flags |= FBINFO_MISC_USEREVENT; -+ fb_blank(fbi, FB_BLANK_POWERDOWN); -+ fbi->flags &= ~FBINFO_MISC_USEREVENT; -+ console_unlock(); -+ -+ /* restore pos to 0,0 avoid fb pan display hang? */ -+ pos.x = 0; -+ pos.y = 0; -+ set_window_position(vout, &pos); -+ -+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) { -+ console_lock(); -+ fbi->fix.smem_start = vout->disp_bufs[0]; -+ fbi->flags |= FBINFO_MISC_USEREVENT; -+ fb_blank(fbi, FB_BLANK_UNBLANK); -+ fbi->flags &= ~FBINFO_MISC_USEREVENT; -+ console_unlock(); -+ -+ } -+ -+ vout->release = true; -+} -+ -+static int mxc_vidioc_streamon(struct file *file, void *fh, -+ enum v4l2_buf_type i) -+{ -+ struct mxc_vout_output *vout = fh; -+ struct videobuf_queue *q = &vout->vbq; -+ int ret; -+ -+ if (q->streaming) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "video output already run\n"); -+ ret = -EBUSY; -+ goto done; -+ } -+ -+ if (deinterlace_3_field(vout) && list_is_singular(&q->stream)) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "deinterlacing: need queue 2 frame before streamon\n"); -+ ret = -EINVAL; -+ goto done; -+ } -+ -+ ret = config_disp_output(vout); -+ if (ret < 0) { -+ v4l2_err(vout->vfd->v4l2_dev, -+ "Config display output failed\n"); -+ goto done; -+ } -+ -+ hrtimer_init(&vout->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); -+ vout->timer.function = mxc_vout_timer_handler; -+ vout->timer_stop = true; -+ -+ vout->start_ktime = hrtimer_cb_get_time(&vout->timer); -+ -+ vout->pre1_vb = NULL; -+ vout->pre2_vb = NULL; -+ -+ ret = videobuf_streamon(q); -+done: -+ return ret; -+} -+ -+static int mxc_vidioc_streamoff(struct file *file, void *fh, -+ enum v4l2_buf_type i) -+{ -+ struct mxc_vout_output *vout = fh; -+ struct videobuf_queue *q = &vout->vbq; -+ int ret = 0; -+ -+ if (q->streaming) { -+ flush_workqueue(vout->v4l_wq); -+ -+ hrtimer_cancel(&vout->timer); -+ -+ /* -+ * Wait for 2 vsyncs to make sure -+ * frames are drained on triple -+ * buffer. -+ */ -+ wait_for_vsync(vout); -+ wait_for_vsync(vout); -+ -+ release_disp_output(vout); -+ -+ ret = videobuf_streamoff(&vout->vbq); -+ } -+ INIT_LIST_HEAD(&vout->queue_list); -+ INIT_LIST_HEAD(&vout->active_list); -+ -+ return ret; -+} -+ -+static const struct v4l2_ioctl_ops mxc_vout_ioctl_ops = { -+ .vidioc_querycap = mxc_vidioc_querycap, -+ .vidioc_enum_fmt_vid_out = mxc_vidioc_enum_fmt_vid_out, -+ .vidioc_g_fmt_vid_out = mxc_vidioc_g_fmt_vid_out, -+ .vidioc_s_fmt_vid_out = mxc_vidioc_s_fmt_vid_out, -+ .vidioc_cropcap = mxc_vidioc_cropcap, -+ .vidioc_g_crop = mxc_vidioc_g_crop, -+ .vidioc_s_crop = mxc_vidioc_s_crop, -+ .vidioc_queryctrl = mxc_vidioc_queryctrl, -+ .vidioc_g_ctrl = mxc_vidioc_g_ctrl, -+ .vidioc_s_ctrl = mxc_vidioc_s_ctrl, -+ .vidioc_reqbufs = mxc_vidioc_reqbufs, -+ .vidioc_querybuf = mxc_vidioc_querybuf, -+ .vidioc_qbuf = mxc_vidioc_qbuf, -+ .vidioc_dqbuf = mxc_vidioc_dqbuf, -+ .vidioc_streamon = mxc_vidioc_streamon, -+ .vidioc_streamoff = mxc_vidioc_streamoff, -+}; -+ -+static const struct v4l2_file_operations mxc_vout_fops = { -+ .owner = THIS_MODULE, -+ .unlocked_ioctl = video_ioctl2, -+ .mmap = mxc_vout_mmap, -+ .open = mxc_vout_open, -+ .release = mxc_vout_release, -+}; -+ -+static struct video_device mxc_vout_template = { -+ .name = "MXC Video Output", -+ .fops = &mxc_vout_fops, -+ .ioctl_ops = &mxc_vout_ioctl_ops, -+ .release = video_device_release, -+}; -+ -+static struct videobuf_queue_ops mxc_vout_vbq_ops = { -+ .buf_setup = mxc_vout_buffer_setup, -+ .buf_prepare = mxc_vout_buffer_prepare, -+ .buf_release = mxc_vout_buffer_release, -+ .buf_queue = mxc_vout_buffer_queue, -+}; -+ -+static void mxc_vout_free_output(struct mxc_vout_dev *dev) -+{ -+ int i; -+ int j; -+ struct mxc_vout_output *vout; -+ struct video_device *vfd; -+ -+ for (i = 0; i < dev->out_num; i++) { -+ vout = dev->out[i]; -+ vfd = vout->vfd; -+ if (vout->vdoa_work.vaddr) -+ free_dma_buf(vout, &vout->vdoa_work); -+ for (j = 0; j < VDOA_FB_BUFS; j++) { -+ if (vout->vdoa_output[j].vaddr) -+ free_dma_buf(vout, &vout->vdoa_output[j]); -+ } -+ if (vfd) { -+ if (!video_is_registered(vfd)) -+ video_device_release(vfd); -+ else -+ video_unregister_device(vfd); -+ } -+ kfree(vout); -+ } -+} -+ -+static int mxc_vout_setup_output(struct mxc_vout_dev *dev) -+{ -+ struct videobuf_queue *q; -+ struct fb_info *fbi; -+ struct mxc_vout_output *vout; -+ int i, ret = 0; -+ -+ update_display_setting(); -+ -+ /* all output/overlay based on fb */ -+ for (i = 0; i < num_registered_fb; i++) { -+ fbi = registered_fb[i]; -+ -+ vout = kzalloc(sizeof(struct mxc_vout_output), GFP_KERNEL); -+ if (!vout) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ dev->out[dev->out_num] = vout; -+ dev->out_num++; -+ -+ vout->fbi = fbi; -+ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; -+ vout->vfd = video_device_alloc(); -+ if (!vout->vfd) { -+ ret = -ENOMEM; -+ break; -+ } -+ -+ *vout->vfd = mxc_vout_template; -+ vout->vfd->debug = debug; -+ vout->vfd->v4l2_dev = &dev->v4l2_dev; -+ vout->vfd->lock = &vout->mutex; -+ vout->vfd->vfl_dir = VFL_DIR_TX; -+ -+ mutex_init(&vout->mutex); -+ mutex_init(&vout->task_lock); -+ -+ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name)); -+ -+ video_set_drvdata(vout->vfd, vout); -+ -+ if (video_register_device(vout->vfd, -+ VFL_TYPE_GRABBER, video_nr + i) < 0) { -+ ret = -ENODEV; -+ break; -+ } -+ -+ q = &vout->vbq; -+ q->dev = dev->dev; -+ spin_lock_init(&vout->vbq_lock); -+ videobuf_queue_dma_contig_init(q, &mxc_vout_vbq_ops, q->dev, -+ &vout->vbq_lock, vout->type, V4L2_FIELD_NONE, -+ sizeof(struct videobuf_buffer), vout, NULL); -+ -+ v4l2_info(vout->vfd->v4l2_dev, "V4L2 device registered as %s\n", -+ video_device_node_name(vout->vfd)); -+ -+ } -+ -+ return ret; -+} -+ -+static int mxc_vout_probe(struct platform_device *pdev) -+{ -+ int ret; -+ struct mxc_vout_dev *dev; -+ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ -+ dev->dev = &pdev->dev; -+ dev->dev->dma_mask = kmalloc(sizeof(*dev->dev->dma_mask), GFP_KERNEL); -+ *dev->dev->dma_mask = DMA_BIT_MASK(32); -+ dev->dev->coherent_dma_mask = DMA_BIT_MASK(32); -+ -+ ret = v4l2_device_register(dev->dev, &dev->v4l2_dev); -+ if (ret) { -+ dev_err(dev->dev, "v4l2_device_register failed\n"); -+ goto free_dev; -+ } -+ -+ ret = mxc_vout_setup_output(dev); -+ if (ret < 0) -+ goto rel_vdev; -+ -+ return 0; -+ -+rel_vdev: -+ mxc_vout_free_output(dev); -+ v4l2_device_unregister(&dev->v4l2_dev); -+free_dev: -+ kfree(dev); -+ return ret; -+} -+ -+static int mxc_vout_remove(struct platform_device *pdev) -+{ -+ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); -+ struct mxc_vout_dev *dev = container_of(v4l2_dev, struct -+ mxc_vout_dev, v4l2_dev); -+ -+ mxc_vout_free_output(dev); -+ v4l2_device_unregister(v4l2_dev); -+ kfree(dev); -+ return 0; -+} -+ -+static const struct of_device_id mxc_v4l2_dt_ids[] = { -+ { .compatible = "fsl,mxc_v4l2_output", }, -+ { /* sentinel */ } -+}; -+ -+static struct platform_driver mxc_vout_driver = { -+ .driver = { -+ .name = "mxc_v4l2_output", -+ .of_match_table = mxc_v4l2_dt_ids, -+ }, -+ .probe = mxc_vout_probe, -+ .remove = mxc_vout_remove, -+}; -+ -+static int __init mxc_vout_init(void) -+{ -+ if (platform_driver_register(&mxc_vout_driver) != 0) { -+ printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+static void mxc_vout_cleanup(void) -+{ -+ platform_driver_unregister(&mxc_vout_driver); -+} -+ -+module_init(mxc_vout_init); -+module_exit(mxc_vout_cleanup); -+ -+MODULE_AUTHOR("Freescale Semiconductor, Inc."); -+MODULE_DESCRIPTION("V4L2-driver for MXC video output"); -+MODULE_LICENSE("GPL"); -diff -Nur linux-3.14.22.orig/drivers/media/v4l2-core/videobuf2-dma-contig.c linux-3.14.22/drivers/media/v4l2-core/videobuf2-dma-contig.c ---- linux-3.14.22.orig/drivers/media/v4l2-core/videobuf2-dma-contig.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/media/v4l2-core/videobuf2-dma-contig.c 2014-10-22 14:55:52.626220001 -0500 -@@ -719,7 +719,7 @@ - - /* get the associated scatterlist for this buffer */ - sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir); -- if (IS_ERR_OR_NULL(sgt)) { -+ if (IS_ERR(sgt)) { - pr_err("Error getting dmabuf scatterlist\n"); - return -EINVAL; - } -diff -Nur linux-3.14.22.orig/drivers/media/v4l2-core/videobuf-dma-contig.c linux-3.14.22/drivers/media/v4l2-core/videobuf-dma-contig.c ---- linux-3.14.22.orig/drivers/media/v4l2-core/videobuf-dma-contig.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/media/v4l2-core/videobuf-dma-contig.c 2014-10-22 14:55:52.626220001 -0500 -@@ -304,7 +304,7 @@ - - /* Try to remap memory */ - size = vma->vm_end - vma->vm_start; -- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - retval = vm_iomap_memory(vma, vma->vm_start, size); - if (retval) { - dev_err(q->dev, "mmap: remap failed with error %d. ", -diff -Nur linux-3.14.22.orig/drivers/mfd/ab8500-core.c linux-3.14.22/drivers/mfd/ab8500-core.c ---- linux-3.14.22.orig/drivers/mfd/ab8500-core.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mfd/ab8500-core.c 2014-10-22 14:55:52.626220001 -0500 -@@ -592,7 +592,7 @@ - - /* If ->irq_base is zero this will give a linear mapping */ - ab8500->domain = irq_domain_add_simple(NULL, -- num_irqs, ab8500->irq_base, -+ num_irqs, 0, - &ab8500_irq_ops, ab8500); - - if (!ab8500->domain) { -@@ -1583,14 +1583,13 @@ - if (!ab8500) - return -ENOMEM; - -- if (plat) -- ab8500->irq_base = plat->irq_base; -- - ab8500->dev = &pdev->dev; - - resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); -- if (!resource) -+ if (!resource) { -+ dev_err(&pdev->dev, "no IRQ resource\n"); - return -ENODEV; -+ } - - ab8500->irq = resource->start; - -@@ -1612,8 +1611,10 @@ - else { - ret = get_register_interruptible(ab8500, AB8500_MISC, - AB8500_IC_NAME_REG, &value); -- if (ret < 0) -+ if (ret < 0) { -+ dev_err(&pdev->dev, "could not probe HW\n"); - return ret; -+ } - - ab8500->version = value; - } -@@ -1759,30 +1760,30 @@ - if (is_ab9540(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, - ARRAY_SIZE(ab9540_devs), NULL, -- ab8500->irq_base, ab8500->domain); -+ 0, ab8500->domain); - else if (is_ab8540(ab8500)) { - ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, - ARRAY_SIZE(ab8540_devs), NULL, -- ab8500->irq_base, NULL); -+ 0, ab8500->domain); - if (ret) - return ret; - - if (is_ab8540_1p2_or_earlier(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs, - ARRAY_SIZE(ab8540_cut1_devs), NULL, -- ab8500->irq_base, NULL); -+ 0, ab8500->domain); - else /* ab8540 >= cut2 */ - ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs, - ARRAY_SIZE(ab8540_cut2_devs), NULL, -- ab8500->irq_base, NULL); -+ 0, ab8500->domain); - } else if (is_ab8505(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, - ARRAY_SIZE(ab8505_devs), NULL, -- ab8500->irq_base, ab8500->domain); -+ 0, ab8500->domain); - else - ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, - ARRAY_SIZE(ab8500_devs), NULL, -- ab8500->irq_base, ab8500->domain); -+ 0, ab8500->domain); - if (ret) - return ret; - -@@ -1790,7 +1791,7 @@ - /* Add battery management devices */ - ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, - ARRAY_SIZE(ab8500_bm_devs), NULL, -- ab8500->irq_base, ab8500->domain); -+ 0, ab8500->domain); - if (ret) - dev_err(ab8500->dev, "error adding bm devices\n"); - } -diff -Nur linux-3.14.22.orig/drivers/mfd/db8500-prcmu.c linux-3.14.22/drivers/mfd/db8500-prcmu.c ---- linux-3.14.22.orig/drivers/mfd/db8500-prcmu.c 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mfd/db8500-prcmu.c 2014-10-22 14:55:52.626220001 -0500 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2678,16 +2679,12 @@ - .xlate = irq_domain_xlate_twocell, - }; - --static int db8500_irq_init(struct device_node *np, int irq_base) -+static int db8500_irq_init(struct device_node *np) - { - int i; - -- /* In the device tree case, just take some IRQs */ -- if (np) -- irq_base = 0; -- - db8500_irq_domain = irq_domain_add_simple( -- np, NUM_PRCMU_WAKEUPS, irq_base, -+ np, NUM_PRCMU_WAKEUPS, 0, - &db8500_irq_ops, NULL); - - if (!db8500_irq_domain) { -@@ -3114,10 +3111,10 @@ - } - - static int db8500_prcmu_register_ab8500(struct device *parent, -- struct ab8500_platform_data *pdata, -- int irq) -+ struct ab8500_platform_data *pdata) - { -- struct resource ab8500_resource = DEFINE_RES_IRQ(irq); -+ struct device_node *np; -+ struct resource ab8500_resource; - struct mfd_cell ab8500_cell = { - .name = "ab8500-core", - .of_compatible = "stericsson,ab8500", -@@ -3128,6 +3125,20 @@ - .num_resources = 1, - }; - -+ if (!parent->of_node) -+ return -ENODEV; -+ -+ /* Look up the device node, sneak the IRQ out of it */ -+ for_each_child_of_node(parent->of_node, np) { -+ if (of_device_is_compatible(np, ab8500_cell.of_compatible)) -+ break; -+ } -+ if (!np) { -+ dev_info(parent, "could not find AB8500 node in the device tree\n"); -+ return -ENODEV; -+ } -+ of_irq_to_resource_table(np, &ab8500_resource, 1); -+ - return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL); - } - -@@ -3180,7 +3191,7 @@ - goto no_irq_return; - } - -- db8500_irq_init(np, pdata->irq_base); -+ db8500_irq_init(np); - - prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); - -@@ -3205,8 +3216,7 @@ - } - } - -- err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata, -- pdata->ab_irq); -+ err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata); - if (err) { - mfd_remove_devices(&pdev->dev); - pr_err("prcmu: Failed to add ab8500 subdevice\n"); -diff -Nur linux-3.14.22.orig/drivers/mfd/Kconfig linux-3.14.22/drivers/mfd/Kconfig ---- linux-3.14.22.orig/drivers/mfd/Kconfig 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mfd/Kconfig 2014-10-22 14:55:52.630220001 -0500 -@@ -163,6 +163,14 @@ - Additional drivers must be enabled in order to use the functionality - of the device. - -+config MFD_MXC_HDMI -+ tristate "Freescale HDMI Core" -+ select MFD_CORE -+ help -+ This is the core driver for the Freescale i.MX6 on-chip HDMI. -+ This MFD driver connects with the video and audio drivers for HDMI. -+ -+ - config MFD_MC13XXX - tristate - depends on (SPI_MASTER || I2C) -@@ -1226,3 +1234,4 @@ - help - Platform configuration infrastructure for the ARM Ltd. - Versatile Express. -+ -diff -Nur linux-3.14.22.orig/drivers/mfd/Makefile linux-3.14.22/drivers/mfd/Makefile ---- linux-3.14.22.orig/drivers/mfd/Makefile 2014-10-15 01:42:04.000000000 -0500 -+++ linux-3.14.22/drivers/mfd/Makefile 2014-10-22 14:55:52.630220001 -0500 -@@ -166,3 +166,4 @@ - obj-$(CONFIG_MFD_AS3711) += as3711.o - obj-$(CONFIG_MFD_AS3722) += as3722.o - obj-$(CONFIG_MFD_STW481X) += stw481x.o -+obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o -diff -Nur linux-3.14.22.orig/drivers/mfd/mxc-hdmi-core.c linux-3.14.22/drivers/mfd/mxc-hdmi-core.c ---- linux-3.14.22.orig/drivers/mfd/mxc-hdmi-core.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.14.22/drivers/mfd/mxc-hdmi-core.c 2014-10-22 14:55:52.630220001 -0500 -@@ -0,0 +1,798 @@ -+/* -+ * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ * -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include corresponding ++ to 3 pair of asrc. ++ - fsl,asrc-dma-tx-events: The tx dma event of the esai, corresponding ++ to 3 pair of asrc. ++ ++Example: ++asrc_p2p: asrc_p2p { ++ compatible = "fsl,imx6q-asrc-p2p"; ++ fsl,output-rate = <48000>; ++ fsl,output-width = <16>; ++ fsl,asrc-dma-rx-events = <17 18 19>; ++ fsl,asrc-dma-tx-events = <20 21 22>; ++ status = "okay"; ++}; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt linux-imx6-3.14/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt +--- linux-3.14.14/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/sound/imx-audio-cs42888.txt 2014-12-08 00:31:50.948418001 -0600 +@@ -0,0 +1,25 @@ ++Freescale i.MX audio complex with CS42888 codec ++ ++Required properties: ++- compatible : "fsl,imx-audio-cs42888" ++- model : The user-visible name of this sound complex ++- esai-controller : The phandle of the i.MX SSI controller ++- audio-codec : The phandle of the CS42888 audio codec ++ ++Optional properties: ++- asrc-controller : The phandle of the i.MX ASRC controller ++- audio-routing : A list of the connections between audio components. ++ Each entry is a pair of strings, the first being the connection's sink, ++ the second being the connection's source. Valid names could be power ++ supplies, CS42888 pins, and the jacks on the board: ++ ++Example: ++ ++sound { ++ compatible = "fsl,imx6q-sabresd-wm8962", ++ "fsl,imx-audio-wm8962"; ++ model = "cs42888-audio"; ++ esai-controller = <&esai>; ++ asrc-controller = <&asrc_p2p>; ++ audio-codec = <&codec>; ++}; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt linux-imx6-3.14/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt +--- linux-3.14.14/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt 2014-12-08 00:31:50.948418001 -0600 +@@ -24,6 +24,12 @@ + Note: The AUDMUX port numbering should start at 1, which is consistent with + hardware manual. + ++Optional properties: ++- hp-det-gpios : The gpio pin to detect plug in/out event that happens to ++ Headphone jack. ++- mic-det-gpios: The gpio pin to detect plug in/out event that happens to ++ Microphone jack. ++ + Example: + + sound { +@@ -43,4 +49,6 @@ + "DMICDAT", "DMIC"; + mux-int-port = <2>; + mux-ext-port = <3>; ++ hp-det-gpios = <&gpio7 8 1>; ++ mic-det-gpios = <&gpio1 9 1>; + }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/sound/wm8962.txt linux-imx6-3.14/Documentation/devicetree/bindings/sound/wm8962.txt +--- linux-3.14.14/Documentation/devicetree/bindings/sound/wm8962.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/sound/wm8962.txt 2014-12-08 00:31:50.948418001 -0600 +@@ -13,6 +13,14 @@ + of R51 (Class D Control 2) gets set, indicating that the speaker is + in mono mode. + ++ - amic-mono: This is a boolean property. If present, indicating that the ++ analog micphone is hardware mono input, the driver would enable monomix ++ for it. ++ ++ - dmic-mono: This is a boolean property. If present, indicating that the ++ digital micphone is hardware mono input, the driver would enable monomix ++ for it. ++ + - mic-cfg : Default register value for R48 (Additional Control 4). + If absent, the default should be the register default. + +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/usb/mxs-phy.txt linux-imx6-3.14/Documentation/devicetree/bindings/usb/mxs-phy.txt +--- linux-3.14.14/Documentation/devicetree/bindings/usb/mxs-phy.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/usb/mxs-phy.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -1,13 +1,16 @@ + * Freescale MXS USB Phy Device + + Required properties: +-- compatible: Should be "fsl,imx23-usbphy" ++- compatible: "fsl,imx23-usbphy" for imx23 and imx28, "fsl,imx6q-usbphy" ++for imx6dq and imx6dl, "fsl,imx6sl-usbphy" for imx6sl + - reg: Should contain registers location and length + - interrupts: Should contain phy interrupt ++- fsl,anatop: phandle for anatop register, it is only for imx6 SoC series + + Example: + usbphy1: usbphy@020c9000 { + compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy"; + reg = <0x020c9000 0x1000>; + interrupts = <0 44 0x04>; ++ fsl,anatop = <&anatop>; + }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt +--- linux-3.14.14/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,csi-v4l2-capture.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -0,0 +1,61 @@ ++* Freescale CMOS Sensor Interface (CSI) V4L2 Capture ++ ++Required properties for CSI ++- compatible: "fsl,-csi". Supported chip includes imx6sl ++- reg: Address and length of the register set for CSI ++- interrupts: Should contain CSI interrupts ++ ++Required properties for v4l2_capture ++- compatible: should be "fsl,-csi-v4l2", supported socs include imx6sl ++ ++Required properties for sensor ++- compatible: "," ++ please check the supported sensor in the Supported Sensor fields. ++- reg: sensor I2C slave address ++- pinctrl-names: should be "default" for parallel sensor ++- pinctrl-0: should depend on the connection between sensor and i.MX ++ connection between sensor and i.MX could be only legacy parallel on i.MX6SL ++- clocks: should be the clock source provided to sensor. ++- clock-names: should be "csi_mclk" ++- AVDD-supply: set according to the board. ++- DVDD-supply: set according to the board. ++- pwn-gpios: set according to the board. ++- rst-gpios: set according to the board. ++- csi_id: csi id for v4l2 capture device ++ should be 0 for i.MX6SL ++- mclk: should the value of mclk clock send out the sensor. unit is Hz. ++- mclk_source: should be 0 for i.MX6SL ++ ++Supported Sensor ++- ovti, ov5640 ++ ++Example for CSI: ++ csi: csi@020e4000 { ++ compatible = "fsl,imx6sl-csi"; ++ reg = <0x020e4000 0x4000>; ++ interrupts = <0 7 0x04>; ++ status = "disabled"; ++ }; ++ ++Examples for v4l2_capture: ++ csi_v4l2_cap { ++ compatible = "fsl,imx6q-v4l2-capture"; ++ status = "okay"; ++ }; ++ ++Examples for sensors: ++ ov564x: ov564x@3c { ++ compatible = "ovti,ov564x"; ++ reg = <0x3c>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_csi_0>; ++ clocks = <&clks IMX6SL_CLK_CSI>; ++ clock-names = "csi_mclk"; ++ AVDD-supply = <&vgen6_reg>; /* 2.8v */ ++ DVDD-supply = <&vgen2_reg>; /* 1.5v*/ ++ pwn-gpios = <&gpio1 25 1>; ++ rst-gpios = <&gpio1 26 0>; ++ csi_id = <0>; ++ mclk = <24000000>; ++ mclk_source = <0>; ++ }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt +--- linux-3.14.14/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,mipi-csi2.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -0,0 +1,42 @@ ++* Freescale MIPI CSI2 Controller for i.MX6DQ/i.MX6SDL ++ ++Required properties for mipi csi2 controller: ++- compatible: should be "fsl,imx6q-mipi-csi2" ++- reg: contains mipi csi2 register base address and range ++- interrupts: where type is a interrupt type, num is the ++ interrupt number and flag is a field that level/trigger information for ++ the interrupt. ++- clocks: the clock sources that mipi csi2 depends on. ++- clock-names: the name is related to the clock source one by one. ++- status: should be set to "disable". ++ ++Required properties for mipi csi2 on specified board: ++- ipu_id: ipu id which mipi csi2 connected to. ++ should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL ++- csi_id: csi id which mipi csi2 connected to. ++ should be 0 or 1 for i.MX6DQ/i.MX6SDL ++- v_channel: virtual channel which send to MIPI CSI2 controller ++ should keep consistent with the input MIPI signal. ++- lanes: data lanes of input MIPI signal. The maximum data lanes is 4. ++ should keep consistent with the input MIPI signal. ++- status: should be set to "okay". ++ ++Examples: ++for SOC imx6qdl.dtsi: ++ mipi_csi@021dc000 { ++ compatible = "fsl,imx6q-mipi-csi2"; ++ reg = <0x021dc000 0x4000>; ++ interrupts = <0 100 0x04>, <0 101 0x04>; ++ clocks = <&clks 138>, <&clks 53>, <&clks 204>; ++ clock-names = "dphy_clk", "pixel_clk", "cfg_clk"; ++ status = "disabled"; ++ }; ++ ++for board imx6qdl-sabresd.dtsi: ++ mipi_csi@021dc000 { ++ status = "okay"; ++ ipu_id = <0>; ++ csi_id = <1>; ++ v_channel = <0>; ++ lanes = <2>; ++ }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/video/fsl,pxp.txt linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,pxp.txt +--- linux-3.14.14/Documentation/devicetree/bindings/video/fsl,pxp.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,pxp.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -0,0 +1,30 @@ ++* Freescale PxP Controller for i.MX6DL, i.MX6SL ++ ++Required properties for PxP controller: ++- compatible: should be "fsl,-pxp-dma" ++- reg: contains pxp register base address and range ++- interrupts: where type is an interrupt type, num is the ++ interrupt number and flag is a field that level/trigger information for ++ the interrupt. ++- clocks: the clock sources that pxp depends on. ++- clock-names: the name is related to the clock source ++ ++Required properties for pxp on specified board: ++- status: should be set to "okay" if want to use PxP ++ ++Examples: ++for SOC imx6dl.dtsi: ++ pxp@020f0000 { ++ compatible = "fsl,imx6dl-pxp-dma"; ++ reg = <0x020f0000 0x4000>; ++ interrupts = <0 98 0x04>; ++ clocks = <&clks 133>; ++ clock-names = "pxp-axi"; ++ status = "disabled"; ++ }; ++ ++ ++for board imx6dl-sabresd.dts: ++ &pxp { ++ status = "okay"; ++ }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt +--- linux-3.14.14/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/video/fsl,v4l2-capture.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -0,0 +1,102 @@ ++* Freescale V4L2 Capture for i.MX6DQ/i.MX6SDL ++ ++Required board properties for IPUv3 capture: ++- clocks: should include the clock provided by i.MX6 to sensor ++- clock-names: sensor clock's name should be "ipux_csiy" ++ x should be 1 or 2 for i.MX6DQ; should be 1 for i.MX6SDL ++ y is 0 or 1 for i.MX6DQ/i.MX6SDL ++Note: other detailed information for IPUv3, please refer to ++Documentation/devicetree/bindings/fb/fsl_ipuv3_fb.txt ++ ++Required properties for v4l2_capture ++- compatible: should be "fsl,imx6q-v4l2-capture" ++- ipu_id: ipu id for v4l2 capture device ++ should be 0 or 1 for i.MX6DQ; should be 0 for i.MX6SDL ++- csi_id: csi id for v4l2 capture device ++ should be 0 or 1 for i.MX6DQ/i.MX6SDL ++- mclk_source: should be 0 or 1. two mclk sources at most now ++- status: should be set to "okay" to enable this device ++ ++Required properties for sensor ++- compatible: "," ++ please check the supported sensor in the Supported Sensor fields. ++- reg: sensor I2C slave address ++- pinctrl-names: should be "default" for parallel sensor ++- pinctrl-0: should depend on the connection between sensor and i.MX ++ connection between sensor and i.MX could be MIPI-CSI2 or legacy parallel ++- clocks: should be the clock source provided to sensor. ++- clock-names: should be "csi_mclk" ++- DOVDD-supply: set according to the board. ++- AVDD-supply: set according to the board. ++- DVDD-supply: set according to the board. ++- pwn-gpios: set according to the board. ++- rst-gpios: set according to the board. ++- csi_id: csi id for v4l2 capture device ++ should be 0 or 1 for i.MX6DQ/i.MX6SDL. ++- mclk: should the value of mclk clock send out the sensor. unit is Hz. ++- mclk_source: should be 0 or 1 and should be the same as the setting in ++ v4l2_capture. ++- cvbs: 1 for CVBS input, 0 YPbPr input. This property is only needed for ++ adv7180 tv decoder. ++ ++Supported Sensor ++- ov5640 ++- ov5642 ++- ov5640_mipi ++- adv7180 ++ ++ ++Example for IPUv3 including capture settings on imx6q-sabresd.dts: ++ ipu1: ipu@02400000 { /* IPU1 */ ++ compatible = "fsl,imx6q-ipuv3"; ++ reg = <0x02400000 0x400000>; ++ interrupts = <0 5 0x04>, < 0 6 0x04>; ++ clocks = <&clks 130>, <&clks 131>, <&clks 132>, <&clks 39>, <&clks 40>, <&clks 169>; ++ clock-names = "ipu1", "ipu1_di0", "ipu1_di1", "ipu1_di0_sel", "ipu1_di1_sel", "ipu1_csi0"; ++ status = "disabled"; ++ }; ++ ++Examples for v4l2_capture: ++ v4l2_cap { ++ compatible = "fsl,imx6q-v4l2-capture"; ++ ipu_id = <0>; ++ csi_id = <0>; ++ mclk_source = <0>; ++ status = "okay"; ++ }; ++ ++Examples for sensors: ++ ov5642: ov5642@3c { ++ compatible = "ovti,ov5642"; ++ reg = <0x3c>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_ipu1_2>; ++ clocks = <&clks 201>; ++ clock-names = "csi_mclk"; ++ DOVDD-supply = <&vgen4_reg>; /* 1.8v */ ++ AVDD-supply = <&vgen3_reg>; /* 2.8v, on rev C board is VGEN3 */ ++ DVDD-supply = <&vgen2_reg>; /* 1.5v*/ ++ pwn-gpios = <&gpio1 16 1>; /* active low: SD1_DAT0 */ ++ rst-gpios = <&gpio1 17 0>; /* active high: SD1_DAT1 */ ++ csi_id = <0>; ++ mclk = <24000000>; ++ mclk_source = <0>; ++ }; ++ ++ adv7180: adv7180@21 { ++ compatible = "adv,adv7180"; ++ reg = <0x21>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_ipu1_3>; ++ clocks = <&clks 201>; ++ clock-names = "csi_mclk"; ++ DOVDD-supply = <®_3p3v>; /* 3.3v, enabled via 2.8 VGEN6 */ ++ AVDD-supply = <®_3p3v>; /* 1.8v */ ++ DVDD-supply = <®_3p3v>; /* 1.8v */ ++ PVDD-supply = <®_3p3v>; /* 1.8v */ ++ pwn-gpios = <&max7310_b 2 0>; ++ csi_id = <0>; ++ mclk = <24000000>; ++ mclk_source = <0>; ++ cvbs = <1>; ++ }; +diff -Nur linux-3.14.14/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt linux-imx6-3.14/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt +--- linux-3.14.14/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/Documentation/devicetree/bindings/video/mxc_hdmi_video.txt 2014-12-08 00:31:50.952418001 -0600 +@@ -0,0 +1,20 @@ ++Device-Tree bindings for hdmi video driver ++ ++Required properties: ++- compatible: value should be "fsl,imx6q-hdmi-video". ++- fsl,hdcp: define the property in dts, hdmi driver will initalize for hdcp, ++ otherwise hdcp function will not supported. ++- fsl,phy_reg_vlev: hdmi phy register,Voltage Level Control Register offset 0x0e, ++ adjust hdmi phy signal voltage level. ++- fsl,phy_reg_cksymtx: hdmi phy register, clock symbol and transmitter control ++ register offset 0x09, adjust hdmi signal pre-emphasis. ++ ++Example: ++ ++ hdmi_video { ++ compatible = "fsl,imx6q-hdmi-video"; ++ fsl,hdcp; ++ fsl,phy_reg_vlev = <0x0294>; ++ fsl,phy_reg_cksymtx = <0x800d>; ++ }; ++ +diff -Nur linux-3.14.14/Documentation/filesystems/hfsplus.txt linux-imx6-3.14/Documentation/filesystems/hfsplus.txt +--- linux-3.14.14/Documentation/filesystems/hfsplus.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/filesystems/hfsplus.txt 2014-12-08 00:31:50.968418001 -0600 +@@ -56,4 +56,4 @@ + + kernel source: + +-Apple Technote 1150 http://developer.apple.com/technotes/tn/tn1150.html ++Apple Technote 1150 https://developer.apple.com/legacy/library/technotes/tn/tn1150.html +diff -Nur linux-3.14.14/Documentation/kernel-parameters.txt linux-imx6-3.14/Documentation/kernel-parameters.txt +--- linux-3.14.14/Documentation/kernel-parameters.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/kernel-parameters.txt 2014-12-08 00:31:50.996418001 -0600 +@@ -603,8 +603,11 @@ + Also note the kernel might malfunction if you disable + some critical bits. + +- cma=nn[MG] [ARM,KNL] +- Sets the size of kernel global memory area for contiguous ++ cma=nn[MG]@[start[MG][-end[MG]]] ++ [ARM,X86,KNL] ++ Sets the size of kernel global memory area for ++ contiguous memory allocations and optionally the ++ placement constraint by the physical address range of + memory allocations. For more information, see + include/linux/dma-contiguous.h + +diff -Nur linux-3.14.14/Documentation/networking/gianfar.txt linux-imx6-3.14/Documentation/networking/gianfar.txt +--- linux-3.14.14/Documentation/networking/gianfar.txt 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/Documentation/networking/gianfar.txt 2014-12-08 00:31:51.008418001 -0600 +@@ -1,38 +1,8 @@ + The Gianfar Ethernet Driver +-Sysfs File description + + Author: Andy Fleming + Updated: 2005-07-28 + +-SYSFS +- +-Several of the features of the gianfar driver are controlled +-through sysfs files. These are: +- +-bd_stash: +-To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to +-bd_stash, echo 'off' or '0' to disable +- +-rx_stash_len: +-To stash the first n bytes of the packet in L2, echo the number +-of bytes to buf_stash_len. echo 0 to disable. +- +-WARNING: You could really screw these up if you set them too low or high! +-fifo_threshold: +-To change the number of bytes the controller needs in the +-fifo before it starts transmission, echo the number of bytes to +-fifo_thresh. Range should be 0-511. +- +-fifo_starve: +-When the FIFO has less than this many bytes during a transmit, it +-enters starve mode, and increases the priority of TX memory +-transactions. To change, echo the number of bytes to +-fifo_starve. Range should be 0-511. +- +-fifo_starve_off: +-Once in starve mode, the FIFO remains there until it has this +-many bytes. To change, echo the number of bytes to +-fifo_starve_off. Range should be 0-511. + + CHECKSUM OFFLOADING + +diff -Nur linux-3.14.14/drivers/ata/acard-ahci.c linux-imx6-3.14/drivers/ata/acard-ahci.c +--- linux-3.14.14/drivers/ata/acard-ahci.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/acard-ahci.c 2014-12-08 00:31:52.424418001 -0600 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/ahci.c linux-imx6-3.14/drivers/ata/ahci.c +--- linux-3.14.14/drivers/ata/ahci.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/ahci.c 2014-12-08 00:31:52.424418001 -0600 +@@ -35,7 +35,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -582,6 +581,7 @@ + unsigned long deadline) + { + struct ata_port *ap = link->ap; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + bool online; + int rc; + +@@ -592,7 +592,7 @@ + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), + deadline, &online, NULL); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class); + +@@ -607,6 +607,7 @@ + { + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -622,7 +623,7 @@ + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), + deadline, &online, NULL); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* The pseudo configuration device on SIMG4726 attached to + * ASUS P5W-DH Deluxe doesn't send signature FIS after +@@ -1118,6 +1119,17 @@ + return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); + } + ++static bool ahci_broken_devslp(struct pci_dev *pdev) ++{ ++ /* device with broken DEVSLP but still showing SDS capability */ ++ static const struct pci_device_id ids[] = { ++ { PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */ ++ {} ++ }; ++ ++ return pci_match_id(ids, pdev); ++} ++ + #ifdef CONFIG_ATA_ACPI + static void ahci_gtf_filter_workaround(struct ata_host *host) + { +@@ -1369,6 +1381,10 @@ + + hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; + ++ /* must set flag prior to save config in order to take effect */ ++ if (ahci_broken_devslp(pdev)) ++ hpriv->flags |= AHCI_HFLAG_NO_DEVSLP; ++ + /* save initial config */ + ahci_pci_save_initial_config(pdev, hpriv); + +diff -Nur linux-3.14.14/drivers/ata/ahci.h linux-imx6-3.14/drivers/ata/ahci.h +--- linux-3.14.14/drivers/ata/ahci.h 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/ahci.h 2014-12-08 00:31:52.424418001 -0600 +@@ -37,6 +37,8 @@ + + #include + #include ++#include ++#include + + /* Enclosure Management Control */ + #define EM_CTRL_MSG_TYPE 0x000f0000 +@@ -51,6 +53,7 @@ + + enum { + AHCI_MAX_PORTS = 32, ++ AHCI_MAX_CLKS = 3, + AHCI_MAX_SG = 168, /* hardware max is 64K */ + AHCI_DMA_BOUNDARY = 0xffffffff, + AHCI_MAX_CMDS = 32, +@@ -233,6 +236,8 @@ + port start (wait until + error-handling stage) */ + AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */ ++ AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */ ++ AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */ + + /* ap->flags bits */ + +@@ -322,8 +327,17 @@ + u32 em_loc; /* enclosure management location */ + u32 em_buf_sz; /* EM buffer size in byte */ + u32 em_msg_type; /* EM message type */ +- struct clk *clk; /* Only for platforms supporting clk */ ++ bool got_runtime_pm; /* Did we do pm_runtime_get? */ ++ struct clk *clks[AHCI_MAX_CLKS]; /* Optional */ ++ struct regulator *target_pwr; /* Optional */ ++ struct phy *phy; /* If platform uses phy */ + void *plat_data; /* Other platform data */ ++ /* ++ * Optional ahci_start_engine override, if not set this gets set to the ++ * default ahci_start_engine during ahci_save_initial_config, this can ++ * be overridden anytime before the host is activated. ++ */ ++ void (*start_engine)(struct ata_port *ap); + }; + + extern int ahci_ignore_sss; +diff -Nur linux-3.14.14/drivers/ata/ahci_imx.c linux-imx6-3.14/drivers/ata/ahci_imx.c +--- linux-3.14.14/drivers/ata/ahci_imx.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/ahci_imx.c 2014-12-08 00:31:52.428418001 -0600 +@@ -26,12 +26,29 @@ + #include + #include + #include ++#include + #include "ahci.h" + + enum { +- PORT_PHY_CTL = 0x178, /* Port0 PHY Control */ +- PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */ +- HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ ++ /* Timer 1-ms Register */ ++ IMX_TIMER1MS = 0x00e0, ++ /* Port0 PHY Control Register */ ++ IMX_P0PHYCR = 0x0178, ++ IMX_P0PHYCR_TEST_PDDQ = 1 << 20, ++ IMX_P0PHYCR_CR_READ = 1 << 19, ++ IMX_P0PHYCR_CR_WRITE = 1 << 18, ++ IMX_P0PHYCR_CR_CAP_DATA = 1 << 17, ++ IMX_P0PHYCR_CR_CAP_ADDR = 1 << 16, ++ /* Port0 PHY Status Register */ ++ IMX_P0PHYSR = 0x017c, ++ IMX_P0PHYSR_CR_ACK = 1 << 18, ++ IMX_P0PHYSR_CR_DATA_OUT = 0xffff << 0, ++ /* Lane0 Output Status Register */ ++ IMX_LANE0_OUT_STAT = 0x2003, ++ IMX_LANE0_OUT_STAT_RX_PLL_STATE = 1 << 1, ++ /* Clock Reset Register */ ++ IMX_CLOCK_RESET = 0x7f3f, ++ IMX_CLOCK_RESET_RESET = 1 << 0, + }; + + enum ahci_imx_type { +@@ -42,62 +59,230 @@ + struct imx_ahci_priv { + struct platform_device *ahci_pdev; + enum ahci_imx_type type; +- +- /* i.MX53 clock */ +- struct clk *sata_gate_clk; +- /* Common clock */ +- struct clk *sata_ref_clk; + struct clk *ahb_clk; +- + struct regmap *gpr; + bool no_device; + bool first_time; ++ u32 phy_params; + }; + + static int ahci_imx_hotplug; + module_param_named(hotplug, ahci_imx_hotplug, int, 0644); + MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); + +-static int imx_sata_clock_enable(struct device *dev) ++static void ahci_imx_host_stop(struct ata_host *host); ++ ++static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert) ++{ ++ int timeout = 10; ++ u32 crval; ++ u32 srval; ++ ++ /* Assert or deassert the bit */ ++ crval = readl(mmio + IMX_P0PHYCR); ++ if (assert) ++ crval |= bit; ++ else ++ crval &= ~bit; ++ writel(crval, mmio + IMX_P0PHYCR); ++ ++ /* Wait for the cr_ack signal */ ++ do { ++ srval = readl(mmio + IMX_P0PHYSR); ++ if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK) ++ break; ++ usleep_range(100, 200); ++ } while (--timeout); ++ ++ return timeout ? 0 : -ETIMEDOUT; ++} ++ ++static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio) + { +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); ++ u32 crval = addr; + int ret; + +- if (imxpriv->type == AHCI_IMX53) { +- ret = clk_prepare_enable(imxpriv->sata_gate_clk); +- if (ret < 0) { +- dev_err(dev, "prepare-enable sata_gate clock err:%d\n", +- ret); +- return ret; +- } ++ /* Supply the address on cr_data_in */ ++ writel(crval, mmio + IMX_P0PHYCR); ++ ++ /* Assert the cr_cap_addr signal */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true); ++ if (ret) ++ return ret; ++ ++ /* Deassert cr_cap_addr */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int imx_phy_reg_write(u16 val, void __iomem *mmio) ++{ ++ u32 crval = val; ++ int ret; ++ ++ /* Supply the data on cr_data_in */ ++ writel(crval, mmio + IMX_P0PHYCR); ++ ++ /* Assert the cr_cap_data signal */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true); ++ if (ret) ++ return ret; ++ ++ /* Deassert cr_cap_data */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false); ++ if (ret) ++ return ret; ++ ++ if (val & IMX_CLOCK_RESET_RESET) { ++ /* ++ * In case we're resetting the phy, it's unable to acknowledge, ++ * so we return immediately here. ++ */ ++ crval |= IMX_P0PHYCR_CR_WRITE; ++ writel(crval, mmio + IMX_P0PHYCR); ++ goto out; + } + +- ret = clk_prepare_enable(imxpriv->sata_ref_clk); +- if (ret < 0) { +- dev_err(dev, "prepare-enable sata_ref clock err:%d\n", +- ret); +- goto clk_err; ++ /* Assert the cr_write signal */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true); ++ if (ret) ++ return ret; ++ ++ /* Deassert cr_write */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false); ++ if (ret) ++ return ret; ++ ++out: ++ return 0; ++} ++ ++static int imx_phy_reg_read(u16 *val, void __iomem *mmio) ++{ ++ int ret; ++ ++ /* Assert the cr_read signal */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true); ++ if (ret) ++ return ret; ++ ++ /* Capture the data from cr_data_out[] */ ++ *val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT; ++ ++ /* Deassert cr_read */ ++ ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int imx_sata_phy_reset(struct ahci_host_priv *hpriv) ++{ ++ void __iomem *mmio = hpriv->mmio; ++ int timeout = 10; ++ u16 val; ++ int ret; ++ ++ /* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */ ++ ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio); ++ if (ret) ++ return ret; ++ ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio); ++ if (ret) ++ return ret; ++ ++ /* Wait for PHY RX_PLL to be stable */ ++ do { ++ usleep_range(100, 200); ++ ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio); ++ if (ret) ++ return ret; ++ ret = imx_phy_reg_read(&val, mmio); ++ if (ret) ++ return ret; ++ if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE) ++ break; ++ } while (--timeout); ++ ++ return timeout ? 0 : -ETIMEDOUT; ++} ++ ++static int imx_sata_enable(struct ahci_host_priv *hpriv) ++{ ++ struct imx_ahci_priv *imxpriv = hpriv->plat_data; ++ struct device *dev = &imxpriv->ahci_pdev->dev; ++ int ret; ++ ++ if (imxpriv->no_device) ++ return 0; ++ ++ if (hpriv->target_pwr) { ++ ret = regulator_enable(hpriv->target_pwr); ++ if (ret) ++ return ret; + } + ++ request_bus_freq(BUS_FREQ_HIGH); ++ ++ ret = ahci_platform_enable_clks(hpriv); ++ if (ret < 0) ++ goto disable_regulator; ++ + if (imxpriv->type == AHCI_IMX6Q) { ++ /* ++ * set PHY Paremeters, two steps to configure the GPR13, ++ * one write for rest of parameters, mask of first write ++ * is 0x07ffffff, and the other one write for setting ++ * the mpll_clk_en. ++ */ ++ regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, ++ IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | ++ IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | ++ IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | ++ IMX6Q_GPR13_SATA_SPD_MODE_MASK | ++ IMX6Q_GPR13_SATA_MPLL_SS_EN | ++ IMX6Q_GPR13_SATA_TX_ATTEN_MASK | ++ IMX6Q_GPR13_SATA_TX_BOOST_MASK | ++ IMX6Q_GPR13_SATA_TX_LVL_MASK | ++ IMX6Q_GPR13_SATA_MPLL_CLK_EN | ++ IMX6Q_GPR13_SATA_TX_EDGE_RATE, ++ imxpriv->phy_params); + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); ++ ++ usleep_range(100, 200); ++ ++ ret = imx_sata_phy_reset(hpriv); ++ if (ret) { ++ dev_err(dev, "failed to reset phy: %d\n", ret); ++ goto disable_regulator; ++ } + } + + usleep_range(1000, 2000); + + return 0; + +-clk_err: +- if (imxpriv->type == AHCI_IMX53) +- clk_disable_unprepare(imxpriv->sata_gate_clk); ++disable_regulator: ++ release_bus_freq(BUS_FREQ_HIGH); ++ ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++ + return ret; + } + +-static void imx_sata_clock_disable(struct device *dev) ++static void imx_sata_disable(struct ahci_host_priv *hpriv) + { +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); ++ struct imx_ahci_priv *imxpriv = hpriv->plat_data; ++ ++ if (imxpriv->no_device) ++ return; + + if (imxpriv->type == AHCI_IMX6Q) { + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, +@@ -105,10 +290,12 @@ + !IMX6Q_GPR13_SATA_MPLL_CLK_EN); + } + +- clk_disable_unprepare(imxpriv->sata_ref_clk); ++ ahci_platform_disable_clks(hpriv); + +- if (imxpriv->type == AHCI_IMX53) +- clk_disable_unprepare(imxpriv->sata_gate_clk); ++ release_bus_freq(BUS_FREQ_HIGH); ++ ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); + } + + static void ahci_imx_error_handler(struct ata_port *ap) +@@ -118,7 +305,7 @@ + struct ata_host *host = dev_get_drvdata(ap->dev); + struct ahci_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->mmio; +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); ++ struct imx_ahci_priv *imxpriv = hpriv->plat_data; + + ahci_error_handler(ap); + +@@ -134,17 +321,23 @@ + * without full reset once the pddq mode is enabled making it + * impossible to use as part of libata LPM. + */ +- reg_val = readl(mmio + PORT_PHY_CTL); +- writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); +- imx_sata_clock_disable(ap->dev); ++ reg_val = readl(mmio + IMX_P0PHYCR); ++ writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR); ++ imx_sata_disable(hpriv); + imxpriv->no_device = true; ++ ++ dev_info(ap->dev, "no device found, disabling link.\n"); ++ dev_info(ap->dev, "pass " MODULE_PARAM_PREFIX ++ ".hotplug=1 to enable hotplug\n"); + } + + static int ahci_imx_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) + { + struct ata_port *ap = link->ap; +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); ++ struct ata_host *host = dev_get_drvdata(ap->dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ struct imx_ahci_priv *imxpriv = hpriv->plat_data; + int ret = -EIO; + + if (imxpriv->type == AHCI_IMX53) +@@ -156,7 +349,8 @@ + } + + static struct ata_port_operations ahci_imx_ops = { +- .inherits = &ahci_platform_ops, ++ .inherits = &ahci_ops, ++ .host_stop = ahci_imx_host_stop, + .error_handler = ahci_imx_error_handler, + .softreset = ahci_imx_softreset, + }; +@@ -168,234 +362,306 @@ + .port_ops = &ahci_imx_ops, + }; + +-static int imx_sata_init(struct device *dev, void __iomem *mmio) +-{ +- int ret = 0; +- unsigned int reg_val; +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); +- +- ret = imx_sata_clock_enable(dev); +- if (ret < 0) +- return ret; ++static const struct of_device_id imx_ahci_of_match[] = { ++ { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, ++ { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, imx_ahci_of_match); + +- /* +- * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, +- * and IP vendor specific register HOST_TIMER1MS. +- * Configure CAP_SSS (support stagered spin up). +- * Implement the port0. +- * Get the ahb clock rate, and configure the TIMER1MS register. +- */ +- reg_val = readl(mmio + HOST_CAP); +- if (!(reg_val & HOST_CAP_SSS)) { +- reg_val |= HOST_CAP_SSS; +- writel(reg_val, mmio + HOST_CAP); +- } +- reg_val = readl(mmio + HOST_PORTS_IMPL); +- if (!(reg_val & 0x1)) { +- reg_val |= 0x1; +- writel(reg_val, mmio + HOST_PORTS_IMPL); +- } ++struct reg_value { ++ u32 of_value; ++ u32 reg_value; ++}; + +- reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; +- writel(reg_val, mmio + HOST_TIMER1MS); ++struct reg_property { ++ const char *name; ++ const struct reg_value *values; ++ size_t num_values; ++ u32 def_value; ++ u32 set_value; ++}; + +- return 0; +-} ++static const struct reg_value gpr13_tx_level[] = { ++ { 937, IMX6Q_GPR13_SATA_TX_LVL_0_937_V }, ++ { 947, IMX6Q_GPR13_SATA_TX_LVL_0_947_V }, ++ { 957, IMX6Q_GPR13_SATA_TX_LVL_0_957_V }, ++ { 966, IMX6Q_GPR13_SATA_TX_LVL_0_966_V }, ++ { 976, IMX6Q_GPR13_SATA_TX_LVL_0_976_V }, ++ { 986, IMX6Q_GPR13_SATA_TX_LVL_0_986_V }, ++ { 996, IMX6Q_GPR13_SATA_TX_LVL_0_996_V }, ++ { 1005, IMX6Q_GPR13_SATA_TX_LVL_1_005_V }, ++ { 1015, IMX6Q_GPR13_SATA_TX_LVL_1_015_V }, ++ { 1025, IMX6Q_GPR13_SATA_TX_LVL_1_025_V }, ++ { 1035, IMX6Q_GPR13_SATA_TX_LVL_1_035_V }, ++ { 1045, IMX6Q_GPR13_SATA_TX_LVL_1_045_V }, ++ { 1054, IMX6Q_GPR13_SATA_TX_LVL_1_054_V }, ++ { 1064, IMX6Q_GPR13_SATA_TX_LVL_1_064_V }, ++ { 1074, IMX6Q_GPR13_SATA_TX_LVL_1_074_V }, ++ { 1084, IMX6Q_GPR13_SATA_TX_LVL_1_084_V }, ++ { 1094, IMX6Q_GPR13_SATA_TX_LVL_1_094_V }, ++ { 1104, IMX6Q_GPR13_SATA_TX_LVL_1_104_V }, ++ { 1113, IMX6Q_GPR13_SATA_TX_LVL_1_113_V }, ++ { 1123, IMX6Q_GPR13_SATA_TX_LVL_1_123_V }, ++ { 1133, IMX6Q_GPR13_SATA_TX_LVL_1_133_V }, ++ { 1143, IMX6Q_GPR13_SATA_TX_LVL_1_143_V }, ++ { 1152, IMX6Q_GPR13_SATA_TX_LVL_1_152_V }, ++ { 1162, IMX6Q_GPR13_SATA_TX_LVL_1_162_V }, ++ { 1172, IMX6Q_GPR13_SATA_TX_LVL_1_172_V }, ++ { 1182, IMX6Q_GPR13_SATA_TX_LVL_1_182_V }, ++ { 1191, IMX6Q_GPR13_SATA_TX_LVL_1_191_V }, ++ { 1201, IMX6Q_GPR13_SATA_TX_LVL_1_201_V }, ++ { 1211, IMX6Q_GPR13_SATA_TX_LVL_1_211_V }, ++ { 1221, IMX6Q_GPR13_SATA_TX_LVL_1_221_V }, ++ { 1230, IMX6Q_GPR13_SATA_TX_LVL_1_230_V }, ++ { 1240, IMX6Q_GPR13_SATA_TX_LVL_1_240_V } ++}; + +-static void imx_sata_exit(struct device *dev) +-{ +- imx_sata_clock_disable(dev); +-} ++static const struct reg_value gpr13_tx_boost[] = { ++ { 0, IMX6Q_GPR13_SATA_TX_BOOST_0_00_DB }, ++ { 370, IMX6Q_GPR13_SATA_TX_BOOST_0_37_DB }, ++ { 740, IMX6Q_GPR13_SATA_TX_BOOST_0_74_DB }, ++ { 1110, IMX6Q_GPR13_SATA_TX_BOOST_1_11_DB }, ++ { 1480, IMX6Q_GPR13_SATA_TX_BOOST_1_48_DB }, ++ { 1850, IMX6Q_GPR13_SATA_TX_BOOST_1_85_DB }, ++ { 2220, IMX6Q_GPR13_SATA_TX_BOOST_2_22_DB }, ++ { 2590, IMX6Q_GPR13_SATA_TX_BOOST_2_59_DB }, ++ { 2960, IMX6Q_GPR13_SATA_TX_BOOST_2_96_DB }, ++ { 3330, IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB }, ++ { 3700, IMX6Q_GPR13_SATA_TX_BOOST_3_70_DB }, ++ { 4070, IMX6Q_GPR13_SATA_TX_BOOST_4_07_DB }, ++ { 4440, IMX6Q_GPR13_SATA_TX_BOOST_4_44_DB }, ++ { 4810, IMX6Q_GPR13_SATA_TX_BOOST_4_81_DB }, ++ { 5280, IMX6Q_GPR13_SATA_TX_BOOST_5_28_DB }, ++ { 5750, IMX6Q_GPR13_SATA_TX_BOOST_5_75_DB } ++}; + +-static int imx_ahci_suspend(struct device *dev) +-{ +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); ++static const struct reg_value gpr13_tx_atten[] = { ++ { 8, IMX6Q_GPR13_SATA_TX_ATTEN_8_16 }, ++ { 9, IMX6Q_GPR13_SATA_TX_ATTEN_9_16 }, ++ { 10, IMX6Q_GPR13_SATA_TX_ATTEN_10_16 }, ++ { 12, IMX6Q_GPR13_SATA_TX_ATTEN_12_16 }, ++ { 14, IMX6Q_GPR13_SATA_TX_ATTEN_14_16 }, ++ { 16, IMX6Q_GPR13_SATA_TX_ATTEN_16_16 }, ++}; + +- /* +- * If no_device is set, The CLKs had been gated off in the +- * initialization so don't do it again here. +- */ +- if (!imxpriv->no_device) +- imx_sata_clock_disable(dev); ++static const struct reg_value gpr13_rx_eq[] = { ++ { 500, IMX6Q_GPR13_SATA_RX_EQ_VAL_0_5_DB }, ++ { 1000, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_0_DB }, ++ { 1500, IMX6Q_GPR13_SATA_RX_EQ_VAL_1_5_DB }, ++ { 2000, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_0_DB }, ++ { 2500, IMX6Q_GPR13_SATA_RX_EQ_VAL_2_5_DB }, ++ { 3000, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB }, ++ { 3500, IMX6Q_GPR13_SATA_RX_EQ_VAL_3_5_DB }, ++ { 4000, IMX6Q_GPR13_SATA_RX_EQ_VAL_4_0_DB }, ++}; + +- return 0; +-} ++static const struct reg_property gpr13_props[] = { ++ { ++ .name = "fsl,transmit-level-mV", ++ .values = gpr13_tx_level, ++ .num_values = ARRAY_SIZE(gpr13_tx_level), ++ .def_value = IMX6Q_GPR13_SATA_TX_LVL_1_025_V, ++ }, { ++ .name = "fsl,transmit-boost-mdB", ++ .values = gpr13_tx_boost, ++ .num_values = ARRAY_SIZE(gpr13_tx_boost), ++ .def_value = IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB, ++ }, { ++ .name = "fsl,transmit-atten-16ths", ++ .values = gpr13_tx_atten, ++ .num_values = ARRAY_SIZE(gpr13_tx_atten), ++ .def_value = IMX6Q_GPR13_SATA_TX_ATTEN_9_16, ++ }, { ++ .name = "fsl,receive-eq-mdB", ++ .values = gpr13_rx_eq, ++ .num_values = ARRAY_SIZE(gpr13_rx_eq), ++ .def_value = IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB, ++ }, { ++ .name = "fsl,no-spread-spectrum", ++ .def_value = IMX6Q_GPR13_SATA_MPLL_SS_EN, ++ .set_value = 0, ++ }, ++}; + +-static int imx_ahci_resume(struct device *dev) ++static u32 imx_ahci_parse_props(struct device *dev, ++ const struct reg_property *prop, size_t num) + { +- struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); +- int ret = 0; +- +- if (!imxpriv->no_device) +- ret = imx_sata_clock_enable(dev); ++ struct device_node *np = dev->of_node; ++ u32 reg_value = 0; ++ int i, j; ++ ++ for (i = 0; i < num; i++, prop++) { ++ u32 of_val; ++ ++ if (prop->num_values == 0) { ++ if (of_property_read_bool(np, prop->name)) ++ reg_value |= prop->set_value; ++ else ++ reg_value |= prop->def_value; ++ continue; ++ } + +- return ret; +-} ++ if (of_property_read_u32(np, prop->name, &of_val)) { ++ dev_info(dev, "%s not specified, using %08x\n", ++ prop->name, prop->def_value); ++ reg_value |= prop->def_value; ++ continue; ++ } + +-static struct ahci_platform_data imx_sata_pdata = { +- .init = imx_sata_init, +- .exit = imx_sata_exit, +- .ata_port_info = &ahci_imx_port_info, +- .suspend = imx_ahci_suspend, +- .resume = imx_ahci_resume, ++ for (j = 0; j < prop->num_values; j++) { ++ if (prop->values[j].of_value == of_val) { ++ dev_info(dev, "%s value %u, using %08x\n", ++ prop->name, of_val, prop->values[j].reg_value); ++ reg_value |= prop->values[j].reg_value; ++ break; ++ } ++ } + +-}; ++ if (j == prop->num_values) { ++ dev_err(dev, "DT property %s is not a valid value\n", ++ prop->name); ++ reg_value |= prop->def_value; ++ } ++ } + +-static const struct of_device_id imx_ahci_of_match[] = { +- { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, +- { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, imx_ahci_of_match); ++ return reg_value; ++} + + static int imx_ahci_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- struct resource *mem, *irq, res[2]; + const struct of_device_id *of_id; +- enum ahci_imx_type type; +- const struct ahci_platform_data *pdata = NULL; ++ struct ahci_host_priv *hpriv; + struct imx_ahci_priv *imxpriv; +- struct device *ahci_dev; +- struct platform_device *ahci_pdev; ++ unsigned int reg_val; + int ret; + + of_id = of_match_device(imx_ahci_of_match, dev); + if (!of_id) + return -EINVAL; + +- type = (enum ahci_imx_type)of_id->data; +- pdata = &imx_sata_pdata; +- + imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); +- if (!imxpriv) { +- dev_err(dev, "can't alloc ahci_host_priv\n"); ++ if (!imxpriv) + return -ENOMEM; +- } +- +- ahci_pdev = platform_device_alloc("ahci", -1); +- if (!ahci_pdev) +- return -ENODEV; +- +- ahci_dev = &ahci_pdev->dev; +- ahci_dev->parent = dev; + ++ imxpriv->ahci_pdev = pdev; + imxpriv->no_device = false; + imxpriv->first_time = true; +- imxpriv->type = type; +- ++ imxpriv->type = (enum ahci_imx_type)of_id->data; + imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); + if (IS_ERR(imxpriv->ahb_clk)) { + dev_err(dev, "can't get ahb clock.\n"); +- ret = PTR_ERR(imxpriv->ahb_clk); +- goto err_out; +- } +- +- if (type == AHCI_IMX53) { +- imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate"); +- if (IS_ERR(imxpriv->sata_gate_clk)) { +- dev_err(dev, "can't get sata_gate clock.\n"); +- ret = PTR_ERR(imxpriv->sata_gate_clk); +- goto err_out; +- } +- } +- +- imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref"); +- if (IS_ERR(imxpriv->sata_ref_clk)) { +- dev_err(dev, "can't get sata_ref clock.\n"); +- ret = PTR_ERR(imxpriv->sata_ref_clk); +- goto err_out; ++ return PTR_ERR(imxpriv->ahb_clk); + } + +- imxpriv->ahci_pdev = ahci_pdev; +- platform_set_drvdata(pdev, imxpriv); +- +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (!mem || !irq) { +- dev_err(dev, "no mmio/irq resource\n"); +- ret = -ENOMEM; +- goto err_out; +- } +- +- res[0] = *mem; +- res[1] = *irq; +- +- ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32); +- ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; +- ahci_dev->of_node = dev->of_node; ++ if (imxpriv->type == AHCI_IMX6Q) { ++ u32 reg_value; + +- if (type == AHCI_IMX6Q) { + imxpriv->gpr = syscon_regmap_lookup_by_compatible( + "fsl,imx6q-iomuxc-gpr"); + if (IS_ERR(imxpriv->gpr)) { + dev_err(dev, + "failed to find fsl,imx6q-iomux-gpr regmap\n"); +- ret = PTR_ERR(imxpriv->gpr); +- goto err_out; ++ return PTR_ERR(imxpriv->gpr); + } + +- /* +- * Set PHY Paremeters, two steps to configure the GPR13, +- * one write for rest of parameters, mask of first write +- * is 0x07fffffe, and the other one write for setting +- * the mpll_clk_en happens in imx_sata_clock_enable(). +- */ +- regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, +- IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK | +- IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK | +- IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK | +- IMX6Q_GPR13_SATA_SPD_MODE_MASK | +- IMX6Q_GPR13_SATA_MPLL_SS_EN | +- IMX6Q_GPR13_SATA_TX_ATTEN_MASK | +- IMX6Q_GPR13_SATA_TX_BOOST_MASK | +- IMX6Q_GPR13_SATA_TX_LVL_MASK | +- IMX6Q_GPR13_SATA_MPLL_CLK_EN | +- IMX6Q_GPR13_SATA_TX_EDGE_RATE, +- IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB | ++ reg_value = imx_ahci_parse_props(dev, gpr13_props, ++ ARRAY_SIZE(gpr13_props)); ++ ++ imxpriv->phy_params = + IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M | + IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F | + IMX6Q_GPR13_SATA_SPD_MODE_3P0G | +- IMX6Q_GPR13_SATA_MPLL_SS_EN | +- IMX6Q_GPR13_SATA_TX_ATTEN_9_16 | +- IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB | +- IMX6Q_GPR13_SATA_TX_LVL_1_025_V); ++ reg_value; + } + +- ret = platform_device_add_resources(ahci_pdev, res, 2); ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); ++ ++ hpriv->plat_data = imxpriv; ++ ++ ret = imx_sata_enable(hpriv); + if (ret) +- goto err_out; ++ return ret; + +- ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata)); ++ /* ++ * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, ++ * and IP vendor specific register IMX_TIMER1MS. ++ * Configure CAP_SSS (support stagered spin up). ++ * Implement the port0. ++ * Get the ahb clock rate, and configure the TIMER1MS register. ++ */ ++ reg_val = readl(hpriv->mmio + HOST_CAP); ++ if (!(reg_val & HOST_CAP_SSS)) { ++ reg_val |= HOST_CAP_SSS; ++ writel(reg_val, hpriv->mmio + HOST_CAP); ++ } ++ reg_val = readl(hpriv->mmio + HOST_PORTS_IMPL); ++ if (!(reg_val & 0x1)) { ++ reg_val |= 0x1; ++ writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL); ++ } ++ ++ reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; ++ writel(reg_val, hpriv->mmio + IMX_TIMER1MS); ++ ++ ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, ++ 0, 0, 0); + if (ret) +- goto err_out; ++ imx_sata_disable(hpriv); ++ ++ return ret; ++} + +- ret = platform_device_add(ahci_pdev); +- if (ret) { +-err_out: +- platform_device_put(ahci_pdev); ++static void ahci_imx_host_stop(struct ata_host *host) ++{ ++ struct ahci_host_priv *hpriv = host->private_data; ++ ++ imx_sata_disable(hpriv); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int imx_ahci_suspend(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int ret; ++ ++ ret = ahci_platform_suspend_host(dev); ++ if (ret) + return ret; +- } ++ ++ imx_sata_disable(hpriv); + + return 0; + } + +-static int imx_ahci_remove(struct platform_device *pdev) ++static int imx_ahci_resume(struct device *dev) + { +- struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev); +- struct platform_device *ahci_pdev = imxpriv->ahci_pdev; ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int ret; + +- platform_device_unregister(ahci_pdev); +- return 0; ++ ret = imx_sata_enable(hpriv); ++ if (ret) ++ return ret; ++ ++ return ahci_platform_resume_host(dev); + } ++#endif ++ ++static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); + + static struct platform_driver imx_ahci_driver = { + .probe = imx_ahci_probe, +- .remove = imx_ahci_remove, ++ .remove = ata_platform_remove_one, + .driver = { + .name = "ahci-imx", + .owner = THIS_MODULE, + .of_match_table = imx_ahci_of_match, ++ .pm = &ahci_imx_pm_ops, + }, + }; + module_platform_driver(imx_ahci_driver); +diff -Nur linux-3.14.14/drivers/ata/ahci_platform.c linux-imx6-3.14/drivers/ata/ahci_platform.c +--- linux-3.14.14/drivers/ata/ahci_platform.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/ahci_platform.c 2014-12-08 00:31:52.428418001 -0600 +@@ -12,135 +12,36 @@ + * any later version. + */ + +-#include + #include +-#include + #include + #include +-#include +-#include + #include + #include + #include + #include + #include "ahci.h" + +-static void ahci_host_stop(struct ata_host *host); +- +-enum ahci_type { +- AHCI, /* standard platform ahci */ +- IMX53_AHCI, /* ahci on i.mx53 */ +- STRICT_AHCI, /* delayed DMA engine start */ +-}; +- +-static struct platform_device_id ahci_devtype[] = { +- { +- .name = "ahci", +- .driver_data = AHCI, +- }, { +- .name = "imx53-ahci", +- .driver_data = IMX53_AHCI, +- }, { +- .name = "strict-ahci", +- .driver_data = STRICT_AHCI, +- }, { +- /* sentinel */ +- } +-}; +-MODULE_DEVICE_TABLE(platform, ahci_devtype); +- +-struct ata_port_operations ahci_platform_ops = { +- .inherits = &ahci_ops, +- .host_stop = ahci_host_stop, +-}; +-EXPORT_SYMBOL_GPL(ahci_platform_ops); +- +-static struct ata_port_operations ahci_platform_retry_srst_ops = { +- .inherits = &ahci_pmp_retry_srst_ops, +- .host_stop = ahci_host_stop, +-}; +- +-static const struct ata_port_info ahci_port_info[] = { +- /* by features */ +- [AHCI] = { +- .flags = AHCI_FLAG_COMMON, +- .pio_mask = ATA_PIO4, +- .udma_mask = ATA_UDMA6, +- .port_ops = &ahci_platform_ops, +- }, +- [IMX53_AHCI] = { +- .flags = AHCI_FLAG_COMMON, +- .pio_mask = ATA_PIO4, +- .udma_mask = ATA_UDMA6, +- .port_ops = &ahci_platform_retry_srst_ops, +- }, +- [STRICT_AHCI] = { +- AHCI_HFLAGS (AHCI_HFLAG_DELAY_ENGINE), +- .flags = AHCI_FLAG_COMMON, +- .pio_mask = ATA_PIO4, +- .udma_mask = ATA_UDMA6, +- .port_ops = &ahci_platform_ops, +- }, +-}; +- +-static struct scsi_host_template ahci_platform_sht = { +- AHCI_SHT("ahci_platform"), ++static const struct ata_port_info ahci_port_info = { ++ .flags = AHCI_FLAG_COMMON, ++ .pio_mask = ATA_PIO4, ++ .udma_mask = ATA_UDMA6, ++ .port_ops = &ahci_platform_ops, + }; + + static int ahci_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct ahci_platform_data *pdata = dev_get_platdata(dev); +- const struct platform_device_id *id = platform_get_device_id(pdev); +- struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0]; +- const struct ata_port_info *ppi[] = { &pi, NULL }; + struct ahci_host_priv *hpriv; +- struct ata_host *host; +- struct resource *mem; +- int irq; +- int n_ports; +- int i; + int rc; + +- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!mem) { +- dev_err(dev, "no mmio space\n"); +- return -EINVAL; +- } +- +- irq = platform_get_irq(pdev, 0); +- if (irq <= 0) { +- dev_err(dev, "no irq\n"); +- return -EINVAL; +- } +- +- if (pdata && pdata->ata_port_info) +- pi = *pdata->ata_port_info; +- +- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); +- if (!hpriv) { +- dev_err(dev, "can't alloc ahci_host_priv\n"); +- return -ENOMEM; +- } +- +- hpriv->flags |= (unsigned long)pi.private_data; ++ hpriv = ahci_platform_get_resources(pdev); ++ if (IS_ERR(hpriv)) ++ return PTR_ERR(hpriv); + +- hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem)); +- if (!hpriv->mmio) { +- dev_err(dev, "can't map %pR\n", mem); +- return -ENOMEM; +- } +- +- hpriv->clk = clk_get(dev, NULL); +- if (IS_ERR(hpriv->clk)) { +- dev_err(dev, "can't get clock\n"); +- } else { +- rc = clk_prepare_enable(hpriv->clk); +- if (rc) { +- dev_err(dev, "clock prepare enable failed"); +- goto free_clk; +- } +- } ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; + + /* + * Some platforms might need to prepare for mmio region access, +@@ -151,69 +52,10 @@ + if (pdata && pdata->init) { + rc = pdata->init(dev, hpriv->mmio); + if (rc) +- goto disable_unprepare_clk; +- } +- +- ahci_save_initial_config(dev, hpriv, +- pdata ? pdata->force_port_map : 0, +- pdata ? pdata->mask_port_map : 0); +- +- /* prepare host */ +- if (hpriv->cap & HOST_CAP_NCQ) +- pi.flags |= ATA_FLAG_NCQ; +- +- if (hpriv->cap & HOST_CAP_PMP) +- pi.flags |= ATA_FLAG_PMP; +- +- ahci_set_em_messages(hpriv, &pi); +- +- /* CAP.NP sometimes indicate the index of the last enabled +- * port, at other times, that of the last possible port, so +- * determining the maximum port number requires looking at +- * both CAP.NP and port_map. +- */ +- n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); +- +- host = ata_host_alloc_pinfo(dev, ppi, n_ports); +- if (!host) { +- rc = -ENOMEM; +- goto pdata_exit; ++ goto disable_resources; + } + +- host->private_data = hpriv; +- +- if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) +- host->flags |= ATA_HOST_PARALLEL_SCAN; +- else +- dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); +- +- if (pi.flags & ATA_FLAG_EM) +- ahci_reset_em(host); +- +- for (i = 0; i < host->n_ports; i++) { +- struct ata_port *ap = host->ports[i]; +- +- ata_port_desc(ap, "mmio %pR", mem); +- ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); +- +- /* set enclosure management message type */ +- if (ap->flags & ATA_FLAG_EM) +- ap->em_message_type = hpriv->em_msg_type; +- +- /* disabled/not-implemented port */ +- if (!(hpriv->port_map & (1 << i))) +- ap->ops = &ata_dummy_port_ops; +- } +- +- rc = ahci_reset_controller(host); +- if (rc) +- goto pdata_exit; +- +- ahci_init_controller(host); +- ahci_print_info(host, "platform"); +- +- rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, +- &ahci_platform_sht); ++ rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0, 0); + if (rc) + goto pdata_exit; + +@@ -221,115 +63,19 @@ + pdata_exit: + if (pdata && pdata->exit) + pdata->exit(dev); +-disable_unprepare_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); +-free_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_put(hpriv->clk); +- return rc; +-} +- +-static void ahci_host_stop(struct ata_host *host) +-{ +- struct device *dev = host->dev; +- struct ahci_platform_data *pdata = dev_get_platdata(dev); +- struct ahci_host_priv *hpriv = host->private_data; +- +- if (pdata && pdata->exit) +- pdata->exit(dev); +- +- if (!IS_ERR(hpriv->clk)) { +- clk_disable_unprepare(hpriv->clk); +- clk_put(hpriv->clk); +- } +-} +- +-#ifdef CONFIG_PM_SLEEP +-static int ahci_suspend(struct device *dev) +-{ +- struct ahci_platform_data *pdata = dev_get_platdata(dev); +- struct ata_host *host = dev_get_drvdata(dev); +- struct ahci_host_priv *hpriv = host->private_data; +- void __iomem *mmio = hpriv->mmio; +- u32 ctl; +- int rc; +- +- if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { +- dev_err(dev, "firmware update required for suspend/resume\n"); +- return -EIO; +- } +- +- /* +- * AHCI spec rev1.1 section 8.3.3: +- * Software must disable interrupts prior to requesting a +- * transition of the HBA to D3 state. +- */ +- ctl = readl(mmio + HOST_CTL); +- ctl &= ~HOST_IRQ_EN; +- writel(ctl, mmio + HOST_CTL); +- readl(mmio + HOST_CTL); /* flush */ +- +- rc = ata_host_suspend(host, PMSG_SUSPEND); +- if (rc) +- return rc; +- +- if (pdata && pdata->suspend) +- return pdata->suspend(dev); +- +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); +- +- return 0; +-} +- +-static int ahci_resume(struct device *dev) +-{ +- struct ahci_platform_data *pdata = dev_get_platdata(dev); +- struct ata_host *host = dev_get_drvdata(dev); +- struct ahci_host_priv *hpriv = host->private_data; +- int rc; +- +- if (!IS_ERR(hpriv->clk)) { +- rc = clk_prepare_enable(hpriv->clk); +- if (rc) { +- dev_err(dev, "clock prepare enable failed"); +- return rc; +- } +- } +- +- if (pdata && pdata->resume) { +- rc = pdata->resume(dev); +- if (rc) +- goto disable_unprepare_clk; +- } +- +- if (dev->power.power_state.event == PM_EVENT_SUSPEND) { +- rc = ahci_reset_controller(host); +- if (rc) +- goto disable_unprepare_clk; +- +- ahci_init_controller(host); +- } +- +- ata_host_resume(host); +- +- return 0; +- +-disable_unprepare_clk: +- if (!IS_ERR(hpriv->clk)) +- clk_disable_unprepare(hpriv->clk); +- ++disable_resources: ++ ahci_platform_disable_resources(hpriv); + return rc; + } +-#endif + +-static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume); ++static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, ++ ahci_platform_resume); + + static const struct of_device_id ahci_of_match[] = { + { .compatible = "snps,spear-ahci", }, + { .compatible = "snps,exynos5440-ahci", }, + { .compatible = "ibm,476gtr-ahci", }, ++ { .compatible = "snps,dwc-ahci", }, + {}, + }; + MODULE_DEVICE_TABLE(of, ahci_of_match); +@@ -343,7 +89,6 @@ + .of_match_table = ahci_of_match, + .pm = &ahci_pm_ops, + }, +- .id_table = ahci_devtype, + }; + module_platform_driver(ahci_driver); + +diff -Nur linux-3.14.14/drivers/ata/ata_generic.c linux-imx6-3.14/drivers/ata/ata_generic.c +--- linux-3.14.14/drivers/ata/ata_generic.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/ata_generic.c 2014-12-08 00:31:52.428418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/Kconfig linux-imx6-3.14/drivers/ata/Kconfig +--- linux-3.14.14/drivers/ata/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/Kconfig 2014-12-08 00:31:52.424418001 -0600 +@@ -99,7 +99,7 @@ + + config AHCI_IMX + tristate "Freescale i.MX AHCI SATA support" +- depends on SATA_AHCI_PLATFORM && MFD_SYSCON ++ depends on MFD_SYSCON + help + This option enables support for the Freescale i.MX SoC's + onboard AHCI SATA. +diff -Nur linux-3.14.14/drivers/ata/libahci.c linux-imx6-3.14/drivers/ata/libahci.c +--- linux-3.14.14/drivers/ata/libahci.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/libahci.c 2014-12-08 00:31:52.428418001 -0600 +@@ -35,7 +35,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -394,6 +393,9 @@ + * + * If inconsistent, config values are fixed up by this function. + * ++ * If it is not set already this function sets hpriv->start_engine to ++ * ahci_start_engine. ++ * + * LOCKING: + * None. + */ +@@ -450,11 +452,23 @@ + cap &= ~HOST_CAP_SNTF; + } + ++ if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) { ++ dev_info(dev, ++ "controller can't do DEVSLP, turning off\n"); ++ cap2 &= ~HOST_CAP2_SDS; ++ cap2 &= ~HOST_CAP2_SADM; ++ } ++ + if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { + dev_info(dev, "controller can do FBS, turning on CAP_FBS\n"); + cap |= HOST_CAP_FBS; + } + ++ if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) { ++ dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n"); ++ cap &= ~HOST_CAP_FBS; ++ } ++ + if (force_port_map && port_map != force_port_map) { + dev_info(dev, "forcing port_map 0x%x -> 0x%x\n", + port_map, force_port_map); +@@ -500,6 +514,9 @@ + hpriv->cap = cap; + hpriv->cap2 = cap2; + hpriv->port_map = port_map; ++ ++ if (!hpriv->start_engine) ++ hpriv->start_engine = ahci_start_engine; + } + EXPORT_SYMBOL_GPL(ahci_save_initial_config); + +@@ -766,7 +783,7 @@ + + /* enable DMA */ + if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* turn on LEDs */ + if (ap->flags & ATA_FLAG_EM) { +@@ -1234,7 +1251,7 @@ + + /* restart engine */ + out_restart: +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + return rc; + } + EXPORT_SYMBOL_GPL(ahci_kick_engine); +@@ -1426,6 +1443,7 @@ + const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context); + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -1443,7 +1461,7 @@ + rc = sata_link_hardreset(link, timing, deadline, &online, + ahci_check_ready); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + if (online) + *class = ahci_dev_classify(ap); +@@ -2007,10 +2025,12 @@ + + void ahci_error_handler(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; ++ + if (!(ap->pflags & ATA_PFLAG_FROZEN)) { + /* restart engine */ + ahci_stop_engine(ap); +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + sata_pmp_error_handler(ap); +@@ -2031,6 +2051,7 @@ + + static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + struct ata_device *dev = ap->link.device; + u32 devslp, dm, dito, mdat, deto; +@@ -2094,7 +2115,7 @@ + PORT_DEVSLP_ADSE); + writel(devslp, port_mmio + PORT_DEVSLP); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + /* enable device sleep feature for the drive */ + err_mask = ata_dev_set_feature(dev, +@@ -2106,6 +2127,7 @@ + + static void ahci_enable_fbs(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 fbs; +@@ -2134,11 +2156,12 @@ + } else + dev_err(ap->host->dev, "Failed to enable FBS\n"); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + static void ahci_disable_fbs(struct ata_port *ap) + { ++ struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *port_mmio = ahci_port_base(ap); + u32 fbs; +@@ -2166,7 +2189,7 @@ + pp->fbs_enabled = false; + } + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + } + + static void ahci_pmp_attach(struct ata_port *ap) +diff -Nur linux-3.14.14/drivers/ata/libahci_platform.c linux-imx6-3.14/drivers/ata/libahci_platform.c +--- linux-3.14.14/drivers/ata/libahci_platform.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/ata/libahci_platform.c 2014-12-08 00:31:52.428418001 -0600 +@@ -0,0 +1,544 @@ ++/* ++ * AHCI SATA platform library ++ * ++ * Copyright 2004-2005 Red Hat, Inc. ++ * Jeff Garzik ++ * Copyright 2010 MontaVista Software, LLC. ++ * Anton Vorontsov ++ * ++ * 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, or (at your option) ++ * any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ahci.h" ++ ++static void ahci_host_stop(struct ata_host *host); ++ ++struct ata_port_operations ahci_platform_ops = { ++ .inherits = &ahci_ops, ++ .host_stop = ahci_host_stop, ++}; ++EXPORT_SYMBOL_GPL(ahci_platform_ops); ++ ++static struct scsi_host_template ahci_platform_sht = { ++ AHCI_SHT("ahci_platform"), ++}; ++ ++/** ++ * ahci_platform_enable_clks - Enable platform clocks ++ * @hpriv: host private area to store config values ++ * ++ * This function enables all the clks found in hpriv->clks, starting at ++ * index 0. If any clk fails to enable it disables all the clks already ++ * enabled in reverse order, and then returns an error. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_enable_clks(struct ahci_host_priv *hpriv) ++{ ++ int c, rc; ++ ++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) { ++ rc = clk_prepare_enable(hpriv->clks[c]); ++ if (rc) ++ goto disable_unprepare_clk; ++ } ++ return 0; ++ ++disable_unprepare_clk: ++ while (--c >= 0) ++ clk_disable_unprepare(hpriv->clks[c]); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_enable_clks); ++ ++/** ++ * ahci_platform_disable_clks - Disable platform clocks ++ * @hpriv: host private area to store config values ++ * ++ * This function disables all the clks found in hpriv->clks, in reverse ++ * order of ahci_platform_enable_clks (starting at the end of the array). ++ */ ++void ahci_platform_disable_clks(struct ahci_host_priv *hpriv) ++{ ++ int c; ++ ++ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--) ++ if (hpriv->clks[c]) ++ clk_disable_unprepare(hpriv->clks[c]); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_disable_clks); ++ ++/** ++ * ahci_platform_enable_resources - Enable platform resources ++ * @hpriv: host private area to store config values ++ * ++ * This function enables all ahci_platform managed resources in the ++ * following order: ++ * 1) Regulator ++ * 2) Clocks (through ahci_platform_enable_clks) ++ * 3) Phy ++ * ++ * If resource enabling fails at any point the previous enabled resources ++ * are disabled in reverse order. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_enable_resources(struct ahci_host_priv *hpriv) ++{ ++ int rc; ++ ++ if (hpriv->target_pwr) { ++ rc = regulator_enable(hpriv->target_pwr); ++ if (rc) ++ return rc; ++ } ++ ++ rc = ahci_platform_enable_clks(hpriv); ++ if (rc) ++ goto disable_regulator; ++ ++ if (hpriv->phy) { ++ rc = phy_init(hpriv->phy); ++ if (rc) ++ goto disable_clks; ++ ++ rc = phy_power_on(hpriv->phy); ++ if (rc) { ++ phy_exit(hpriv->phy); ++ goto disable_clks; ++ } ++ } ++ ++ return 0; ++ ++disable_clks: ++ ahci_platform_disable_clks(hpriv); ++ ++disable_regulator: ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_enable_resources); ++ ++/** ++ * ahci_platform_disable_resources - Disable platform resources ++ * @hpriv: host private area to store config values ++ * ++ * This function disables all ahci_platform managed resources in the ++ * following order: ++ * 1) Phy ++ * 2) Clocks (through ahci_platform_disable_clks) ++ * 3) Regulator ++ */ ++void ahci_platform_disable_resources(struct ahci_host_priv *hpriv) ++{ ++ if (hpriv->phy) { ++ phy_power_off(hpriv->phy); ++ phy_exit(hpriv->phy); ++ } ++ ++ ahci_platform_disable_clks(hpriv); ++ ++ if (hpriv->target_pwr) ++ regulator_disable(hpriv->target_pwr); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_disable_resources); ++ ++static void ahci_platform_put_resources(struct device *dev, void *res) ++{ ++ struct ahci_host_priv *hpriv = res; ++ int c; ++ ++ if (hpriv->got_runtime_pm) { ++ pm_runtime_put_sync(dev); ++ pm_runtime_disable(dev); ++ } ++ ++ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) ++ clk_put(hpriv->clks[c]); ++} ++ ++/** ++ * ahci_platform_get_resources - Get platform resources ++ * @pdev: platform device to get resources for ++ * ++ * This function allocates an ahci_host_priv struct, and gets the following ++ * resources, storing a reference to them inside the returned struct: ++ * ++ * 1) mmio registers (IORESOURCE_MEM 0, mandatory) ++ * 2) regulator for controlling the targets power (optional) ++ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node, ++ * or for non devicetree enabled platforms a single clock ++ * 4) phy (optional) ++ * ++ * RETURNS: ++ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value ++ */ ++struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct ahci_host_priv *hpriv; ++ struct clk *clk; ++ int i, rc = -ENOMEM; ++ ++ if (!devres_open_group(dev, NULL, GFP_KERNEL)) ++ return ERR_PTR(-ENOMEM); ++ ++ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), ++ GFP_KERNEL); ++ if (!hpriv) ++ goto err_out; ++ ++ devres_add(dev, hpriv); ++ ++ hpriv->mmio = devm_ioremap_resource(dev, ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ if (IS_ERR(hpriv->mmio)) { ++ dev_err(dev, "no mmio space\n"); ++ rc = PTR_ERR(hpriv->mmio); ++ goto err_out; ++ } ++ ++ hpriv->target_pwr = devm_regulator_get_optional(dev, "target"); ++ if (IS_ERR(hpriv->target_pwr)) { ++ rc = PTR_ERR(hpriv->target_pwr); ++ if (rc == -EPROBE_DEFER) ++ goto err_out; ++ hpriv->target_pwr = NULL; ++ } ++ ++ for (i = 0; i < AHCI_MAX_CLKS; i++) { ++ /* ++ * For now we must use clk_get(dev, NULL) for the first clock, ++ * because some platforms (da850, spear13xx) are not yet ++ * converted to use devicetree for clocks. For new platforms ++ * this is equivalent to of_clk_get(dev->of_node, 0). ++ */ ++ if (i == 0) ++ clk = clk_get(dev, NULL); ++ else ++ clk = of_clk_get(dev->of_node, i); ++ ++ if (IS_ERR(clk)) { ++ rc = PTR_ERR(clk); ++ if (rc == -EPROBE_DEFER) ++ goto err_out; ++ break; ++ } ++ hpriv->clks[i] = clk; ++ } ++ ++ hpriv->phy = devm_phy_get(dev, "sata-phy"); ++ if (IS_ERR(hpriv->phy)) { ++ rc = PTR_ERR(hpriv->phy); ++ switch (rc) { ++ case -ENODEV: ++ case -ENOSYS: ++ /* continue normally */ ++ hpriv->phy = NULL; ++ break; ++ ++ case -EPROBE_DEFER: ++ goto err_out; ++ ++ default: ++ dev_err(dev, "couldn't get sata-phy\n"); ++ goto err_out; ++ } ++ } ++ ++ pm_runtime_enable(dev); ++ pm_runtime_get_sync(dev); ++ hpriv->got_runtime_pm = true; ++ ++ devres_remove_group(dev, NULL); ++ return hpriv; ++ ++err_out: ++ devres_release_group(dev, NULL); ++ return ERR_PTR(rc); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_get_resources); ++ ++/** ++ * ahci_platform_init_host - Bring up an ahci-platform host ++ * @pdev: platform device pointer for the host ++ * @hpriv: ahci-host private data for the host ++ * @pi_template: template for the ata_port_info to use ++ * @host_flags: ahci host flags used in ahci_host_priv ++ * @force_port_map: param passed to ahci_save_initial_config ++ * @mask_port_map: param passed to ahci_save_initial_config ++ * ++ * This function does all the usual steps needed to bring up an ++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) ++ * must be initialized / enabled before calling this. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_init_host(struct platform_device *pdev, ++ struct ahci_host_priv *hpriv, ++ const struct ata_port_info *pi_template, ++ unsigned long host_flags, ++ unsigned int force_port_map, ++ unsigned int mask_port_map) ++{ ++ struct device *dev = &pdev->dev; ++ struct ata_port_info pi = *pi_template; ++ const struct ata_port_info *ppi[] = { &pi, NULL }; ++ struct ata_host *host; ++ int i, irq, n_ports, rc; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq <= 0) { ++ dev_err(dev, "no irq\n"); ++ return -EINVAL; ++ } ++ ++ /* prepare host */ ++ pi.private_data = (void *)host_flags; ++ hpriv->flags |= host_flags; ++ ++ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map); ++ ++ if (hpriv->cap & HOST_CAP_NCQ) ++ pi.flags |= ATA_FLAG_NCQ; ++ ++ if (hpriv->cap & HOST_CAP_PMP) ++ pi.flags |= ATA_FLAG_PMP; ++ ++ ahci_set_em_messages(hpriv, &pi); ++ ++ /* CAP.NP sometimes indicate the index of the last enabled ++ * port, at other times, that of the last possible port, so ++ * determining the maximum port number requires looking at ++ * both CAP.NP and port_map. ++ */ ++ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); ++ ++ host = ata_host_alloc_pinfo(dev, ppi, n_ports); ++ if (!host) ++ return -ENOMEM; ++ ++ host->private_data = hpriv; ++ ++ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) ++ host->flags |= ATA_HOST_PARALLEL_SCAN; ++ else ++ dev_info(dev, "SSS flag set, parallel bus scan disabled\n"); ++ ++ if (pi.flags & ATA_FLAG_EM) ++ ahci_reset_em(host); ++ ++ for (i = 0; i < host->n_ports; i++) { ++ struct ata_port *ap = host->ports[i]; ++ ++ ata_port_desc(ap, "mmio %pR", ++ platform_get_resource(pdev, IORESOURCE_MEM, 0)); ++ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80); ++ ++ /* set enclosure management message type */ ++ if (ap->flags & ATA_FLAG_EM) ++ ap->em_message_type = hpriv->em_msg_type; ++ ++ /* disabled/not-implemented port */ ++ if (!(hpriv->port_map & (1 << i))) ++ ap->ops = &ata_dummy_port_ops; ++ } ++ ++ rc = ahci_reset_controller(host); ++ if (rc) ++ return rc; ++ ++ ahci_init_controller(host); ++ ahci_print_info(host, "platform"); ++ ++ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, ++ &ahci_platform_sht); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_init_host); ++ ++static void ahci_host_stop(struct ata_host *host) ++{ ++ struct device *dev = host->dev; ++ struct ahci_platform_data *pdata = dev_get_platdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ ++ if (pdata && pdata->exit) ++ pdata->exit(dev); ++ ++ ahci_platform_disable_resources(hpriv); ++} ++ ++#ifdef CONFIG_PM_SLEEP ++/** ++ * ahci_platform_suspend_host - Suspend an ahci-platform host ++ * @dev: device pointer for the host ++ * ++ * This function does all the usual steps needed to suspend an ++ * ahci-platform host, note any necessary resources (ie clks, phy, etc.) ++ * must be disabled after calling this. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_suspend_host(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ void __iomem *mmio = hpriv->mmio; ++ u32 ctl; ++ ++ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { ++ dev_err(dev, "firmware update required for suspend/resume\n"); ++ return -EIO; ++ } ++ ++ /* ++ * AHCI spec rev1.1 section 8.3.3: ++ * Software must disable interrupts prior to requesting a ++ * transition of the HBA to D3 state. ++ */ ++ ctl = readl(mmio + HOST_CTL); ++ ctl &= ~HOST_IRQ_EN; ++ writel(ctl, mmio + HOST_CTL); ++ readl(mmio + HOST_CTL); /* flush */ ++ ++ return ata_host_suspend(host, PMSG_SUSPEND); ++} ++EXPORT_SYMBOL_GPL(ahci_platform_suspend_host); ++ ++/** ++ * ahci_platform_resume_host - Resume an ahci-platform host ++ * @dev: device pointer for the host ++ * ++ * This function does all the usual steps needed to resume an ahci-platform ++ * host, note any necessary resources (ie clks, phy, etc.) must be ++ * initialized / enabled before calling this. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_resume_host(struct device *dev) ++{ ++ struct ata_host *host = dev_get_drvdata(dev); ++ int rc; ++ ++ if (dev->power.power_state.event == PM_EVENT_SUSPEND) { ++ rc = ahci_reset_controller(host); ++ if (rc) ++ return rc; ++ ++ ahci_init_controller(host); ++ } ++ ++ ata_host_resume(host); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_resume_host); ++ ++/** ++ * ahci_platform_suspend - Suspend an ahci-platform device ++ * @dev: the platform device to suspend ++ * ++ * This function suspends the host associated with the device, followed by ++ * disabling all the resources of the device. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_suspend(struct device *dev) ++{ ++ struct ahci_platform_data *pdata = dev_get_platdata(dev); ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int rc; ++ ++ rc = ahci_platform_suspend_host(dev); ++ if (rc) ++ return rc; ++ ++ if (pdata && pdata->suspend) { ++ rc = pdata->suspend(dev); ++ if (rc) ++ goto resume_host; ++ } ++ ++ ahci_platform_disable_resources(hpriv); ++ ++ return 0; ++ ++resume_host: ++ ahci_platform_resume_host(dev); ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_suspend); ++ ++/** ++ * ahci_platform_resume - Resume an ahci-platform device ++ * @dev: the platform device to resume ++ * ++ * This function enables all the resources of the device followed by ++ * resuming the host associated with the device. ++ * ++ * RETURNS: ++ * 0 on success otherwise a negative error code ++ */ ++int ahci_platform_resume(struct device *dev) ++{ ++ struct ahci_platform_data *pdata = dev_get_platdata(dev); ++ struct ata_host *host = dev_get_drvdata(dev); ++ struct ahci_host_priv *hpriv = host->private_data; ++ int rc; ++ ++ rc = ahci_platform_enable_resources(hpriv); ++ if (rc) ++ return rc; ++ ++ if (pdata && pdata->resume) { ++ rc = pdata->resume(dev); ++ if (rc) ++ goto disable_resources; ++ } ++ ++ rc = ahci_platform_resume_host(dev); ++ if (rc) ++ goto disable_resources; ++ ++ /* We resumed so update PM runtime state */ ++ pm_runtime_disable(dev); ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ ++ return 0; ++ ++disable_resources: ++ ahci_platform_disable_resources(hpriv); ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(ahci_platform_resume); ++#endif ++ ++MODULE_DESCRIPTION("AHCI SATA platform library"); ++MODULE_AUTHOR("Anton Vorontsov "); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/ata/libata-core.c linux-imx6-3.14/drivers/ata/libata-core.c +--- linux-3.14.14/drivers/ata/libata-core.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/libata-core.c 2014-12-08 00:31:52.428418001 -0600 +@@ -1524,7 +1524,7 @@ + * @dev: Device to which the command is sent + * @tf: Taskfile registers for the command and the result + * @cdb: CDB for packet command +- * @dma_dir: Data tranfer direction of the command ++ * @dma_dir: Data transfer direction of the command + * @sgl: sg list for the data buffer of the command + * @n_elem: Number of sg entries + * @timeout: Timeout in msecs (0 for default) +@@ -1712,7 +1712,7 @@ + * @dev: Device to which the command is sent + * @tf: Taskfile registers for the command and the result + * @cdb: CDB for packet command +- * @dma_dir: Data tranfer direction of the command ++ * @dma_dir: Data transfer direction of the command + * @buf: Data buffer of the command + * @buflen: Length of data buffer + * @timeout: Timeout in msecs (0 for default) +diff -Nur linux-3.14.14/drivers/ata/Makefile linux-imx6-3.14/drivers/ata/Makefile +--- linux-3.14.14/drivers/ata/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/Makefile 2014-12-08 00:31:52.424418001 -0600 +@@ -4,13 +4,13 @@ + # non-SFF interface + obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o + obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o +-obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o ++obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o + obj-$(CONFIG_SATA_FSL) += sata_fsl.o + obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o + obj-$(CONFIG_SATA_SIL24) += sata_sil24.o + obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o + obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o +-obj-$(CONFIG_AHCI_IMX) += ahci_imx.o ++obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o + + # SFF w/ custom DMA + obj-$(CONFIG_PDC_ADMA) += pdc_adma.o +diff -Nur linux-3.14.14/drivers/ata/pata_acpi.c linux-imx6-3.14/drivers/ata/pata_acpi.c +--- linux-3.14.14/drivers/ata/pata_acpi.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_acpi.c 2014-12-08 00:31:52.432418001 -0600 +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_amd.c linux-imx6-3.14/drivers/ata/pata_amd.c +--- linux-3.14.14/drivers/ata/pata_amd.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_amd.c 2014-12-08 00:31:52.432418001 -0600 +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_artop.c linux-imx6-3.14/drivers/ata/pata_artop.c +--- linux-3.14.14/drivers/ata/pata_artop.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_artop.c 2014-12-08 00:31:52.432418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_at91.c linux-imx6-3.14/drivers/ata/pata_at91.c +--- linux-3.14.14/drivers/ata/pata_at91.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_at91.c 2014-12-08 00:31:52.432418001 -0600 +@@ -18,7 +18,6 @@ + + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_atiixp.c linux-imx6-3.14/drivers/ata/pata_atiixp.c +--- linux-3.14.14/drivers/ata/pata_atiixp.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_atiixp.c 2014-12-08 00:31:52.432418001 -0600 +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_atp867x.c linux-imx6-3.14/drivers/ata/pata_atp867x.c +--- linux-3.14.14/drivers/ata/pata_atp867x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_atp867x.c 2014-12-08 00:31:52.432418001 -0600 +@@ -29,7 +29,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cmd640.c linux-imx6-3.14/drivers/ata/pata_cmd640.c +--- linux-3.14.14/drivers/ata/pata_cmd640.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cmd640.c 2014-12-08 00:31:52.432418001 -0600 +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cmd64x.c linux-imx6-3.14/drivers/ata/pata_cmd64x.c +--- linux-3.14.14/drivers/ata/pata_cmd64x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cmd64x.c 2014-12-08 00:31:52.432418001 -0600 +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cs5520.c linux-imx6-3.14/drivers/ata/pata_cs5520.c +--- linux-3.14.14/drivers/ata/pata_cs5520.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cs5520.c 2014-12-08 00:31:52.432418001 -0600 +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cs5530.c linux-imx6-3.14/drivers/ata/pata_cs5530.c +--- linux-3.14.14/drivers/ata/pata_cs5530.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cs5530.c 2014-12-08 00:31:52.432418001 -0600 +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cs5535.c linux-imx6-3.14/drivers/ata/pata_cs5535.c +--- linux-3.14.14/drivers/ata/pata_cs5535.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cs5535.c 2014-12-08 00:31:52.432418001 -0600 +@@ -31,7 +31,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cs5536.c linux-imx6-3.14/drivers/ata/pata_cs5536.c +--- linux-3.14.14/drivers/ata/pata_cs5536.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cs5536.c 2014-12-08 00:31:52.432418001 -0600 +@@ -33,7 +33,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_cypress.c linux-imx6-3.14/drivers/ata/pata_cypress.c +--- linux-3.14.14/drivers/ata/pata_cypress.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_cypress.c 2014-12-08 00:31:52.436418001 -0600 +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_efar.c linux-imx6-3.14/drivers/ata/pata_efar.c +--- linux-3.14.14/drivers/ata/pata_efar.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_efar.c 2014-12-08 00:31:52.436418001 -0600 +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_ep93xx.c linux-imx6-3.14/drivers/ata/pata_ep93xx.c +--- linux-3.14.14/drivers/ata/pata_ep93xx.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_ep93xx.c 2014-12-08 00:31:52.436418001 -0600 +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_hpt366.c linux-imx6-3.14/drivers/ata/pata_hpt366.c +--- linux-3.14.14/drivers/ata/pata_hpt366.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_hpt366.c 2014-12-08 00:31:52.436418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_hpt37x.c linux-imx6-3.14/drivers/ata/pata_hpt37x.c +--- linux-3.14.14/drivers/ata/pata_hpt37x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_hpt37x.c 2014-12-08 00:31:52.436418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_hpt3x2n.c linux-imx6-3.14/drivers/ata/pata_hpt3x2n.c +--- linux-3.14.14/drivers/ata/pata_hpt3x2n.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_hpt3x2n.c 2014-12-08 00:31:52.436418001 -0600 +@@ -20,7 +20,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_hpt3x3.c linux-imx6-3.14/drivers/ata/pata_hpt3x3.c +--- linux-3.14.14/drivers/ata/pata_hpt3x3.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_hpt3x3.c 2014-12-08 00:31:52.436418001 -0600 +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_imx.c linux-imx6-3.14/drivers/ata/pata_imx.c +--- linux-3.14.14/drivers/ata/pata_imx.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_imx.c 2014-12-08 00:31:52.436418001 -0600 +@@ -15,7 +15,6 @@ + */ + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_it8213.c linux-imx6-3.14/drivers/ata/pata_it8213.c +--- linux-3.14.14/drivers/ata/pata_it8213.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_it8213.c 2014-12-08 00:31:52.436418001 -0600 +@@ -10,7 +10,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_it821x.c linux-imx6-3.14/drivers/ata/pata_it821x.c +--- linux-3.14.14/drivers/ata/pata_it821x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_it821x.c 2014-12-08 00:31:52.436418001 -0600 +@@ -72,7 +72,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_jmicron.c linux-imx6-3.14/drivers/ata/pata_jmicron.c +--- linux-3.14.14/drivers/ata/pata_jmicron.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_jmicron.c 2014-12-08 00:31:52.436418001 -0600 +@@ -10,7 +10,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_marvell.c linux-imx6-3.14/drivers/ata/pata_marvell.c +--- linux-3.14.14/drivers/ata/pata_marvell.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_marvell.c 2014-12-08 00:31:52.436418001 -0600 +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_mpiix.c linux-imx6-3.14/drivers/ata/pata_mpiix.c +--- linux-3.14.14/drivers/ata/pata_mpiix.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_mpiix.c 2014-12-08 00:31:52.436418001 -0600 +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_netcell.c linux-imx6-3.14/drivers/ata/pata_netcell.c +--- linux-3.14.14/drivers/ata/pata_netcell.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_netcell.c 2014-12-08 00:31:52.436418001 -0600 +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_ninja32.c linux-imx6-3.14/drivers/ata/pata_ninja32.c +--- linux-3.14.14/drivers/ata/pata_ninja32.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_ninja32.c 2014-12-08 00:31:52.436418001 -0600 +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_ns87410.c linux-imx6-3.14/drivers/ata/pata_ns87410.c +--- linux-3.14.14/drivers/ata/pata_ns87410.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_ns87410.c 2014-12-08 00:31:52.436418001 -0600 +@@ -20,7 +20,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_ns87415.c linux-imx6-3.14/drivers/ata/pata_ns87415.c +--- linux-3.14.14/drivers/ata/pata_ns87415.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_ns87415.c 2014-12-08 00:31:52.436418001 -0600 +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_oldpiix.c linux-imx6-3.14/drivers/ata/pata_oldpiix.c +--- linux-3.14.14/drivers/ata/pata_oldpiix.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_oldpiix.c 2014-12-08 00:31:52.436418001 -0600 +@@ -16,7 +16,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_opti.c linux-imx6-3.14/drivers/ata/pata_opti.c +--- linux-3.14.14/drivers/ata/pata_opti.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_opti.c 2014-12-08 00:31:52.436418001 -0600 +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_optidma.c linux-imx6-3.14/drivers/ata/pata_optidma.c +--- linux-3.14.14/drivers/ata/pata_optidma.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_optidma.c 2014-12-08 00:31:52.436418001 -0600 +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_pcmcia.c linux-imx6-3.14/drivers/ata/pata_pcmcia.c +--- linux-3.14.14/drivers/ata/pata_pcmcia.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_pcmcia.c 2014-12-08 00:31:52.436418001 -0600 +@@ -26,7 +26,6 @@ + + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_pdc2027x.c linux-imx6-3.14/drivers/ata/pata_pdc2027x.c +--- linux-3.14.14/drivers/ata/pata_pdc2027x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_pdc2027x.c 2014-12-08 00:31:52.440418001 -0600 +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_pdc202xx_old.c linux-imx6-3.14/drivers/ata/pata_pdc202xx_old.c +--- linux-3.14.14/drivers/ata/pata_pdc202xx_old.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_pdc202xx_old.c 2014-12-08 00:31:52.440418001 -0600 +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_piccolo.c linux-imx6-3.14/drivers/ata/pata_piccolo.c +--- linux-3.14.14/drivers/ata/pata_piccolo.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_piccolo.c 2014-12-08 00:31:52.440418001 -0600 +@@ -18,7 +18,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_platform.c linux-imx6-3.14/drivers/ata/pata_platform.c +--- linux-3.14.14/drivers/ata/pata_platform.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_platform.c 2014-12-08 00:31:52.440418001 -0600 +@@ -13,7 +13,6 @@ + */ + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_pxa.c linux-imx6-3.14/drivers/ata/pata_pxa.c +--- linux-3.14.14/drivers/ata/pata_pxa.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_pxa.c 2014-12-08 00:31:52.440418001 -0600 +@@ -20,7 +20,6 @@ + + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_radisys.c linux-imx6-3.14/drivers/ata/pata_radisys.c +--- linux-3.14.14/drivers/ata/pata_radisys.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_radisys.c 2014-12-08 00:31:52.440418001 -0600 +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_rdc.c linux-imx6-3.14/drivers/ata/pata_rdc.c +--- linux-3.14.14/drivers/ata/pata_rdc.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_rdc.c 2014-12-08 00:31:52.440418001 -0600 +@@ -24,7 +24,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_rz1000.c linux-imx6-3.14/drivers/ata/pata_rz1000.c +--- linux-3.14.14/drivers/ata/pata_rz1000.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_rz1000.c 2014-12-08 00:31:52.440418001 -0600 +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_sc1200.c linux-imx6-3.14/drivers/ata/pata_sc1200.c +--- linux-3.14.14/drivers/ata/pata_sc1200.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_sc1200.c 2014-12-08 00:31:52.440418001 -0600 +@@ -32,7 +32,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_scc.c linux-imx6-3.14/drivers/ata/pata_scc.c +--- linux-3.14.14/drivers/ata/pata_scc.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_scc.c 2014-12-08 00:31:52.440418001 -0600 +@@ -35,7 +35,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_sch.c linux-imx6-3.14/drivers/ata/pata_sch.c +--- linux-3.14.14/drivers/ata/pata_sch.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_sch.c 2014-12-08 00:31:52.440418001 -0600 +@@ -27,7 +27,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_serverworks.c linux-imx6-3.14/drivers/ata/pata_serverworks.c +--- linux-3.14.14/drivers/ata/pata_serverworks.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_serverworks.c 2014-12-08 00:31:52.440418001 -0600 +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_sil680.c linux-imx6-3.14/drivers/ata/pata_sil680.c +--- linux-3.14.14/drivers/ata/pata_sil680.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_sil680.c 2014-12-08 00:31:52.440418001 -0600 +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_sis.c linux-imx6-3.14/drivers/ata/pata_sis.c +--- linux-3.14.14/drivers/ata/pata_sis.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_sis.c 2014-12-08 00:31:52.440418001 -0600 +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_sl82c105.c linux-imx6-3.14/drivers/ata/pata_sl82c105.c +--- linux-3.14.14/drivers/ata/pata_sl82c105.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_sl82c105.c 2014-12-08 00:31:52.440418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_triflex.c linux-imx6-3.14/drivers/ata/pata_triflex.c +--- linux-3.14.14/drivers/ata/pata_triflex.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_triflex.c 2014-12-08 00:31:52.440418001 -0600 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pata_via.c linux-imx6-3.14/drivers/ata/pata_via.c +--- linux-3.14.14/drivers/ata/pata_via.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pata_via.c 2014-12-08 00:31:52.440418001 -0600 +@@ -55,7 +55,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/pdc_adma.c linux-imx6-3.14/drivers/ata/pdc_adma.c +--- linux-3.14.14/drivers/ata/pdc_adma.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/pdc_adma.c 2014-12-08 00:31:52.440418001 -0600 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_dwc_460ex.c linux-imx6-3.14/drivers/ata/sata_dwc_460ex.c +--- linux-3.14.14/drivers/ata/sata_dwc_460ex.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_dwc_460ex.c 2014-12-08 00:31:52.440418001 -0600 +@@ -29,7 +29,6 @@ + + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_highbank.c linux-imx6-3.14/drivers/ata/sata_highbank.c +--- linux-3.14.14/drivers/ata/sata_highbank.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_highbank.c 2014-12-08 00:31:52.440418001 -0600 +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -403,6 +402,7 @@ + static const unsigned long timing[] = { 5, 100, 500}; + struct ata_port *ap = link->ap; + struct ahci_port_priv *pp = ap->private_data; ++ struct ahci_host_priv *hpriv = ap->host->private_data; + u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; + struct ata_taskfile tf; + bool online; +@@ -431,7 +431,7 @@ + break; + } while (!online && retry--); + +- ahci_start_engine(ap); ++ hpriv->start_engine(ap); + + if (online) + *class = ahci_dev_classify(ap); +diff -Nur linux-3.14.14/drivers/ata/sata_nv.c linux-imx6-3.14/drivers/ata/sata_nv.c +--- linux-3.14.14/drivers/ata/sata_nv.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_nv.c 2014-12-08 00:31:52.444418001 -0600 +@@ -40,7 +40,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_promise.c linux-imx6-3.14/drivers/ata/sata_promise.c +--- linux-3.14.14/drivers/ata/sata_promise.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_promise.c 2014-12-08 00:31:52.444418001 -0600 +@@ -35,7 +35,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_qstor.c linux-imx6-3.14/drivers/ata/sata_qstor.c +--- linux-3.14.14/drivers/ata/sata_qstor.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_qstor.c 2014-12-08 00:31:52.444418001 -0600 +@@ -31,7 +31,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_sil.c linux-imx6-3.14/drivers/ata/sata_sil.c +--- linux-3.14.14/drivers/ata/sata_sil.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_sil.c 2014-12-08 00:31:52.444418001 -0600 +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_sis.c linux-imx6-3.14/drivers/ata/sata_sis.c +--- linux-3.14.14/drivers/ata/sata_sis.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_sis.c 2014-12-08 00:31:52.444418001 -0600 +@@ -33,7 +33,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_svw.c linux-imx6-3.14/drivers/ata/sata_svw.c +--- linux-3.14.14/drivers/ata/sata_svw.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_svw.c 2014-12-08 00:31:52.444418001 -0600 +@@ -39,7 +39,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_sx4.c linux-imx6-3.14/drivers/ata/sata_sx4.c +--- linux-3.14.14/drivers/ata/sata_sx4.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_sx4.c 2014-12-08 00:31:52.444418001 -0600 +@@ -82,7 +82,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_uli.c linux-imx6-3.14/drivers/ata/sata_uli.c +--- linux-3.14.14/drivers/ata/sata_uli.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_uli.c 2014-12-08 00:31:52.444418001 -0600 +@@ -28,7 +28,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_via.c linux-imx6-3.14/drivers/ata/sata_via.c +--- linux-3.14.14/drivers/ata/sata_via.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_via.c 2014-12-08 00:31:52.444418001 -0600 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/ata/sata_vsc.c linux-imx6-3.14/drivers/ata/sata_vsc.c +--- linux-3.14.14/drivers/ata/sata_vsc.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/ata/sata_vsc.c 2014-12-08 00:31:52.444418001 -0600 +@@ -37,7 +37,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff -Nur linux-3.14.14/drivers/base/bus.c linux-imx6-3.14/drivers/base/bus.c +--- linux-3.14.14/drivers/base/bus.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/base/bus.c 2014-12-08 00:31:52.456418001 -0600 +@@ -1218,7 +1218,7 @@ + * with the name of the subsystem. The root device can carry subsystem- + * wide attributes. All registered devices are below this single root + * device and are named after the subsystem with a simple enumeration +- * number appended. The registered devices are not explicitely named; ++ * number appended. The registered devices are not explicitly named; + * only 'id' in the device needs to be set. + * + * Do not use this interface for anything new, it exists for compatibility +diff -Nur linux-3.14.14/drivers/base/cpu.c linux-imx6-3.14/drivers/base/cpu.c +--- linux-3.14.14/drivers/base/cpu.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/base/cpu.c 2014-12-08 00:31:52.456418001 -0600 +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include "base.h" + +@@ -286,6 +287,45 @@ + */ + } + ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE ++#ifdef CONFIG_GENERIC_CPU_AUTOPROBE ++static ssize_t print_cpu_modalias(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t n; ++ u32 i; ++ ++ n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", ++ CPU_FEATURE_TYPEVAL); ++ ++ for (i = 0; i < MAX_CPU_FEATURES; i++) ++ if (cpu_have_feature(i)) { ++ if (PAGE_SIZE < n + sizeof(",XXXX\n")) { ++ WARN(1, "CPU features overflow page\n"); ++ break; ++ } ++ n += sprintf(&buf[n], ",%04X", i); ++ } ++ buf[n++] = '\n'; ++ return n; ++} ++#else ++#define print_cpu_modalias arch_print_cpu_modalias ++#endif ++ ++static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) ++{ ++ char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); ++ if (buf) { ++ print_cpu_modalias(NULL, NULL, buf); ++ add_uevent_var(env, "MODALIAS=%s", buf); ++ kfree(buf); ++ } ++ return 0; ++} ++#endif ++ + /* + * register_cpu - Setup a sysfs device for a CPU. + * @cpu - cpu->hotpluggable field set to 1 will generate a control file in +@@ -306,8 +346,8 @@ + cpu->dev.offline_disabled = !cpu->hotpluggable; + cpu->dev.offline = !cpu_online(num); + cpu->dev.of_node = of_get_cpu_node(num, NULL); +-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE +- cpu->dev.bus->uevent = arch_cpu_uevent; ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE ++ cpu->dev.bus->uevent = cpu_uevent; + #endif + cpu->dev.groups = common_cpu_attr_groups; + if (cpu->hotpluggable) +@@ -330,8 +370,8 @@ + } + EXPORT_SYMBOL_GPL(get_cpu_device); + +-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE +-static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE ++static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); + #endif + + static struct attribute *cpu_root_attrs[] = { +@@ -344,7 +384,7 @@ + &cpu_attrs[2].attr.attr, + &dev_attr_kernel_max.attr, + &dev_attr_offline.attr, +-#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE ++#ifdef CONFIG_HAVE_CPU_AUTOPROBE + &dev_attr_modalias.attr, + #endif + NULL +diff -Nur linux-3.14.14/drivers/base/dma-buf.c linux-imx6-3.14/drivers/base/dma-buf.c +--- linux-3.14.14/drivers/base/dma-buf.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/base/dma-buf.c 2014-12-08 00:31:52.456418001 -0600 +@@ -251,9 +251,8 @@ + * @dmabuf: [in] buffer to attach device to. + * @dev: [in] device to be attached. + * +- * Returns struct dma_buf_attachment * for this attachment; may return negative +- * error codes. +- * ++ * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on ++ * error. + */ + struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, + struct device *dev) +@@ -319,9 +318,8 @@ + * @attach: [in] attachment whose scatterlist is to be returned + * @direction: [in] direction of DMA transfer + * +- * Returns sg_table containing the scatterlist to be returned; may return NULL +- * or ERR_PTR. +- * ++ * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR ++ * on error. + */ + struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, + enum dma_data_direction direction) +@@ -334,6 +332,8 @@ + return ERR_PTR(-EINVAL); + + sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); ++ if (!sg_table) ++ sg_table = ERR_PTR(-ENOMEM); + + return sg_table; + } +@@ -544,6 +544,8 @@ + * These calls are optional in drivers. The intended use for them + * is for mapping objects linear in kernel space for high use objects. + * Please attempt to use kmap/kunmap before thinking about these interfaces. ++ * ++ * Returns NULL on error. + */ + void *dma_buf_vmap(struct dma_buf *dmabuf) + { +@@ -566,7 +568,9 @@ + BUG_ON(dmabuf->vmap_ptr); + + ptr = dmabuf->ops->vmap(dmabuf); +- if (IS_ERR_OR_NULL(ptr)) ++ if (WARN_ON_ONCE(IS_ERR(ptr))) ++ ptr = NULL; ++ if (!ptr) + goto out_unlock; + + dmabuf->vmap_ptr = ptr; +diff -Nur linux-3.14.14/drivers/base/dma-contiguous.c linux-imx6-3.14/drivers/base/dma-contiguous.c +--- linux-3.14.14/drivers/base/dma-contiguous.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/base/dma-contiguous.c 2014-12-08 00:31:52.456418001 -0600 +@@ -24,22 +24,9 @@ + + #include + #include +-#include +-#include +-#include + #include +-#include +-#include +-#include + #include +- +-struct cma { +- unsigned long base_pfn; +- unsigned long count; +- unsigned long *bitmap; +-}; +- +-struct cma *dma_contiguous_default_area; ++#include + + #ifdef CONFIG_CMA_SIZE_MBYTES + #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES +@@ -47,6 +34,8 @@ + #define CMA_SIZE_MBYTES 0 + #endif + ++struct cma *dma_contiguous_default_area; ++ + /* + * Default global CMA area size can be defined in kernel's .config. + * This is useful mainly for distro maintainers to create a kernel +@@ -59,11 +48,22 @@ + */ + static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M; + static phys_addr_t size_cmdline = -1; ++static phys_addr_t base_cmdline; ++static phys_addr_t limit_cmdline; + + static int __init early_cma(char *p) + { + pr_debug("%s(%s)\n", __func__, p); + size_cmdline = memparse(p, &p); ++ if (*p != '@') ++ return 0; ++ base_cmdline = memparse(p + 1, &p); ++ if (*p != '-') { ++ limit_cmdline = base_cmdline + size_cmdline; ++ return 0; ++ } ++ limit_cmdline = memparse(p + 1, &p); ++ + return 0; + } + early_param("cma", early_cma); +@@ -107,11 +107,18 @@ + void __init dma_contiguous_reserve(phys_addr_t limit) + { + phys_addr_t selected_size = 0; ++ phys_addr_t selected_base = 0; ++ phys_addr_t selected_limit = limit; ++ bool fixed = false; + + pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); + + if (size_cmdline != -1) { + selected_size = size_cmdline; ++ selected_base = base_cmdline; ++ selected_limit = min_not_zero(limit_cmdline, limit); ++ if (base_cmdline + size_cmdline == limit_cmdline) ++ fixed = true; + } else { + #ifdef CONFIG_CMA_SIZE_SEL_MBYTES + selected_size = size_bytes; +@@ -128,68 +135,12 @@ + pr_debug("%s: reserving %ld MiB for global area\n", __func__, + (unsigned long)selected_size / SZ_1M); + +- dma_contiguous_reserve_area(selected_size, 0, limit, +- &dma_contiguous_default_area); +- } +-}; +- +-static DEFINE_MUTEX(cma_mutex); +- +-static int __init cma_activate_area(struct cma *cma) +-{ +- int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long); +- unsigned long base_pfn = cma->base_pfn, pfn = base_pfn; +- unsigned i = cma->count >> pageblock_order; +- struct zone *zone; +- +- cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); +- +- if (!cma->bitmap) +- return -ENOMEM; +- +- WARN_ON_ONCE(!pfn_valid(pfn)); +- zone = page_zone(pfn_to_page(pfn)); +- +- do { +- unsigned j; +- base_pfn = pfn; +- for (j = pageblock_nr_pages; j; --j, pfn++) { +- WARN_ON_ONCE(!pfn_valid(pfn)); +- /* +- * alloc_contig_range requires the pfn range +- * specified to be in the same zone. Make this +- * simple by forcing the entire CMA resv range +- * to be in the same zone. +- */ +- if (page_zone(pfn_to_page(pfn)) != zone) +- goto err; +- } +- init_cma_reserved_pageblock(pfn_to_page(base_pfn)); +- } while (--i); +- +- return 0; +- +-err: +- kfree(cma->bitmap); +- return -EINVAL; +-} +- +-static struct cma cma_areas[MAX_CMA_AREAS]; +-static unsigned cma_area_count; +- +-static int __init cma_init_reserved_areas(void) +-{ +- int i; +- +- for (i = 0; i < cma_area_count; i++) { +- int ret = cma_activate_area(&cma_areas[i]); +- if (ret) +- return ret; ++ dma_contiguous_reserve_area(selected_size, selected_base, ++ selected_limit, ++ &dma_contiguous_default_area, ++ fixed); + } +- +- return 0; + } +-core_initcall(cma_init_reserved_areas); + + /** + * dma_contiguous_reserve_area() - reserve custom contiguous area +@@ -197,78 +148,32 @@ + * @base: Base address of the reserved area optional, use 0 for any + * @limit: End address of the reserved memory (optional, 0 for any). + * @res_cma: Pointer to store the created cma region. ++ * @fixed: hint about where to place the reserved area + * + * This function reserves memory from early allocator. It should be + * called by arch specific code once the early allocator (memblock or bootmem) + * has been activated and all other subsystems have already allocated/reserved + * memory. This function allows to create custom reserved areas for specific + * devices. ++ * ++ * If @fixed is true, reserve contiguous area at exactly @base. If false, ++ * reserve in range from @base to @limit. + */ + int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, +- phys_addr_t limit, struct cma **res_cma) ++ phys_addr_t limit, struct cma **res_cma, ++ bool fixed) + { +- struct cma *cma = &cma_areas[cma_area_count]; +- phys_addr_t alignment; +- int ret = 0; +- +- pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__, +- (unsigned long)size, (unsigned long)base, +- (unsigned long)limit); +- +- /* Sanity checks */ +- if (cma_area_count == ARRAY_SIZE(cma_areas)) { +- pr_err("Not enough slots for CMA reserved regions!\n"); +- return -ENOSPC; +- } +- +- if (!size) +- return -EINVAL; +- +- /* Sanitise input arguments */ +- alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); +- base = ALIGN(base, alignment); +- size = ALIGN(size, alignment); +- limit &= ~(alignment - 1); +- +- /* Reserve memory */ +- if (base) { +- if (memblock_is_region_reserved(base, size) || +- memblock_reserve(base, size) < 0) { +- ret = -EBUSY; +- goto err; +- } +- } else { +- /* +- * Use __memblock_alloc_base() since +- * memblock_alloc_base() panic()s. +- */ +- phys_addr_t addr = __memblock_alloc_base(size, alignment, limit); +- if (!addr) { +- ret = -ENOMEM; +- goto err; +- } else { +- base = addr; +- } +- } +- +- /* +- * Each reserved area must be initialised later, when more kernel +- * subsystems (like slab allocator) are available. +- */ +- cma->base_pfn = PFN_DOWN(base); +- cma->count = size >> PAGE_SHIFT; +- *res_cma = cma; +- cma_area_count++; ++ int ret; + +- pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M, +- (unsigned long)base); ++ ret = cma_declare_contiguous(base, size, limit, 0, 0, fixed, res_cma); ++ if (ret) ++ return ret; + + /* Architecture specific contiguous memory fixup. */ +- dma_contiguous_early_fixup(base, size); ++ dma_contiguous_early_fixup(cma_get_base(*res_cma), ++ cma_get_size(*res_cma)); ++ + return 0; +-err: +- pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M); +- return ret; + } + + /** +@@ -279,57 +184,16 @@ + * + * This function allocates memory buffer for specified device. It uses + * device specific contiguous memory area if available or the default +- * global one. Requires architecture specific get_dev_cma_area() helper ++ * global one. Requires architecture specific dev_get_cma_area() helper + * function. + */ + struct page *dma_alloc_from_contiguous(struct device *dev, int count, + unsigned int align) + { +- unsigned long mask, pfn, pageno, start = 0; +- struct cma *cma = dev_get_cma_area(dev); +- struct page *page = NULL; +- int ret; +- +- if (!cma || !cma->count) +- return NULL; +- + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; + +- pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma, +- count, align); +- +- if (!count) +- return NULL; +- +- mask = (1 << align) - 1; +- +- mutex_lock(&cma_mutex); +- +- for (;;) { +- pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count, +- start, count, mask); +- if (pageno >= cma->count) +- break; +- +- pfn = cma->base_pfn + pageno; +- ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA); +- if (ret == 0) { +- bitmap_set(cma->bitmap, pageno, count); +- page = pfn_to_page(pfn); +- break; +- } else if (ret != -EBUSY) { +- break; +- } +- pr_debug("%s(): memory range at %p is busy, retrying\n", +- __func__, pfn_to_page(pfn)); +- /* try again with a bit different memory target */ +- start = pageno + mask + 1; +- } +- +- mutex_unlock(&cma_mutex); +- pr_debug("%s(): returned %p\n", __func__, page); +- return page; ++ return cma_alloc(dev_get_cma_area(dev), count, align); + } + + /** +@@ -345,25 +209,5 @@ + bool dma_release_from_contiguous(struct device *dev, struct page *pages, + int count) + { +- struct cma *cma = dev_get_cma_area(dev); +- unsigned long pfn; +- +- if (!cma || !pages) +- return false; +- +- pr_debug("%s(page %p)\n", __func__, (void *)pages); +- +- pfn = page_to_pfn(pages); +- +- if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count) +- return false; +- +- VM_BUG_ON(pfn + count > cma->base_pfn + cma->count); +- +- mutex_lock(&cma_mutex); +- bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count); +- free_contig_range(pfn, count); +- mutex_unlock(&cma_mutex); +- +- return true; ++ return cma_release(dev_get_cma_area(dev), pages, count); + } +diff -Nur linux-3.14.14/drivers/base/Kconfig linux-imx6-3.14/drivers/base/Kconfig +--- linux-3.14.14/drivers/base/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/base/Kconfig 2014-12-08 00:31:52.456418001 -0600 +@@ -185,6 +185,14 @@ + bool + default n + ++config HAVE_CPU_AUTOPROBE ++ def_bool ARCH_HAS_CPU_AUTOPROBE ++ ++config GENERIC_CPU_AUTOPROBE ++ bool ++ depends on !ARCH_HAS_CPU_AUTOPROBE ++ select HAVE_CPU_AUTOPROBE ++ + config SOC_BUS + bool + +@@ -266,16 +274,6 @@ + + If unsure, leave the default value "8". + +-config CMA_AREAS +- int "Maximum count of the CMA device-private areas" +- default 7 +- help +- CMA allows to create CMA areas for particular devices. This parameter +- sets the maximum number of such device private CMA areas in the +- system. +- +- If unsure, leave the default value "7". +- + endif + + endmenu +diff -Nur linux-3.14.14/drivers/bus/arm-cci.c linux-imx6-3.14/drivers/bus/arm-cci.c +--- linux-3.14.14/drivers/bus/arm-cci.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/bus/arm-cci.c 2014-12-08 00:31:52.496418001 -0600 +@@ -26,6 +26,7 @@ + + #include + #include ++#include + #include + #include + +@@ -544,6 +545,7 @@ + + cci_pmu->plat_device = pdev; + cci_pmu->num_events = pmu_get_max_counters(); ++ cpumask_setall(&cci_pmu->valid_cpus); + + return armpmu_register(cci_pmu, -1); + } +@@ -969,6 +971,11 @@ + const char *match_str; + bool is_ace; + ++ if (psci_probe() == 0) { ++ pr_debug("psci found. Aborting cci probe\n"); ++ return -ENODEV; ++ } ++ + np = of_find_matching_node(NULL, arm_cci_matches); + if (!np) + return -ENODEV; +diff -Nur linux-3.14.14/drivers/char/fsl_otp.c linux-imx6-3.14/drivers/char/fsl_otp.c +--- linux-3.14.14/drivers/char/fsl_otp.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/char/fsl_otp.c 2014-12-08 00:31:52.500418001 -0600 +@@ -0,0 +1,299 @@ ++/* ++ * Freescale On-Chip OTP driver ++ * ++ * Copyright (C) 2010-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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HW_OCOTP_CTRL 0x00000000 ++#define HW_OCOTP_CTRL_SET 0x00000004 ++#define BP_OCOTP_CTRL_WR_UNLOCK 16 ++#define BM_OCOTP_CTRL_WR_UNLOCK 0xFFFF0000 ++#define BM_OCOTP_CTRL_RELOAD_SHADOWS 0x00000400 ++#define BM_OCOTP_CTRL_ERROR 0x00000200 ++#define BM_OCOTP_CTRL_BUSY 0x00000100 ++#define BP_OCOTP_CTRL_ADDR 0 ++#define BM_OCOTP_CTRL_ADDR 0x0000007F ++ ++#define HW_OCOTP_TIMING 0x00000010 ++#define BP_OCOTP_TIMING_STROBE_READ 16 ++#define BM_OCOTP_TIMING_STROBE_READ 0x003F0000 ++#define BP_OCOTP_TIMING_RELAX 12 ++#define BM_OCOTP_TIMING_RELAX 0x0000F000 ++#define BP_OCOTP_TIMING_STROBE_PROG 0 ++#define BM_OCOTP_TIMING_STROBE_PROG 0x00000FFF ++ ++#define HW_OCOTP_DATA 0x00000020 ++ ++#define HW_OCOTP_CUST_N(n) (0x00000400 + (n) * 0x10) ++#define BF(value, field) (((value) << BP_##field) & BM_##field) ++ ++#define DEF_RELAX 20 /* > 16.5ns */ ++ ++#define BANK(a, b, c, d, e, f, g, h) { \ ++ "HW_OCOTP_"#a, "HW_OCOTP_"#b, "HW_OCOTP_"#c, "HW_OCOTP_"#d, \ ++ "HW_OCOTP_"#e, "HW_OCOTP_"#f, "HW_OCOTP_"#g, "HW_OCOTP_"#h, \ ++} ++ ++static const char *imx6q_otp_desc[16][8] = { ++ BANK(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6), ++ BANK(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2), ++ BANK(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7), ++ BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7), ++ BANK(RESP0, HSJC_RESP1, MAC0, MAC1, HDCP_KSV0, HDCP_KSV1, GP1, GP2), ++ BANK(DTCP_KEY0, DTCP_KEY1, DTCP_KEY2, DTCP_KEY3, DTCP_KEY4, MISC_CONF, FIELD_RETURN, SRK_REVOKE), ++ BANK(HDCP_KEY0, HDCP_KEY1, HDCP_KEY2, HDCP_KEY3, HDCP_KEY4, HDCP_KEY5, HDCP_KEY6, HDCP_KEY7), ++ BANK(HDCP_KEY8, HDCP_KEY9, HDCP_KEY10, HDCP_KEY11, HDCP_KEY12, HDCP_KEY13, HDCP_KEY14, HDCP_KEY15), ++ BANK(HDCP_KEY16, HDCP_KEY17, HDCP_KEY18, HDCP_KEY19, HDCP_KEY20, HDCP_KEY21, HDCP_KEY22, HDCP_KEY23), ++ BANK(HDCP_KEY24, HDCP_KEY25, HDCP_KEY26, HDCP_KEY27, HDCP_KEY28, HDCP_KEY29, HDCP_KEY30, HDCP_KEY31), ++ BANK(HDCP_KEY32, HDCP_KEY33, HDCP_KEY34, HDCP_KEY35, HDCP_KEY36, HDCP_KEY37, HDCP_KEY38, HDCP_KEY39), ++ BANK(HDCP_KEY40, HDCP_KEY41, HDCP_KEY42, HDCP_KEY43, HDCP_KEY44, HDCP_KEY45, HDCP_KEY46, HDCP_KEY47), ++ BANK(HDCP_KEY48, HDCP_KEY49, HDCP_KEY50, HDCP_KEY51, HDCP_KEY52, HDCP_KEY53, HDCP_KEY54, HDCP_KEY55), ++ BANK(HDCP_KEY56, HDCP_KEY57, HDCP_KEY58, HDCP_KEY59, HDCP_KEY60, HDCP_KEY61, HDCP_KEY62, HDCP_KEY63), ++ BANK(HDCP_KEY64, HDCP_KEY65, HDCP_KEY66, HDCP_KEY67, HDCP_KEY68, HDCP_KEY69, HDCP_KEY70, HDCP_KEY71), ++ BANK(CRC0, CRC1, CRC2, CRC3, CRC4, CRC5, CRC6, CRC7), ++}; ++ ++static DEFINE_MUTEX(otp_mutex); ++static void __iomem *otp_base; ++static struct clk *otp_clk; ++struct kobject *otp_kobj; ++struct kobj_attribute *otp_kattr; ++struct attribute_group *otp_attr_group; ++ ++static void set_otp_timing(void) ++{ ++ unsigned long clk_rate = 0; ++ unsigned long strobe_read, relex, strobe_prog; ++ u32 timing = 0; ++ ++ clk_rate = clk_get_rate(otp_clk); ++ ++ /* do optimization for too many zeros */ ++ relex = clk_rate / (1000000000 / DEF_RELAX) - 1; ++ strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; ++ strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; ++ ++ timing = BF(relex, OCOTP_TIMING_RELAX); ++ timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ); ++ timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG); ++ ++ __raw_writel(timing, otp_base + HW_OCOTP_TIMING); ++} ++ ++static int otp_wait_busy(u32 flags) ++{ ++ int count; ++ u32 c; ++ ++ for (count = 10000; count >= 0; count--) { ++ c = __raw_readl(otp_base + HW_OCOTP_CTRL); ++ if (!(c & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR | flags))) ++ break; ++ cpu_relax(); ++ } ++ ++ if (count < 0) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr, ++ char *buf) ++{ ++ unsigned int index = attr - otp_kattr; ++ u32 value = 0; ++ int ret; ++ ++ ret = clk_prepare_enable(otp_clk); ++ if (ret) ++ return 0; ++ ++ mutex_lock(&otp_mutex); ++ ++ set_otp_timing(); ++ ret = otp_wait_busy(0); ++ if (ret) ++ goto out; ++ ++ value = __raw_readl(otp_base + HW_OCOTP_CUST_N(index)); ++ ++out: ++ mutex_unlock(&otp_mutex); ++ clk_disable_unprepare(otp_clk); ++ return ret ? 0 : sprintf(buf, "0x%x\n", value); ++} ++ ++static int otp_write_bits(int addr, u32 data, u32 magic) ++{ ++ u32 c; /* for control register */ ++ ++ /* init the control register */ ++ c = __raw_readl(otp_base + HW_OCOTP_CTRL); ++ c &= ~BM_OCOTP_CTRL_ADDR; ++ c |= BF(addr, OCOTP_CTRL_ADDR); ++ c |= BF(magic, OCOTP_CTRL_WR_UNLOCK); ++ __raw_writel(c, otp_base + HW_OCOTP_CTRL); ++ ++ /* init the data register */ ++ __raw_writel(data, otp_base + HW_OCOTP_DATA); ++ otp_wait_busy(0); ++ ++ mdelay(2); /* Write Postamble */ ++ ++ return 0; ++} ++ ++static ssize_t fsl_otp_store(struct kobject *kobj, struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned int index = attr - otp_kattr; ++ u32 value; ++ int ret; ++ ++ sscanf(buf, "0x%x", &value); ++ ++ ret = clk_prepare_enable(otp_clk); ++ if (ret) ++ return 0; ++ ++ mutex_lock(&otp_mutex); ++ ++ set_otp_timing(); ++ ret = otp_wait_busy(0); ++ if (ret) ++ goto out; ++ ++ otp_write_bits(index, value, 0x3e77); ++ ++ /* Reload all the shadow registers */ ++ __raw_writel(BM_OCOTP_CTRL_RELOAD_SHADOWS, ++ otp_base + HW_OCOTP_CTRL_SET); ++ udelay(1); ++ otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS); ++ ++out: ++ mutex_unlock(&otp_mutex); ++ clk_disable_unprepare(otp_clk); ++ return ret ? 0 : count; ++} ++ ++static int fsl_otp_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct attribute **attrs; ++ const char **desc; ++ int i, num; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ otp_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(otp_base)) { ++ ret = PTR_ERR(otp_base); ++ dev_err(&pdev->dev, "failed to ioremap resource: %d\n", ret); ++ return ret; ++ } ++ ++ otp_clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(otp_clk)) { ++ ret = PTR_ERR(otp_clk); ++ dev_err(&pdev->dev, "failed to get clock: %d\n", ret); ++ return ret; ++ } ++ ++ desc = (const char **) imx6q_otp_desc; ++ num = sizeof(imx6q_otp_desc) / sizeof(void *); ++ ++ /* The last one is NULL, which is used to detect the end */ ++ attrs = devm_kzalloc(&pdev->dev, (num + 1) * sizeof(*attrs), ++ GFP_KERNEL); ++ otp_kattr = devm_kzalloc(&pdev->dev, num * sizeof(*otp_kattr), ++ GFP_KERNEL); ++ otp_attr_group = devm_kzalloc(&pdev->dev, sizeof(*otp_attr_group), ++ GFP_KERNEL); ++ if (!attrs || !otp_kattr || !otp_attr_group) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) { ++ sysfs_attr_init(&otp_kattr[i].attr); ++ otp_kattr[i].attr.name = desc[i]; ++ otp_kattr[i].attr.mode = 0600; ++ otp_kattr[i].show = fsl_otp_show; ++ otp_kattr[i].store = fsl_otp_store; ++ attrs[i] = &otp_kattr[i].attr; ++ } ++ otp_attr_group->attrs = attrs; ++ ++ otp_kobj = kobject_create_and_add("fsl_otp", NULL); ++ if (!otp_kobj) { ++ dev_err(&pdev->dev, "failed to add kobject\n"); ++ return -ENOMEM; ++ } ++ ++ ret = sysfs_create_group(otp_kobj, otp_attr_group); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to create sysfs group: %d\n", ret); ++ kobject_put(otp_kobj); ++ return ret; ++ } ++ ++ mutex_init(&otp_mutex); ++ ++ return 0; ++} ++ ++static int fsl_otp_remove(struct platform_device *pdev) ++{ ++ sysfs_remove_group(otp_kobj, otp_attr_group); ++ kobject_put(otp_kobj); ++ ++ return 0; ++} ++ ++static const struct of_device_id fsl_otp_dt_ids[] = { ++ { .compatible = "fsl,imx6q-ocotp", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, fsl_otp_dt_ids); ++ ++static struct platform_driver fsl_otp_driver = { ++ .driver = { ++ .name = "imx-ocotp", ++ .owner = THIS_MODULE, ++ .of_match_table = fsl_otp_dt_ids, ++ }, ++ .probe = fsl_otp_probe, ++ .remove = fsl_otp_remove, ++}; ++module_platform_driver(fsl_otp_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Huang Shijie "); ++MODULE_DESCRIPTION("Freescale i.MX OCOTP driver"); +diff -Nur linux-3.14.14/drivers/char/Kconfig linux-imx6-3.14/drivers/char/Kconfig +--- linux-3.14.14/drivers/char/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/char/Kconfig 2014-12-08 00:31:52.496418001 -0600 +@@ -82,6 +82,21 @@ + + If unsure, say N. + ++config FSL_OTP ++ tristate "Freescale On-Chip OTP Memory Support" ++ depends on HAS_IOMEM && OF ++ help ++ If you say Y here, you will get support for a character device ++ interface into the One Time Programmable memory pages that are ++ stored on the some Freescale i.MX processors. This will not get ++ you access to the secure memory pages however. You will need to ++ write your own secure code and reader for that. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called fsl_otp. ++ ++ If unsure, it is safe to say Y. ++ + config PRINTER + tristate "Parallel printer support" + depends on PARPORT +diff -Nur linux-3.14.14/drivers/char/Makefile linux-imx6-3.14/drivers/char/Makefile +--- linux-3.14.14/drivers/char/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/char/Makefile 2014-12-08 00:31:52.496418001 -0600 +@@ -16,6 +16,7 @@ + obj-$(CONFIG_IBM_BSR) += bsr.o + obj-$(CONFIG_SGI_MBCS) += mbcs.o + obj-$(CONFIG_BFIN_OTP) += bfin-otp.o ++obj-$(CONFIG_FSL_OTP) += fsl_otp.o + + obj-$(CONFIG_PRINTER) += lp.o + +diff -Nur linux-3.14.14/drivers/clk/clk.c linux-imx6-3.14/drivers/clk/clk.c +--- linux-3.14.14/drivers/clk/clk.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/clk/clk.c 2014-12-08 00:31:52.520418001 -0600 +@@ -1702,6 +1702,7 @@ + */ + int clk_set_parent(struct clk *clk, struct clk *parent) + { ++ struct clk *child; + int ret = 0; + int p_index = 0; + unsigned long p_rate = 0; +@@ -1728,6 +1729,18 @@ + goto out; + } + ++ /* check two consecutive basic mux clocks */ ++ if (clk->flags & CLK_IS_BASIC_MUX) { ++ hlist_for_each_entry(child, &clk->children, child_node) { ++ if (child->flags & CLK_IS_BASIC_MUX) { ++ pr_err("%s: failed to switch parent of %s due to child mux %s\n", ++ __func__, clk->name, child->name); ++ ret = -EBUSY; ++ goto out; ++ } ++ } ++ } ++ + /* try finding the new parent index */ + if (parent) { + p_index = clk_fetch_parent_index(clk, parent); +diff -Nur linux-3.14.14/drivers/clk/clk-mux.c linux-imx6-3.14/drivers/clk/clk-mux.c +--- linux-3.14.14/drivers/clk/clk-mux.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/clk/clk-mux.c 2014-12-08 00:31:52.516418001 -0600 +@@ -143,7 +143,7 @@ + init.ops = &clk_mux_ro_ops; + else + init.ops = &clk_mux_ops; +- init.flags = flags | CLK_IS_BASIC; ++ init.flags = flags | CLK_IS_BASIC | CLK_IS_BASIC_MUX; + init.parent_names = parent_names; + init.num_parents = num_parents; + +diff -Nur linux-3.14.14/drivers/cpufreq/cpufreq_interactive.c linux-imx6-3.14/drivers/cpufreq/cpufreq_interactive.c +--- linux-3.14.14/drivers/cpufreq/cpufreq_interactive.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/cpufreq/cpufreq_interactive.c 2014-12-08 00:31:52.540418001 -0600 +@@ -0,0 +1,1349 @@ ++/* ++ * drivers/cpufreq/cpufreq_interactive.c ++ * ++ * Copyright (C) 2010 Google, Inc. ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Author: Mike Chan (mike@android.com) ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++struct cpufreq_interactive_cpuinfo { ++ struct timer_list cpu_timer; ++ struct timer_list cpu_slack_timer; ++ spinlock_t load_lock; /* protects the next 4 fields */ ++ u64 time_in_idle; ++ u64 time_in_idle_timestamp; ++ u64 cputime_speedadj; ++ u64 cputime_speedadj_timestamp; ++ struct cpufreq_policy *policy; ++ struct cpufreq_frequency_table *freq_table; ++ unsigned int target_freq; ++ unsigned int floor_freq; ++ u64 floor_validate_time; ++ u64 hispeed_validate_time; ++ struct rw_semaphore enable_sem; ++ int governor_enabled; ++}; ++ ++static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo); ++ ++/* realtime thread handles frequency scaling */ ++static struct task_struct *speedchange_task; ++static cpumask_t speedchange_cpumask; ++static spinlock_t speedchange_cpumask_lock; ++static struct mutex gov_lock; ++ ++/* Target load. Lower values result in higher CPU speeds. */ ++#define DEFAULT_TARGET_LOAD 90 ++static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; ++ ++#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC) ++#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE ++static unsigned int default_above_hispeed_delay[] = { ++ DEFAULT_ABOVE_HISPEED_DELAY }; ++ ++struct cpufreq_interactive_tunables { ++ int usage_count; ++ /* Hi speed to bump to from lo speed when load burst (default max) */ ++ unsigned int hispeed_freq; ++ /* Go to hi speed when CPU load at or above this value. */ ++#define DEFAULT_GO_HISPEED_LOAD 99 ++ unsigned long go_hispeed_load; ++ /* Target load. Lower values result in higher CPU speeds. */ ++ spinlock_t target_loads_lock; ++ unsigned int *target_loads; ++ int ntarget_loads; ++ /* ++ * The minimum amount of time to spend at a frequency before we can ramp ++ * down. ++ */ ++#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC) ++ unsigned long min_sample_time; ++ /* ++ * The sample rate of the timer used to increase frequency ++ */ ++ unsigned long timer_rate; ++ /* ++ * Wait this long before raising speed above hispeed, by default a ++ * single timer interval. ++ */ ++ spinlock_t above_hispeed_delay_lock; ++ unsigned int *above_hispeed_delay; ++ int nabove_hispeed_delay; ++ /* Non-zero means indefinite speed boost active */ ++ int boost_val; ++ /* Duration of a boot pulse in usecs */ ++ int boostpulse_duration_val; ++ /* End time of boost pulse in ktime converted to usecs */ ++ u64 boostpulse_endtime; ++ /* ++ * Max additional time to wait in idle, beyond timer_rate, at speeds ++ * above minimum before wakeup to reduce speed, or -1 if unnecessary. ++ */ ++#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE) ++ int timer_slack_val; ++ bool io_is_busy; ++}; ++ ++/* For cases where we have single governor instance for system */ ++struct cpufreq_interactive_tunables *common_tunables; ++ ++static struct attribute_group *get_sysfs_attr(void); ++ ++static void cpufreq_interactive_timer_resched( ++ struct cpufreq_interactive_cpuinfo *pcpu) ++{ ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ unsigned long expires; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ pcpu->time_in_idle = ++ get_cpu_idle_time(smp_processor_id(), ++ &pcpu->time_in_idle_timestamp, ++ tunables->io_is_busy); ++ pcpu->cputime_speedadj = 0; ++ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; ++ expires = jiffies + usecs_to_jiffies(tunables->timer_rate); ++ mod_timer_pinned(&pcpu->cpu_timer, expires); ++ ++ if (tunables->timer_slack_val >= 0 && ++ pcpu->target_freq > pcpu->policy->min) { ++ expires += usecs_to_jiffies(tunables->timer_slack_val); ++ mod_timer_pinned(&pcpu->cpu_slack_timer, expires); ++ } ++ ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++} ++ ++/* The caller shall take enable_sem write semaphore to avoid any timer race. ++ * The cpu_timer and cpu_slack_timer must be deactivated when calling this ++ * function. ++ */ ++static void cpufreq_interactive_timer_start( ++ struct cpufreq_interactive_tunables *tunables, int cpu) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); ++ unsigned long expires = jiffies + ++ usecs_to_jiffies(tunables->timer_rate); ++ unsigned long flags; ++ ++ pcpu->cpu_timer.expires = expires; ++ add_timer_on(&pcpu->cpu_timer, cpu); ++ if (tunables->timer_slack_val >= 0 && ++ pcpu->target_freq > pcpu->policy->min) { ++ expires += usecs_to_jiffies(tunables->timer_slack_val); ++ pcpu->cpu_slack_timer.expires = expires; ++ add_timer_on(&pcpu->cpu_slack_timer, cpu); ++ } ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ pcpu->time_in_idle = ++ get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp, ++ tunables->io_is_busy); ++ pcpu->cputime_speedadj = 0; ++ pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++} ++ ++static unsigned int freq_to_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, ++ unsigned int freq) ++{ ++ int i; ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ ++ for (i = 0; i < tunables->nabove_hispeed_delay - 1 && ++ freq >= tunables->above_hispeed_delay[i+1]; i += 2) ++ ; ++ ++ ret = tunables->above_hispeed_delay[i]; ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return ret; ++} ++ ++static unsigned int freq_to_targetload( ++ struct cpufreq_interactive_tunables *tunables, unsigned int freq) ++{ ++ int i; ++ unsigned int ret; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ ++ for (i = 0; i < tunables->ntarget_loads - 1 && ++ freq >= tunables->target_loads[i+1]; i += 2) ++ ; ++ ++ ret = tunables->target_loads[i]; ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return ret; ++} ++ ++/* ++ * If increasing frequencies never map to a lower target load then ++ * choose_freq() will find the minimum frequency that does not exceed its ++ * target load given the current load. ++ */ ++static unsigned int choose_freq(struct cpufreq_interactive_cpuinfo *pcpu, ++ unsigned int loadadjfreq) ++{ ++ unsigned int freq = pcpu->policy->cur; ++ unsigned int prevfreq, freqmin, freqmax; ++ unsigned int tl; ++ int index; ++ ++ freqmin = 0; ++ freqmax = UINT_MAX; ++ ++ do { ++ prevfreq = freq; ++ tl = freq_to_targetload(pcpu->policy->governor_data, freq); ++ ++ /* ++ * Find the lowest frequency where the computed load is less ++ * than or equal to the target load. ++ */ ++ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, loadadjfreq / tl, ++ CPUFREQ_RELATION_L, &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ if (freq > prevfreq) { ++ /* The previous frequency is too low. */ ++ freqmin = prevfreq; ++ ++ if (freq >= freqmax) { ++ /* ++ * Find the highest frequency that is less ++ * than freqmax. ++ */ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, ++ freqmax - 1, CPUFREQ_RELATION_H, ++ &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ if (freq == freqmin) { ++ /* ++ * The first frequency below freqmax ++ * has already been found to be too ++ * low. freqmax is the lowest speed ++ * we found that is fast enough. ++ */ ++ freq = freqmax; ++ break; ++ } ++ } ++ } else if (freq < prevfreq) { ++ /* The previous frequency is high enough. */ ++ freqmax = prevfreq; ++ ++ if (freq <= freqmin) { ++ /* ++ * Find the lowest frequency that is higher ++ * than freqmin. ++ */ ++ if (cpufreq_frequency_table_target( ++ pcpu->policy, pcpu->freq_table, ++ freqmin + 1, CPUFREQ_RELATION_L, ++ &index)) ++ break; ++ freq = pcpu->freq_table[index].frequency; ++ ++ /* ++ * If freqmax is the first frequency above ++ * freqmin then we have already found that ++ * this speed is fast enough. ++ */ ++ if (freq == freqmax) ++ break; ++ } ++ } ++ ++ /* If same frequency chosen as previous then done. */ ++ } while (freq != prevfreq); ++ ++ return freq; ++} ++ ++static u64 update_load(int cpu) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ u64 now; ++ u64 now_idle; ++ unsigned int delta_idle; ++ unsigned int delta_time; ++ u64 active_time; ++ ++ now_idle = get_cpu_idle_time(cpu, &now, tunables->io_is_busy); ++ delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle); ++ delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp); ++ ++ if (delta_time <= delta_idle) ++ active_time = 0; ++ else ++ active_time = delta_time - delta_idle; ++ ++ pcpu->cputime_speedadj += active_time * pcpu->policy->cur; ++ ++ pcpu->time_in_idle = now_idle; ++ pcpu->time_in_idle_timestamp = now; ++ return now; ++} ++ ++static void cpufreq_interactive_timer(unsigned long data) ++{ ++ u64 now; ++ unsigned int delta_time; ++ u64 cputime_speedadj; ++ int cpu_load; ++ struct cpufreq_interactive_cpuinfo *pcpu = ++ &per_cpu(cpuinfo, data); ++ struct cpufreq_interactive_tunables *tunables = ++ pcpu->policy->governor_data; ++ unsigned int new_freq; ++ unsigned int loadadjfreq; ++ unsigned int index; ++ unsigned long flags; ++ bool boosted; ++ ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return; ++ if (!pcpu->governor_enabled) ++ goto exit; ++ ++ spin_lock_irqsave(&pcpu->load_lock, flags); ++ now = update_load(data); ++ delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp); ++ cputime_speedadj = pcpu->cputime_speedadj; ++ spin_unlock_irqrestore(&pcpu->load_lock, flags); ++ ++ if (WARN_ON_ONCE(!delta_time)) ++ goto rearm; ++ ++ do_div(cputime_speedadj, delta_time); ++ loadadjfreq = (unsigned int)cputime_speedadj * 100; ++ cpu_load = loadadjfreq / pcpu->target_freq; ++ boosted = tunables->boost_val || now < tunables->boostpulse_endtime; ++ ++ if (cpu_load >= tunables->go_hispeed_load || boosted) { ++ if (pcpu->target_freq < tunables->hispeed_freq) { ++ new_freq = tunables->hispeed_freq; ++ } else { ++ new_freq = choose_freq(pcpu, loadadjfreq); ++ ++ if (new_freq < tunables->hispeed_freq) ++ new_freq = tunables->hispeed_freq; ++ } ++ } else { ++ new_freq = choose_freq(pcpu, loadadjfreq); ++ } ++ ++ if (pcpu->target_freq >= tunables->hispeed_freq && ++ new_freq > pcpu->target_freq && ++ now - pcpu->hispeed_validate_time < ++ freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) { ++ trace_cpufreq_interactive_notyet( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ goto rearm; ++ } ++ ++ pcpu->hispeed_validate_time = now; ++ ++ if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, ++ new_freq, CPUFREQ_RELATION_L, ++ &index)) ++ goto rearm; ++ ++ new_freq = pcpu->freq_table[index].frequency; ++ ++ /* ++ * Do not scale below floor_freq unless we have been at or above the ++ * floor frequency for the minimum sample time since last validated. ++ */ ++ if (new_freq < pcpu->floor_freq) { ++ if (now - pcpu->floor_validate_time < ++ tunables->min_sample_time) { ++ trace_cpufreq_interactive_notyet( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ goto rearm; ++ } ++ } ++ ++ /* ++ * Update the timestamp for checking whether speed has been held at ++ * or above the selected frequency for a minimum of min_sample_time, ++ * if not boosted to hispeed_freq. If boosted to hispeed_freq then we ++ * allow the speed to drop as soon as the boostpulse duration expires ++ * (or the indefinite boost is turned off). ++ */ ++ ++ if (!boosted || new_freq > tunables->hispeed_freq) { ++ pcpu->floor_freq = new_freq; ++ pcpu->floor_validate_time = now; ++ } ++ ++ if (pcpu->target_freq == new_freq) { ++ trace_cpufreq_interactive_already( ++ data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ goto rearm_if_notmax; ++ } ++ ++ trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq, ++ pcpu->policy->cur, new_freq); ++ ++ pcpu->target_freq = new_freq; ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ cpumask_set_cpu(data, &speedchange_cpumask); ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); ++ wake_up_process(speedchange_task); ++ ++rearm_if_notmax: ++ /* ++ * Already set max speed and don't see a need to change that, ++ * wait until next idle to re-evaluate, don't need timer. ++ */ ++ if (pcpu->target_freq == pcpu->policy->max) ++ goto exit; ++ ++rearm: ++ if (!timer_pending(&pcpu->cpu_timer)) ++ cpufreq_interactive_timer_resched(pcpu); ++ ++exit: ++ up_read(&pcpu->enable_sem); ++ return; ++} ++ ++static void cpufreq_interactive_idle_start(void) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = ++ &per_cpu(cpuinfo, smp_processor_id()); ++ int pending; ++ ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ return; ++ } ++ ++ pending = timer_pending(&pcpu->cpu_timer); ++ ++ if (pcpu->target_freq != pcpu->policy->min) { ++ /* ++ * Entering idle while not at lowest speed. On some ++ * platforms this can hold the other CPU(s) at that speed ++ * even though the CPU is idle. Set a timer to re-evaluate ++ * speed so this idle CPU doesn't hold the other CPUs above ++ * min indefinitely. This should probably be a quirk of ++ * the CPUFreq driver. ++ */ ++ if (!pending) ++ cpufreq_interactive_timer_resched(pcpu); ++ } ++ ++ up_read(&pcpu->enable_sem); ++} ++ ++static void cpufreq_interactive_idle_end(void) ++{ ++ struct cpufreq_interactive_cpuinfo *pcpu = ++ &per_cpu(cpuinfo, smp_processor_id()); ++ ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ return; ++ } ++ ++ /* Arm the timer for 1-2 ticks later if not already. */ ++ if (!timer_pending(&pcpu->cpu_timer)) { ++ cpufreq_interactive_timer_resched(pcpu); ++ } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) { ++ del_timer(&pcpu->cpu_timer); ++ del_timer(&pcpu->cpu_slack_timer); ++ cpufreq_interactive_timer(smp_processor_id()); ++ } ++ ++ up_read(&pcpu->enable_sem); ++} ++ ++static int cpufreq_interactive_speedchange_task(void *data) ++{ ++ unsigned int cpu; ++ cpumask_t tmp_mask; ++ unsigned long flags; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ ++ while (1) { ++ set_current_state(TASK_INTERRUPTIBLE); ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ ++ if (cpumask_empty(&speedchange_cpumask)) { ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, ++ flags); ++ schedule(); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ } ++ ++ set_current_state(TASK_RUNNING); ++ tmp_mask = speedchange_cpumask; ++ cpumask_clear(&speedchange_cpumask); ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); ++ ++ for_each_cpu(cpu, &tmp_mask) { ++ unsigned int j; ++ unsigned int max_freq = 0; ++ ++ pcpu = &per_cpu(cpuinfo, cpu); ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ continue; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ continue; ++ } ++ ++ for_each_cpu(j, pcpu->policy->cpus) { ++ struct cpufreq_interactive_cpuinfo *pjcpu = ++ &per_cpu(cpuinfo, j); ++ ++ if (pjcpu->target_freq > max_freq) ++ max_freq = pjcpu->target_freq; ++ } ++ ++ if (max_freq != pcpu->policy->cur) ++ __cpufreq_driver_target(pcpu->policy, ++ max_freq, ++ CPUFREQ_RELATION_H); ++ trace_cpufreq_interactive_setspeed(cpu, ++ pcpu->target_freq, ++ pcpu->policy->cur); ++ ++ up_read(&pcpu->enable_sem); ++ } ++ } ++ ++ return 0; ++} ++ ++static void cpufreq_interactive_boost(void) ++{ ++ int i; ++ int anyboost = 0; ++ unsigned long flags; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ struct cpufreq_interactive_tunables *tunables; ++ ++ spin_lock_irqsave(&speedchange_cpumask_lock, flags); ++ ++ for_each_online_cpu(i) { ++ pcpu = &per_cpu(cpuinfo, i); ++ tunables = pcpu->policy->governor_data; ++ ++ if (pcpu->target_freq < tunables->hispeed_freq) { ++ pcpu->target_freq = tunables->hispeed_freq; ++ cpumask_set_cpu(i, &speedchange_cpumask); ++ pcpu->hispeed_validate_time = ++ ktime_to_us(ktime_get()); ++ anyboost = 1; ++ } ++ ++ /* ++ * Set floor freq and (re)start timer for when last ++ * validated. ++ */ ++ ++ pcpu->floor_freq = tunables->hispeed_freq; ++ pcpu->floor_validate_time = ktime_to_us(ktime_get()); ++ } ++ ++ spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); ++ ++ if (anyboost) ++ wake_up_process(speedchange_task); ++} ++ ++static int cpufreq_interactive_notifier( ++ struct notifier_block *nb, unsigned long val, void *data) ++{ ++ struct cpufreq_freqs *freq = data; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ int cpu; ++ unsigned long flags; ++ ++ if (val == CPUFREQ_POSTCHANGE) { ++ pcpu = &per_cpu(cpuinfo, freq->cpu); ++ if (!down_read_trylock(&pcpu->enable_sem)) ++ return 0; ++ if (!pcpu->governor_enabled) { ++ up_read(&pcpu->enable_sem); ++ return 0; ++ } ++ ++ for_each_cpu(cpu, pcpu->policy->cpus) { ++ struct cpufreq_interactive_cpuinfo *pjcpu = ++ &per_cpu(cpuinfo, cpu); ++ if (cpu != freq->cpu) { ++ if (!down_read_trylock(&pjcpu->enable_sem)) ++ continue; ++ if (!pjcpu->governor_enabled) { ++ up_read(&pjcpu->enable_sem); ++ continue; ++ } ++ } ++ spin_lock_irqsave(&pjcpu->load_lock, flags); ++ update_load(cpu); ++ spin_unlock_irqrestore(&pjcpu->load_lock, flags); ++ if (cpu != freq->cpu) ++ up_read(&pjcpu->enable_sem); ++ } ++ ++ up_read(&pcpu->enable_sem); ++ } ++ return 0; ++} ++ ++static struct notifier_block cpufreq_notifier_block = { ++ .notifier_call = cpufreq_interactive_notifier, ++}; ++ ++static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) ++{ ++ const char *cp; ++ int i; ++ int ntokens = 1; ++ unsigned int *tokenized_data; ++ int err = -EINVAL; ++ ++ cp = buf; ++ while ((cp = strpbrk(cp + 1, " :"))) ++ ntokens++; ++ ++ if (!(ntokens & 0x1)) ++ goto err; ++ ++ tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); ++ if (!tokenized_data) { ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ cp = buf; ++ i = 0; ++ while (i < ntokens) { ++ if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) ++ goto err_kfree; ++ ++ cp = strpbrk(cp, " :"); ++ if (!cp) ++ break; ++ cp++; ++ } ++ ++ if (i != ntokens) ++ goto err_kfree; ++ ++ *num_tokens = ntokens; ++ return tokenized_data; ++ ++err_kfree: ++ kfree(tokenized_data); ++err: ++ return ERR_PTR(err); ++} ++ ++static ssize_t show_target_loads( ++ struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ int i; ++ ssize_t ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ ++ for (i = 0; i < tunables->ntarget_loads; i++) ++ ret += sprintf(buf + ret, "%u%s", tunables->target_loads[i], ++ i & 0x1 ? ":" : " "); ++ ++ sprintf(buf + ret - 1, "\n"); ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return ret; ++} ++ ++static ssize_t store_target_loads( ++ struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ntokens; ++ unsigned int *new_target_loads = NULL; ++ unsigned long flags; ++ ++ new_target_loads = get_tokenized_data(buf, &ntokens); ++ if (IS_ERR(new_target_loads)) ++ return PTR_RET(new_target_loads); ++ ++ spin_lock_irqsave(&tunables->target_loads_lock, flags); ++ if (tunables->target_loads != default_target_loads) ++ kfree(tunables->target_loads); ++ tunables->target_loads = new_target_loads; ++ tunables->ntarget_loads = ntokens; ++ spin_unlock_irqrestore(&tunables->target_loads_lock, flags); ++ return count; ++} ++ ++static ssize_t show_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, char *buf) ++{ ++ int i; ++ ssize_t ret = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ ++ for (i = 0; i < tunables->nabove_hispeed_delay; i++) ++ ret += sprintf(buf + ret, "%u%s", ++ tunables->above_hispeed_delay[i], ++ i & 0x1 ? ":" : " "); ++ ++ sprintf(buf + ret - 1, "\n"); ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return ret; ++} ++ ++static ssize_t store_above_hispeed_delay( ++ struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ntokens; ++ unsigned int *new_above_hispeed_delay = NULL; ++ unsigned long flags; ++ ++ new_above_hispeed_delay = get_tokenized_data(buf, &ntokens); ++ if (IS_ERR(new_above_hispeed_delay)) ++ return PTR_RET(new_above_hispeed_delay); ++ ++ spin_lock_irqsave(&tunables->above_hispeed_delay_lock, flags); ++ if (tunables->above_hispeed_delay != default_above_hispeed_delay) ++ kfree(tunables->above_hispeed_delay); ++ tunables->above_hispeed_delay = new_above_hispeed_delay; ++ tunables->nabove_hispeed_delay = ntokens; ++ spin_unlock_irqrestore(&tunables->above_hispeed_delay_lock, flags); ++ return count; ++ ++} ++ ++static ssize_t show_hispeed_freq(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%u\n", tunables->hispeed_freq); ++} ++ ++static ssize_t store_hispeed_freq(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ long unsigned int val; ++ ++ ret = strict_strtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->hispeed_freq = val; ++ return count; ++} ++ ++static ssize_t show_go_hispeed_load(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->go_hispeed_load); ++} ++ ++static ssize_t store_go_hispeed_load(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = strict_strtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->go_hispeed_load = val; ++ return count; ++} ++ ++static ssize_t show_min_sample_time(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->min_sample_time); ++} ++ ++static ssize_t store_min_sample_time(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = strict_strtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->min_sample_time = val; ++ return count; ++} ++ ++static ssize_t show_timer_rate(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%lu\n", tunables->timer_rate); ++} ++ ++static ssize_t store_timer_rate(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = strict_strtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->timer_rate = val; ++ return count; ++} ++ ++static ssize_t show_timer_slack(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->timer_slack_val); ++} ++ ++static ssize_t store_timer_slack(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtol(buf, 10, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->timer_slack_val = val; ++ return count; ++} ++ ++static ssize_t show_boost(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->boost_val); ++} ++ ++static ssize_t store_boost(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boost_val = val; ++ ++ if (tunables->boost_val) { ++ trace_cpufreq_interactive_boost("on"); ++ cpufreq_interactive_boost(); ++ } else { ++ trace_cpufreq_interactive_unboost("off"); ++ } ++ ++ return count; ++} ++ ++static ssize_t store_boostpulse(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boostpulse_endtime = ktime_to_us(ktime_get()) + ++ tunables->boostpulse_duration_val; ++ trace_cpufreq_interactive_boost("pulse"); ++ cpufreq_interactive_boost(); ++ return count; ++} ++ ++static ssize_t show_boostpulse_duration(struct cpufreq_interactive_tunables ++ *tunables, char *buf) ++{ ++ return sprintf(buf, "%d\n", tunables->boostpulse_duration_val); ++} ++ ++static ssize_t store_boostpulse_duration(struct cpufreq_interactive_tunables ++ *tunables, const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ ++ tunables->boostpulse_duration_val = val; ++ return count; ++} ++ ++static ssize_t show_io_is_busy(struct cpufreq_interactive_tunables *tunables, ++ char *buf) ++{ ++ return sprintf(buf, "%u\n", tunables->io_is_busy); ++} ++ ++static ssize_t store_io_is_busy(struct cpufreq_interactive_tunables *tunables, ++ const char *buf, size_t count) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = kstrtoul(buf, 0, &val); ++ if (ret < 0) ++ return ret; ++ tunables->io_is_busy = val; ++ return count; ++} ++ ++/* ++ * Create show/store routines ++ * - sys: One governor instance for complete SYSTEM ++ * - pol: One governor instance per struct cpufreq_policy ++ */ ++#define show_gov_pol_sys(file_name) \ ++static ssize_t show_##file_name##_gov_sys \ ++(struct kobject *kobj, struct attribute *attr, char *buf) \ ++{ \ ++ return show_##file_name(common_tunables, buf); \ ++} \ ++ \ ++static ssize_t show_##file_name##_gov_pol \ ++(struct cpufreq_policy *policy, char *buf) \ ++{ \ ++ return show_##file_name(policy->governor_data, buf); \ ++} ++ ++#define store_gov_pol_sys(file_name) \ ++static ssize_t store_##file_name##_gov_sys \ ++(struct kobject *kobj, struct attribute *attr, const char *buf, \ ++ size_t count) \ ++{ \ ++ return store_##file_name(common_tunables, buf, count); \ ++} \ ++ \ ++static ssize_t store_##file_name##_gov_pol \ ++(struct cpufreq_policy *policy, const char *buf, size_t count) \ ++{ \ ++ return store_##file_name(policy->governor_data, buf, count); \ ++} ++ ++#define show_store_gov_pol_sys(file_name) \ ++show_gov_pol_sys(file_name); \ ++store_gov_pol_sys(file_name) ++ ++show_store_gov_pol_sys(target_loads); ++show_store_gov_pol_sys(above_hispeed_delay); ++show_store_gov_pol_sys(hispeed_freq); ++show_store_gov_pol_sys(go_hispeed_load); ++show_store_gov_pol_sys(min_sample_time); ++show_store_gov_pol_sys(timer_rate); ++show_store_gov_pol_sys(timer_slack); ++show_store_gov_pol_sys(boost); ++store_gov_pol_sys(boostpulse); ++show_store_gov_pol_sys(boostpulse_duration); ++show_store_gov_pol_sys(io_is_busy); ++ ++#define gov_sys_attr_rw(_name) \ ++static struct global_attr _name##_gov_sys = \ ++__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys) ++ ++#define gov_pol_attr_rw(_name) \ ++static struct freq_attr _name##_gov_pol = \ ++__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol) ++ ++#define gov_sys_pol_attr_rw(_name) \ ++ gov_sys_attr_rw(_name); \ ++ gov_pol_attr_rw(_name) ++ ++gov_sys_pol_attr_rw(target_loads); ++gov_sys_pol_attr_rw(above_hispeed_delay); ++gov_sys_pol_attr_rw(hispeed_freq); ++gov_sys_pol_attr_rw(go_hispeed_load); ++gov_sys_pol_attr_rw(min_sample_time); ++gov_sys_pol_attr_rw(timer_rate); ++gov_sys_pol_attr_rw(timer_slack); ++gov_sys_pol_attr_rw(boost); ++gov_sys_pol_attr_rw(boostpulse_duration); ++gov_sys_pol_attr_rw(io_is_busy); ++ ++static struct global_attr boostpulse_gov_sys = ++ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_sys); ++ ++static struct freq_attr boostpulse_gov_pol = ++ __ATTR(boostpulse, 0200, NULL, store_boostpulse_gov_pol); ++ ++/* One Governor instance for entire system */ ++static struct attribute *interactive_attributes_gov_sys[] = { ++ &target_loads_gov_sys.attr, ++ &above_hispeed_delay_gov_sys.attr, ++ &hispeed_freq_gov_sys.attr, ++ &go_hispeed_load_gov_sys.attr, ++ &min_sample_time_gov_sys.attr, ++ &timer_rate_gov_sys.attr, ++ &timer_slack_gov_sys.attr, ++ &boost_gov_sys.attr, ++ &boostpulse_gov_sys.attr, ++ &boostpulse_duration_gov_sys.attr, ++ &io_is_busy_gov_sys.attr, ++ NULL, ++}; ++ ++static struct attribute_group interactive_attr_group_gov_sys = { ++ .attrs = interactive_attributes_gov_sys, ++ .name = "interactive", ++}; ++ ++/* Per policy governor instance */ ++static struct attribute *interactive_attributes_gov_pol[] = { ++ &target_loads_gov_pol.attr, ++ &above_hispeed_delay_gov_pol.attr, ++ &hispeed_freq_gov_pol.attr, ++ &go_hispeed_load_gov_pol.attr, ++ &min_sample_time_gov_pol.attr, ++ &timer_rate_gov_pol.attr, ++ &timer_slack_gov_pol.attr, ++ &boost_gov_pol.attr, ++ &boostpulse_gov_pol.attr, ++ &boostpulse_duration_gov_pol.attr, ++ &io_is_busy_gov_pol.attr, ++ NULL, ++}; ++ ++static struct attribute_group interactive_attr_group_gov_pol = { ++ .attrs = interactive_attributes_gov_pol, ++ .name = "interactive", ++}; ++ ++static struct attribute_group *get_sysfs_attr(void) ++{ ++ if (have_governor_per_policy()) ++ return &interactive_attr_group_gov_pol; ++ else ++ return &interactive_attr_group_gov_sys; ++} ++ ++static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, ++ unsigned long val, ++ void *data) ++{ ++ switch (val) { ++ case IDLE_START: ++ cpufreq_interactive_idle_start(); ++ break; ++ case IDLE_END: ++ cpufreq_interactive_idle_end(); ++ break; ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block cpufreq_interactive_idle_nb = { ++ .notifier_call = cpufreq_interactive_idle_notifier, ++}; ++ ++static int cpufreq_governor_interactive(struct cpufreq_policy *policy, ++ unsigned int event) ++{ ++ int rc; ++ unsigned int j; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ struct cpufreq_frequency_table *freq_table; ++ struct cpufreq_interactive_tunables *tunables; ++ ++ if (have_governor_per_policy()) ++ tunables = policy->governor_data; ++ else ++ tunables = common_tunables; ++ ++ WARN_ON(!tunables && (event != CPUFREQ_GOV_POLICY_INIT)); ++ ++ switch (event) { ++ case CPUFREQ_GOV_POLICY_INIT: ++ if (have_governor_per_policy()) { ++ WARN_ON(tunables); ++ } else if (tunables) { ++ tunables->usage_count++; ++ policy->governor_data = tunables; ++ return 0; ++ } ++ ++ tunables = kzalloc(sizeof(*tunables), GFP_KERNEL); ++ if (!tunables) { ++ pr_err("%s: POLICY_INIT: kzalloc failed\n", __func__); ++ return -ENOMEM; ++ } ++ ++ tunables->usage_count = 1; ++ tunables->above_hispeed_delay = default_above_hispeed_delay; ++ tunables->nabove_hispeed_delay = ++ ARRAY_SIZE(default_above_hispeed_delay); ++ tunables->go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; ++ tunables->target_loads = default_target_loads; ++ tunables->ntarget_loads = ARRAY_SIZE(default_target_loads); ++ tunables->min_sample_time = DEFAULT_MIN_SAMPLE_TIME; ++ tunables->timer_rate = DEFAULT_TIMER_RATE; ++ tunables->boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; ++ tunables->timer_slack_val = DEFAULT_TIMER_SLACK; ++ ++ spin_lock_init(&tunables->target_loads_lock); ++ spin_lock_init(&tunables->above_hispeed_delay_lock); ++ ++ policy->governor_data = tunables; ++ if (!have_governor_per_policy()) { ++ common_tunables = tunables; ++ WARN_ON(cpufreq_get_global_kobject()); ++ } ++ ++ rc = sysfs_create_group(get_governor_parent_kobj(policy), ++ get_sysfs_attr()); ++ if (rc) { ++ kfree(tunables); ++ policy->governor_data = NULL; ++ if (!have_governor_per_policy()) ++ common_tunables = NULL; ++ return rc; ++ } ++ ++ if (!policy->governor->initialized) { ++ idle_notifier_register(&cpufreq_interactive_idle_nb); ++ cpufreq_register_notifier(&cpufreq_notifier_block, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ } ++ ++ break; ++ ++ case CPUFREQ_GOV_POLICY_EXIT: ++ if (!--tunables->usage_count) { ++ sysfs_remove_group(get_governor_parent_kobj(policy), ++ get_sysfs_attr()); ++ ++ if (!have_governor_per_policy()) ++ cpufreq_put_global_kobject(); ++ ++ if (policy->governor->initialized == 1) { ++ cpufreq_unregister_notifier(&cpufreq_notifier_block, ++ CPUFREQ_TRANSITION_NOTIFIER); ++ idle_notifier_unregister(&cpufreq_interactive_idle_nb); ++ } ++ ++ kfree(tunables); ++ common_tunables = NULL; ++ } ++ ++ policy->governor_data = NULL; ++ break; ++ ++ case CPUFREQ_GOV_START: ++ mutex_lock(&gov_lock); ++ ++ freq_table = cpufreq_frequency_get_table(policy->cpu); ++ if (!tunables->hispeed_freq) ++ tunables->hispeed_freq = policy->max; ++ ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ pcpu->policy = policy; ++ pcpu->target_freq = policy->cur; ++ pcpu->freq_table = freq_table; ++ pcpu->floor_freq = pcpu->target_freq; ++ pcpu->floor_validate_time = ++ ktime_to_us(ktime_get()); ++ pcpu->hispeed_validate_time = ++ pcpu->floor_validate_time; ++ down_write(&pcpu->enable_sem); ++ del_timer_sync(&pcpu->cpu_timer); ++ del_timer_sync(&pcpu->cpu_slack_timer); ++ cpufreq_interactive_timer_start(tunables, j); ++ pcpu->governor_enabled = 1; ++ up_write(&pcpu->enable_sem); ++ } ++ ++ mutex_unlock(&gov_lock); ++ break; ++ ++ case CPUFREQ_GOV_STOP: ++ mutex_lock(&gov_lock); ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ down_write(&pcpu->enable_sem); ++ pcpu->governor_enabled = 0; ++ del_timer_sync(&pcpu->cpu_timer); ++ del_timer_sync(&pcpu->cpu_slack_timer); ++ up_write(&pcpu->enable_sem); ++ } ++ ++ mutex_unlock(&gov_lock); ++ break; ++ ++ case CPUFREQ_GOV_LIMITS: ++ if (policy->max < policy->cur) ++ __cpufreq_driver_target(policy, ++ policy->max, CPUFREQ_RELATION_H); ++ else if (policy->min > policy->cur) ++ __cpufreq_driver_target(policy, ++ policy->min, CPUFREQ_RELATION_L); ++ for_each_cpu(j, policy->cpus) { ++ pcpu = &per_cpu(cpuinfo, j); ++ ++ /* hold write semaphore to avoid race */ ++ down_write(&pcpu->enable_sem); ++ if (pcpu->governor_enabled == 0) { ++ up_write(&pcpu->enable_sem); ++ continue; ++ } ++ ++ /* update target_freq firstly */ ++ if (policy->max < pcpu->target_freq) ++ pcpu->target_freq = policy->max; ++ else if (policy->min > pcpu->target_freq) ++ pcpu->target_freq = policy->min; ++ ++ /* Reschedule timer. ++ * Delete the timers, else the timer callback may ++ * return without re-arm the timer when failed ++ * acquire the semaphore. This race may cause timer ++ * stopped unexpectedly. ++ */ ++ del_timer_sync(&pcpu->cpu_timer); ++ del_timer_sync(&pcpu->cpu_slack_timer); ++ cpufreq_interactive_timer_start(tunables, j); ++ up_write(&pcpu->enable_sem); ++ } ++ break; ++ } ++ return 0; ++} ++ ++#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++static ++#endif ++struct cpufreq_governor cpufreq_gov_interactive = { ++ .name = "interactive", ++ .governor = cpufreq_governor_interactive, ++ .max_transition_latency = 10000000, ++ .owner = THIS_MODULE, ++}; ++ ++static void cpufreq_interactive_nop_timer(unsigned long data) ++{ ++} ++ ++static int __init cpufreq_interactive_init(void) ++{ ++ unsigned int i; ++ struct cpufreq_interactive_cpuinfo *pcpu; ++ struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; ++ ++ /* Initalize per-cpu timers */ ++ for_each_possible_cpu(i) { ++ pcpu = &per_cpu(cpuinfo, i); ++ init_timer_deferrable(&pcpu->cpu_timer); ++ pcpu->cpu_timer.function = cpufreq_interactive_timer; ++ pcpu->cpu_timer.data = i; ++ init_timer(&pcpu->cpu_slack_timer); ++ pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; ++ spin_lock_init(&pcpu->load_lock); ++ init_rwsem(&pcpu->enable_sem); ++ } ++ ++ spin_lock_init(&speedchange_cpumask_lock); ++ mutex_init(&gov_lock); ++ speedchange_task = ++ kthread_create(cpufreq_interactive_speedchange_task, NULL, ++ "cfinteractive"); ++ if (IS_ERR(speedchange_task)) ++ return PTR_ERR(speedchange_task); ++ ++ sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, ¶m); ++ get_task_struct(speedchange_task); ++ ++ /* NB: wake up so the thread does not look hung to the freezer */ ++ wake_up_process(speedchange_task); ++ ++ return cpufreq_register_governor(&cpufreq_gov_interactive); ++} ++ ++#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++fs_initcall(cpufreq_interactive_init); ++#else ++module_init(cpufreq_interactive_init); ++#endif ++ ++static void __exit cpufreq_interactive_exit(void) ++{ ++ cpufreq_unregister_governor(&cpufreq_gov_interactive); ++ kthread_stop(speedchange_task); ++ put_task_struct(speedchange_task); ++} ++ ++module_exit(cpufreq_interactive_exit); ++ ++MODULE_AUTHOR("Mike Chan "); ++MODULE_DESCRIPTION("'cpufreq_interactive' - A cpufreq governor for " ++ "Latency sensitive workloads"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/cpufreq/highbank-cpufreq.c linux-imx6-3.14/drivers/cpufreq/highbank-cpufreq.c +--- linux-3.14.14/drivers/cpufreq/highbank-cpufreq.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/cpufreq/highbank-cpufreq.c 2014-12-08 00:31:52.540418001 -0600 +@@ -19,7 +19,7 @@ + #include + #include + #include +-#include ++#include + #include + + #define HB_CPUFREQ_CHANGE_NOTE 0x80000001 +diff -Nur linux-3.14.14/drivers/cpufreq/imx6-cpufreq.c linux-imx6-3.14/drivers/cpufreq/imx6-cpufreq.c +--- linux-3.14.14/drivers/cpufreq/imx6-cpufreq.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/cpufreq/imx6-cpufreq.c 2014-12-08 00:31:52.540418001 -0600 +@@ -0,0 +1,393 @@ ++/* ++ * Copyright (C) 2013 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PU_SOC_VOLTAGE_NORMAL 1250000 ++#define PU_SOC_VOLTAGE_HIGH 1275000 ++#define FREQ_1P2_GHZ 1200000000 ++ ++static struct regulator *arm_reg; ++static struct regulator *pu_reg; ++static struct regulator *soc_reg; ++ ++static struct clk *arm_clk; ++static struct clk *pll1_sys_clk; ++static struct clk *pll1_sw_clk; ++static struct clk *step_clk; ++static struct clk *pll2_pfd2_396m_clk; ++ ++static struct device *cpu_dev; ++static struct cpufreq_frequency_table *freq_table; ++static unsigned int transition_latency; ++static struct mutex set_cpufreq_lock; ++ ++static u32 *imx6_soc_volt; ++static u32 soc_opp_count; ++ ++static int imx6_set_target(struct cpufreq_policy *policy, unsigned int index) ++{ ++ struct dev_pm_opp *opp; ++ unsigned long freq_hz, volt, volt_old; ++ unsigned int old_freq, new_freq; ++ int ret; ++ ++ mutex_lock(&set_cpufreq_lock); ++ ++ new_freq = freq_table[index].frequency; ++ freq_hz = new_freq * 1000; ++ old_freq = clk_get_rate(arm_clk) / 1000; ++ ++ rcu_read_lock(); ++ opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); ++ if (IS_ERR(opp)) { ++ rcu_read_unlock(); ++ dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); ++ ret = PTR_ERR(opp); ++ goto unlock; ++ } ++ ++ volt = dev_pm_opp_get_voltage(opp); ++ rcu_read_unlock(); ++ volt_old = regulator_get_voltage(arm_reg); ++ ++ dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", ++ old_freq / 1000, volt_old / 1000, ++ new_freq / 1000, volt / 1000); ++ ++ /* ++ * CPU freq is increasing, so need to ensure ++ * that bus frequency is increased too. ++ */ ++ if (old_freq == freq_table[0].frequency) ++ request_bus_freq(BUS_FREQ_HIGH); ++ ++ /* scaling up? scale voltage before frequency */ ++ if (new_freq > old_freq) { ++ if (regulator_is_enabled(pu_reg)) { ++ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); ++ if (ret) { ++ dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); ++ goto unlock; ++ } ++ } ++ ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); ++ if (ret) { ++ dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); ++ goto unlock; ++ } ++ ret = regulator_set_voltage_tol(arm_reg, volt, 0); ++ if (ret) { ++ dev_err(cpu_dev, ++ "failed to scale vddarm up: %d\n", ret); ++ goto unlock; ++ } ++ } ++ ++ /* ++ * The setpoints are selected per PLL/PDF frequencies, so we need to ++ * reprogram PLL for frequency scaling. The procedure of reprogramming ++ * PLL1 is as below. ++ * ++ * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it ++ * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it ++ * - Disable pll2_pfd2_396m_clk ++ */ ++ clk_set_parent(step_clk, pll2_pfd2_396m_clk); ++ clk_set_parent(pll1_sw_clk, step_clk); ++ if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { ++ clk_set_rate(pll1_sys_clk, new_freq * 1000); ++ clk_set_parent(pll1_sw_clk, pll1_sys_clk); ++ } ++ ++ /* Ensure the arm clock divider is what we expect */ ++ ret = clk_set_rate(arm_clk, new_freq * 1000); ++ if (ret) { ++ dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); ++ regulator_set_voltage_tol(arm_reg, volt_old, 0); ++ goto unlock; ++ } ++ ++ /* scaling down? scale voltage after frequency */ ++ if (new_freq < old_freq) { ++ ret = regulator_set_voltage_tol(arm_reg, volt, 0); ++ if (ret) { ++ dev_warn(cpu_dev, ++ "failed to scale vddarm down: %d\n", ret); ++ ret = 0; ++ } ++ ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); ++ if (ret) { ++ dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); ++ ret = 0; ++ } ++ if (regulator_is_enabled(pu_reg)) { ++ ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); ++ if (ret) { ++ dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); ++ ret = 0; ++ } ++ } ++ } ++ ++ if (policy->cur == freq_table[0].frequency) ++ release_bus_freq(BUS_FREQ_HIGH); ++ ++unlock: ++ mutex_unlock(&set_cpufreq_lock); ++ return ret; ++} ++ ++static int imx6_cpufreq_init(struct cpufreq_policy *policy) ++{ ++ policy->clk = arm_clk; ++ ++ if (policy->cur > freq_table[0].frequency) ++ request_bus_freq(BUS_FREQ_HIGH); ++ ++ return cpufreq_generic_init(policy, freq_table, transition_latency); ++} ++ ++static struct cpufreq_driver imx6_cpufreq_driver = { ++ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, ++ .verify = cpufreq_generic_frequency_table_verify, ++ .target_index = imx6_set_target, ++ .get = cpufreq_generic_get, ++ .init = imx6_cpufreq_init, ++ .exit = cpufreq_generic_exit, ++ .name = "imx6-cpufreq", ++ .attr = cpufreq_generic_attr, ++}; ++ ++static int imx6_cpufreq_pm_notify(struct notifier_block *nb, ++ unsigned long event, void *dummy) ++{ ++ struct cpufreq_policy *data = cpufreq_cpu_get(0); ++ static u32 cpufreq_policy_min_pre_suspend; ++ ++ /* ++ * During suspend/resume, When cpufreq driver try to increase ++ * voltage/freq, it needs to control I2C/SPI to communicate ++ * with external PMIC to adjust voltage, but these I2C/SPI ++ * devices may be already suspended, to avoid such scenario, ++ * we just increase cpufreq to highest setpoint before suspend. ++ */ ++ switch (event) { ++ case PM_SUSPEND_PREPARE: ++ cpufreq_policy_min_pre_suspend = data->user_policy.min; ++ data->user_policy.min = data->user_policy.max; ++ break; ++ case PM_POST_SUSPEND: ++ data->user_policy.min = cpufreq_policy_min_pre_suspend; ++ break; ++ default: ++ break; ++ } ++ ++ cpufreq_update_policy(0); ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block imx6_cpufreq_pm_notifier = { ++ .notifier_call = imx6_cpufreq_pm_notify, ++}; ++ ++static int imx6_cpufreq_probe(struct platform_device *pdev) ++{ ++ struct device_node *np; ++ struct dev_pm_opp *opp; ++ unsigned long min_volt, max_volt; ++ int num, ret; ++ const struct property *prop; ++ const __be32 *val; ++ u32 nr, i, j; ++ ++ cpu_dev = get_cpu_device(0); ++ if (!cpu_dev) { ++ pr_err("failed to get cpu0 device\n"); ++ return -ENODEV; ++ } ++ ++ np = of_node_get(cpu_dev->of_node); ++ if (!np) { ++ dev_err(cpu_dev, "failed to find cpu0 node\n"); ++ return -ENOENT; ++ } ++ ++ arm_clk = devm_clk_get(cpu_dev, "arm"); ++ pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); ++ pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); ++ step_clk = devm_clk_get(cpu_dev, "step"); ++ pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m"); ++ if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || ++ IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { ++ dev_err(cpu_dev, "failed to get clocks\n"); ++ ret = -ENOENT; ++ goto put_node; ++ } ++ ++ arm_reg = devm_regulator_get(cpu_dev, "arm"); ++ pu_reg = devm_regulator_get(cpu_dev, "pu"); ++ soc_reg = devm_regulator_get(cpu_dev, "soc"); ++ if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) { ++ dev_err(cpu_dev, "failed to get regulators\n"); ++ ret = -ENOENT; ++ goto put_node; ++ } ++ ++ /* ++ * We expect an OPP table supplied by platform. ++ * Just, incase the platform did not supply the OPP ++ * table, it will try to get it. ++ */ ++ num = dev_pm_opp_get_opp_count(cpu_dev); ++ if (num < 0) { ++ ret = of_init_opp_table(cpu_dev); ++ if (ret < 0) { ++ dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); ++ goto put_node; ++ } ++ ++ num = dev_pm_opp_get_opp_count(cpu_dev); ++ if (num < 0) { ++ ret = num; ++ dev_err(cpu_dev, "no OPP table is found: %d\n", ret); ++ goto put_node; ++ } ++ } ++ ++ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); ++ if (ret) { ++ dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); ++ goto put_node; ++ } ++ ++ /* Make imx6_soc_volt array's size same as arm opp number */ ++ imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); ++ if (imx6_soc_volt == NULL) { ++ ret = -ENOMEM; ++ goto free_freq_table; ++ } ++ ++ prop = of_find_property(np, "fsl,soc-operating-points", NULL); ++ if (!prop || !prop->value) ++ goto soc_opp_out; ++ ++ /* ++ * Each OPP is a set of tuples consisting of frequency and ++ * voltage like . ++ */ ++ nr = prop->length / sizeof(u32); ++ if (nr % 2 || (nr / 2) < num) ++ goto soc_opp_out; ++ ++ for (j = 0; j < num; j++) { ++ val = prop->value; ++ for (i = 0; i < nr / 2; i++) { ++ unsigned long freq = be32_to_cpup(val++); ++ unsigned long volt = be32_to_cpup(val++); ++ if (freq_table[j].frequency == freq) { ++ imx6_soc_volt[soc_opp_count++] = volt; ++ break; ++ } ++ } ++ } ++ ++soc_opp_out: ++ /* use fixed soc opp volt if no valid soc opp info found in dtb */ ++ if (soc_opp_count != num) { ++ dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); ++ for (j = 0; j < num; j++) ++ imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; ++ if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) ++ imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; ++ } ++ ++ if (of_property_read_u32(np, "clock-latency", &transition_latency)) ++ transition_latency = CPUFREQ_ETERNAL; ++ ++ /* ++ * Calculate the ramp time for max voltage change in the ++ * VDDSOC and VDDPU regulators. ++ */ ++ ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); ++ if (ret > 0) ++ transition_latency += ret * 1000; ++ ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); ++ if (ret > 0) ++ transition_latency += ret * 1000; ++ ++ /* ++ * OPP is maintained in order of increasing frequency, and ++ * freq_table initialised from OPP is therefore sorted in the ++ * same order. ++ */ ++ rcu_read_lock(); ++ opp = dev_pm_opp_find_freq_exact(cpu_dev, ++ freq_table[0].frequency * 1000, true); ++ min_volt = dev_pm_opp_get_voltage(opp); ++ opp = dev_pm_opp_find_freq_exact(cpu_dev, ++ freq_table[--num].frequency * 1000, true); ++ max_volt = dev_pm_opp_get_voltage(opp); ++ rcu_read_unlock(); ++ ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); ++ if (ret > 0) ++ transition_latency += ret * 1000; ++ ++ mutex_init(&set_cpufreq_lock); ++ register_pm_notifier(&imx6_cpufreq_pm_notifier); ++ ++ ret = cpufreq_register_driver(&imx6_cpufreq_driver); ++ if (ret) { ++ dev_err(cpu_dev, "failed register driver: %d\n", ret); ++ goto free_freq_table; ++ } ++ ++ of_node_put(np); ++ return 0; ++ ++free_freq_table: ++ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); ++put_node: ++ of_node_put(np); ++ return ret; ++} ++ ++static int imx6_cpufreq_remove(struct platform_device *pdev) ++{ ++ cpufreq_unregister_driver(&imx6_cpufreq_driver); ++ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); ++ ++ return 0; ++} ++ ++static struct platform_driver imx6_cpufreq_platdrv = { ++ .driver = { ++ .name = "imx6-cpufreq", ++ .owner = THIS_MODULE, ++ }, ++ .probe = imx6_cpufreq_probe, ++ .remove = imx6_cpufreq_remove, ++}; ++module_platform_driver(imx6_cpufreq_platdrv); ++ ++MODULE_AUTHOR("Shawn Guo "); ++MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/cpufreq/imx6q-cpufreq.c linux-imx6-3.14/drivers/cpufreq/imx6q-cpufreq.c +--- linux-3.14.14/drivers/cpufreq/imx6q-cpufreq.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/cpufreq/imx6q-cpufreq.c 1969-12-31 18:00:00.000000000 -0600 +@@ -1,330 +0,0 @@ +-/* +- * Copyright (C) 2013 Freescale Semiconductor, Inc. +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define PU_SOC_VOLTAGE_NORMAL 1250000 +-#define PU_SOC_VOLTAGE_HIGH 1275000 +-#define FREQ_1P2_GHZ 1200000000 +- +-static struct regulator *arm_reg; +-static struct regulator *pu_reg; +-static struct regulator *soc_reg; +- +-static struct clk *arm_clk; +-static struct clk *pll1_sys_clk; +-static struct clk *pll1_sw_clk; +-static struct clk *step_clk; +-static struct clk *pll2_pfd2_396m_clk; +- +-static struct device *cpu_dev; +-static struct cpufreq_frequency_table *freq_table; +-static unsigned int transition_latency; +- +-static u32 *imx6_soc_volt; +-static u32 soc_opp_count; +- +-static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) +-{ +- struct dev_pm_opp *opp; +- unsigned long freq_hz, volt, volt_old; +- unsigned int old_freq, new_freq; +- int ret; +- +- new_freq = freq_table[index].frequency; +- freq_hz = new_freq * 1000; +- old_freq = clk_get_rate(arm_clk) / 1000; +- +- rcu_read_lock(); +- opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); +- if (IS_ERR(opp)) { +- rcu_read_unlock(); +- dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz); +- return PTR_ERR(opp); +- } +- +- volt = dev_pm_opp_get_voltage(opp); +- rcu_read_unlock(); +- volt_old = regulator_get_voltage(arm_reg); +- +- dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", +- old_freq / 1000, volt_old / 1000, +- new_freq / 1000, volt / 1000); +- +- /* scaling up? scale voltage before frequency */ +- if (new_freq > old_freq) { +- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); +- if (ret) { +- dev_err(cpu_dev, "failed to scale vddpu up: %d\n", ret); +- return ret; +- } +- ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); +- if (ret) { +- dev_err(cpu_dev, "failed to scale vddsoc up: %d\n", ret); +- return ret; +- } +- ret = regulator_set_voltage_tol(arm_reg, volt, 0); +- if (ret) { +- dev_err(cpu_dev, +- "failed to scale vddarm up: %d\n", ret); +- return ret; +- } +- } +- +- /* +- * The setpoints are selected per PLL/PDF frequencies, so we need to +- * reprogram PLL for frequency scaling. The procedure of reprogramming +- * PLL1 is as below. +- * +- * - Enable pll2_pfd2_396m_clk and reparent pll1_sw_clk to it +- * - Reprogram pll1_sys_clk and reparent pll1_sw_clk back to it +- * - Disable pll2_pfd2_396m_clk +- */ +- clk_set_parent(step_clk, pll2_pfd2_396m_clk); +- clk_set_parent(pll1_sw_clk, step_clk); +- if (freq_hz > clk_get_rate(pll2_pfd2_396m_clk)) { +- clk_set_rate(pll1_sys_clk, new_freq * 1000); +- clk_set_parent(pll1_sw_clk, pll1_sys_clk); +- } +- +- /* Ensure the arm clock divider is what we expect */ +- ret = clk_set_rate(arm_clk, new_freq * 1000); +- if (ret) { +- dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); +- regulator_set_voltage_tol(arm_reg, volt_old, 0); +- return ret; +- } +- +- /* scaling down? scale voltage after frequency */ +- if (new_freq < old_freq) { +- ret = regulator_set_voltage_tol(arm_reg, volt, 0); +- if (ret) { +- dev_warn(cpu_dev, +- "failed to scale vddarm down: %d\n", ret); +- ret = 0; +- } +- ret = regulator_set_voltage_tol(soc_reg, imx6_soc_volt[index], 0); +- if (ret) { +- dev_warn(cpu_dev, "failed to scale vddsoc down: %d\n", ret); +- ret = 0; +- } +- ret = regulator_set_voltage_tol(pu_reg, imx6_soc_volt[index], 0); +- if (ret) { +- dev_warn(cpu_dev, "failed to scale vddpu down: %d\n", ret); +- ret = 0; +- } +- } +- +- return 0; +-} +- +-static int imx6q_cpufreq_init(struct cpufreq_policy *policy) +-{ +- policy->clk = arm_clk; +- return cpufreq_generic_init(policy, freq_table, transition_latency); +-} +- +-static struct cpufreq_driver imx6q_cpufreq_driver = { +- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, +- .verify = cpufreq_generic_frequency_table_verify, +- .target_index = imx6q_set_target, +- .get = cpufreq_generic_get, +- .init = imx6q_cpufreq_init, +- .exit = cpufreq_generic_exit, +- .name = "imx6q-cpufreq", +- .attr = cpufreq_generic_attr, +-}; +- +-static int imx6q_cpufreq_probe(struct platform_device *pdev) +-{ +- struct device_node *np; +- struct dev_pm_opp *opp; +- unsigned long min_volt, max_volt; +- int num, ret; +- const struct property *prop; +- const __be32 *val; +- u32 nr, i, j; +- +- cpu_dev = get_cpu_device(0); +- if (!cpu_dev) { +- pr_err("failed to get cpu0 device\n"); +- return -ENODEV; +- } +- +- np = of_node_get(cpu_dev->of_node); +- if (!np) { +- dev_err(cpu_dev, "failed to find cpu0 node\n"); +- return -ENOENT; +- } +- +- arm_clk = devm_clk_get(cpu_dev, "arm"); +- pll1_sys_clk = devm_clk_get(cpu_dev, "pll1_sys"); +- pll1_sw_clk = devm_clk_get(cpu_dev, "pll1_sw"); +- step_clk = devm_clk_get(cpu_dev, "step"); +- pll2_pfd2_396m_clk = devm_clk_get(cpu_dev, "pll2_pfd2_396m"); +- if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) || +- IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) { +- dev_err(cpu_dev, "failed to get clocks\n"); +- ret = -ENOENT; +- goto put_node; +- } +- +- arm_reg = devm_regulator_get(cpu_dev, "arm"); +- pu_reg = devm_regulator_get(cpu_dev, "pu"); +- soc_reg = devm_regulator_get(cpu_dev, "soc"); +- if (IS_ERR(arm_reg) || IS_ERR(pu_reg) || IS_ERR(soc_reg)) { +- dev_err(cpu_dev, "failed to get regulators\n"); +- ret = -ENOENT; +- goto put_node; +- } +- +- /* +- * We expect an OPP table supplied by platform. +- * Just, incase the platform did not supply the OPP +- * table, it will try to get it. +- */ +- num = dev_pm_opp_get_opp_count(cpu_dev); +- if (num < 0) { +- ret = of_init_opp_table(cpu_dev); +- if (ret < 0) { +- dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); +- goto put_node; +- } +- +- num = dev_pm_opp_get_opp_count(cpu_dev); +- if (num < 0) { +- ret = num; +- dev_err(cpu_dev, "no OPP table is found: %d\n", ret); +- goto put_node; +- } +- } +- +- ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); +- if (ret) { +- dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); +- goto put_node; +- } +- +- /* Make imx6_soc_volt array's size same as arm opp number */ +- imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL); +- if (imx6_soc_volt == NULL) { +- ret = -ENOMEM; +- goto free_freq_table; +- } +- +- prop = of_find_property(np, "fsl,soc-operating-points", NULL); +- if (!prop || !prop->value) +- goto soc_opp_out; +- +- /* +- * Each OPP is a set of tuples consisting of frequency and +- * voltage like . +- */ +- nr = prop->length / sizeof(u32); +- if (nr % 2 || (nr / 2) < num) +- goto soc_opp_out; +- +- for (j = 0; j < num; j++) { +- val = prop->value; +- for (i = 0; i < nr / 2; i++) { +- unsigned long freq = be32_to_cpup(val++); +- unsigned long volt = be32_to_cpup(val++); +- if (freq_table[j].frequency == freq) { +- imx6_soc_volt[soc_opp_count++] = volt; +- break; +- } +- } +- } +- +-soc_opp_out: +- /* use fixed soc opp volt if no valid soc opp info found in dtb */ +- if (soc_opp_count != num) { +- dev_warn(cpu_dev, "can NOT find valid fsl,soc-operating-points property in dtb, use default value!\n"); +- for (j = 0; j < num; j++) +- imx6_soc_volt[j] = PU_SOC_VOLTAGE_NORMAL; +- if (freq_table[num - 1].frequency * 1000 == FREQ_1P2_GHZ) +- imx6_soc_volt[num - 1] = PU_SOC_VOLTAGE_HIGH; +- } +- +- if (of_property_read_u32(np, "clock-latency", &transition_latency)) +- transition_latency = CPUFREQ_ETERNAL; +- +- /* +- * Calculate the ramp time for max voltage change in the +- * VDDSOC and VDDPU regulators. +- */ +- ret = regulator_set_voltage_time(soc_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); +- if (ret > 0) +- transition_latency += ret * 1000; +- ret = regulator_set_voltage_time(pu_reg, imx6_soc_volt[0], imx6_soc_volt[num - 1]); +- if (ret > 0) +- transition_latency += ret * 1000; +- +- /* +- * OPP is maintained in order of increasing frequency, and +- * freq_table initialised from OPP is therefore sorted in the +- * same order. +- */ +- rcu_read_lock(); +- opp = dev_pm_opp_find_freq_exact(cpu_dev, +- freq_table[0].frequency * 1000, true); +- min_volt = dev_pm_opp_get_voltage(opp); +- opp = dev_pm_opp_find_freq_exact(cpu_dev, +- freq_table[--num].frequency * 1000, true); +- max_volt = dev_pm_opp_get_voltage(opp); +- rcu_read_unlock(); +- ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt); +- if (ret > 0) +- transition_latency += ret * 1000; +- +- ret = cpufreq_register_driver(&imx6q_cpufreq_driver); +- if (ret) { +- dev_err(cpu_dev, "failed register driver: %d\n", ret); +- goto free_freq_table; +- } +- +- of_node_put(np); +- return 0; +- +-free_freq_table: +- dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); +-put_node: +- of_node_put(np); +- return ret; +-} +- +-static int imx6q_cpufreq_remove(struct platform_device *pdev) +-{ +- cpufreq_unregister_driver(&imx6q_cpufreq_driver); +- dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); +- +- return 0; +-} +- +-static struct platform_driver imx6q_cpufreq_platdrv = { +- .driver = { +- .name = "imx6q-cpufreq", +- .owner = THIS_MODULE, +- }, +- .probe = imx6q_cpufreq_probe, +- .remove = imx6q_cpufreq_remove, +-}; +-module_platform_driver(imx6q_cpufreq_platdrv); +- +-MODULE_AUTHOR("Shawn Guo "); +-MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); +-MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/cpufreq/Kconfig linux-imx6-3.14/drivers/cpufreq/Kconfig +--- linux-3.14.14/drivers/cpufreq/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/cpufreq/Kconfig 2014-12-08 00:31:52.536418001 -0600 +@@ -91,6 +91,15 @@ + governor. If unsure have a look at the help section of the + driver. Fallback governor will be the performance governor. + ++config CPU_FREQ_DEFAULT_GOV_INTERACTIVE ++ bool "interactive" ++ select CPU_FREQ_GOV_INTERACTIVE ++ help ++ Use the CPUFreq governor 'interactive' as default. This allows ++ you to get a full dynamic cpu frequency capable system by simply ++ loading your cpufreq low-level hardware driver, using the ++ 'interactive' governor for latency-sensitive workloads. ++ + config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE + bool "conservative" + select CPU_FREQ_GOV_CONSERVATIVE +@@ -157,6 +166,24 @@ + + For details, take a look at linux/Documentation/cpu-freq. + ++ If in doubt, say N. ++ ++config CPU_FREQ_GOV_INTERACTIVE ++ tristate "'interactive' cpufreq policy governor" ++ default n ++ help ++ 'interactive' - This driver adds a dynamic cpufreq policy governor ++ designed for latency-sensitive workloads. ++ ++ This governor attempts to reduce the latency of clock ++ increases so that the system is more responsive to ++ interactive workloads. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called cpufreq_interactive. ++ ++ For details, take a look at linux/Documentation/cpu-freq. ++ + If in doubt, say N. + + config CPU_FREQ_GOV_CONSERVATIVE +diff -Nur linux-3.14.14/drivers/cpufreq/Kconfig.arm linux-imx6-3.14/drivers/cpufreq/Kconfig.arm +--- linux-3.14.14/drivers/cpufreq/Kconfig.arm 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/cpufreq/Kconfig.arm 2014-12-08 00:31:52.536418001 -0600 +@@ -4,7 +4,8 @@ + + config ARM_BIG_LITTLE_CPUFREQ + tristate "Generic ARM big LITTLE CPUfreq driver" +- depends on ARM && BIG_LITTLE && ARM_CPU_TOPOLOGY && HAVE_CLK ++ depends on (BIG_LITTLE && ARM_CPU_TOPOLOGY) || (ARM64 && SMP) ++ depends on HAVE_CLK + select PM_OPP + help + This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. +@@ -95,7 +96,7 @@ + + If in doubt, say N. + +-config ARM_IMX6Q_CPUFREQ ++config ARM_IMX6_CPUFREQ + tristate "Freescale i.MX6 cpufreq support" + depends on ARCH_MXC + depends on REGULATOR_ANATOP +diff -Nur linux-3.14.14/drivers/cpufreq/Makefile linux-imx6-3.14/drivers/cpufreq/Makefile +--- linux-3.14.14/drivers/cpufreq/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/cpufreq/Makefile 2014-12-08 00:31:52.536418001 -0600 +@@ -8,6 +8,7 @@ + obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o + obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o + obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o ++obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o + obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o + obj-$(CONFIG_CPU_FREQ_GOV_COMMON) += cpufreq_governor.o + +@@ -55,7 +56,7 @@ + obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ) += exynos5250-cpufreq.o + obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o + obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o +-obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o ++obj-$(CONFIG_ARM_IMX6_CPUFREQ) += imx6-cpufreq.o + obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o + obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o + obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o +diff -Nur linux-3.14.14/drivers/crypto/caam/secvio.c linux-imx6-3.14/drivers/crypto/caam/secvio.c +--- linux-3.14.14/drivers/crypto/caam/secvio.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/secvio.c 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,335 @@ ++ ++/* ++ * CAAM/SEC 4.x Security Violation Handler ++ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved ++ */ ++ ++#include "compat.h" ++#include "intern.h" ++#include "secvio.h" ++#include "regs.h" ++ ++/* ++ * These names are associated with each violation handler. ++ * The source names were taken from MX6, and are based on recommendations ++ * for most common SoCs. ++ */ ++static const u8 *violation_src_name[] = { ++ "CAAM Security Violation", ++ "JTAG Alarm", ++ "Watchdog", ++ "(reserved)", ++ "External Boot", ++ "Tamper Detect", ++}; ++ ++/* Top-level security violation interrupt */ ++static irqreturn_t caam_secvio_interrupt(int irq, void *snvsdev) ++{ ++ struct device *dev = snvsdev; ++ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); ++ u32 irqstate; ++ ++ /* Check the HP secvio status register */ ++ irqstate = rd_reg32(&svpriv->svregs->hp.secvio_status) | ++ HP_SECVIOST_SECVIOMASK; ++ ++ if (!irqstate) ++ return IRQ_NONE; ++ ++ /* Mask out one or more causes for deferred service */ ++ clrbits32(&svpriv->svregs->hp.secvio_int_ctl, irqstate); ++ ++ /* Now ACK causes */ ++ setbits32(&svpriv->svregs->hp.secvio_status, irqstate); ++ ++ /* And run deferred service */ ++ preempt_disable(); ++ tasklet_schedule(&svpriv->irqtask[smp_processor_id()]); ++ preempt_enable(); ++ ++ return IRQ_HANDLED; ++} ++ ++/* Deferred service handler. Tasklet arg is simply the SNVS dev */ ++static void caam_secvio_dispatch(unsigned long indev) ++{ ++ struct device *dev = (struct device *)indev; ++ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); ++ unsigned long flags, cause; ++ int i; ++ ++ ++ /* ++ * Capture the interrupt cause, using masked interrupts as ++ * identification. This only works if all are enabled; if ++ * this changes in the future, a "cause queue" will have to ++ * be built ++ */ ++ cause = rd_reg32(&svpriv->svregs->hp.secvio_int_ctl) & ++ (HP_SECVIO_INTEN_SRC5 | HP_SECVIO_INTEN_SRC4 | ++ HP_SECVIO_INTEN_SRC3 | HP_SECVIO_INTEN_SRC2 | ++ HP_SECVIO_INTEN_SRC1 | HP_SECVIO_INTEN_SRC0); ++ ++ /* Look through causes, call each handler if exists */ ++ for (i = 0; i < MAX_SECVIO_SOURCES; i++) ++ if (cause & (1 << i)) { ++ spin_lock_irqsave(&svpriv->svlock, flags); ++ svpriv->intsrc[i].handler(dev, i, ++ svpriv->intsrc[i].ext); ++ spin_unlock_irqrestore(&svpriv->svlock, flags); ++ }; ++ ++ /* Re-enable now-serviced interrupts */ ++ setbits32(&svpriv->svregs->hp.secvio_int_ctl, cause); ++} ++ ++/* ++ * Default cause handler, used in lieu of an application-defined handler. ++ * All it does at this time is print a console message. It could force a halt. ++ */ ++static void caam_secvio_default(struct device *dev, u32 cause, void *ext) ++{ ++ struct caam_drv_private_secvio *svpriv = dev_get_drvdata(dev); ++ ++ dev_err(dev, "Unhandled Security Violation Interrupt %d = %s\n", ++ cause, svpriv->intsrc[cause].intname); ++} ++ ++/* ++ * Install an application-defined handler for a specified cause ++ * Arguments: ++ * - dev points to SNVS-owning device ++ * - cause interrupt source cause ++ * - handler application-defined handler, gets called with dev ++ * source cause, and locally-defined handler argument ++ * - cause_description points to a string to override the default cause ++ * name, this can be used as an alternate for error ++ * messages and such. If left NULL, the default ++ * description string is used. ++ * - ext pointer to any extra data needed by the handler. ++ */ ++int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, ++ void (*handler)(struct device *dev, u32 cause, ++ void *ext), ++ u8 *cause_description, void *ext) ++{ ++ unsigned long flags; ++ struct caam_drv_private_secvio *svpriv; ++ ++ svpriv = dev_get_drvdata(dev); ++ ++ if ((handler == NULL) || (cause > SECVIO_CAUSE_SOURCE_5)) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&svpriv->svlock, flags); ++ svpriv->intsrc[cause].handler = handler; ++ if (cause_description != NULL) ++ svpriv->intsrc[cause].intname = cause_description; ++ if (ext != NULL) ++ svpriv->intsrc[cause].ext = ext; ++ spin_unlock_irqrestore(&svpriv->svlock, flags); ++ ++ return 0; ++} ++EXPORT_SYMBOL(caam_secvio_install_handler); ++ ++/* ++ * Remove an application-defined handler for a specified cause (and, by ++ * implication, restore the "default". ++ * Arguments: ++ * - dev points to SNVS-owning device ++ * - cause interrupt source cause ++ */ ++int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause) ++{ ++ unsigned long flags; ++ struct caam_drv_private_secvio *svpriv; ++ ++ svpriv = dev_get_drvdata(dev); ++ ++ if (cause > SECVIO_CAUSE_SOURCE_5) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&svpriv->svlock, flags); ++ svpriv->intsrc[cause].intname = violation_src_name[cause]; ++ svpriv->intsrc[cause].handler = caam_secvio_default; ++ svpriv->intsrc[cause].ext = NULL; ++ spin_unlock_irqrestore(&svpriv->svlock, flags); ++ return 0; ++} ++EXPORT_SYMBOL(caam_secvio_remove_handler); ++ ++int caam_secvio_startup(struct platform_device *pdev) ++{ ++ struct device *ctrldev, *svdev; ++ struct caam_drv_private *ctrlpriv; ++ struct caam_drv_private_secvio *svpriv; ++ struct platform_device *svpdev; ++ struct device_node *np; ++ const void *prop; ++ int i, error, secvio_inten_src; ++ ++ ctrldev = &pdev->dev; ++ ctrlpriv = dev_get_drvdata(ctrldev); ++ /* ++ * Set up the private block for secure memory ++ * Only one instance is possible ++ */ ++ svpriv = kzalloc(sizeof(struct caam_drv_private_secvio), GFP_KERNEL); ++ if (svpriv == NULL) { ++ dev_err(ctrldev, "can't alloc private mem for secvio\n"); ++ return -ENOMEM; ++ } ++ svpriv->parentdev = ctrldev; ++ ++ /* Create the security violation dev */ ++#ifdef CONFIG_OF ++ ++ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-secvio"); ++ if (!np) ++ return -ENODEV; ++ ++ ctrlpriv->secvio_irq = of_irq_to_resource(np, 0, NULL); ++ ++ prop = of_get_property(np, "secvio_src", NULL); ++ if (prop) ++ secvio_inten_src = of_read_ulong(prop, 1); ++ else ++ secvio_inten_src = HP_SECVIO_INTEN_ALL; ++ ++ printk(KERN_ERR "secvio_inten_src = %x\n", secvio_inten_src); ++ ++ svpdev = of_platform_device_create(np, NULL, ctrldev); ++ if (!svpdev) ++ return -ENODEV; ++ ++#else ++ svpdev = platform_device_register_data(ctrldev, "caam_secvio", 0, ++ svpriv, ++ sizeof(struct caam_drv_private_secvio)); ++ ++ secvio_inten_src = HP_SECVIO_INTEN_ALL; ++#endif ++ if (svpdev == NULL) { ++ kfree(svpriv); ++ return -EINVAL; ++ } ++ svdev = &svpdev->dev; ++ dev_set_drvdata(svdev, svpriv); ++ ctrlpriv->secviodev = svdev; ++ svpriv->svregs = ctrlpriv->snvs; ++ ++ /* ++ * Now we have all the dev data set up. Init interrupt ++ * source descriptions ++ */ ++ for (i = 0; i < MAX_SECVIO_SOURCES; i++) { ++ svpriv->intsrc[i].intname = violation_src_name[i]; ++ svpriv->intsrc[i].handler = caam_secvio_default; ++ } ++ ++ /* Connect main handler */ ++ for_each_possible_cpu(i) ++ tasklet_init(&svpriv->irqtask[i], caam_secvio_dispatch, ++ (unsigned long)svdev); ++ ++ error = request_irq(ctrlpriv->secvio_irq, caam_secvio_interrupt, ++ IRQF_SHARED, "caam_secvio", svdev); ++ if (error) { ++ dev_err(svdev, "can't connect secvio interrupt\n"); ++ irq_dispose_mapping(ctrlpriv->secvio_irq); ++ ctrlpriv->secvio_irq = 0; ++ return -EINVAL; ++ } ++ ++ /* Enable all sources */ ++ wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, secvio_inten_src); ++ ++ dev_info(svdev, "security violation service handlers armed\n"); ++ ++ return 0; ++} ++ ++void caam_secvio_shutdown(struct platform_device *pdev) ++{ ++ struct device *ctrldev, *svdev; ++ struct caam_drv_private *priv; ++ struct caam_drv_private_secvio *svpriv; ++ int i; ++ ++ ctrldev = &pdev->dev; ++ priv = dev_get_drvdata(ctrldev); ++ svdev = priv->secviodev; ++ svpriv = dev_get_drvdata(svdev); ++ ++ /* Shut off all sources */ ++ ++ wr_reg32(&svpriv->svregs->hp.secvio_int_ctl, 0); ++ ++ /* Remove tasklets and release interrupt */ ++ for_each_possible_cpu(i) ++ tasklet_kill(&svpriv->irqtask[i]); ++ ++ free_irq(priv->secvio_irq, svdev); ++ ++ kfree(svpriv); ++} ++ ++ ++#ifdef CONFIG_OF ++static void __exit caam_secvio_exit(void) ++{ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); ++ if (!dev_node) ++ return; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return; ++ ++ of_node_get(dev_node); ++ ++ caam_secvio_shutdown(pdev); ++ ++} ++ ++static int __init caam_secvio_init(void) ++{ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ /* ++ * Do of_find_compatible_node() then of_find_device_by_node() ++ * once a functional device tree is available ++ */ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, ++ "arm,imx6-caam-secvio"); ++ if (!dev_node) ++ return -ENODEV; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return -ENODEV; ++ ++ of_node_put(dev_node); ++ ++ return caam_secvio_startup(pdev); ++} ++ ++module_init(caam_secvio_init); ++module_exit(caam_secvio_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL CAAM/SNVS Security Violation Handler"); ++MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); ++#endif +diff -Nur linux-3.14.14/drivers/crypto/caam/secvio.h linux-imx6-3.14/drivers/crypto/caam/secvio.h +--- linux-3.14.14/drivers/crypto/caam/secvio.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/secvio.h 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,64 @@ ++ ++/* ++ * CAAM Security Violation Handler ++ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved ++ */ ++ ++#ifndef SECVIO_H ++#define SECVIO_H ++ ++#include "snvsregs.h" ++ ++ ++/* ++ * Defines the published interfaces to install/remove application-specified ++ * handlers for catching violations ++ */ ++ ++#define MAX_SECVIO_SOURCES 6 ++ ++/* these are the untranslated causes */ ++enum secvio_cause { ++ SECVIO_CAUSE_SOURCE_0, ++ SECVIO_CAUSE_SOURCE_1, ++ SECVIO_CAUSE_SOURCE_2, ++ SECVIO_CAUSE_SOURCE_3, ++ SECVIO_CAUSE_SOURCE_4, ++ SECVIO_CAUSE_SOURCE_5 ++}; ++ ++/* These are common "recommended" cause definitions for most devices */ ++#define SECVIO_CAUSE_CAAM_VIOLATION SECVIO_CAUSE_SOURCE_0 ++#define SECVIO_CAUSE JTAG_ALARM SECVIO_CAUSE_SOURCE_1 ++#define SECVIO_CAUSE_WATCHDOG SECVIO_CAUSE_SOURCE_2 ++#define SECVIO_CAUSE_EXTERNAL_BOOT SECVIO_CAUSE_SOURCE_4 ++#define SECVIO_CAUSE_TAMPER_DETECT SECVIO_CAUSE_SOURCE_5 ++ ++int caam_secvio_install_handler(struct device *dev, enum secvio_cause cause, ++ void (*handler)(struct device *dev, u32 cause, ++ void *ext), ++ u8 *cause_description, void *ext); ++int caam_secvio_remove_handler(struct device *dev, enum secvio_cause cause); ++ ++/* ++ * Private data definitions for the secvio "driver" ++ */ ++ ++struct secvio_int_src { ++ const u8 *intname; /* Points to a descriptive name for source */ ++ void *ext; /* Extended data to pass to the handler */ ++ void (*handler)(struct device *dev, u32 cause, void *ext); ++}; ++ ++struct caam_drv_private_secvio { ++ struct device *parentdev; /* points back to the controller */ ++ spinlock_t svlock ____cacheline_aligned; ++ struct tasklet_struct irqtask[NR_CPUS]; ++ struct snvs_full __iomem *svregs; /* both HP and LP domains */ ++ ++ /* Registered handlers for each violation */ ++ struct secvio_int_src intsrc[MAX_SECVIO_SOURCES]; ++ ++}; ++ ++#endif /* SECVIO_H */ +diff -Nur linux-3.14.14/drivers/crypto/caam/sm.h linux-imx6-3.14/drivers/crypto/caam/sm.h +--- linux-3.14.14/drivers/crypto/caam/sm.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/sm.h 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,88 @@ ++ ++/* ++ * CAAM Secure Memory/Keywrap API Definitions ++ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. ++ */ ++ ++#ifndef SM_H ++#define SM_H ++ ++ ++/* Storage access permissions */ ++#define SM_PERM_READ 0x01 ++#define SM_PERM_WRITE 0x02 ++#define SM_PERM_BLOB 0x03 ++ ++ ++/* Keystore maintenance functions */ ++void sm_init_keystore(struct device *dev); ++u32 sm_detect_keystore_units(struct device *dev); ++int sm_establish_keystore(struct device *dev, u32 unit); ++void sm_release_keystore(struct device *dev, u32 unit); ++void caam_sm_shutdown(struct platform_device *pdev); ++int caam_sm_example_init(struct platform_device *pdev); ++ ++/* Keystore accessor functions */ ++extern int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, ++ u32 *slot); ++extern int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot); ++extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, ++ const u8 *key_data, u32 key_length); ++extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, ++ u32 key_length, u8 *key_data); ++extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, ++ u32 inslot, u32 outslot, u16 secretlen, ++ u8 *keymod, u16 keymodlen); ++extern int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, ++ u32 inslot, u32 outslot, u16 secretlen, ++ u8 *keymod, u16 keymodlen); ++ ++/* Data structure to hold per-slot information */ ++struct keystore_data_slot_info { ++ u8 allocated; /* Track slot assignments */ ++ u32 key_length; /* Size of the key */ ++}; ++ ++/* Data structure to hold keystore information */ ++struct keystore_data { ++ void *base_address; /* Base of the Secure Partition */ ++ u32 slot_count; /* Number of slots in the keystore */ ++ struct keystore_data_slot_info *slot; /* Per-slot information */ ++}; ++ ++/* store the detected attributes of a secure memory page */ ++struct sm_page_descriptor { ++ u16 phys_pagenum; /* may be discontiguous */ ++ u16 own_part; /* Owning partition */ ++ void *pg_base; /* Calculated virtual address */ ++ struct keystore_data *ksdata; ++}; ++ ++struct caam_drv_private_sm { ++ struct device *parentdev; /* this ends up as the controller */ ++ struct device *smringdev; /* ring that owns this instance */ ++ spinlock_t kslock ____cacheline_aligned; ++ ++ /* Default parameters for geometry */ ++ u32 max_pages; /* maximum pages this instance can support */ ++ u32 top_partition; /* highest partition number in this instance */ ++ u32 top_page; /* highest page number in this instance */ ++ u32 page_size; /* page size */ ++ u32 slot_size; /* selected size of each storage block */ ++ ++ /* Partition/Page Allocation Map */ ++ u32 localpages; /* Number of pages we can access */ ++ struct sm_page_descriptor *pagedesc; /* Allocated per-page */ ++ ++ /* Installed handlers for keystore access */ ++ int (*data_init)(struct device *dev, u32 unit); ++ void (*data_cleanup)(struct device *dev, u32 unit); ++ int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot); ++ int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot); ++ void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle); ++ u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle); ++ u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle); ++ u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle); ++}; ++ ++#endif /* SM_H */ +diff -Nur linux-3.14.14/drivers/crypto/caam/sm_store.c linux-imx6-3.14/drivers/crypto/caam/sm_store.c +--- linux-3.14.14/drivers/crypto/caam/sm_store.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/sm_store.c 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,896 @@ ++ ++/* ++ * CAAM Secure Memory Storage Interface ++ * Copyright (C) 2008-2013 Freescale Semiconductor, Inc. ++ * ++ * Loosely based on the SHW Keystore API for SCC/SCC2 ++ * Experimental implementation and NOT intended for upstream use. Expect ++ * this interface to be amended significantly in the future once it becomes ++ * integrated into live applications. ++ * ++ * Known issues: ++ * ++ * - Executes one instance of an secure memory "driver". This is tied to the ++ * fact that job rings can't run as standalone instances in the present ++ * configuration. ++ * ++ * - It does not expose a userspace interface. The value of a userspace ++ * interface for access to secrets is a point for further architectural ++ * discussion. ++ * ++ * - Partition/permission management is not part of this interface. It ++ * depends on some level of "knowledge" agreed upon between bootloader, ++ * provisioning applications, and OS-hosted software (which uses this ++ * driver). ++ * ++ * - No means of identifying the location or purpose of secrets managed by ++ * this interface exists; "slot location" and format of a given secret ++ * needs to be agreed upon between bootloader, provisioner, and OS-hosted ++ * application. ++ */ ++ ++#include "compat.h" ++#include "regs.h" ++#include "jr.h" ++#include "desc.h" ++#include "intern.h" ++#include "error.h" ++#include "sm.h" ++ ++#ifdef SM_DEBUG_CONT ++void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ u32 i, *smdata; ++ ++ dev_info(dev, "physical page %d content at 0x%08x\n", ++ pgdesc->phys_pagenum, pgdesc->pg_base); ++ smdata = pgdesc->pg_base; ++ for (i = 0; i < (smpriv->page_size / sizeof(u32)); i += 4) ++ dev_info(dev, "[0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", ++ (u32)&smdata[i], smdata[i], smdata[i+1], smdata[i+2], ++ smdata[i+3]); ++} ++#endif ++ ++/* ++ * Construct a secure memory blob encapsulation job descriptor ++ * ++ * - desc pointer to hold new (to be allocated) pointer to the generated ++ * descriptor for later use. Calling thread can kfree the ++ * descriptor after execution. ++ * - keymod Physical pointer to key modifier (contiguous piece). ++ * - keymodsz Size of key modifier in bytes (should normally be 8). ++ * - secretbuf Physical pointer (within an accessible secure memory page) ++ * of the secret to be encapsulated. ++ * - outbuf Physical pointer (within an accessible secure memory page) ++ * of the encapsulated output. This will be larger than the ++ * input secret because of the added encapsulation data. ++ * - secretsz Size of input secret, in bytes. ++ * - auth If nonzero, use AES-CCM for encapsulation, else use ECB ++ * ++ * Note: this uses 32-bit pointers at present ++ */ ++#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */ ++static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, ++ dma_addr_t secretbuf, dma_addr_t outbuf, ++ u16 secretsz, bool auth) ++{ ++ u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; ++ u16 dsize, idx; ++ ++ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); ++ idx = 1; ++ ++ /* Load key modifier */ ++ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | ++ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | ++ (keymodsz & LDST_LEN_MASK); ++ ++ tmpdesc[idx++] = (u32)keymod; ++ ++ /* Encapsulate to secure memory */ ++ tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz; ++ tmpdesc[idx++] = (u32)secretbuf; ++ ++ /* Add space for BKEK and MAC tag */ ++ tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16)); ++ ++ tmpdesc[idx++] = (u32)outbuf; ++ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB | ++ OP_PCL_BLOB_PTXT_SECMEM; ++ if (auth) ++ tmpdesc[idx] |= OP_PCL_BLOB_EKT; ++ ++ idx++; ++ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); ++ dsize = idx * sizeof(u32); ++ ++ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); ++ if (tdesc == NULL) ++ return 0; ++ ++ memcpy(tdesc, tmpdesc, dsize); ++ *desc = tdesc; ++ return dsize; ++} ++ ++/* ++ * Construct a secure memory blob decapsulation job descriptor ++ * ++ * - desc pointer to hold new (to be allocated) pointer to the generated ++ * descriptor for later use. Calling thread can kfree the ++ * descriptor after execution. ++ * - keymod Physical pointer to key modifier (contiguous piece). ++ * - keymodsz Size of key modifier in bytes (should normally be 16). ++ * - blobbuf Physical pointer (within an accessible secure memory page) ++ * of the blob to be decapsulated. ++ * - outbuf Physical pointer (within an accessible secure memory page) ++ * of the decapsulated output. ++ * - secretsz Size of input blob, in bytes. ++ * - auth If nonzero, assume AES-CCM for decapsulation, else use ECB ++ * ++ * Note: this uses 32-bit pointers at present ++ */ ++static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz, ++ dma_addr_t blobbuf, dma_addr_t outbuf, ++ u16 blobsz, bool auth) ++{ ++ u32 *tdesc, tmpdesc[INITIAL_DESCSZ]; ++ u16 dsize, idx; ++ ++ memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32)); ++ idx = 1; ++ ++ /* Load key modifier */ ++ tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY | ++ ((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) | ++ (keymodsz & LDST_LEN_MASK); ++ ++ tmpdesc[idx++] = (u32)keymod; ++ ++ /* Compensate BKEK + MAC tag */ ++ tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16); ++ ++ tmpdesc[idx++] = (u32)blobbuf; ++ tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz; ++ tmpdesc[idx++] = (u32)outbuf; ++ ++ /* Decapsulate from secure memory partition to black blob */ ++ tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB | ++ OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK; ++ if (auth) ++ tmpdesc[idx] |= OP_PCL_BLOB_EKT; ++ ++ idx++; ++ tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK); ++ dsize = idx * sizeof(u32); ++ ++ tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA); ++ if (tdesc == NULL) ++ return 0; ++ ++ memcpy(tdesc, tmpdesc, dsize); ++ *desc = tdesc; ++ return dsize; ++} ++ ++/* ++ * Pseudo-synchronous ring access functions for carrying out key ++ * encapsulation and decapsulation ++ */ ++ ++struct sm_key_job_result { ++ int error; ++ struct completion completion; ++}; ++ ++void sm_key_job_done(struct device *dev, u32 *desc, u32 err, void *context) ++{ ++ struct sm_key_job_result *res = context; ++ ++ res->error = err; /* save off the error for postprocessing */ ++ complete(&res->completion); /* mark us complete */ ++} ++ ++static int sm_key_job(struct device *ksdev, u32 *jobdesc) ++{ ++ struct sm_key_job_result testres; ++ struct caam_drv_private_sm *kspriv; ++ int rtn = 0; ++ ++ kspriv = dev_get_drvdata(ksdev); ++ ++ init_completion(&testres.completion); ++ ++ rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, sm_key_job_done, ++ &testres); ++ if (!rtn) { ++ wait_for_completion_interruptible(&testres.completion); ++ rtn = testres.error; ++ } ++ return rtn; ++} ++ ++/* ++ * Following section establishes the default methods for keystore access ++ * They are NOT intended for use external to this module ++ * ++ * In the present version, these are the only means for the higher-level ++ * interface to deal with the mechanics of accessing the phyiscal keystore ++ */ ++ ++ ++int slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; ++ u32 i; ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_alloc(): requesting slot for %d bytes\n", size); ++#endif ++ ++ if (size > smpriv->slot_size) ++ return -EKEYREJECTED; ++ ++ for (i = 0; i < ksdata->slot_count; i++) { ++ if (ksdata->slot[i].allocated == 0) { ++ ksdata->slot[i].allocated = 1; ++ (*slot) = i; ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_alloc(): new slot %d allocated\n", ++ *slot); ++#endif ++ return 0; ++ } ++ } ++ ++ return -ENOSPC; ++} ++EXPORT_SYMBOL(slot_alloc); ++ ++int slot_dealloc(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; ++ u8 __iomem *slotdata; ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_dealloc(): releasing slot %d\n", slot); ++#endif ++ if (slot >= ksdata->slot_count) ++ return -EINVAL; ++ slotdata = ksdata->base_address + slot * smpriv->slot_size; ++ ++ if (ksdata->slot[slot].allocated == 1) { ++ /* Forcibly overwrite the data from the keystore */ ++ memset(ksdata->base_address + slot * smpriv->slot_size, 0, ++ smpriv->slot_size); ++ ++ ksdata->slot[slot].allocated = 0; ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_dealloc(): slot %d released\n", slot); ++#endif ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++EXPORT_SYMBOL(slot_dealloc); ++ ++void *slot_get_address(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; ++ ++ if (slot >= ksdata->slot_count) ++ return NULL; ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_get_address(): slot %d is 0x%08x\n", slot, ++ (u32)ksdata->base_address + slot * smpriv->slot_size); ++#endif ++ ++ return ksdata->base_address + slot * smpriv->slot_size; ++} ++ ++u32 slot_get_base(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; ++ ++ /* ++ * There could potentially be more than one secure partition object ++ * associated with this keystore. For now, there is just one. ++ */ ++ ++ (void)slot; ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_get_base(): slot %d = 0x%08x\n", ++ slot, (u32)ksdata->base_address); ++#endif ++ ++ return (u32)(ksdata->base_address); ++} ++ ++u32 slot_get_offset(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata; ++ ++ if (slot >= ksdata->slot_count) ++ return -EINVAL; ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_get_offset(): slot %d = %d\n", slot, ++ slot * smpriv->slot_size); ++#endif ++ ++ return slot * smpriv->slot_size; ++} ++ ++u32 slot_get_slot_size(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "slot_get_slot_size(): slot %d = %d\n", slot, ++ smpriv->slot_size); ++#endif ++ /* All slots are the same size in the default implementation */ ++ return smpriv->slot_size; ++} ++ ++ ++ ++int kso_init_data(struct device *dev, u32 unit) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = -EINVAL; ++ struct keystore_data *keystore_data = NULL; ++ u32 slot_count; ++ u32 keystore_data_size; ++ ++ /* ++ * Calculate the required size of the keystore data structure, based ++ * on the number of keys that can fit in the partition. ++ */ ++ slot_count = smpriv->page_size / smpriv->slot_size; ++#ifdef SM_DEBUG ++ dev_info(dev, "kso_init_data: %d slots initializing\n", slot_count); ++#endif ++ ++ keystore_data_size = sizeof(struct keystore_data) + ++ slot_count * ++ sizeof(struct keystore_data_slot_info); ++ ++ keystore_data = kzalloc(keystore_data_size, GFP_KERNEL); ++ ++ if (keystore_data == NULL) { ++ retval = -ENOSPC; ++ goto out; ++ } ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "kso_init_data: keystore data size = %d\n", ++ keystore_data_size); ++#endif ++ ++ /* ++ * Place the slot information structure directly after the keystore data ++ * structure. ++ */ ++ keystore_data->slot = (struct keystore_data_slot_info *) ++ (keystore_data + 1); ++ keystore_data->slot_count = slot_count; ++ ++ smpriv->pagedesc[unit].ksdata = keystore_data; ++ smpriv->pagedesc[unit].ksdata->base_address = ++ smpriv->pagedesc[unit].pg_base; ++ ++ retval = 0; ++ ++out: ++ if (retval != 0) ++ if (keystore_data != NULL) ++ kfree(keystore_data); ++ ++ ++ return retval; ++} ++ ++void kso_cleanup_data(struct device *dev, u32 unit) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ struct keystore_data *keystore_data = NULL; ++ ++ if (smpriv->pagedesc[unit].ksdata != NULL) ++ keystore_data = smpriv->pagedesc[unit].ksdata; ++ ++ /* Release the allocated keystore management data */ ++ kfree(smpriv->pagedesc[unit].ksdata); ++ ++ return; ++} ++ ++ ++ ++/* ++ * Keystore management section ++ */ ++ ++void sm_init_keystore(struct device *dev) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ ++ smpriv->data_init = kso_init_data; ++ smpriv->data_cleanup = kso_cleanup_data; ++ smpriv->slot_alloc = slot_alloc; ++ smpriv->slot_dealloc = slot_dealloc; ++ smpriv->slot_get_address = slot_get_address; ++ smpriv->slot_get_base = slot_get_base; ++ smpriv->slot_get_offset = slot_get_offset; ++ smpriv->slot_get_slot_size = slot_get_slot_size; ++#ifdef SM_DEBUG ++ dev_info(dev, "sm_init_keystore(): handlers installed\n"); ++#endif ++} ++EXPORT_SYMBOL(sm_init_keystore); ++ ++/* Return available pages/units */ ++u32 sm_detect_keystore_units(struct device *dev) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ ++ return smpriv->localpages; ++} ++EXPORT_SYMBOL(sm_detect_keystore_units); ++ ++/* ++ * Do any keystore specific initializations ++ */ ++int sm_establish_keystore(struct device *dev, u32 unit) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "sm_establish_keystore(): unit %d initializing\n", unit); ++#endif ++ ++ if (smpriv->data_init == NULL) ++ return -EINVAL; ++ ++ /* Call the data_init function for any user setup */ ++ return smpriv->data_init(dev, unit); ++} ++EXPORT_SYMBOL(sm_establish_keystore); ++ ++void sm_release_keystore(struct device *dev, u32 unit) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ ++#ifdef SM_DEBUG ++ dev_info(dev, "sm_establish_keystore(): unit %d releasing\n", unit); ++#endif ++ if ((smpriv != NULL) && (smpriv->data_cleanup != NULL)) ++ smpriv->data_cleanup(dev, unit); ++ ++ return; ++} ++EXPORT_SYMBOL(sm_release_keystore); ++ ++/* ++ * Subsequent interfacce (sm_keystore_*) forms the accessor interfacce to ++ * the keystore ++ */ ++int sm_keystore_slot_alloc(struct device *dev, u32 unit, u32 size, u32 *slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = -EINVAL; ++ ++ spin_lock(&smpriv->kslock); ++ ++ if ((smpriv->slot_alloc == NULL) || ++ (smpriv->pagedesc[unit].ksdata == NULL)) ++ goto out; ++ ++ retval = smpriv->slot_alloc(dev, unit, size, slot); ++ ++out: ++ spin_unlock(&smpriv->kslock); ++ return retval; ++} ++EXPORT_SYMBOL(sm_keystore_slot_alloc); ++ ++int sm_keystore_slot_dealloc(struct device *dev, u32 unit, u32 slot) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = -EINVAL; ++ ++ spin_lock(&smpriv->kslock); ++ ++ if ((smpriv->slot_alloc == NULL) || ++ (smpriv->pagedesc[unit].ksdata == NULL)) ++ goto out; ++ ++ retval = smpriv->slot_dealloc(dev, unit, slot); ++out: ++ spin_unlock(&smpriv->kslock); ++ return retval; ++} ++EXPORT_SYMBOL(sm_keystore_slot_dealloc); ++ ++int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot, ++ const u8 *key_data, u32 key_length) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = -EINVAL; ++ u32 slot_size; ++ u32 i; ++ u8 __iomem *slot_location; ++ ++ spin_lock(&smpriv->kslock); ++ ++ slot_size = smpriv->slot_get_slot_size(dev, unit, slot); ++ ++ if (key_length > slot_size) { ++ retval = -EFBIG; ++ goto out; ++ } ++ ++ slot_location = smpriv->slot_get_address(dev, unit, slot); ++ ++ for (i = 0; i < key_length; i++) ++ slot_location[i] = key_data[i]; ++ ++ retval = 0; ++ ++out: ++ spin_unlock(&smpriv->kslock); ++ return retval; ++} ++EXPORT_SYMBOL(sm_keystore_slot_load); ++ ++int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot, ++ u32 key_length, u8 *key_data) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = -EINVAL; ++ u8 __iomem *slot_addr; ++ u32 slot_size; ++ ++ spin_lock(&smpriv->kslock); ++ ++ slot_addr = smpriv->slot_get_address(dev, unit, slot); ++ slot_size = smpriv->slot_get_slot_size(dev, unit, slot); ++ ++ if (key_length > slot_size) { ++ retval = -EKEYREJECTED; ++ goto out; ++ } ++ ++ memcpy(key_data, slot_addr, key_length); ++ retval = 0; ++ ++out: ++ spin_unlock(&smpriv->kslock); ++ return retval; ++} ++EXPORT_SYMBOL(sm_keystore_slot_read); ++ ++int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot, ++ u32 outslot, u16 secretlen, u8 *keymod, ++ u16 keymodlen) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = 0; ++ u32 slot_length, dsize, jstat; ++ u32 __iomem *encapdesc = NULL; ++ u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; ++ dma_addr_t keymod_dma; ++ ++ /* Ensure that the full blob will fit in the key slot */ ++ slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); ++ if ((secretlen + 48) > slot_length) ++ goto out; ++ ++ /* Get the base addresses of both keystore slots */ ++ inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); ++ outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); ++ ++ /* Build the key modifier */ ++ lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); ++ memcpy(lkeymod, keymod, keymodlen); ++ keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); ++ dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); ++ ++ /* Build the encapsulation job descriptor */ ++ dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen, ++ __pa(inpslotaddr), __pa(outslotaddr), ++ secretlen, 0); ++ if (!dsize) { ++ dev_err(dev, "can't alloc an encap descriptor\n"); ++ retval = -ENOMEM; ++ goto out; ++ } ++ jstat = sm_key_job(dev, encapdesc); ++ ++ dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); ++ kfree(encapdesc); ++ ++out: ++ return retval; ++ ++} ++EXPORT_SYMBOL(sm_keystore_slot_encapsulate); ++ ++int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot, ++ u32 outslot, u16 secretlen, u8 *keymod, ++ u16 keymodlen) ++{ ++ struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev); ++ int retval = 0; ++ u32 slot_length, dsize, jstat; ++ u32 __iomem *decapdesc = NULL; ++ u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr; ++ dma_addr_t keymod_dma; ++ ++ /* Ensure that the decap data will fit in the key slot */ ++ slot_length = smpriv->slot_get_slot_size(dev, unit, outslot); ++ if (secretlen > slot_length) ++ goto out; ++ ++ /* Get the base addresses of both keystore slots */ ++ inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot); ++ outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot); ++ ++ /* Build the key modifier */ ++ lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA); ++ memcpy(lkeymod, keymod, keymodlen); ++ keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE); ++ dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); ++ ++ /* Build the decapsulation job descriptor */ ++ dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen, ++ __pa(inpslotaddr), __pa(outslotaddr), ++ secretlen, 0); ++ if (!dsize) { ++ dev_err(dev, "can't alloc a decap descriptor\n"); ++ retval = -ENOMEM; ++ goto out; ++ } ++ jstat = sm_key_job(dev, decapdesc); ++ ++ dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE); ++ kfree(decapdesc); ++ ++out: ++ return retval; ++ ++} ++EXPORT_SYMBOL(sm_keystore_slot_decapsulate); ++ ++ ++/* ++ * Initialization/shutdown subsystem ++ * Assumes statically-invoked startup/shutdown from the controller driver ++ * for the present time, to be reworked when a device tree becomes ++ * available. This code will not modularize in present form. ++ * ++ * Also, simply uses ring 0 for execution at the present ++ */ ++ ++int caam_sm_startup(struct platform_device *pdev) ++{ ++ struct device *ctrldev, *smdev; ++ struct caam_drv_private *ctrlpriv; ++ struct caam_drv_private_sm *smpriv; ++ struct caam_drv_private_jr *jrpriv; /* need this for reg page */ ++ struct platform_device *sm_pdev; ++ struct sm_page_descriptor *lpagedesc; ++ u32 page, pgstat, lpagect, detectedpage; ++ ++ struct device_node *np; ++ ctrldev = &pdev->dev; ++ ctrlpriv = dev_get_drvdata(ctrldev); ++ ++ /* ++ * Set up the private block for secure memory ++ * Only one instance is possible ++ */ ++ smpriv = kzalloc(sizeof(struct caam_drv_private_sm), GFP_KERNEL); ++ if (smpriv == NULL) { ++ dev_err(ctrldev, "can't alloc private mem for secure memory\n"); ++ return -ENOMEM; ++ } ++ smpriv->parentdev = ctrldev; /* copy of parent dev is handy */ ++ ++ /* Create the dev */ ++#ifdef CONFIG_OF ++ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-caam-sm"); ++ sm_pdev = of_platform_device_create(np, "caam_sm", ctrldev); ++#else ++ sm_pdev = platform_device_register_data(ctrldev, "caam_sm", 0, ++ smpriv, ++ sizeof(struct caam_drv_private_sm)); ++#endif ++ if (sm_pdev == NULL) { ++ kfree(smpriv); ++ return -EINVAL; ++ } ++ smdev = &sm_pdev->dev; ++ dev_set_drvdata(smdev, smpriv); ++ ctrlpriv->smdev = smdev; ++ ++ /* ++ * Collect configuration limit data for reference ++ * This batch comes from the partition data/vid registers in perfmon ++ */ ++ smpriv->max_pages = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) ++ & SMPART_MAX_NUMPG_MASK) >> ++ SMPART_MAX_NUMPG_SHIFT) + 1; ++ smpriv->top_partition = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) ++ & SMPART_MAX_PNUM_MASK) >> ++ SMPART_MAX_PNUM_SHIFT) + 1; ++ smpriv->top_page = ((rd_reg32(&ctrlpriv->ctrl->perfmon.smpart) ++ & SMPART_MAX_PG_MASK) >> SMPART_MAX_PG_SHIFT) + 1; ++ smpriv->page_size = 1024 << ((rd_reg32(&ctrlpriv->ctrl->perfmon.smvid) ++ & SMVID_PG_SIZE_MASK) >> SMVID_PG_SIZE_SHIFT); ++ smpriv->slot_size = 1 << CONFIG_CRYPTO_DEV_FSL_CAAM_SM_SLOTSIZE; ++ ++#ifdef SM_DEBUG ++ dev_info(smdev, "max pages = %d, top partition = %d\n", ++ smpriv->max_pages, smpriv->top_partition); ++ dev_info(smdev, "top page = %d, page size = %d (total = %d)\n", ++ smpriv->top_page, smpriv->page_size, ++ smpriv->top_page * smpriv->page_size); ++ dev_info(smdev, "selected slot size = %d\n", smpriv->slot_size); ++#endif ++ ++ /* ++ * Now probe for partitions/pages to which we have access. Note that ++ * these have likely been set up by a bootloader or platform ++ * provisioning application, so we have to assume that we "inherit" ++ * a configuration and work within the constraints of what it might be. ++ * ++ * Assume use of the zeroth ring in the present iteration (until ++ * we can divorce the controller and ring drivers, and then assign ++ * an SM instance to any ring instance). ++ */ ++ smpriv->smringdev = ctrlpriv->jrdev[0]; ++ jrpriv = dev_get_drvdata(smpriv->smringdev); ++ lpagect = 0; ++ lpagedesc = kzalloc(sizeof(struct sm_page_descriptor) ++ * smpriv->max_pages, GFP_KERNEL); ++ if (lpagedesc == NULL) { ++ kfree(smpriv); ++ return -ENOMEM; ++ } ++ ++ for (page = 0; page < smpriv->max_pages; page++) { ++ wr_reg32(&jrpriv->rregs->sm_cmd, ++ ((page << SMC_PAGE_SHIFT) & SMC_PAGE_MASK) | ++ (SMC_CMD_PAGE_INQUIRY & SMC_CMD_MASK)); ++ pgstat = rd_reg32(&jrpriv->rregs->sm_status); ++ if (((pgstat & SMCS_PGWON_MASK) >> SMCS_PGOWN_SHIFT) ++ == SMCS_PGOWN_OWNED) { /* our page? */ ++ lpagedesc[page].phys_pagenum = ++ (pgstat & SMCS_PAGE_MASK) >> SMCS_PAGE_SHIFT; ++ lpagedesc[page].own_part = ++ (pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK; ++ lpagedesc[page].pg_base = ctrlpriv->sm_base + ++ ((smpriv->page_size * page) / sizeof(u32)); ++ lpagect++; ++#ifdef SM_DEBUG ++ dev_info(smdev, ++ "physical page %d, owning partition = %d\n", ++ lpagedesc[page].phys_pagenum, ++ lpagedesc[page].own_part); ++#endif ++ } ++ } ++ ++ smpriv->pagedesc = kzalloc(sizeof(struct sm_page_descriptor) * lpagect, ++ GFP_KERNEL); ++ if (smpriv->pagedesc == NULL) { ++ kfree(lpagedesc); ++ kfree(smpriv); ++ return -ENOMEM; ++ } ++ smpriv->localpages = lpagect; ++ ++ detectedpage = 0; ++ for (page = 0; page < smpriv->max_pages; page++) { ++ if (lpagedesc[page].pg_base != NULL) { /* e.g. live entry */ ++ memcpy(&smpriv->pagedesc[detectedpage], ++ &lpagedesc[page], ++ sizeof(struct sm_page_descriptor)); ++#ifdef SM_DEBUG_CONT ++ sm_show_page(smdev, &smpriv->pagedesc[detectedpage]); ++#endif ++ detectedpage++; ++ } ++ } ++ ++ kfree(lpagedesc); ++ ++ sm_init_keystore(smdev); ++ ++ return 0; ++} ++ ++void caam_sm_shutdown(struct platform_device *pdev) ++{ ++ struct device *ctrldev, *smdev; ++ struct caam_drv_private *priv; ++ struct caam_drv_private_sm *smpriv; ++ ++ ctrldev = &pdev->dev; ++ priv = dev_get_drvdata(ctrldev); ++ smdev = priv->smdev; ++ smpriv = dev_get_drvdata(smdev); ++ ++ kfree(smpriv->pagedesc); ++ kfree(smpriv); ++} ++EXPORT_SYMBOL(caam_sm_shutdown); ++#ifdef CONFIG_OF ++static void __exit caam_sm_exit(void) ++{ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); ++ if (!dev_node) ++ return; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return; ++ ++ of_node_put(dev_node); ++ ++ caam_sm_shutdown(pdev); ++ ++ return; ++} ++ ++static int __init caam_sm_init(void) ++{ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ /* ++ * Do of_find_compatible_node() then of_find_device_by_node() ++ * once a functional device tree is available ++ */ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); ++ if (!dev_node) ++ return -ENODEV; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return -ENODEV; ++ ++ of_node_get(dev_node); ++ ++ caam_sm_startup(pdev); ++ ++ return 0; ++} ++ ++module_init(caam_sm_init); ++module_exit(caam_sm_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL CAAM Secure Memory / Keystore"); ++MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); ++#endif +diff -Nur linux-3.14.14/drivers/crypto/caam/sm_test.c linux-imx6-3.14/drivers/crypto/caam/sm_test.c +--- linux-3.14.14/drivers/crypto/caam/sm_test.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/sm_test.c 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,844 @@ ++/* ++ * Secure Memory / Keystore Exemplification Module ++ * Copyright (C) 2013 Freescale Semiconductor, Inc. All Rights Reserved ++ * ++ * Serves as a functional example, and as a self-contained unit test for ++ * the functionality contained in sm_store.c. ++ * ++ * The example function, caam_sm_example_init(), runs a thread that: ++ * ++ * - initializes a set of fixed keys ++ * - stores one copy in clear buffers ++ * - stores them again in secure memory ++ * - extracts stored keys back out for use ++ * - intializes 3 data buffers for a test: ++ * (1) containing cleartext ++ * (2) to hold ciphertext encrypted with an extracted black key ++ * (3) to hold extracted cleartext decrypted with an equivalent clear key ++ * ++ * The function then builds simple job descriptors that reference the key ++ * material and buffers as initialized, and executes an encryption job ++ * with a black key, and a decryption job using a the same key held in the ++ * clear. The output of the decryption job is compared to the original ++ * cleartext; if they don't compare correctly, one can assume a key problem ++ * exists, where the function will exit with an error. ++ * ++ * This module can use a substantial amount of refactoring, which may occur ++ * after the API gets some mileage. Furthermore, expect this module to ++ * eventually disappear once the API is integrated into "real" software. ++ */ ++ ++#include "compat.h" ++#include "intern.h" ++#include "desc.h" ++#include "error.h" ++#include "jr.h" ++#include "sm.h" ++ ++static u8 skeymod[] = { ++ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, ++ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 ++}; ++static u8 symkey[] = { ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ++ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f ++}; ++ ++static u8 symdata[] = { ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x0f, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ++ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, ++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, ++ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, ++ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, ++ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, ++ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, ++ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, ++ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, ++ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, ++ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, ++ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, ++ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, ++ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, ++ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, ++ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, ++ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, ++ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, ++ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, ++ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ++ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, ++ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, ++ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ++ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff ++}; ++ ++static int mk_job_desc(u32 *desc, dma_addr_t key, u16 keysz, dma_addr_t indata, ++ dma_addr_t outdata, u16 sz, u32 cipherdir, u32 keymode) ++{ ++ desc[1] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK) | keymode; ++ desc[2] = (u32)key; ++ desc[3] = CMD_OPERATION | OP_TYPE_CLASS1_ALG | OP_ALG_AAI_ECB | ++ cipherdir; ++ desc[4] = CMD_FIFO_LOAD | FIFOLD_CLASS_CLASS1 | ++ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1 | sz; ++ desc[5] = (u32)indata; ++ desc[6] = CMD_FIFO_STORE | FIFOST_TYPE_MESSAGE_DATA | sz; ++ desc[7] = (u32)outdata; ++ ++ desc[0] = CMD_DESC_HDR | HDR_ONE | (8 & HDR_DESCLEN_MASK); ++ return 8 * sizeof(u32); ++} ++ ++struct exec_test_result { ++ int error; ++ struct completion completion; ++}; ++ ++void exec_test_done(struct device *dev, u32 *desc, u32 err, void *context) ++{ ++ struct exec_test_result *res = context; ++ ++ if (err) { ++ char tmp[CAAM_ERROR_STR_MAX]; ++ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); ++ } ++ ++ res->error = err; ++ complete(&res->completion); ++} ++ ++static int exec_test_job(struct device *ksdev, u32 *jobdesc) ++{ ++ struct exec_test_result testres; ++ struct caam_drv_private_sm *kspriv; ++ int rtn = 0; ++ ++ kspriv = dev_get_drvdata(ksdev); ++ ++ init_completion(&testres.completion); ++ ++ rtn = caam_jr_enqueue(kspriv->smringdev, jobdesc, exec_test_done, ++ &testres); ++ if (!rtn) { ++ wait_for_completion_interruptible(&testres.completion); ++ rtn = testres.error; ++ } ++ return rtn; ++} ++ ++ ++int caam_sm_example_init(struct platform_device *pdev) ++{ ++ struct device *ctrldev, *ksdev; ++ struct caam_drv_private *ctrlpriv; ++ struct caam_drv_private_sm *kspriv; ++ u32 unit, units, jdescsz; ++ int stat, jstat, rtnval = 0; ++ u8 __iomem *syminp, *symint, *symout = NULL; ++ dma_addr_t syminp_dma, symint_dma, symout_dma; ++ u8 __iomem *black_key_des, *black_key_aes128; ++ u8 __iomem *black_key_aes256; ++ dma_addr_t black_key_des_dma, black_key_aes128_dma; ++ dma_addr_t black_key_aes256_dma; ++ u8 __iomem *clear_key_des, *clear_key_aes128, *clear_key_aes256; ++ dma_addr_t clear_key_des_dma, clear_key_aes128_dma; ++ dma_addr_t clear_key_aes256_dma; ++ u32 __iomem *jdesc; ++ u32 keyslot_des, keyslot_aes128, keyslot_aes256 = 0; ++ ++ jdesc = NULL; ++ black_key_des = black_key_aes128 = black_key_aes256 = NULL; ++ clear_key_des = clear_key_aes128 = clear_key_aes256 = NULL; ++ ++ /* We can lose this cruft once we can get a pdev by name */ ++ ctrldev = &pdev->dev; ++ ctrlpriv = dev_get_drvdata(ctrldev); ++ ksdev = ctrlpriv->smdev; ++ kspriv = dev_get_drvdata(ksdev); ++ if (kspriv == NULL) ++ return -ENODEV; ++ ++ /* Now that we have the dev for the single SM instance, connect */ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test_init() running\n"); ++#endif ++ /* Probe to see what keystores are available to us */ ++ units = sm_detect_keystore_units(ksdev); ++ if (!units) ++ dev_err(ksdev, "caam_sm_test: no keystore units available\n"); ++ ++ /* ++ * MX6 bootloader stores some stuff in unit 0, so let's ++ * use 1 or above ++ */ ++ if (units < 2) { ++ dev_err(ksdev, "caam_sm_test: insufficient keystore units\n"); ++ return -ENODEV; ++ } ++ unit = 1; ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: %d keystore units available\n", units); ++#endif ++ ++ /* Initialize/Establish Keystore */ ++ sm_establish_keystore(ksdev, unit); /* Initalize store in #1 */ ++ ++ /* ++ * Top of main test thread ++ */ ++ ++ /* Allocate test data blocks (input, intermediate, output) */ ++ syminp = kmalloc(256, GFP_KERNEL | GFP_DMA); ++ symint = kmalloc(256, GFP_KERNEL | GFP_DMA); ++ symout = kmalloc(256, GFP_KERNEL | GFP_DMA); ++ if ((syminp == NULL) || (symint == NULL) || (symout == NULL)) { ++ rtnval = -ENOMEM; ++ dev_err(ksdev, "caam_sm_test: can't get test data buffers\n"); ++ goto freemem; ++ } ++ ++ /* Allocate storage for 3 black keys: encapsulated 8, 16, 32 */ ++ black_key_des = kmalloc(16, GFP_KERNEL | GFP_DMA); /* padded to 16... */ ++ black_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); ++ black_key_aes256 = kmalloc(16, GFP_KERNEL | GFP_DMA); ++ if ((black_key_des == NULL) || (black_key_aes128 == NULL) || ++ (black_key_aes256 == NULL)) { ++ rtnval = -ENOMEM; ++ dev_err(ksdev, "caam_sm_test: can't black key buffers\n"); ++ goto freemem; ++ } ++ ++ clear_key_des = kmalloc(8, GFP_KERNEL | GFP_DMA); ++ clear_key_aes128 = kmalloc(16, GFP_KERNEL | GFP_DMA); ++ clear_key_aes256 = kmalloc(32, GFP_KERNEL | GFP_DMA); ++ if ((clear_key_des == NULL) || (clear_key_aes128 == NULL) || ++ (clear_key_aes256 == NULL)) { ++ rtnval = -ENOMEM; ++ dev_err(ksdev, "caam_sm_test: can't get clear key buffers\n"); ++ goto freemem; ++ } ++ ++ /* Allocate storage for job descriptor */ ++ jdesc = kmalloc(8 * sizeof(u32), GFP_KERNEL | GFP_DMA); ++ if (jdesc == NULL) { ++ rtnval = -ENOMEM; ++ dev_err(ksdev, "caam_sm_test: can't get descriptor buffers\n"); ++ goto freemem; ++ } ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: all buffers allocated\n"); ++#endif ++ ++ /* Load up input data block, clear outputs */ ++ memcpy(syminp, symdata, 256); ++ memset(symint, 0, 256); ++ memset(symout, 0, 256); ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[0], syminp[1], syminp[2], syminp[3], ++ syminp[4], syminp[5], syminp[6], syminp[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[0], symout[1], symout[2], symout[3], ++ symout[4], symout[5], symout[6], symout[7]); ++ ++ dev_info(ksdev, "caam_sm_test: data buffers initialized\n"); ++#endif ++ ++ /* Load up clear keys */ ++ memcpy(clear_key_des, symkey, 8); ++ memcpy(clear_key_aes128, symkey, 16); ++ memcpy(clear_key_aes256, symkey, 32); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: all clear keys loaded\n"); ++#endif ++ ++ /* ++ * Place clear keys in keystore. ++ * All the interesting stuff happens here. ++ */ ++ /* 8 bit DES key */ ++ stat = sm_keystore_slot_alloc(ksdev, unit, 8, &keyslot_des); ++ if (stat) ++ goto freemem; ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: 8 byte key slot in %d\n", keyslot_des); ++#endif ++ stat = sm_keystore_slot_load(ksdev, unit, keyslot_des, clear_key_des, ++ 8); ++ if (stat) { ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: can't load 8 byte key in %d\n", ++ keyslot_des); ++#endif ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ goto freemem; ++ } ++ ++ /* 16 bit AES key */ ++ stat = sm_keystore_slot_alloc(ksdev, unit, 16, &keyslot_aes128); ++ if (stat) { ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ goto freemem; ++ } ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: 16 byte key slot in %d\n", ++ keyslot_aes128); ++#endif ++ stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes128, ++ clear_key_aes128, 16); ++ if (stat) { ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: can't load 16 byte key in %d\n", ++ keyslot_aes128); ++#endif ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ goto freemem; ++ } ++ ++ /* 32 bit AES key */ ++ stat = sm_keystore_slot_alloc(ksdev, unit, 32, &keyslot_aes256); ++ if (stat) { ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ goto freemem; ++ } ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: 32 byte key slot in %d\n", ++ keyslot_aes256); ++#endif ++ stat = sm_keystore_slot_load(ksdev, unit, keyslot_aes256, ++ clear_key_aes256, 32); ++ if (stat) { ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: can't load 32 byte key in %d\n", ++ keyslot_aes128); ++#endif ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); ++ sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ goto freemem; ++ } ++ ++ /* Encapsulate all keys as SM blobs */ ++ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_des, ++ keyslot_des, 8, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't encapsulate DES key\n"); ++ goto freekeys; ++ } ++ ++ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes128, ++ keyslot_aes128, 16, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't encapsulate AES128 key\n"); ++ goto freekeys; ++ } ++ ++ stat = sm_keystore_slot_encapsulate(ksdev, unit, keyslot_aes256, ++ keyslot_aes256, 32, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't encapsulate AES256 key\n"); ++ goto freekeys; ++ } ++ ++ /* Now decapsulate as black key blobs */ ++ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_des, ++ keyslot_des, 8, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't decapsulate DES key\n"); ++ goto freekeys; ++ } ++ ++ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes128, ++ keyslot_aes128, 16, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); ++ goto freekeys; ++ } ++ ++ stat = sm_keystore_slot_decapsulate(ksdev, unit, keyslot_aes256, ++ keyslot_aes256, 32, skeymod, 8); ++ if (stat) { ++ dev_info(ksdev, "caam_sm_test: can't decapsulate AES128 key\n"); ++ goto freekeys; ++ } ++ ++ /* Extract 8/16/32 byte black keys */ ++ sm_keystore_slot_read(ksdev, unit, keyslot_des, 8, black_key_des); ++ sm_keystore_slot_read(ksdev, unit, keyslot_aes128, 16, ++ black_key_aes128); ++ sm_keystore_slot_read(ksdev, unit, keyslot_aes256, 32, ++ black_key_aes256); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: all black keys extracted\n"); ++#endif ++ ++ /* DES encrypt using 8 byte black key */ ++ black_key_des_dma = dma_map_single(ksdev, black_key_des, 8, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); ++ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, black_key_des_dma, 8, syminp_dma, ++ symint_dma, 256, ++ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_DES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, black_key_des_dma, 8, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "input block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[0], syminp[1], syminp[2], syminp[3], ++ syminp[4], syminp[5], syminp[6], syminp[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[8], syminp[9], syminp[10], syminp[11], ++ syminp[12], syminp[13], syminp[14], syminp[15]); ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "caam_sm_test: encrypt cycle with 8 byte key\n"); ++#endif ++ ++ /* DES decrypt using 8 byte clear key */ ++ clear_key_des_dma = dma_map_single(ksdev, clear_key_des, 8, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, clear_key_des_dma, 8, symint_dma, ++ symout_dma, 256, ++ OP_ALG_DECRYPT | OP_ALG_ALGSEL_DES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, clear_key_des_dma, 8, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "decrypted block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[0], symout[1], symout[2], symout[3], ++ symout[4], symout[5], symout[6], symout[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[8], symout[9], symout[10], symout[11], ++ symout[12], symout[13], symout[14], symout[15]); ++ dev_info(ksdev, "caam_sm_test: decrypt cycle with 8 byte key\n"); ++#endif ++ ++ /* Check result */ ++ if (memcmp(symout, syminp, 256)) { ++ dev_info(ksdev, "caam_sm_test: 8-byte key test mismatch\n"); ++ rtnval = -1; ++ goto freekeys; ++ } else ++ dev_info(ksdev, "caam_sm_test: 8-byte key test match OK\n"); ++ ++ /* AES-128 encrypt using 16 byte black key */ ++ black_key_aes128_dma = dma_map_single(ksdev, black_key_aes128, 16, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, black_key_aes128_dma, 16, ++ DMA_TO_DEVICE); ++ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, black_key_aes128_dma, 16, syminp_dma, ++ symint_dma, 256, ++ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, black_key_aes128_dma, 16, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "input block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[0], syminp[1], syminp[2], syminp[3], ++ syminp[4], syminp[5], syminp[6], syminp[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[8], syminp[9], syminp[10], syminp[11], ++ syminp[12], syminp[13], syminp[14], syminp[15]); ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "caam_sm_test: encrypt cycle with 16 byte key\n"); ++#endif ++ ++ /* AES-128 decrypt using 16 byte clear key */ ++ clear_key_aes128_dma = dma_map_single(ksdev, clear_key_aes128, 16, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, clear_key_aes128_dma, 16, ++ DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, clear_key_aes128_dma, 16, symint_dma, ++ symout_dma, 256, ++ OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, clear_key_aes128_dma, 16, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "decrypted block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[0], symout[1], symout[2], symout[3], ++ symout[4], symout[5], symout[6], symout[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[8], symout[9], symout[10], symout[11], ++ symout[12], symout[13], symout[14], symout[15]); ++ dev_info(ksdev, "caam_sm_test: decrypt cycle with 16 byte key\n"); ++#endif ++ ++ /* Check result */ ++ if (memcmp(symout, syminp, 256)) { ++ dev_info(ksdev, "caam_sm_test: 16-byte key test mismatch\n"); ++ rtnval = -1; ++ goto freekeys; ++ } else ++ dev_info(ksdev, "caam_sm_test: 16-byte key test match OK\n"); ++ ++ /* AES-256 encrypt using 32 byte black key */ ++ black_key_aes256_dma = dma_map_single(ksdev, black_key_aes256, 32, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, black_key_aes256_dma, 32, ++ DMA_TO_DEVICE); ++ syminp_dma = dma_map_single(ksdev, syminp, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, black_key_aes256_dma, 32, syminp_dma, ++ symint_dma, 256, ++ OP_ALG_ENCRYPT | OP_ALG_ALGSEL_AES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, syminp_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, black_key_aes256_dma, 32, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "input block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[0], syminp[1], syminp[2], syminp[3], ++ syminp[4], syminp[5], syminp[6], syminp[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ syminp[8], syminp[9], syminp[10], syminp[11], ++ syminp[12], syminp[13], syminp[14], syminp[15]); ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "caam_sm_test: encrypt cycle with 32 byte key\n"); ++#endif ++ ++ /* AES-256 decrypt using 32-byte black key */ ++ clear_key_aes256_dma = dma_map_single(ksdev, clear_key_aes256, 32, ++ DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, clear_key_aes256_dma, 32, ++ DMA_TO_DEVICE); ++ symint_dma = dma_map_single(ksdev, symint, 256, DMA_TO_DEVICE); ++ dma_sync_single_for_device(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ symout_dma = dma_map_single(ksdev, symout, 256, DMA_FROM_DEVICE); ++ ++ jdescsz = mk_job_desc(jdesc, clear_key_aes256_dma, 32, symint_dma, ++ symout_dma, 256, ++ OP_ALG_DECRYPT | OP_ALG_ALGSEL_AES, 0); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "jobdesc:\n"); ++ dev_info(ksdev, "0x%08x\n", jdesc[0]); ++ dev_info(ksdev, "0x%08x\n", jdesc[1]); ++ dev_info(ksdev, "0x%08x\n", jdesc[2]); ++ dev_info(ksdev, "0x%08x\n", jdesc[3]); ++ dev_info(ksdev, "0x%08x\n", jdesc[4]); ++ dev_info(ksdev, "0x%08x\n", jdesc[5]); ++ dev_info(ksdev, "0x%08x\n", jdesc[6]); ++ dev_info(ksdev, "0x%08x\n", jdesc[7]); ++#endif ++ ++ jstat = exec_test_job(ksdev, jdesc); ++ ++ dma_sync_single_for_cpu(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symout_dma, 256, DMA_FROM_DEVICE); ++ dma_unmap_single(ksdev, symint_dma, 256, DMA_TO_DEVICE); ++ dma_unmap_single(ksdev, clear_key_aes256_dma, 32, DMA_TO_DEVICE); ++ ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "intermediate block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[0], symint[1], symint[2], symint[3], ++ symint[4], symint[5], symint[6], symint[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symint[8], symint[9], symint[10], symint[11], ++ symint[12], symint[13], symint[14], symint[15]); ++ dev_info(ksdev, "decrypted block:\n"); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[0], symout[1], symout[2], symout[3], ++ symout[4], symout[5], symout[6], symout[7]); ++ dev_info(ksdev, "0x%02x 0x%02x 0x%02x 0x%02x " \ ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ symout[8], symout[9], symout[10], symout[11], ++ symout[12], symout[13], symout[14], symout[15]); ++ dev_info(ksdev, "caam_sm_test: decrypt cycle with 32 byte key\n"); ++#endif ++ ++ /* Check result */ ++ if (memcmp(symout, syminp, 256)) { ++ dev_info(ksdev, "caam_sm_test: 32-byte key test mismatch\n"); ++ rtnval = -1; ++ goto freekeys; ++ } else ++ dev_info(ksdev, "caam_sm_test: 32-byte key test match OK\n"); ++ ++ ++ /* Remove 8/16/32 byte keys from keystore */ ++freekeys: ++ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_des); ++ if (stat) ++ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", ++ keyslot_des); ++ ++ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes128); ++ if (stat) ++ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", ++ keyslot_aes128); ++ ++ stat = sm_keystore_slot_dealloc(ksdev, unit, keyslot_aes256); ++ if (stat) ++ dev_info(ksdev, "caam_sm_test: can't release slot %d\n", ++ keyslot_aes256); ++ ++ ++ /* Free resources */ ++freemem: ++#ifdef SM_TEST_DETAIL ++ dev_info(ksdev, "caam_sm_test: cleaning up\n"); ++#endif ++ kfree(syminp); ++ kfree(symint); ++ kfree(symout); ++ kfree(clear_key_des); ++ kfree(clear_key_aes128); ++ kfree(clear_key_aes256); ++ kfree(black_key_des); ++ kfree(black_key_aes128); ++ kfree(black_key_aes256); ++ kfree(jdesc); ++ ++ /* Disconnect from keystore and leave */ ++ sm_release_keystore(ksdev, unit); ++ ++ return rtnval; ++} ++EXPORT_SYMBOL(caam_sm_example_init); ++ ++void caam_sm_example_shutdown(void) ++{ ++ /* unused in present version */ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ /* ++ * Do of_find_compatible_node() then of_find_device_by_node() ++ * once a functional device tree is available ++ */ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); ++ if (!dev_node) ++ return; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return; ++ ++ of_node_get(dev_node); ++ ++} ++ ++static int __init caam_sm_test_init(void) ++{ ++ struct device_node *dev_node; ++ struct platform_device *pdev; ++ ++ /* ++ * Do of_find_compatible_node() then of_find_device_by_node() ++ * once a functional device tree is available ++ */ ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); ++ if (!dev_node) { ++ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); ++ if (!dev_node) ++ return -ENODEV; ++ } ++ ++ pdev = of_find_device_by_node(dev_node); ++ if (!pdev) ++ return -ENODEV; ++ ++ of_node_put(dev_node); ++ ++ caam_sm_example_init(pdev); ++ ++ return 0; ++} ++ ++ ++/* Module-based initialization needs to wait for dev tree */ ++#ifdef CONFIG_OF ++module_init(caam_sm_test_init); ++module_exit(caam_sm_example_shutdown); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("FSL CAAM Keystore Usage Example"); ++MODULE_AUTHOR("Freescale Semiconductor - NMSG/MAD"); ++#endif +diff -Nur linux-3.14.14/drivers/crypto/caam/snvsregs.h linux-imx6-3.14/drivers/crypto/caam/snvsregs.h +--- linux-3.14.14/drivers/crypto/caam/snvsregs.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/crypto/caam/snvsregs.h 2014-12-08 00:31:52.552418001 -0600 +@@ -0,0 +1,237 @@ ++/* ++ * SNVS hardware register-level view ++ * ++ * Copyright (C) 2013 Freescale Semiconductor, Inc., All Rights Reserved ++ */ ++ ++#ifndef SNVSREGS_H ++#define SNVSREGS_H ++ ++#include ++#include ++ ++/* ++ * SNVS High Power Domain ++ * Includes security violations, HA counter, RTC, alarm ++ */ ++struct snvs_hp { ++ u32 lock; ++ u32 cmd; ++ u32 ctl; ++ u32 secvio_int_en; /* Security Violation Interrupt Enable */ ++ u32 secvio_int_ctl; /* Security Violation Interrupt Control */ ++ u32 status; ++ u32 secvio_status; /* Security Violation Status */ ++ u32 ha_counteriv; /* High Assurance Counter IV */ ++ u32 ha_counter; /* High Assurance Counter */ ++ u32 rtc_msb; /* Real Time Clock/Counter MSB */ ++ u32 rtc_lsb; /* Real Time Counter LSB */ ++ u32 time_alarm_msb; /* Time Alarm MSB */ ++ u32 time_alarm_lsb; /* Time Alarm LSB */ ++}; ++ ++#define HP_LOCK_HAC_LCK 0x00040000 ++#define HP_LOCK_HPSICR_LCK 0x00020000 ++#define HP_LOCK_HPSVCR_LCK 0x00010000 ++#define HP_LOCK_MKEYSEL_LCK 0x00000200 ++#define HP_LOCK_TAMPCFG_LCK 0x00000100 ++#define HP_LOCK_TAMPFLT_LCK 0x00000080 ++#define HP_LOCK_SECVIO_LCK 0x00000040 ++#define HP_LOCK_GENP_LCK 0x00000020 ++#define HP_LOCK_MONOCTR_LCK 0x00000010 ++#define HP_LOCK_CALIB_LCK 0x00000008 ++#define HP_LOCK_SRTC_LCK 0x00000004 ++#define HP_LOCK_ZMK_RD_LCK 0x00000002 ++#define HP_LOCK_ZMK_WT_LCK 0x00000001 ++ ++#define HP_CMD_NONPRIV_AXS 0x80000000 ++#define HP_CMD_HAC_STOP 0x00080000 ++#define HP_CMD_HAC_CLEAR 0x00040000 ++#define HP_CMD_HAC_LOAD 0x00020000 ++#define HP_CMD_HAC_CFG_EN 0x00010000 ++#define HP_CMD_SNVS_MSTR_KEY 0x00002000 ++#define HP_CMD_PROG_ZMK 0x00001000 ++#define HP_CMD_SW_LPSV 0x00000400 ++#define HP_CMD_SW_FSV 0x00000200 ++#define HP_CMD_SW_SV 0x00000100 ++#define HP_CMD_LP_SWR_DIS 0x00000020 ++#define HP_CMD_LP_SWR 0x00000010 ++#define HP_CMD_SSM_SFNS_DIS 0x00000004 ++#define HP_CMD_SSM_ST_DIS 0x00000002 ++#define HP_CMD_SMM_ST 0x00000001 ++ ++#define HP_CTL_TIME_SYNC 0x00010000 ++#define HP_CTL_CAL_VAL_SHIFT 10 ++#define HP_CTL_CAL_VAL_MASK (0x1f << HP_CTL_CALIB_SHIFT) ++#define HP_CTL_CALIB_EN 0x00000100 ++#define HP_CTL_PI_FREQ_SHIFT 4 ++#define HP_CTL_PI_FREQ_MASK (0xf << HP_CTL_PI_FREQ_SHIFT) ++#define HP_CTL_PI_EN 0x00000008 ++#define HP_CTL_TIMEALARM_EN 0x00000002 ++#define HP_CTL_RTC_EN 0x00000001 ++ ++#define HP_SECVIO_INTEN_EN 0x10000000 ++#define HP_SECVIO_INTEN_SRC5 0x00000020 ++#define HP_SECVIO_INTEN_SRC4 0x00000010 ++#define HP_SECVIO_INTEN_SRC3 0x00000008 ++#define HP_SECVIO_INTEN_SRC2 0x00000004 ++#define HP_SECVIO_INTEN_SRC1 0x00000002 ++#define HP_SECVIO_INTEN_SRC0 0x00000001 ++#define HP_SECVIO_INTEN_ALL 0x8000003f ++ ++#define HP_SECVIO_ICTL_CFG_SHIFT 30 ++#define HP_SECVIO_ICTL_CFG_MASK (0x3 << HP_SECVIO_ICTL_CFG_SHIFT) ++#define HP_SECVIO_ICTL_CFG5_SHIFT 5 ++#define HP_SECVIO_ICTL_CFG5_MASK (0x3 << HP_SECVIO_ICTL_CFG5_SHIFT) ++#define HP_SECVIO_ICTL_CFG_DISABLE 0 ++#define HP_SECVIO_ICTL_CFG_NONFATAL 1 ++#define HP_SECVIO_ICTL_CFG_FATAL 2 ++#define HP_SECVIO_ICTL_CFG4_FATAL 0x00000010 ++#define HP_SECVIO_ICTL_CFG3_FATAL 0x00000008 ++#define HP_SECVIO_ICTL_CFG2_FATAL 0x00000004 ++#define HP_SECVIO_ICTL_CFG1_FATAL 0x00000002 ++#define HP_SECVIO_ICTL_CFG0_FATAL 0x00000001 ++ ++#define HP_STATUS_ZMK_ZERO 0x80000000 ++#define HP_STATUS_OTPMK_ZERO 0x08000000 ++#define HP_STATUS_OTPMK_SYN_SHIFT 16 ++#define HP_STATUS_OTPMK_SYN_MASK (0x1ff << HP_STATUS_OTPMK_SYN_SHIFT) ++#define HP_STATUS_SSM_ST_SHIFT 8 ++#define HP_STATUS_SSM_ST_MASK (0xf << HP_STATUS_SSM_ST_SHIFT) ++#define HP_STATUS_SSM_ST_INIT 0 ++#define HP_STATUS_SSM_ST_HARDFAIL 1 ++#define HP_STATUS_SSM_ST_SOFTFAIL 3 ++#define HP_STATUS_SSM_ST_INITINT 8 ++#define HP_STATUS_SSM_ST_CHECK 9 ++#define HP_STATUS_SSM_ST_NONSECURE 11 ++#define HP_STATUS_SSM_ST_TRUSTED 13 ++#define HP_STATUS_SSM_ST_SECURE 15 ++ ++#define HP_SECVIOST_ZMK_ECC_FAIL 0x08000000 /* write to clear */ ++#define HP_SECVIOST_ZMK_SYN_SHIFT 16 ++#define HP_SECVIOST_ZMK_SYN_MASK (0x1ff << HP_SECVIOST_ZMK_SYN_SHIFT) ++#define HP_SECVIOST_SECVIO5 0x00000020 ++#define HP_SECVIOST_SECVIO4 0x00000010 ++#define HP_SECVIOST_SECVIO3 0x00000008 ++#define HP_SECVIOST_SECVIO2 0x00000004 ++#define HP_SECVIOST_SECVIO1 0x00000002 ++#define HP_SECVIOST_SECVIO0 0x00000001 ++#define HP_SECVIOST_SECVIOMASK 0x0000003f ++ ++/* ++ * SNVS Low Power Domain ++ * Includes glitch detector, SRTC, alarm, monotonic counter, ZMK ++ */ ++struct snvs_lp { ++ u32 lock; ++ u32 ctl; ++ u32 mstr_key_ctl; /* Master Key Control */ ++ u32 secvio_ctl; /* Security Violation Control */ ++ u32 tamper_filt_cfg; /* Tamper Glitch Filters Configuration */ ++ u32 tamper_det_cfg; /* Tamper Detectors Configuration */ ++ u32 status; ++ u32 srtc_msb; /* Secure Real Time Clock/Counter MSB */ ++ u32 srtc_lsb; /* Secure Real Time Clock/Counter LSB */ ++ u32 time_alarm; /* Time Alarm */ ++ u32 smc_msb; /* Secure Monotonic Counter MSB */ ++ u32 smc_lsb; /* Secure Monotonic Counter LSB */ ++ u32 pwr_glitch_det; /* Power Glitch Detector */ ++ u32 gen_purpose; ++ u32 zmk[8]; /* Zeroizable Master Key */ ++}; ++ ++#define LP_LOCK_MKEYSEL_LCK 0x00000200 ++#define LP_LOCK_TAMPDET_LCK 0x00000100 ++#define LP_LOCK_TAMPFLT_LCK 0x00000080 ++#define LP_LOCK_SECVIO_LCK 0x00000040 ++#define LP_LOCK_GENP_LCK 0x00000020 ++#define LP_LOCK_MONOCTR_LCK 0x00000010 ++#define LP_LOCK_CALIB_LCK 0x00000008 ++#define LP_LOCK_SRTC_LCK 0x00000004 ++#define LP_LOCK_ZMK_RD_LCK 0x00000002 ++#define LP_LOCK_ZMK_WT_LCK 0x00000001 ++ ++#define LP_CTL_CAL_VAL_SHIFT 10 ++#define LP_CTL_CAL_VAL_MASK (0x1f << LP_CTL_CAL_VAL_SHIFT) ++#define LP_CTL_CALIB_EN 0x00000100 ++#define LP_CTL_SRTC_INVAL_EN 0x00000010 ++#define LP_CTL_WAKE_INT_EN 0x00000008 ++#define LP_CTL_MONOCTR_EN 0x00000004 ++#define LP_CTL_TIMEALARM_EN 0x00000002 ++#define LP_CTL_SRTC_EN 0x00000001 ++ ++#define LP_MKEYCTL_ZMKECC_SHIFT 8 ++#define LP_MKEYCTL_ZMKECC_MASK (0xff << LP_MKEYCTL_ZMKECC_SHIFT) ++#define LP_MKEYCTL_ZMKECC_EN 0x00000010 ++#define LP_MKEYCTL_ZMKECC_VAL 0x00000008 ++#define LP_MKEYCTL_ZMKECC_PROG 0x00000004 ++#define LP_MKEYCTL_MKSEL_SHIFT 0 ++#define LP_MKEYCTL_MKSEL_MASK (3 << LP_MKEYCTL_MKSEL_SHIFT) ++#define LP_MKEYCTL_MK_OTP 0 ++#define LP_MKEYCTL_MK_ZMK 2 ++#define LP_MKEYCTL_MK_COMB 3 ++ ++#define LP_SECVIO_CTL_SRC5 0x20 ++#define LP_SECVIO_CTL_SRC4 0x10 ++#define LP_SECVIO_CTL_SRC3 0x08 ++#define LP_SECVIO_CTL_SRC2 0x04 ++#define LP_SECVIO_CTL_SRC1 0x02 ++#define LP_SECVIO_CTL_SRC0 0x01 ++ ++#define LP_TAMPFILT_EXT2_EN 0x80000000 ++#define LP_TAMPFILT_EXT2_SHIFT 24 ++#define LP_TAMPFILT_EXT2_MASK (0x1f << LP_TAMPFILT_EXT2_SHIFT) ++#define LP_TAMPFILT_EXT1_EN 0x00800000 ++#define LP_TAMPFILT_EXT1_SHIFT 16 ++#define LP_TAMPFILT_EXT1_MASK (0x1f << LP_TAMPFILT_EXT1_SHIFT) ++#define LP_TAMPFILT_WM_EN 0x00000080 ++#define LP_TAMPFILT_WM_SHIFT 0 ++#define LP_TAMPFILT_WM_MASK (0x1f << LP_TAMPFILT_WM_SHIFT) ++ ++#define LP_TAMPDET_OSC_BPS 0x10000000 ++#define LP_TAMPDET_VRC_SHIFT 24 ++#define LP_TAMPDET_VRC_MASK (3 << LP_TAMPFILT_VRC_SHIFT) ++#define LP_TAMPDET_HTDC_SHIFT 20 ++#define LP_TAMPDET_HTDC_MASK (3 << LP_TAMPFILT_HTDC_SHIFT) ++#define LP_TAMPDET_LTDC_SHIFT 16 ++#define LP_TAMPDET_LTDC_MASK (3 << LP_TAMPFILT_LTDC_SHIFT) ++#define LP_TAMPDET_POR_OBS 0x00008000 ++#define LP_TAMPDET_PFD_OBS 0x00004000 ++#define LP_TAMPDET_ET2_EN 0x00000400 ++#define LP_TAMPDET_ET1_EN 0x00000200 ++#define LP_TAMPDET_WMT2_EN 0x00000100 ++#define LP_TAMPDET_WMT1_EN 0x00000080 ++#define LP_TAMPDET_VT_EN 0x00000040 ++#define LP_TAMPDET_TT_EN 0x00000020 ++#define LP_TAMPDET_CT_EN 0x00000010 ++#define LP_TAMPDET_MCR_EN 0x00000004 ++#define LP_TAMPDET_SRTCR_EN 0x00000002 ++ ++#define LP_STATUS_SECURE ++#define LP_STATUS_NONSECURE ++#define LP_STATUS_SCANEXIT 0x00100000 /* all write 1 clear here on */ ++#define LP_STATUS_EXT_SECVIO 0x00010000 ++#define LP_STATUS_ET2 0x00000400 ++#define LP_STATUS_ET1 0x00000200 ++#define LP_STATUS_WMT2 0x00000100 ++#define LP_STATUS_WMT1 0x00000080 ++#define LP_STATUS_VTD 0x00000040 ++#define LP_STATUS_TTD 0x00000020 ++#define LP_STATUS_CTD 0x00000010 ++#define LP_STATUS_PGD 0x00000008 ++#define LP_STATUS_MCR 0x00000004 ++#define LP_STATUS_SRTCR 0x00000002 ++#define LP_STATUS_LPTA 0x00000001 ++ ++/* Full SNVS register page, including version/options */ ++struct snvs_full { ++ struct snvs_hp hp; ++ struct snvs_lp lp; ++ u32 rsvd[731]; /* deadspace 0x08c-0xbf7 */ ++ ++ /* Version / Revision / Option ID space - end of register page */ ++ u32 vid; /* 0xbf8 HP Version ID (VID 1) */ ++ u32 opt_rev; /* 0xbfc HP Options / Revision (VID 2) */ ++}; ++ ++#endif /* SNVSREGS_H */ +diff -Nur linux-3.14.14/drivers/dma/imx-sdma.c linux-imx6-3.14/drivers/dma/imx-sdma.c +--- linux-3.14.14/drivers/dma/imx-sdma.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/dma/imx-sdma.c 2014-12-08 00:31:52.568418001 -0600 +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -232,6 +233,14 @@ + + struct sdma_engine; + ++enum sdma_mode { ++ SDMA_MODE_INVALID = 0, ++ SDMA_MODE_LOOP, ++ SDMA_MODE_NORMAL, ++ SDMA_MODE_P2P, ++ SDMA_MODE_NO_BD, ++}; ++ + /** + * struct sdma_channel - housekeeping for a SDMA channel + * +@@ -244,6 +253,7 @@ + * @word_size peripheral access size + * @buf_tail ID of the buffer that was processed + * @num_bd max NUM_BD. number of descriptors currently handling ++ * @bd_iram flag indicating the memory location of buffer descriptor + */ + struct sdma_channel { + struct sdma_engine *sdma; +@@ -255,14 +265,19 @@ + enum dma_slave_buswidth word_size; + unsigned int buf_tail; + unsigned int num_bd; ++ unsigned int period_len; + struct sdma_buffer_descriptor *bd; + dma_addr_t bd_phys; ++ bool bd_iram; + unsigned int pc_from_device, pc_to_device; +- unsigned long flags; +- dma_addr_t per_address; ++ unsigned int device_to_device; ++ unsigned int other_script; ++ enum sdma_mode mode; ++ dma_addr_t per_address, per_address2; + unsigned long event_mask[2]; + unsigned long watermark_level; + u32 shp_addr, per_addr; ++ u32 data_addr1, data_addr2; + struct dma_chan chan; + spinlock_t lock; + struct dma_async_tx_descriptor desc; +@@ -272,8 +287,6 @@ + struct tasklet_struct tasklet; + }; + +-#define IMX_DMA_SG_LOOP BIT(0) +- + #define MAX_DMA_CHANNELS 32 + #define MXC_SDMA_DEFAULT_PRIORITY 1 + #define MXC_SDMA_MIN_PRIORITY 1 +@@ -325,6 +338,7 @@ + spinlock_t channel_0_lock; + u32 script_number; + struct sdma_script_start_addrs *script_addrs; ++ struct gen_pool *iram_pool; + const struct sdma_driver_data *drvdata; + }; + +@@ -540,12 +554,14 @@ + dma_addr_t buf_phys; + int ret; + unsigned long flags; ++ bool use_iram = true; + +- buf_virt = dma_alloc_coherent(NULL, +- size, +- &buf_phys, GFP_KERNEL); ++ buf_virt = gen_pool_dma_alloc(sdma->iram_pool, size, &buf_phys); + if (!buf_virt) { +- return -ENOMEM; ++ use_iram = false; ++ buf_virt = dma_alloc_coherent(NULL, size, &buf_phys, GFP_KERNEL); ++ if (!buf_virt) ++ return -ENOMEM; + } + + spin_lock_irqsave(&sdma->channel_0_lock, flags); +@@ -562,7 +578,10 @@ + + spin_unlock_irqrestore(&sdma->channel_0_lock, flags); + +- dma_free_coherent(NULL, size, buf_virt, buf_phys); ++ if (use_iram) ++ gen_pool_free(sdma->iram_pool, (unsigned long)buf_virt, size); ++ else ++ dma_free_coherent(NULL, size, buf_virt, buf_phys); + + return ret; + } +@@ -593,6 +612,12 @@ + + static void sdma_handle_channel_loop(struct sdma_channel *sdmac) + { ++ if (sdmac->desc.callback) ++ sdmac->desc.callback(sdmac->desc.callback_param); ++} ++ ++static void sdma_update_channel_loop(struct sdma_channel *sdmac) ++{ + struct sdma_buffer_descriptor *bd; + + /* +@@ -607,15 +632,10 @@ + + if (bd->mode.status & BD_RROR) + sdmac->status = DMA_ERROR; +- else +- sdmac->status = DMA_IN_PROGRESS; + + bd->mode.status |= BD_DONE; + sdmac->buf_tail++; + sdmac->buf_tail %= sdmac->num_bd; +- +- if (sdmac->desc.callback) +- sdmac->desc.callback(sdmac->desc.callback_param); + } + } + +@@ -647,14 +667,31 @@ + sdmac->desc.callback(sdmac->desc.callback_param); + } + ++static void sdma_handle_other_intr(struct sdma_channel *sdmac) ++{ ++ if (sdmac->desc.callback) ++ sdmac->desc.callback(sdmac->desc.callback_param); ++} ++ + static void sdma_tasklet(unsigned long data) + { + struct sdma_channel *sdmac = (struct sdma_channel *) data; ++ struct sdma_engine *sdma = sdmac->sdma; + +- if (sdmac->flags & IMX_DMA_SG_LOOP) ++ switch (sdmac->mode) { ++ case SDMA_MODE_LOOP: + sdma_handle_channel_loop(sdmac); +- else ++ break; ++ case SDMA_MODE_NORMAL: + mxc_sdma_handle_channel_normal(sdmac); ++ break; ++ case SDMA_MODE_NO_BD: ++ sdma_handle_other_intr(sdmac); ++ break; ++ default: ++ dev_err(sdma->dev, "invalid SDMA MODE!\n"); ++ break; ++ } + } + + static irqreturn_t sdma_int_handler(int irq, void *dev_id) +@@ -671,6 +708,9 @@ + int channel = fls(stat) - 1; + struct sdma_channel *sdmac = &sdma->channel[channel]; + ++ if (sdmac->mode & SDMA_MODE_LOOP) ++ sdma_update_channel_loop(sdmac); ++ + tasklet_schedule(&sdmac->tasklet); + + __clear_bit(channel, &stat); +@@ -692,9 +732,12 @@ + * two peripherals or memory-to-memory transfers + */ + int per_2_per = 0, emi_2_emi = 0; ++ int other = 0; + + sdmac->pc_from_device = 0; + sdmac->pc_to_device = 0; ++ sdmac->device_to_device = 0; ++ sdmac->other_script = 0; + + switch (peripheral_type) { + case IMX_DMATYPE_MEMORY: +@@ -740,8 +783,8 @@ + emi_2_per = sdma->script_addrs->mcu_2_shp_addr; + break; + case IMX_DMATYPE_ASRC: +- per_2_emi = sdma->script_addrs->asrc_2_mcu_addr; +- emi_2_per = sdma->script_addrs->asrc_2_mcu_addr; ++ per_2_emi = sdma->script_addrs->shp_2_mcu_addr; ++ emi_2_per = sdma->script_addrs->mcu_2_shp_addr; + per_2_per = sdma->script_addrs->per_2_per_addr; + break; + case IMX_DMATYPE_MSHC: +@@ -758,12 +801,17 @@ + case IMX_DMATYPE_IPU_MEMORY: + emi_2_per = sdma->script_addrs->ext_mem_2_ipu_addr; + break; ++ case IMX_DMATYPE_HDMI: ++ other = sdma->script_addrs->hdmi_dma_addr; ++ break; + default: + break; + } + + sdmac->pc_from_device = per_2_emi; + sdmac->pc_to_device = emi_2_per; ++ sdmac->device_to_device = per_2_per; ++ sdmac->other_script = other; + } + + static int sdma_load_context(struct sdma_channel *sdmac) +@@ -776,11 +824,14 @@ + int ret; + unsigned long flags; + +- if (sdmac->direction == DMA_DEV_TO_MEM) { ++ if (sdmac->direction == DMA_DEV_TO_MEM) + load_address = sdmac->pc_from_device; +- } else { ++ else if (sdmac->direction == DMA_DEV_TO_DEV) ++ load_address = sdmac->device_to_device; ++ else if (sdmac->direction == DMA_MEM_TO_DEV) + load_address = sdmac->pc_to_device; +- } ++ else ++ load_address = sdmac->other_script; + + if (load_address < 0) + return load_address; +@@ -800,11 +851,16 @@ + /* Send by context the event mask,base address for peripheral + * and watermark level + */ +- context->gReg[0] = sdmac->event_mask[1]; +- context->gReg[1] = sdmac->event_mask[0]; +- context->gReg[2] = sdmac->per_addr; +- context->gReg[6] = sdmac->shp_addr; +- context->gReg[7] = sdmac->watermark_level; ++ if (sdmac->peripheral_type == IMX_DMATYPE_HDMI) { ++ context->gReg[4] = sdmac->data_addr1; ++ context->gReg[6] = sdmac->data_addr2; ++ } else { ++ context->gReg[0] = sdmac->event_mask[1]; ++ context->gReg[1] = sdmac->event_mask[0]; ++ context->gReg[2] = sdmac->per_addr; ++ context->gReg[6] = sdmac->shp_addr; ++ context->gReg[7] = sdmac->watermark_level; ++ } + + bd0->mode.command = C0_SETDM; + bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; +@@ -829,6 +885,7 @@ + + static int sdma_config_channel(struct sdma_channel *sdmac) + { ++ struct imx_dma_data *data = sdmac->chan.private; + int ret; + + sdma_disable_channel(sdmac); +@@ -837,12 +894,19 @@ + sdmac->event_mask[1] = 0; + sdmac->shp_addr = 0; + sdmac->per_addr = 0; ++ sdmac->data_addr1 = 0; ++ sdmac->data_addr2 = 0; + + if (sdmac->event_id0) { + if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events) + return -EINVAL; + sdma_event_enable(sdmac, sdmac->event_id0); + } ++ if (sdmac->event_id1) { ++ if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events) ++ return -EINVAL; ++ sdma_event_enable(sdmac, sdmac->event_id1); ++ } + + switch (sdmac->peripheral_type) { + case IMX_DMATYPE_DSP: +@@ -862,19 +926,75 @@ + (sdmac->peripheral_type != IMX_DMATYPE_DSP)) { + /* Handle multiple event channels differently */ + if (sdmac->event_id1) { +- sdmac->event_mask[1] = BIT(sdmac->event_id1 % 32); +- if (sdmac->event_id1 > 31) +- __set_bit(31, &sdmac->watermark_level); +- sdmac->event_mask[0] = BIT(sdmac->event_id0 % 32); +- if (sdmac->event_id0 > 31) +- __set_bit(30, &sdmac->watermark_level); ++ if (sdmac->event_id0 > 31) { ++ sdmac->event_mask[0] |= 0; ++ __set_bit(28, &sdmac->watermark_level); ++ sdmac->event_mask[1] |= ++ BIT(sdmac->event_id0 % 32); ++ } else { ++ sdmac->event_mask[1] |= 0; ++ sdmac->event_mask[0] |= ++ BIT(sdmac->event_id0 % 32); ++ } ++ if (sdmac->event_id1 > 31) { ++ sdmac->event_mask[0] |= 0; ++ __set_bit(29, &sdmac->watermark_level); ++ sdmac->event_mask[1] |= ++ BIT(sdmac->event_id1 % 32); ++ } else { ++ sdmac->event_mask[1] |= 0; ++ sdmac->event_mask[0] |= ++ BIT(sdmac->event_id1 % 32); ++ } ++ /* BIT 11: ++ * 1 : Source on SPBA ++ * 0 : Source on AIPS ++ */ ++ __set_bit(11, &sdmac->watermark_level); ++ /* BIT 12: ++ * 1 : Destination on SPBA ++ * 0 : Destination on AIPS ++ */ ++ __set_bit(12, &sdmac->watermark_level); ++ __set_bit(31, &sdmac->watermark_level); ++ /* BIT 31: ++ * 1 : Amount of samples to be transferred is ++ * unknown and script will keep on transferring ++ * samples as long as both events are detected ++ * and script must be manually stopped by the ++ * application. ++ * 0 : The amount of samples to be is equal to ++ * the count field of mode word ++ * */ ++ __set_bit(25, &sdmac->watermark_level); ++ __clear_bit(24, &sdmac->watermark_level); + } else { +- __set_bit(sdmac->event_id0, sdmac->event_mask); ++ if (sdmac->event_id0 > 31) { ++ sdmac->event_mask[0] = 0; ++ sdmac->event_mask[1] |= ++ BIT(sdmac->event_id0 % 32); ++ } else { ++ sdmac->event_mask[0] |= ++ BIT(sdmac->event_id0 % 32); ++ sdmac->event_mask[1] = 0; ++ } + } + /* Watermark Level */ + sdmac->watermark_level |= sdmac->watermark_level; + /* Address */ +- sdmac->shp_addr = sdmac->per_address; ++ if (sdmac->direction == DMA_DEV_TO_DEV) { ++ sdmac->shp_addr = sdmac->per_address2; ++ sdmac->per_addr = sdmac->per_address; ++ } else if (sdmac->direction == DMA_TRANS_NONE) { ++ if (sdmac->peripheral_type != IMX_DMATYPE_HDMI || ++ !data->data_addr1 || !data->data_addr2) ++ return -EINVAL; ++ sdmac->data_addr1 = *(u32 *)data->data_addr1; ++ sdmac->data_addr2 = *(u32 *)data->data_addr2; ++ sdmac->watermark_level = 0; ++ } else { ++ sdmac->shp_addr = sdmac->per_address; ++ } + } else { + sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */ + } +@@ -906,10 +1026,15 @@ + int channel = sdmac->channel; + int ret = -EBUSY; + +- sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL); ++ sdmac->bd_iram = true; ++ sdmac->bd = gen_pool_dma_alloc(sdma->iram_pool, PAGE_SIZE, &sdmac->bd_phys); + if (!sdmac->bd) { +- ret = -ENOMEM; +- goto out; ++ sdmac->bd_iram = false; ++ sdmac->bd = dma_alloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, GFP_KERNEL); ++ if (!sdmac->bd) { ++ ret = -ENOMEM; ++ goto out; ++ } + } + + memset(sdmac->bd, 0, PAGE_SIZE); +@@ -967,7 +1092,8 @@ + } + + sdmac->peripheral_type = data->peripheral_type; +- sdmac->event_id0 = data->dma_request; ++ sdmac->event_id0 = data->dma_request0; ++ sdmac->event_id1 = data->dma_request1; + + clk_enable(sdmac->sdma->clk_ipg); + clk_enable(sdmac->sdma->clk_ahb); +@@ -985,6 +1111,9 @@ + /* txd.flags will be overwritten in prep funcs */ + sdmac->desc.flags = DMA_CTRL_ACK; + ++ /* Set SDMA channel mode to unvalid to avoid misconfig */ ++ sdmac->mode = SDMA_MODE_INVALID; ++ + return 0; + } + +@@ -1005,7 +1134,10 @@ + + sdma_set_channel_priority(sdmac, 0); + +- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); ++ if (sdmac->bd_iram) ++ gen_pool_free(sdma->iram_pool, (unsigned long)sdmac->bd, PAGE_SIZE); ++ else ++ dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); + + clk_disable(sdma->clk_ipg); + clk_disable(sdma->clk_ahb); +@@ -1026,7 +1158,7 @@ + return NULL; + sdmac->status = DMA_IN_PROGRESS; + +- sdmac->flags = 0; ++ sdmac->mode = SDMA_MODE_NORMAL; + + sdmac->buf_tail = 0; + +@@ -1119,9 +1251,9 @@ + { + struct sdma_channel *sdmac = to_sdma_chan(chan); + struct sdma_engine *sdma = sdmac->sdma; +- int num_periods = buf_len / period_len; + int channel = sdmac->channel; + int ret, i = 0, buf = 0; ++ int num_periods; + + dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); + +@@ -1131,13 +1263,35 @@ + sdmac->status = DMA_IN_PROGRESS; + + sdmac->buf_tail = 0; ++ sdmac->period_len = period_len; + +- sdmac->flags |= IMX_DMA_SG_LOOP; + sdmac->direction = direction; ++ ++ switch (sdmac->direction) { ++ case DMA_DEV_TO_DEV: ++ sdmac->mode = SDMA_MODE_P2P; ++ break; ++ case DMA_TRANS_NONE: ++ sdmac->mode = SDMA_MODE_NO_BD; ++ break; ++ case DMA_MEM_TO_DEV: ++ case DMA_DEV_TO_MEM: ++ sdmac->mode = SDMA_MODE_LOOP; ++ break; ++ default: ++ dev_err(sdma->dev, "invalid SDMA direction %d\n", direction); ++ return NULL; ++ } ++ + ret = sdma_load_context(sdmac); + if (ret) + goto err_out; + ++ if (period_len) ++ num_periods = buf_len / period_len; ++ else ++ return &sdmac->desc; ++ + if (num_periods > NUM_BD) { + dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n", + channel, num_periods, NUM_BD); +@@ -1202,18 +1356,31 @@ + sdma_disable_channel(sdmac); + return 0; + case DMA_SLAVE_CONFIG: +- if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { ++ if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) { ++ sdmac->per_address = dmaengine_cfg->src_addr; ++ sdmac->per_address2 = dmaengine_cfg->dst_addr; ++ sdmac->watermark_level = 0; ++ sdmac->watermark_level |= ++ dmaengine_cfg->src_maxburst; ++ sdmac->watermark_level |= ++ dmaengine_cfg->dst_maxburst << 16; ++ sdmac->word_size = dmaengine_cfg->dst_addr_width; ++ } else if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) { + sdmac->per_address = dmaengine_cfg->src_addr; + sdmac->watermark_level = dmaengine_cfg->src_maxburst * + dmaengine_cfg->src_addr_width; + sdmac->word_size = dmaengine_cfg->src_addr_width; +- } else { ++ } else if (dmaengine_cfg->direction == DMA_MEM_TO_DEV) { + sdmac->per_address = dmaengine_cfg->dst_addr; + sdmac->watermark_level = dmaengine_cfg->dst_maxburst * + dmaengine_cfg->dst_addr_width; + sdmac->word_size = dmaengine_cfg->dst_addr_width; + } + sdmac->direction = dmaengine_cfg->direction; ++ if (dmaengine_cfg->dma_request0) ++ sdmac->event_id0 = dmaengine_cfg->dma_request0; ++ if (dmaengine_cfg->dma_request1) ++ sdmac->event_id1 = dmaengine_cfg->dma_request1; + return sdma_config_channel(sdmac); + default: + return -ENOSYS; +@@ -1227,9 +1394,15 @@ + struct dma_tx_state *txstate) + { + struct sdma_channel *sdmac = to_sdma_chan(chan); ++ u32 residue; ++ ++ if (sdmac->mode & SDMA_MODE_LOOP) ++ residue = (sdmac->num_bd - sdmac->buf_tail) * sdmac->period_len; ++ else ++ residue = sdmac->chn_count - sdmac->chn_real_count; + + dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, +- sdmac->chn_count - sdmac->chn_real_count); ++ residue); + + return sdmac->status; + } +@@ -1285,7 +1458,10 @@ + goto err_firmware; + switch (header->version_major) { + case 1: +- sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; ++ if (header->version_minor > 0) ++ sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; ++ else ++ sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1; + break; + case 2: + sdma->script_number = SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V2; +@@ -1331,7 +1507,7 @@ + + static int __init sdma_init(struct sdma_engine *sdma) + { +- int i, ret; ++ int i, ret, ccbsize; + dma_addr_t ccb_phys; + + clk_enable(sdma->clk_ipg); +@@ -1340,14 +1516,17 @@ + /* Be sure SDMA has not started yet */ + writel_relaxed(0, sdma->regs + SDMA_H_C0PTR); + +- sdma->channel_control = dma_alloc_coherent(NULL, +- MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) + +- sizeof(struct sdma_context_data), +- &ccb_phys, GFP_KERNEL); ++ ccbsize = MAX_DMA_CHANNELS * sizeof (struct sdma_channel_control) ++ + sizeof(struct sdma_context_data); + ++ sdma->channel_control = gen_pool_dma_alloc(sdma->iram_pool, ccbsize, &ccb_phys); + if (!sdma->channel_control) { +- ret = -ENOMEM; +- goto err_dma_alloc; ++ sdma->channel_control = dma_alloc_coherent(NULL, ccbsize, ++ &ccb_phys, GFP_KERNEL); ++ if (!sdma->channel_control) { ++ ret = -ENOMEM; ++ goto err_dma_alloc; ++ } + } + + sdma->context = (void *)sdma->channel_control + +@@ -1422,9 +1601,10 @@ + if (dma_spec->args_count != 3) + return NULL; + +- data.dma_request = dma_spec->args[0]; ++ data.dma_request0 = dma_spec->args[0]; + data.peripheral_type = dma_spec->args[1]; + data.priority = dma_spec->args[2]; ++ data.dma_request1 = 0; + + return dma_request_channel(mask, sdma_filter_fn, &data); + } +@@ -1542,6 +1722,11 @@ + &sdma->dma_device.channels); + } + ++ if (np) ++ sdma->iram_pool = of_get_named_gen_pool(np, "iram", 0); ++ if (!sdma->iram_pool) ++ dev_warn(&pdev->dev, "no iram assigned, using external mem\n"); ++ + ret = sdma_init(sdma); + if (ret) + goto err_init; +diff -Nur linux-3.14.14/drivers/dma/Kconfig linux-imx6-3.14/drivers/dma/Kconfig +--- linux-3.14.14/drivers/dma/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/dma/Kconfig 2014-12-08 00:31:52.564418001 -0600 +@@ -137,6 +137,19 @@ + To avoid bloating the irq_desc[] array we allocate a sufficient + number of IRQ slots and map them dynamically to specific sources. + ++config MXC_PXP_V2 ++ bool "MXC PxP V2 support" ++ depends on ARM ++ select DMA_ENGINE ++ help ++ Support the PxP (Pixel Pipeline) on i.MX6 DualLite and i.MX6 SoloLite. ++ If unsure, select N. ++ ++config MXC_PXP_CLIENT_DEVICE ++ bool "MXC PxP Client Device" ++ default y ++ depends on MXC_PXP_V2 ++ + config TXX9_DMAC + tristate "Toshiba TXx9 SoC DMA support" + depends on MACH_TX49XX || MACH_TX39XX +diff -Nur linux-3.14.14/drivers/dma/Makefile linux-imx6-3.14/drivers/dma/Makefile +--- linux-3.14.14/drivers/dma/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/dma/Makefile 2014-12-08 00:31:52.564418001 -0600 +@@ -18,6 +18,7 @@ + obj-$(CONFIG_DW_DMAC_CORE) += dw/ + obj-$(CONFIG_AT_HDMAC) += at_hdmac.o + obj-$(CONFIG_MX3_IPU) += ipu/ ++obj-$(CONFIG_MXC_PXP_V2) += pxp/ + obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o + obj-$(CONFIG_SH_DMAE_BASE) += sh/ + obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o +diff -Nur linux-3.14.14/drivers/dma/pxp/Makefile linux-imx6-3.14/drivers/dma/pxp/Makefile +--- linux-3.14.14/drivers/dma/pxp/Makefile 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/dma/pxp/Makefile 2014-12-08 00:31:52.572418001 -0600 +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_MXC_PXP_V2) += pxp_dma_v2.o ++obj-$(CONFIG_MXC_PXP_CLIENT_DEVICE) += pxp_device.o +diff -Nur linux-3.14.14/drivers/dma/pxp/pxp_device.c linux-imx6-3.14/drivers/dma/pxp/pxp_device.c +--- linux-3.14.14/drivers/dma/pxp/pxp_device.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/dma/pxp/pxp_device.c 2014-12-08 00:31:52.572418001 -0600 +@@ -0,0 +1,765 @@ ++/* ++ * Copyright (C) 2010-2014 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BUFFER_HASH_ORDER 4 ++ ++static struct pxp_buffer_hash bufhash; ++static struct pxp_irq_info irq_info[NR_PXP_VIRT_CHANNEL]; ++ ++static int pxp_ht_create(struct pxp_buffer_hash *hash, int order) ++{ ++ unsigned long i; ++ unsigned long table_size; ++ ++ table_size = 1U << order; ++ ++ hash->order = order; ++ hash->hash_table = kmalloc(sizeof(*hash->hash_table) * table_size, GFP_KERNEL); ++ ++ if (!hash->hash_table) { ++ pr_err("%s: Out of memory for hash table\n", __func__); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < table_size; i++) ++ INIT_HLIST_HEAD(&hash->hash_table[i]); ++ ++ return 0; ++} ++ ++static int pxp_ht_insert_item(struct pxp_buffer_hash *hash, ++ struct pxp_buf_obj *new) ++{ ++ unsigned long hashkey; ++ struct hlist_head *h_list; ++ ++ hashkey = hash_long(new->offset >> PAGE_SHIFT, hash->order); ++ h_list = &hash->hash_table[hashkey]; ++ ++ spin_lock(&hash->hash_lock); ++ hlist_add_head_rcu(&new->item, h_list); ++ spin_unlock(&hash->hash_lock); ++ ++ return 0; ++} ++ ++static int pxp_ht_remove_item(struct pxp_buffer_hash *hash, ++ struct pxp_buf_obj *obj) ++{ ++ spin_lock(&hash->hash_lock); ++ hlist_del_init_rcu(&obj->item); ++ spin_unlock(&hash->hash_lock); ++ return 0; ++} ++ ++static struct hlist_node *pxp_ht_find_key(struct pxp_buffer_hash *hash, ++ unsigned long key) ++{ ++ struct pxp_buf_obj *entry; ++ struct hlist_head *h_list; ++ unsigned long hashkey; ++ ++ hashkey = hash_long(key, hash->order); ++ h_list = &hash->hash_table[hashkey]; ++ ++ hlist_for_each_entry_rcu(entry, h_list, item) { ++ if (entry->offset >> PAGE_SHIFT == key) ++ return &entry->item; ++ } ++ ++ return NULL; ++} ++ ++static void pxp_ht_destroy(struct pxp_buffer_hash *hash) ++{ ++ kfree(hash->hash_table); ++ hash->hash_table = NULL; ++} ++ ++static int pxp_buffer_handle_create(struct pxp_file *file_priv, ++ struct pxp_buf_obj *obj, ++ uint32_t *handlep) ++{ ++ int ret; ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock(&file_priv->buffer_lock); ++ ++ ret = idr_alloc(&file_priv->buffer_idr, obj, 1, 0, GFP_NOWAIT); ++ ++ spin_unlock(&file_priv->buffer_lock); ++ idr_preload_end(); ++ ++ if (ret < 0) ++ return ret; ++ ++ *handlep = ret; ++ ++ return 0; ++} ++ ++static struct pxp_buf_obj * ++pxp_buffer_object_lookup(struct pxp_file *file_priv, ++ uint32_t handle) ++{ ++ struct pxp_buf_obj *obj; ++ ++ spin_lock(&file_priv->buffer_lock); ++ ++ obj = idr_find(&file_priv->buffer_idr, handle); ++ if (!obj) { ++ spin_unlock(&file_priv->buffer_lock); ++ return NULL; ++ } ++ ++ spin_unlock(&file_priv->buffer_lock); ++ ++ return obj; ++} ++ ++static int pxp_buffer_handle_delete(struct pxp_file *file_priv, ++ uint32_t handle) ++{ ++ struct pxp_buf_obj *obj; ++ ++ spin_lock(&file_priv->buffer_lock); ++ ++ obj = idr_find(&file_priv->buffer_idr, handle); ++ if (!obj) { ++ spin_unlock(&file_priv->buffer_lock); ++ return -EINVAL; ++ } ++ ++ idr_remove(&file_priv->buffer_idr, handle); ++ spin_unlock(&file_priv->buffer_lock); ++ ++ return 0; ++} ++ ++static int pxp_channel_handle_create(struct pxp_file *file_priv, ++ struct pxp_chan_obj *obj, ++ uint32_t *handlep) ++{ ++ int ret; ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock(&file_priv->channel_lock); ++ ++ ret = idr_alloc(&file_priv->channel_idr, obj, 0, 0, GFP_NOWAIT); ++ ++ spin_unlock(&file_priv->channel_lock); ++ idr_preload_end(); ++ ++ if (ret < 0) ++ return ret; ++ ++ *handlep = ret; ++ ++ return 0; ++} ++ ++static struct pxp_chan_obj * ++pxp_channel_object_lookup(struct pxp_file *file_priv, ++ uint32_t handle) ++{ ++ struct pxp_chan_obj *obj; ++ ++ spin_lock(&file_priv->channel_lock); ++ ++ obj = idr_find(&file_priv->channel_idr, handle); ++ if (!obj) { ++ spin_unlock(&file_priv->channel_lock); ++ return NULL; ++ } ++ ++ spin_unlock(&file_priv->channel_lock); ++ ++ return obj; ++} ++ ++static int pxp_channel_handle_delete(struct pxp_file *file_priv, ++ uint32_t handle) ++{ ++ struct pxp_chan_obj *obj; ++ ++ spin_lock(&file_priv->channel_lock); ++ ++ obj = idr_find(&file_priv->channel_idr, handle); ++ if (!obj) { ++ spin_unlock(&file_priv->channel_lock); ++ return -EINVAL; ++ } ++ ++ idr_remove(&file_priv->channel_idr, handle); ++ spin_unlock(&file_priv->channel_lock); ++ ++ return 0; ++} ++ ++static int pxp_alloc_dma_buffer(struct pxp_buf_obj *obj) ++{ ++ obj->virtual = dma_alloc_coherent(NULL, PAGE_ALIGN(obj->size), ++ (dma_addr_t *) (&obj->offset), ++ GFP_DMA | GFP_KERNEL); ++ pr_debug("[ALLOC] mem alloc phys_addr = 0x%lx\n", obj->offset); ++ ++ if (obj->virtual == NULL) { ++ printk(KERN_ERR "Physical memory allocation error!\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void pxp_free_dma_buffer(struct pxp_buf_obj *obj) ++{ ++ if (obj->virtual != NULL) { ++ dma_free_coherent(0, PAGE_ALIGN(obj->size), ++ obj->virtual, (dma_addr_t)obj->offset); ++ } ++} ++ ++static int ++pxp_buffer_object_free(int id, void *ptr, void *data) ++{ ++ struct pxp_file *file_priv = data; ++ struct pxp_buf_obj *obj = ptr; ++ int ret; ++ ++ ret = pxp_buffer_handle_delete(file_priv, obj->handle); ++ if (ret < 0) ++ return ret; ++ ++ pxp_ht_remove_item(&bufhash, obj); ++ pxp_free_dma_buffer(obj); ++ kfree(obj); ++ ++ return 0; ++} ++ ++static int ++pxp_channel_object_free(int id, void *ptr, void *data) ++{ ++ struct pxp_file *file_priv = data; ++ struct pxp_chan_obj *obj = ptr; ++ int chan_id; ++ ++ chan_id = obj->chan->chan_id; ++ wait_event(irq_info[chan_id].waitq, ++ atomic_read(&irq_info[chan_id].irq_pending) == 0); ++ ++ pxp_channel_handle_delete(file_priv, obj->handle); ++ dma_release_channel(obj->chan); ++ kfree(obj); ++ ++ return 0; ++} ++ ++static void pxp_free_buffers(struct pxp_file *file_priv) ++{ ++ idr_for_each(&file_priv->buffer_idr, ++ &pxp_buffer_object_free, file_priv); ++ idr_destroy(&file_priv->buffer_idr); ++} ++ ++static void pxp_free_channels(struct pxp_file *file_priv) ++{ ++ idr_for_each(&file_priv->channel_idr, ++ &pxp_channel_object_free, file_priv); ++ idr_destroy(&file_priv->channel_idr); ++} ++ ++/* Callback function triggered after PxP receives an EOF interrupt */ ++static void pxp_dma_done(void *arg) ++{ ++ struct pxp_tx_desc *tx_desc = to_tx_desc(arg); ++ struct dma_chan *chan = tx_desc->txd.chan; ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ int chan_id = pxp_chan->dma_chan.chan_id; ++ ++ pr_debug("DMA Done ISR, chan_id %d\n", chan_id); ++ ++ atomic_dec(&irq_info[chan_id].irq_pending); ++ irq_info[chan_id].hist_status = tx_desc->hist_status; ++ ++ wake_up(&(irq_info[chan_id].waitq)); ++} ++ ++static int pxp_ioc_config_chan(struct pxp_file *priv, unsigned long arg) ++{ ++ struct scatterlist sg[3]; ++ struct pxp_tx_desc *desc; ++ struct dma_async_tx_descriptor *txd; ++ struct pxp_config_data pxp_conf; ++ dma_cookie_t cookie; ++ int handle, chan_id; ++ int i, length, ret; ++ struct dma_chan *chan; ++ struct pxp_chan_obj *obj; ++ ++ ret = copy_from_user(&pxp_conf, ++ (struct pxp_config_data *)arg, ++ sizeof(struct pxp_config_data)); ++ if (ret) ++ return -EFAULT; ++ ++ handle = pxp_conf.handle; ++ obj = pxp_channel_object_lookup(priv, handle); ++ if (!obj) ++ return -EINVAL; ++ chan = obj->chan; ++ chan_id = chan->chan_id; ++ ++ sg_init_table(sg, 3); ++ ++ txd = chan->device->device_prep_slave_sg(chan, ++ sg, 3, ++ DMA_TO_DEVICE, ++ DMA_PREP_INTERRUPT, ++ NULL); ++ if (!txd) { ++ pr_err("Error preparing a DMA transaction descriptor.\n"); ++ return -EIO; ++ } ++ ++ txd->callback_param = txd; ++ txd->callback = pxp_dma_done; ++ ++ desc = to_tx_desc(txd); ++ ++ length = desc->len; ++ for (i = 0; i < length; i++) { ++ if (i == 0) { /* S0 */ ++ memcpy(&desc->proc_data, ++ &pxp_conf.proc_data, ++ sizeof(struct pxp_proc_data)); ++ memcpy(&desc->layer_param.s0_param, ++ &pxp_conf.s0_param, ++ sizeof(struct pxp_layer_param)); ++ } else if (i == 1) { /* Output */ ++ memcpy(&desc->layer_param.out_param, ++ &pxp_conf.out_param, ++ sizeof(struct pxp_layer_param)); ++ } else { ++ /* OverLay */ ++ memcpy(&desc->layer_param.ol_param, ++ &pxp_conf.ol_param, ++ sizeof(struct pxp_layer_param)); ++ } ++ ++ desc = desc->next; ++ } ++ ++ cookie = txd->tx_submit(txd); ++ if (cookie < 0) { ++ pr_err("Error tx_submit\n"); ++ return -EIO; ++ } ++ ++ atomic_inc(&irq_info[chan_id].irq_pending); ++ ++ return 0; ++} ++ ++static int pxp_device_open(struct inode *inode, struct file *filp) ++{ ++ struct pxp_file *priv; ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ ++ if (!priv) ++ return -ENOMEM; ++ ++ filp->private_data = priv; ++ priv->filp = filp; ++ ++ idr_init(&priv->buffer_idr); ++ spin_lock_init(&priv->buffer_lock); ++ ++ idr_init(&priv->channel_idr); ++ spin_lock_init(&priv->channel_lock); ++ ++ return 0; ++} ++ ++static int pxp_device_release(struct inode *inode, struct file *filp) ++{ ++ struct pxp_file *priv = filp->private_data; ++ ++ if (priv) { ++ pxp_free_channels(priv); ++ pxp_free_buffers(priv); ++ kfree(priv); ++ filp->private_data = NULL; ++ } ++ ++ return 0; ++} ++ ++static int pxp_device_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int request_size; ++ struct hlist_node *node; ++ struct pxp_buf_obj *obj; ++ ++ request_size = vma->vm_end - vma->vm_start; ++ ++ pr_debug("start=0x%x, pgoff=0x%x, size=0x%x\n", ++ (unsigned int)(vma->vm_start), (unsigned int)(vma->vm_pgoff), ++ request_size); ++ ++ node = pxp_ht_find_key(&bufhash, vma->vm_pgoff); ++ if (!node) ++ return -EINVAL; ++ ++ obj = list_entry(node, struct pxp_buf_obj, item); ++ if (obj->offset + (obj->size >> PAGE_SHIFT) < ++ (vma->vm_pgoff + vma_pages(vma))) ++ return -ENOMEM; ++ ++ switch (obj->mem_type) { ++ case MEMORY_TYPE_UNCACHED: ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ break; ++ case MEMORY_TYPE_WC: ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ break; ++ case MEMORY_TYPE_CACHED: ++ break; ++ default: ++ pr_err("%s: invalid memory type!\n", __func__); ++ return -EINVAL; ++ } ++ ++ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, ++ request_size, vma->vm_page_prot) ? -EAGAIN : 0; ++} ++ ++static bool chan_filter(struct dma_chan *chan, void *arg) ++{ ++ if (imx_dma_is_pxp(chan)) ++ return true; ++ else ++ return false; ++} ++ ++static long pxp_device_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ struct pxp_file *file_priv = filp->private_data; ++ ++ switch (cmd) { ++ case PXP_IOC_GET_CHAN: ++ { ++ int ret; ++ struct dma_chan *chan = NULL; ++ dma_cap_mask_t mask; ++ struct pxp_chan_obj *obj = NULL; ++ ++ pr_debug("drv: PXP_IOC_GET_CHAN Line %d\n", __LINE__); ++ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_cap_set(DMA_PRIVATE, mask); ++ ++ chan = dma_request_channel(mask, chan_filter, NULL); ++ if (!chan) { ++ pr_err("Unsccessfully received channel!\n"); ++ return -EBUSY; ++ } ++ ++ pr_debug("Successfully received channel." ++ "chan_id %d\n", chan->chan_id); ++ ++ obj = kzalloc(sizeof(*obj), GFP_KERNEL); ++ if (!obj) { ++ dma_release_channel(chan); ++ return -ENOMEM; ++ } ++ obj->chan = chan; ++ ++ ret = pxp_channel_handle_create(file_priv, obj, ++ &obj->handle); ++ if (ret) { ++ dma_release_channel(chan); ++ kfree(obj); ++ return ret; ++ } ++ ++ init_waitqueue_head(&(irq_info[chan->chan_id].waitq)); ++ if (put_user(obj->handle, (u32 __user *) arg)) { ++ pxp_channel_handle_delete(file_priv, obj->handle); ++ dma_release_channel(chan); ++ kfree(obj); ++ return -EFAULT; ++ } ++ ++ break; ++ } ++ case PXP_IOC_PUT_CHAN: ++ { ++ int handle; ++ struct pxp_chan_obj *obj; ++ ++ if (get_user(handle, (u32 __user *) arg)) ++ return -EFAULT; ++ ++ pr_debug("%d release handle %d\n", __LINE__, handle); ++ ++ obj = pxp_channel_object_lookup(file_priv, handle); ++ if (!obj) ++ return -EINVAL; ++ ++ pxp_channel_handle_delete(file_priv, obj->handle); ++ dma_release_channel(obj->chan); ++ kfree(obj); ++ ++ break; ++ } ++ case PXP_IOC_CONFIG_CHAN: ++ { ++ int ret; ++ ++ ret = pxp_ioc_config_chan(file_priv, arg); ++ if (ret) ++ return ret; ++ ++ break; ++ } ++ case PXP_IOC_START_CHAN: ++ { ++ int handle; ++ struct pxp_chan_obj *obj = NULL; ++ ++ if (get_user(handle, (u32 __user *) arg)) ++ return -EFAULT; ++ ++ obj = pxp_channel_object_lookup(file_priv, handle); ++ if (!obj) ++ return -EINVAL; ++ ++ dma_async_issue_pending(obj->chan); ++ ++ break; ++ } ++ case PXP_IOC_GET_PHYMEM: ++ { ++ struct pxp_mem_desc buffer; ++ struct pxp_buf_obj *obj; ++ ++ ret = copy_from_user(&buffer, ++ (struct pxp_mem_desc *)arg, ++ sizeof(struct pxp_mem_desc)); ++ if (ret) ++ return -EFAULT; ++ ++ pr_debug("[ALLOC] mem alloc size = 0x%x\n", ++ buffer.size); ++ ++ obj = kzalloc(sizeof(*obj), GFP_KERNEL); ++ if (!obj) ++ return -ENOMEM; ++ obj->size = buffer.size; ++ obj->mem_type = buffer.mtype; ++ ++ ret = pxp_alloc_dma_buffer(obj); ++ if (ret == -1) { ++ printk(KERN_ERR ++ "Physical memory allocation error!\n"); ++ kfree(obj); ++ return ret; ++ } ++ ++ ret = pxp_buffer_handle_create(file_priv, obj, &obj->handle); ++ if (ret) { ++ pxp_free_dma_buffer(obj); ++ kfree(obj); ++ return ret; ++ } ++ buffer.handle = obj->handle; ++ buffer.phys_addr = obj->offset; ++ ++ ret = copy_to_user((void __user *)arg, &buffer, ++ sizeof(struct pxp_mem_desc)); ++ if (ret) { ++ pxp_buffer_handle_delete(file_priv, buffer.handle); ++ pxp_free_dma_buffer(obj); ++ kfree(obj); ++ return -EFAULT; ++ } ++ ++ pxp_ht_insert_item(&bufhash, obj); ++ ++ break; ++ } ++ case PXP_IOC_PUT_PHYMEM: ++ { ++ struct pxp_mem_desc pxp_mem; ++ struct pxp_buf_obj *obj; ++ ++ ret = copy_from_user(&pxp_mem, ++ (struct pxp_mem_desc *)arg, ++ sizeof(struct pxp_mem_desc)); ++ if (ret) ++ return -EACCES; ++ ++ obj = pxp_buffer_object_lookup(file_priv, pxp_mem.handle); ++ if (!obj) ++ return -EINVAL; ++ ++ ret = pxp_buffer_handle_delete(file_priv, obj->handle); ++ if (ret) ++ return ret; ++ ++ pxp_ht_remove_item(&bufhash, obj); ++ pxp_free_dma_buffer(obj); ++ kfree(obj); ++ ++ break; ++ } ++ case PXP_IOC_FLUSH_PHYMEM: ++ { ++ int ret; ++ struct pxp_mem_flush flush; ++ struct pxp_buf_obj *obj; ++ ++ ret = copy_from_user(&flush, ++ (struct pxp_mem_flush *)arg, ++ sizeof(struct pxp_mem_flush)); ++ if (ret) ++ return -EACCES; ++ ++ obj = pxp_buffer_object_lookup(file_priv, flush.handle); ++ if (!obj) ++ return -EINVAL; ++ ++ switch (flush.type) { ++ case CACHE_CLEAN: ++ dma_sync_single_for_device(NULL, obj->offset, ++ obj->size, DMA_TO_DEVICE); ++ break; ++ case CACHE_INVALIDATE: ++ dma_sync_single_for_device(NULL, obj->offset, ++ obj->size, DMA_FROM_DEVICE); ++ break; ++ case CACHE_FLUSH: ++ dma_sync_single_for_device(NULL, obj->offset, ++ obj->size, DMA_TO_DEVICE); ++ dma_sync_single_for_device(NULL, obj->offset, ++ obj->size, DMA_FROM_DEVICE); ++ break; ++ default: ++ pr_err("%s: invalid cache flush type\n", __func__); ++ return -EINVAL; ++ } ++ ++ break; ++ } ++ case PXP_IOC_WAIT4CMPLT: ++ { ++ struct pxp_chan_handle chan_handle; ++ int ret, chan_id, handle; ++ struct pxp_chan_obj *obj = NULL; ++ ++ ret = copy_from_user(&chan_handle, ++ (struct pxp_chan_handle *)arg, ++ sizeof(struct pxp_chan_handle)); ++ if (ret) ++ return -EFAULT; ++ ++ handle = chan_handle.handle; ++ obj = pxp_channel_object_lookup(file_priv, handle); ++ if (!obj) ++ return -EINVAL; ++ chan_id = obj->chan->chan_id; ++ ++ ret = wait_event_interruptible ++ (irq_info[chan_id].waitq, ++ (atomic_read(&irq_info[chan_id].irq_pending) == 0)); ++ if (ret < 0) { ++ printk(KERN_WARNING ++ "WAIT4CMPLT: signal received.\n"); ++ return -ERESTARTSYS; ++ } ++ ++ chan_handle.hist_status = irq_info[chan_id].hist_status; ++ ret = copy_to_user((struct pxp_chan_handle *)arg, ++ &chan_handle, ++ sizeof(struct pxp_chan_handle)); ++ if (ret) ++ return -EFAULT; ++ break; ++ } ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct file_operations pxp_device_fops = { ++ .open = pxp_device_open, ++ .release = pxp_device_release, ++ .unlocked_ioctl = pxp_device_ioctl, ++ .mmap = pxp_device_mmap, ++}; ++ ++static struct miscdevice pxp_device_miscdev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "pxp_device", ++ .fops = &pxp_device_fops, ++}; ++ ++int register_pxp_device(void) ++{ ++ int ret; ++ ++ ret = misc_register(&pxp_device_miscdev); ++ if (ret) ++ return ret; ++ ++ ret = pxp_ht_create(&bufhash, BUFFER_HASH_ORDER); ++ if (ret) ++ return ret; ++ spin_lock_init(&(bufhash.hash_lock)); ++ ++ pr_debug("PxP_Device registered Successfully\n"); ++ return 0; ++} ++ ++void unregister_pxp_device(void) ++{ ++ pxp_ht_destroy(&bufhash); ++ misc_deregister(&pxp_device_miscdev); ++} +diff -Nur linux-3.14.14/drivers/dma/pxp/pxp_dma_v2.c linux-imx6-3.14/drivers/dma/pxp/pxp_dma_v2.c +--- linux-3.14.14/drivers/dma/pxp/pxp_dma_v2.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/dma/pxp/pxp_dma_v2.c 2014-12-08 00:31:52.576418001 -0600 +@@ -0,0 +1,1854 @@ ++/* ++ * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++/* ++ * Based on STMP378X PxP driver ++ * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "regs-pxp_v2.h" ++ ++#define PXP_DOWNSCALE_THRESHOLD 0x4000 ++ ++static LIST_HEAD(head); ++static int timeout_in_ms = 600; ++static unsigned int block_size; ++static struct kmem_cache *tx_desc_cache; ++ ++struct pxp_dma { ++ struct dma_device dma; ++}; ++ ++struct pxps { ++ struct platform_device *pdev; ++ struct clk *clk; ++ void __iomem *base; ++ int irq; /* PXP IRQ to the CPU */ ++ ++ spinlock_t lock; ++ struct mutex clk_mutex; ++ int clk_stat; ++#define CLK_STAT_OFF 0 ++#define CLK_STAT_ON 1 ++ int pxp_ongoing; ++ int lut_state; ++ ++ struct device *dev; ++ struct pxp_dma pxp_dma; ++ struct pxp_channel channel[NR_PXP_VIRT_CHANNEL]; ++ struct work_struct work; ++ ++ /* describes most recent processing configuration */ ++ struct pxp_config_data pxp_conf_state; ++ ++ /* to turn clock off when pxp is inactive */ ++ struct timer_list clk_timer; ++ ++ /* for pxp config dispatch asynchronously*/ ++ struct task_struct *dispatch; ++ wait_queue_head_t thread_waitq; ++ struct completion complete; ++}; ++ ++#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma) ++#define to_tx_desc(tx) container_of(tx, struct pxp_tx_desc, txd) ++#define to_pxp_channel(d) container_of(d, struct pxp_channel, dma_chan) ++#define to_pxp(id) container_of(id, struct pxps, pxp_dma) ++ ++#define PXP_DEF_BUFS 2 ++#define PXP_MIN_PIX 8 ++ ++static uint32_t pxp_s0_formats[] = { ++ PXP_PIX_FMT_RGB32, ++ PXP_PIX_FMT_RGB565, ++ PXP_PIX_FMT_RGB555, ++ PXP_PIX_FMT_YUV420P, ++ PXP_PIX_FMT_YUV422P, ++}; ++ ++/* ++ * PXP common functions ++ */ ++static void dump_pxp_reg(struct pxps *pxp) ++{ ++ dev_dbg(pxp->dev, "PXP_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CTRL)); ++ dev_dbg(pxp->dev, "PXP_STAT 0x%x", ++ __raw_readl(pxp->base + HW_PXP_STAT)); ++ dev_dbg(pxp->dev, "PXP_OUT_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_CTRL)); ++ dev_dbg(pxp->dev, "PXP_OUT_BUF 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_BUF)); ++ dev_dbg(pxp->dev, "PXP_OUT_BUF2 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_BUF2)); ++ dev_dbg(pxp->dev, "PXP_OUT_PITCH 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_PITCH)); ++ dev_dbg(pxp->dev, "PXP_OUT_LRC 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_LRC)); ++ dev_dbg(pxp->dev, "PXP_OUT_PS_ULC 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_PS_ULC)); ++ dev_dbg(pxp->dev, "PXP_OUT_PS_LRC 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_PS_LRC)); ++ dev_dbg(pxp->dev, "PXP_OUT_AS_ULC 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_AS_ULC)); ++ dev_dbg(pxp->dev, "PXP_OUT_AS_LRC 0x%x", ++ __raw_readl(pxp->base + HW_PXP_OUT_AS_LRC)); ++ dev_dbg(pxp->dev, "PXP_PS_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_CTRL)); ++ dev_dbg(pxp->dev, "PXP_PS_BUF 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_BUF)); ++ dev_dbg(pxp->dev, "PXP_PS_UBUF 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_UBUF)); ++ dev_dbg(pxp->dev, "PXP_PS_VBUF 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_VBUF)); ++ dev_dbg(pxp->dev, "PXP_PS_PITCH 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_PITCH)); ++ dev_dbg(pxp->dev, "PXP_PS_BACKGROUND 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_BACKGROUND)); ++ dev_dbg(pxp->dev, "PXP_PS_SCALE 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_SCALE)); ++ dev_dbg(pxp->dev, "PXP_PS_OFFSET 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_OFFSET)); ++ dev_dbg(pxp->dev, "PXP_PS_CLRKEYLOW 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYLOW)); ++ dev_dbg(pxp->dev, "PXP_PS_CLRKEYHIGH 0x%x", ++ __raw_readl(pxp->base + HW_PXP_PS_CLRKEYHIGH)); ++ dev_dbg(pxp->dev, "PXP_AS_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_AS_CTRL)); ++ dev_dbg(pxp->dev, "PXP_AS_BUF 0x%x", ++ __raw_readl(pxp->base + HW_PXP_AS_BUF)); ++ dev_dbg(pxp->dev, "PXP_AS_PITCH 0x%x", ++ __raw_readl(pxp->base + HW_PXP_AS_PITCH)); ++ dev_dbg(pxp->dev, "PXP_AS_CLRKEYLOW 0x%x", ++ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYLOW)); ++ dev_dbg(pxp->dev, "PXP_AS_CLRKEYHIGH 0x%x", ++ __raw_readl(pxp->base + HW_PXP_AS_CLRKEYHIGH)); ++ dev_dbg(pxp->dev, "PXP_CSC1_COEF0 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC1_COEF0)); ++ dev_dbg(pxp->dev, "PXP_CSC1_COEF1 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC1_COEF1)); ++ dev_dbg(pxp->dev, "PXP_CSC1_COEF2 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC1_COEF2)); ++ dev_dbg(pxp->dev, "PXP_CSC2_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_CTRL)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF0 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF0)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF1 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF1)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF2 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF2)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF3 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF3)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF4 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF4)); ++ dev_dbg(pxp->dev, "PXP_CSC2_COEF5 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CSC2_COEF5)); ++ dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_LUT_CTRL)); ++ dev_dbg(pxp->dev, "PXP_LUT_ADDR 0x%x", ++ __raw_readl(pxp->base + HW_PXP_LUT_ADDR)); ++ dev_dbg(pxp->dev, "PXP_LUT_DATA 0x%x", ++ __raw_readl(pxp->base + HW_PXP_LUT_DATA)); ++ dev_dbg(pxp->dev, "PXP_LUT_EXTMEM 0x%x", ++ __raw_readl(pxp->base + HW_PXP_LUT_EXTMEM)); ++ dev_dbg(pxp->dev, "PXP_CFA 0x%x", ++ __raw_readl(pxp->base + HW_PXP_CFA)); ++ dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST_CTRL)); ++ dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST2_PARAM)); ++ dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST4_PARAM)); ++ dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM0)); ++ dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST8_PARAM1)); ++ dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM0)); ++ dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM1)); ++ dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM2)); ++ dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x", ++ __raw_readl(pxp->base + HW_PXP_HIST16_PARAM3)); ++ dev_dbg(pxp->dev, "PXP_POWER 0x%x", ++ __raw_readl(pxp->base + HW_PXP_POWER)); ++ dev_dbg(pxp->dev, "PXP_NEXT 0x%x", ++ __raw_readl(pxp->base + HW_PXP_NEXT)); ++ dev_dbg(pxp->dev, "PXP_DEBUGCTRL 0x%x", ++ __raw_readl(pxp->base + HW_PXP_DEBUGCTRL)); ++ dev_dbg(pxp->dev, "PXP_DEBUG 0x%x", ++ __raw_readl(pxp->base + HW_PXP_DEBUG)); ++ dev_dbg(pxp->dev, "PXP_VERSION 0x%x", ++ __raw_readl(pxp->base + HW_PXP_VERSION)); ++} ++ ++static bool is_yuv(u32 pix_fmt) ++{ ++ if ((pix_fmt == PXP_PIX_FMT_YUYV) | ++ (pix_fmt == PXP_PIX_FMT_UYVY) | ++ (pix_fmt == PXP_PIX_FMT_YVYU) | ++ (pix_fmt == PXP_PIX_FMT_VYUY) | ++ (pix_fmt == PXP_PIX_FMT_Y41P) | ++ (pix_fmt == PXP_PIX_FMT_YUV444) | ++ (pix_fmt == PXP_PIX_FMT_NV12) | ++ (pix_fmt == PXP_PIX_FMT_NV16) | ++ (pix_fmt == PXP_PIX_FMT_NV61) | ++ (pix_fmt == PXP_PIX_FMT_GREY) | ++ (pix_fmt == PXP_PIX_FMT_GY04) | ++ (pix_fmt == PXP_PIX_FMT_YVU410P) | ++ (pix_fmt == PXP_PIX_FMT_YUV410P) | ++ (pix_fmt == PXP_PIX_FMT_YVU420P) | ++ (pix_fmt == PXP_PIX_FMT_YUV420P) | ++ (pix_fmt == PXP_PIX_FMT_YUV420P2) | ++ (pix_fmt == PXP_PIX_FMT_YVU422P) | ++ (pix_fmt == PXP_PIX_FMT_YUV422P)) { ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++static void pxp_set_ctrl(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; ++ u32 ctrl; ++ u32 fmt_ctrl; ++ int need_swap = 0; /* to support YUYV and YVYU formats */ ++ ++ /* Configure S0 input format */ ++ switch (pxp_conf->s0_param.pixel_fmt) { ++ case PXP_PIX_FMT_RGB32: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB888; ++ break; ++ case PXP_PIX_FMT_RGB565: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB565; ++ break; ++ case PXP_PIX_FMT_RGB555: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__RGB555; ++ break; ++ case PXP_PIX_FMT_YUV420P: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420; ++ break; ++ case PXP_PIX_FMT_YVU420P: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV420; ++ break; ++ case PXP_PIX_FMT_GREY: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y8; ++ break; ++ case PXP_PIX_FMT_GY04: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__Y4; ++ break; ++ case PXP_PIX_FMT_YUV422P: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV422; ++ break; ++ case PXP_PIX_FMT_UYVY: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; ++ break; ++ case PXP_PIX_FMT_YUYV: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__UYVY1P422; ++ need_swap = 1; ++ break; ++ case PXP_PIX_FMT_VYUY: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422; ++ break; ++ case PXP_PIX_FMT_YVYU: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__VYUY1P422; ++ need_swap = 1; ++ break; ++ case PXP_PIX_FMT_NV12: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P420; ++ break; ++ case PXP_PIX_FMT_NV21: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P420; ++ break; ++ case PXP_PIX_FMT_NV16: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YUV2P422; ++ break; ++ case PXP_PIX_FMT_NV61: ++ fmt_ctrl = BV_PXP_PS_CTRL_FORMAT__YVU2P422; ++ break; ++ default: ++ fmt_ctrl = 0; ++ } ++ ++ ctrl = BF_PXP_PS_CTRL_FORMAT(fmt_ctrl) | BF_PXP_PS_CTRL_SWAP(need_swap); ++ __raw_writel(ctrl, pxp->base + HW_PXP_PS_CTRL_SET); ++ ++ /* Configure output format based on out_channel format */ ++ switch (pxp_conf->out_param.pixel_fmt) { ++ case PXP_PIX_FMT_RGB32: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888; ++ break; ++ case PXP_PIX_FMT_BGRA32: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__ARGB8888; ++ break; ++ case PXP_PIX_FMT_RGB24: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB888P; ++ break; ++ case PXP_PIX_FMT_RGB565: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB565; ++ break; ++ case PXP_PIX_FMT_RGB555: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__RGB555; ++ break; ++ case PXP_PIX_FMT_GREY: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y8; ++ break; ++ case PXP_PIX_FMT_GY04: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__Y4; ++ break; ++ case PXP_PIX_FMT_UYVY: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__UYVY1P422; ++ break; ++ case PXP_PIX_FMT_VYUY: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__VYUY1P422; ++ break; ++ case PXP_PIX_FMT_NV12: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P420; ++ break; ++ case PXP_PIX_FMT_NV21: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P420; ++ break; ++ case PXP_PIX_FMT_NV16: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YUV2P422; ++ break; ++ case PXP_PIX_FMT_NV61: ++ fmt_ctrl = BV_PXP_OUT_CTRL_FORMAT__YVU2P422; ++ break; ++ default: ++ fmt_ctrl = 0; ++ } ++ ++ ctrl = BF_PXP_OUT_CTRL_FORMAT(fmt_ctrl); ++ __raw_writel(ctrl, pxp->base + HW_PXP_OUT_CTRL); ++ ++ ctrl = 0; ++ if (proc_data->scaling) ++ ; ++ if (proc_data->vflip) ++ ctrl |= BM_PXP_CTRL_VFLIP; ++ if (proc_data->hflip) ++ ctrl |= BM_PXP_CTRL_HFLIP; ++ if (proc_data->rotate) { ++ ctrl |= BF_PXP_CTRL_ROTATE(proc_data->rotate / 90); ++ if (proc_data->rot_pos) ++ ctrl |= BM_PXP_CTRL_ROT_POS; ++ } ++ ++ /* In default, the block size is set to 8x8 ++ * But block size can be set to 16x16 due to ++ * blocksize variable modification ++ */ ++ ctrl |= block_size << 23; ++ ++ __raw_writel(ctrl, pxp->base + HW_PXP_CTRL); ++} ++ ++static int pxp_start(struct pxps *pxp) ++{ ++ __raw_writel(BM_PXP_CTRL_IRQ_ENABLE, pxp->base + HW_PXP_CTRL_SET); ++ __raw_writel(BM_PXP_CTRL_ENABLE, pxp->base + HW_PXP_CTRL_SET); ++ dump_pxp_reg(pxp); ++ ++ return 0; ++} ++ ++static void pxp_set_outbuf(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *out_params = &pxp_conf->out_param; ++ ++ __raw_writel(out_params->paddr, pxp->base + HW_PXP_OUT_BUF); ++ ++ __raw_writel(BF_PXP_OUT_LRC_X(out_params->width - 1) | ++ BF_PXP_OUT_LRC_Y(out_params->height - 1), ++ pxp->base + HW_PXP_OUT_LRC); ++ ++ if (out_params->pixel_fmt == PXP_PIX_FMT_RGB24) { ++ __raw_writel(out_params->stride * 3, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else if (out_params->pixel_fmt == PXP_PIX_FMT_BGRA32 || ++ out_params->pixel_fmt == PXP_PIX_FMT_RGB32) { ++ __raw_writel(out_params->stride << 2, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else if (out_params->pixel_fmt == PXP_PIX_FMT_RGB565) { ++ __raw_writel(out_params->stride << 1, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else if (out_params->pixel_fmt == PXP_PIX_FMT_UYVY || ++ (out_params->pixel_fmt == PXP_PIX_FMT_VYUY)) { ++ __raw_writel(out_params->stride << 1, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GREY || ++ out_params->pixel_fmt == PXP_PIX_FMT_NV12 || ++ out_params->pixel_fmt == PXP_PIX_FMT_NV21 || ++ out_params->pixel_fmt == PXP_PIX_FMT_NV16 || ++ out_params->pixel_fmt == PXP_PIX_FMT_NV61) { ++ __raw_writel(out_params->stride, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else if (out_params->pixel_fmt == PXP_PIX_FMT_GY04) { ++ __raw_writel(out_params->stride >> 1, ++ pxp->base + HW_PXP_OUT_PITCH); ++ } else { ++ __raw_writel(0, pxp->base + HW_PXP_OUT_PITCH); ++ } ++ ++ /* set global alpha if necessary */ ++ if (out_params->global_alpha_enable) { ++ __raw_writel(out_params->global_alpha << 24, ++ pxp->base + HW_PXP_OUT_CTRL_SET); ++ __raw_writel(BM_PXP_OUT_CTRL_ALPHA_OUTPUT, ++ pxp->base + HW_PXP_OUT_CTRL_SET); ++ } ++} ++ ++static void pxp_set_s0colorkey(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; ++ ++ /* Low and high are set equal. V4L does not allow a chromakey range */ ++ if (s0_params->color_key_enable == 0 || s0_params->color_key == -1) { ++ /* disable color key */ ++ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_PS_CLRKEYLOW); ++ __raw_writel(0, pxp->base + HW_PXP_PS_CLRKEYHIGH); ++ } else { ++ __raw_writel(s0_params->color_key, ++ pxp->base + HW_PXP_PS_CLRKEYLOW); ++ __raw_writel(s0_params->color_key, ++ pxp->base + HW_PXP_PS_CLRKEYHIGH); ++ } ++} ++ ++static void pxp_set_olcolorkey(int layer_no, struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[layer_no]; ++ ++ /* Low and high are set equal. V4L does not allow a chromakey range */ ++ if (ol_params->color_key_enable != 0 && ol_params->color_key != -1) { ++ __raw_writel(ol_params->color_key, ++ pxp->base + HW_PXP_AS_CLRKEYLOW); ++ __raw_writel(ol_params->color_key, ++ pxp->base + HW_PXP_AS_CLRKEYHIGH); ++ } else { ++ /* disable color key */ ++ __raw_writel(0xFFFFFF, pxp->base + HW_PXP_AS_CLRKEYLOW); ++ __raw_writel(0, pxp->base + HW_PXP_AS_CLRKEYHIGH); ++ } ++} ++ ++static void pxp_set_oln(int layer_no, struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; ++ dma_addr_t phys_addr = olparams_data->paddr; ++ u32 pitch = olparams_data->stride ? olparams_data->stride : ++ olparams_data->width; ++ ++ __raw_writel(phys_addr, pxp->base + HW_PXP_AS_BUF); ++ ++ /* Fixme */ ++ if (olparams_data->width == 0 && olparams_data->height == 0) { ++ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_AS_ULC); ++ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_LRC); ++ } else { ++ __raw_writel(0x0, pxp->base + HW_PXP_OUT_AS_ULC); ++ if (pxp_conf->proc_data.rotate == 90 || ++ pxp_conf->proc_data.rotate == 270) { ++ if (pxp_conf->proc_data.rot_pos == 1) { ++ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->height - 1) | ++ BF_PXP_OUT_AS_LRC_Y(olparams_data->width - 1), ++ pxp->base + HW_PXP_OUT_AS_LRC); ++ } else { ++ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) | ++ BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1), ++ pxp->base + HW_PXP_OUT_AS_LRC); ++ } ++ } else { ++ __raw_writel(BF_PXP_OUT_AS_LRC_X(olparams_data->width - 1) | ++ BF_PXP_OUT_AS_LRC_Y(olparams_data->height - 1), ++ pxp->base + HW_PXP_OUT_AS_LRC); ++ } ++ } ++ ++ if ((olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) | ++ (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32)) { ++ __raw_writel(pitch << 2, ++ pxp->base + HW_PXP_AS_PITCH); ++ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) { ++ __raw_writel(pitch << 1, ++ pxp->base + HW_PXP_AS_PITCH); ++ } else { ++ __raw_writel(0, pxp->base + HW_PXP_AS_PITCH); ++ } ++} ++ ++static void pxp_set_olparam(int layer_no, struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *olparams_data = &pxp_conf->ol_param[layer_no]; ++ u32 olparam; ++ ++ olparam = BF_PXP_AS_CTRL_ALPHA(olparams_data->global_alpha); ++ if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB32) { ++ olparam |= ++ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB888); ++ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_BGRA32) { ++ olparam |= ++ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__ARGB8888); ++ if (!olparams_data->combine_enable) { ++ olparam |= ++ BF_PXP_AS_CTRL_ALPHA_CTRL ++ (BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs); ++ olparam |= 0x3 << 16; ++ } ++ } else if (olparams_data->pixel_fmt == PXP_PIX_FMT_RGB565) { ++ olparam |= ++ BF_PXP_AS_CTRL_FORMAT(BV_PXP_AS_CTRL_FORMAT__RGB565); ++ } ++ if (olparams_data->global_alpha_enable) { ++ if (olparams_data->global_override) { ++ olparam |= ++ BF_PXP_AS_CTRL_ALPHA_CTRL ++ (BV_PXP_AS_CTRL_ALPHA_CTRL__Override); ++ } else { ++ olparam |= ++ BF_PXP_AS_CTRL_ALPHA_CTRL ++ (BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply); ++ } ++ if (olparams_data->alpha_invert) ++ olparam |= BM_PXP_AS_CTRL_ALPHA_INVERT; ++ } ++ if (olparams_data->color_key_enable) ++ olparam |= BM_PXP_AS_CTRL_ENABLE_COLORKEY; ++ ++ __raw_writel(olparam, pxp->base + HW_PXP_AS_CTRL); ++} ++ ++static void pxp_set_s0param(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; ++ u32 s0param; ++ ++ /* contains the coordinate for the PS in the OUTPUT buffer. */ ++ if ((pxp_conf->s0_param).width == 0 && ++ (pxp_conf->s0_param).height == 0) { ++ __raw_writel(0xffffffff, pxp->base + HW_PXP_OUT_PS_ULC); ++ __raw_writel(0x0, pxp->base + HW_PXP_OUT_PS_LRC); ++ } else { ++ s0param = BF_PXP_OUT_PS_ULC_X(proc_data->drect.left); ++ s0param |= BF_PXP_OUT_PS_ULC_Y(proc_data->drect.top); ++ __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_ULC); ++ s0param = BF_PXP_OUT_PS_LRC_X(proc_data->drect.left + ++ proc_data->drect.width - 1); ++ s0param |= BF_PXP_OUT_PS_LRC_Y(proc_data->drect.top + ++ proc_data->drect.height - 1); ++ __raw_writel(s0param, pxp->base + HW_PXP_OUT_PS_LRC); ++ } ++} ++ ++/* crop behavior is re-designed in h/w. */ ++static void pxp_set_s0crop(struct pxps *pxp) ++{ ++ /* ++ * place-holder, it's implemented in other functions in this driver. ++ * Refer to "Clipping source images" section in RM for detail. ++ */ ++} ++ ++static int pxp_set_scaling(struct pxps *pxp) ++{ ++ int ret = 0; ++ u32 xscale, yscale, s0scale; ++ u32 decx, decy, xdec = 0, ydec = 0; ++ struct pxp_proc_data *proc_data = &pxp->pxp_conf_state.proc_data; ++ ++ if (((proc_data->srect.width == proc_data->drect.width) && ++ (proc_data->srect.height == proc_data->drect.height)) || ++ ((proc_data->srect.width == 0) && (proc_data->srect.height == 0))) { ++ proc_data->scaling = 0; ++ __raw_writel(0x10001000, pxp->base + HW_PXP_PS_SCALE); ++ __raw_writel(0, pxp->base + HW_PXP_PS_CTRL); ++ goto out; ++ } ++ ++ proc_data->scaling = 1; ++ decx = proc_data->srect.width / proc_data->drect.width; ++ decy = proc_data->srect.height / proc_data->drect.height; ++ if (decx > 0) { ++ if (decx >= 2 && decx < 4) { ++ decx = 2; ++ xdec = 1; ++ } else if (decx >= 4 && decx < 8) { ++ decx = 4; ++ xdec = 2; ++ } else if (decx >= 8) { ++ decx = 8; ++ xdec = 3; ++ } ++ xscale = proc_data->srect.width * 0x1000 / ++ (proc_data->drect.width * decx); ++ } else ++ xscale = proc_data->srect.width * 0x1000 / ++ proc_data->drect.width; ++ if (decy > 0) { ++ if (decy >= 2 && decy < 4) { ++ decy = 2; ++ ydec = 1; ++ } else if (decy >= 4 && decy < 8) { ++ decy = 4; ++ ydec = 2; ++ } else if (decy >= 8) { ++ decy = 8; ++ ydec = 3; ++ } ++ yscale = proc_data->srect.height * 0x1000 / ++ (proc_data->drect.height * decy); ++ } else ++ yscale = proc_data->srect.height * 0x1000 / ++ proc_data->drect.height; ++ ++ __raw_writel((xdec << 10) | (ydec << 8), pxp->base + HW_PXP_PS_CTRL); ++ ++ if (xscale > PXP_DOWNSCALE_THRESHOLD) ++ xscale = PXP_DOWNSCALE_THRESHOLD; ++ if (yscale > PXP_DOWNSCALE_THRESHOLD) ++ yscale = PXP_DOWNSCALE_THRESHOLD; ++ s0scale = BF_PXP_PS_SCALE_YSCALE(yscale) | ++ BF_PXP_PS_SCALE_XSCALE(xscale); ++ __raw_writel(s0scale, pxp->base + HW_PXP_PS_SCALE); ++ ++out: ++ pxp_set_ctrl(pxp); ++ ++ return ret; ++} ++ ++static void pxp_set_bg(struct pxps *pxp) ++{ ++ __raw_writel(pxp->pxp_conf_state.proc_data.bgcolor, ++ pxp->base + HW_PXP_PS_BACKGROUND); ++} ++ ++static void pxp_set_lut(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ int lut_op = pxp_conf->proc_data.lut_transform; ++ u32 reg_val; ++ int i; ++ bool use_cmap = (lut_op & PXP_LUT_USE_CMAP) ? true : false; ++ u8 *cmap = pxp_conf->proc_data.lut_map; ++ u32 entry_src; ++ u32 pix_val; ++ u8 entry[4]; ++ ++ /* ++ * If LUT already configured as needed, return... ++ * Unless CMAP is needed and it has been updated. ++ */ ++ if ((pxp->lut_state == lut_op) && ++ !(use_cmap && pxp_conf->proc_data.lut_map_updated)) ++ return; ++ ++ if (lut_op == PXP_LUT_NONE) { ++ __raw_writel(BM_PXP_LUT_CTRL_BYPASS, ++ pxp->base + HW_PXP_LUT_CTRL); ++ } else if (((lut_op & PXP_LUT_INVERT) != 0) ++ && ((lut_op & PXP_LUT_BLACK_WHITE) != 0)) { ++ /* Fill out LUT table with inverted monochromized values */ ++ ++ /* clear bypass bit, set lookup mode & out mode */ ++ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE ++ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | ++ BF_PXP_LUT_CTRL_OUT_MODE ++ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), ++ pxp->base + HW_PXP_LUT_CTRL); ++ ++ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ ++ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); ++ ++ /* LUT address pointer auto-increments after each data write */ ++ for (pix_val = 0; pix_val < 256; pix_val += 4) { ++ for (i = 0; i < 4; i++) { ++ entry_src = use_cmap ? ++ cmap[pix_val + i] : pix_val + i; ++ entry[i] = (entry_src < 0x80) ? 0xFF : 0x00; ++ } ++ reg_val = (entry[3] << 24) | (entry[2] << 16) | ++ (entry[1] << 8) | entry[0]; ++ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); ++ } ++ } else if ((lut_op & PXP_LUT_INVERT) != 0) { ++ /* Fill out LUT table with 8-bit inverted values */ ++ ++ /* clear bypass bit, set lookup mode & out mode */ ++ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE ++ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | ++ BF_PXP_LUT_CTRL_OUT_MODE ++ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), ++ pxp->base + HW_PXP_LUT_CTRL); ++ ++ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ ++ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); ++ ++ /* LUT address pointer auto-increments after each data write */ ++ for (pix_val = 0; pix_val < 256; pix_val += 4) { ++ for (i = 0; i < 4; i++) { ++ entry_src = use_cmap ? ++ cmap[pix_val + i] : pix_val + i; ++ entry[i] = ~entry_src & 0xFF; ++ } ++ reg_val = (entry[3] << 24) | (entry[2] << 16) | ++ (entry[1] << 8) | entry[0]; ++ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); ++ } ++ } else if ((lut_op & PXP_LUT_BLACK_WHITE) != 0) { ++ /* Fill out LUT table with 8-bit monochromized values */ ++ ++ /* clear bypass bit, set lookup mode & out mode */ ++ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE ++ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | ++ BF_PXP_LUT_CTRL_OUT_MODE ++ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), ++ pxp->base + HW_PXP_LUT_CTRL); ++ ++ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ ++ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); ++ ++ /* LUT address pointer auto-increments after each data write */ ++ for (pix_val = 0; pix_val < 256; pix_val += 4) { ++ for (i = 0; i < 4; i++) { ++ entry_src = use_cmap ? ++ cmap[pix_val + i] : pix_val + i; ++ entry[i] = (entry_src < 0x80) ? 0x00 : 0xFF; ++ } ++ reg_val = (entry[3] << 24) | (entry[2] << 16) | ++ (entry[1] << 8) | entry[0]; ++ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); ++ } ++ } else if (use_cmap) { ++ /* Fill out LUT table using colormap values */ ++ ++ /* clear bypass bit, set lookup mode & out mode */ ++ __raw_writel(BF_PXP_LUT_CTRL_LOOKUP_MODE ++ (BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8) | ++ BF_PXP_LUT_CTRL_OUT_MODE ++ (BV_PXP_LUT_CTRL_OUT_MODE__Y8), ++ pxp->base + HW_PXP_LUT_CTRL); ++ ++ /* Initialize LUT address to 0 and set NUM_BYTES to 0 */ ++ __raw_writel(0, pxp->base + HW_PXP_LUT_ADDR); ++ ++ /* LUT address pointer auto-increments after each data write */ ++ for (pix_val = 0; pix_val < 256; pix_val += 4) { ++ for (i = 0; i < 4; i++) ++ entry[i] = cmap[pix_val + i]; ++ reg_val = (entry[3] << 24) | (entry[2] << 16) | ++ (entry[1] << 8) | entry[0]; ++ __raw_writel(reg_val, pxp->base + HW_PXP_LUT_DATA); ++ } ++ } ++ ++ pxp->lut_state = lut_op; ++} ++ ++static void pxp_set_csc(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; ++ struct pxp_layer_param *ol_params = &pxp_conf->ol_param[0]; ++ struct pxp_layer_param *out_params = &pxp_conf->out_param; ++ ++ bool input_is_YUV = is_yuv(s0_params->pixel_fmt); ++ bool output_is_YUV = is_yuv(out_params->pixel_fmt); ++ ++ if (input_is_YUV && output_is_YUV) { ++ /* ++ * Input = YUV, Output = YUV ++ * No CSC unless we need to do combining ++ */ ++ if (ol_params->combine_enable) { ++ /* Must convert to RGB for combining with RGB overlay */ ++ ++ /* CSC1 - YUV->RGB */ ++ __raw_writel(0x04030000, pxp->base + HW_PXP_CSC1_COEF0); ++ __raw_writel(0x01230208, pxp->base + HW_PXP_CSC1_COEF1); ++ __raw_writel(0x076b079c, pxp->base + HW_PXP_CSC1_COEF2); ++ ++ /* CSC2 - RGB->YUV */ ++ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); ++ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); ++ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); ++ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); ++ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); ++ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); ++ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); ++ } else { ++ /* Input & Output both YUV, so bypass both CSCs */ ++ ++ /* CSC1 - Bypass */ ++ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); ++ ++ /* CSC2 - Bypass */ ++ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); ++ } ++ } else if (input_is_YUV && !output_is_YUV) { ++ /* ++ * Input = YUV, Output = RGB ++ * Use CSC1 to convert to RGB ++ */ ++ ++ /* CSC1 - YUV->RGB */ ++ __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSC1_COEF0); ++ __raw_writel(0x01980204, pxp->base + HW_PXP_CSC1_COEF1); ++ __raw_writel(0x0730079c, pxp->base + HW_PXP_CSC1_COEF2); ++ ++ /* CSC2 - Bypass */ ++ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); ++ } else if (!input_is_YUV && output_is_YUV) { ++ /* ++ * Input = RGB, Output = YUV ++ * Use CSC2 to convert to YUV ++ */ ++ ++ /* CSC1 - Bypass */ ++ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); ++ ++ /* CSC2 - RGB->YUV */ ++ __raw_writel(0x4, pxp->base + HW_PXP_CSC2_CTRL); ++ __raw_writel(0x0096004D, pxp->base + HW_PXP_CSC2_COEF0); ++ __raw_writel(0x05DA001D, pxp->base + HW_PXP_CSC2_COEF1); ++ __raw_writel(0x007005B6, pxp->base + HW_PXP_CSC2_COEF2); ++ __raw_writel(0x057C009E, pxp->base + HW_PXP_CSC2_COEF3); ++ __raw_writel(0x000005E6, pxp->base + HW_PXP_CSC2_COEF4); ++ __raw_writel(0x00000000, pxp->base + HW_PXP_CSC2_COEF5); ++ } else { ++ /* ++ * Input = RGB, Output = RGB ++ * Input & Output both RGB, so bypass both CSCs ++ */ ++ ++ /* CSC1 - Bypass */ ++ __raw_writel(0x40000000, pxp->base + HW_PXP_CSC1_COEF0); ++ ++ /* CSC2 - Bypass */ ++ __raw_writel(0x1, pxp->base + HW_PXP_CSC2_CTRL); ++ } ++ ++ /* YCrCb colorspace */ ++ /* Not sure when we use this...no YCrCb formats are defined for PxP */ ++ /* ++ __raw_writel(0x84ab01f0, HW_PXP_CSCCOEFF0_ADDR); ++ __raw_writel(0x01230204, HW_PXP_CSCCOEFF1_ADDR); ++ __raw_writel(0x0730079c, HW_PXP_CSCCOEFF2_ADDR); ++ */ ++ ++} ++ ++static void pxp_set_s0buf(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_layer_param *s0_params = &pxp_conf->s0_param; ++ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; ++ dma_addr_t Y, U, V; ++ dma_addr_t Y1, U1, V1; ++ u32 offset, bpp = 1; ++ u32 pitch = s0_params->stride ? s0_params->stride : ++ s0_params->width; ++ ++ Y = s0_params->paddr; ++ ++ if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) ++ bpp = 2; ++ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32) ++ bpp = 4; ++ offset = (proc_data->srect.top * s0_params->width + ++ proc_data->srect.left) * bpp; ++ /* clipping or cropping */ ++ Y1 = Y + offset; ++ __raw_writel(Y1, pxp->base + HW_PXP_PS_BUF); ++ if ((s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_GREY) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P)) { ++ /* Set to 1 if YUV format is 4:2:2 rather than 4:2:0 */ ++ int s = 2; ++ if (s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) ++ s = 1; ++ ++ offset = proc_data->srect.top * s0_params->width / 4 + ++ proc_data->srect.left / 2; ++ U = Y + (s0_params->width * s0_params->height); ++ U1 = U + offset; ++ V = U + ((s0_params->width * s0_params->height) >> s); ++ V1 = V + offset; ++ if (s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P) { ++ __raw_writel(V1, pxp->base + HW_PXP_PS_UBUF); ++ __raw_writel(U1, pxp->base + HW_PXP_PS_VBUF); ++ } else { ++ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF); ++ __raw_writel(V1, pxp->base + HW_PXP_PS_VBUF); ++ } ++ } else if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV12) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_NV21) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_NV16) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) { ++ int s = 2; ++ if ((s0_params->pixel_fmt == PXP_PIX_FMT_NV16) || ++ (s0_params->pixel_fmt == PXP_PIX_FMT_NV61)) ++ s = 1; ++ ++ offset = (proc_data->srect.top * s0_params->width + ++ proc_data->srect.left) / s; ++ U = Y + (s0_params->width * s0_params->height); ++ U1 = U + offset; ++ ++ __raw_writel(U1, pxp->base + HW_PXP_PS_UBUF); ++ } ++ ++ /* TODO: only support RGB565, Y8, Y4, YUV420 */ ++ if (s0_params->pixel_fmt == PXP_PIX_FMT_GREY || ++ s0_params->pixel_fmt == PXP_PIX_FMT_YUV420P || ++ s0_params->pixel_fmt == PXP_PIX_FMT_YVU420P || ++ s0_params->pixel_fmt == PXP_PIX_FMT_NV12 || ++ s0_params->pixel_fmt == PXP_PIX_FMT_NV21 || ++ s0_params->pixel_fmt == PXP_PIX_FMT_NV16 || ++ s0_params->pixel_fmt == PXP_PIX_FMT_NV61 || ++ s0_params->pixel_fmt == PXP_PIX_FMT_YUV422P) { ++ __raw_writel(pitch, pxp->base + HW_PXP_PS_PITCH); ++ } ++ else if (s0_params->pixel_fmt == PXP_PIX_FMT_GY04) ++ __raw_writel(pitch >> 1, ++ pxp->base + HW_PXP_PS_PITCH); ++ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB32) ++ __raw_writel(pitch << 2, ++ pxp->base + HW_PXP_PS_PITCH); ++ else if (s0_params->pixel_fmt == PXP_PIX_FMT_UYVY || ++ s0_params->pixel_fmt == PXP_PIX_FMT_YUYV || ++ s0_params->pixel_fmt == PXP_PIX_FMT_VYUY || ++ s0_params->pixel_fmt == PXP_PIX_FMT_YVYU) ++ __raw_writel(pitch << 1, ++ pxp->base + HW_PXP_PS_PITCH); ++ else if (s0_params->pixel_fmt == PXP_PIX_FMT_RGB565) ++ __raw_writel(pitch << 1, ++ pxp->base + HW_PXP_PS_PITCH); ++ else ++ __raw_writel(0, pxp->base + HW_PXP_PS_PITCH); ++} ++ ++/** ++ * pxp_config() - configure PxP for a processing task ++ * @pxps: PXP context. ++ * @pxp_chan: PXP channel. ++ * @return: 0 on success or negative error code on failure. ++ */ ++static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan) ++{ ++ struct pxp_config_data *pxp_conf_data = &pxp->pxp_conf_state; ++ int ol_nr; ++ int i; ++ ++ /* Configure PxP regs */ ++ pxp_set_ctrl(pxp); ++ pxp_set_s0param(pxp); ++ pxp_set_s0crop(pxp); ++ pxp_set_scaling(pxp); ++ ol_nr = pxp_conf_data->layer_nr - 2; ++ while (ol_nr > 0) { ++ i = pxp_conf_data->layer_nr - 2 - ol_nr; ++ pxp_set_oln(i, pxp); ++ pxp_set_olparam(i, pxp); ++ /* only the color key in higher overlay will take effect. */ ++ pxp_set_olcolorkey(i, pxp); ++ ol_nr--; ++ } ++ pxp_set_s0colorkey(pxp); ++ pxp_set_csc(pxp); ++ pxp_set_bg(pxp); ++ pxp_set_lut(pxp); ++ ++ pxp_set_s0buf(pxp); ++ pxp_set_outbuf(pxp); ++ ++ return 0; ++} ++ ++static void pxp_clk_enable(struct pxps *pxp) ++{ ++ mutex_lock(&pxp->clk_mutex); ++ ++ if (pxp->clk_stat == CLK_STAT_ON) { ++ mutex_unlock(&pxp->clk_mutex); ++ return; ++ } ++ ++ clk_prepare_enable(pxp->clk); ++ pxp->clk_stat = CLK_STAT_ON; ++ ++ mutex_unlock(&pxp->clk_mutex); ++} ++ ++static void pxp_clk_disable(struct pxps *pxp) ++{ ++ unsigned long flags; ++ ++ mutex_lock(&pxp->clk_mutex); ++ ++ if (pxp->clk_stat == CLK_STAT_OFF) { ++ mutex_unlock(&pxp->clk_mutex); ++ return; ++ } ++ ++ spin_lock_irqsave(&pxp->lock, flags); ++ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) { ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ clk_disable_unprepare(pxp->clk); ++ pxp->clk_stat = CLK_STAT_OFF; ++ } else ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ ++ mutex_unlock(&pxp->clk_mutex); ++} ++ ++static inline void clkoff_callback(struct work_struct *w) ++{ ++ struct pxps *pxp = container_of(w, struct pxps, work); ++ ++ pxp_clk_disable(pxp); ++} ++ ++static void pxp_clkoff_timer(unsigned long arg) ++{ ++ struct pxps *pxp = (struct pxps *)arg; ++ ++ if ((pxp->pxp_ongoing == 0) && list_empty(&head)) ++ schedule_work(&pxp->work); ++ else ++ mod_timer(&pxp->clk_timer, ++ jiffies + msecs_to_jiffies(timeout_in_ms)); ++} ++ ++static struct pxp_tx_desc *pxpdma_first_queued(struct pxp_channel *pxp_chan) ++{ ++ return list_entry(pxp_chan->queue.next, struct pxp_tx_desc, list); ++} ++ ++/* called with pxp_chan->lock held */ ++static void __pxpdma_dostart(struct pxp_channel *pxp_chan) ++{ ++ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device); ++ struct pxps *pxp = to_pxp(pxp_dma); ++ struct pxp_tx_desc *desc; ++ struct pxp_tx_desc *child; ++ int i = 0; ++ ++ /* S0 */ ++ desc = list_first_entry(&head, struct pxp_tx_desc, list); ++ memcpy(&pxp->pxp_conf_state.s0_param, ++ &desc->layer_param.s0_param, sizeof(struct pxp_layer_param)); ++ memcpy(&pxp->pxp_conf_state.proc_data, ++ &desc->proc_data, sizeof(struct pxp_proc_data)); ++ ++ /* Save PxP configuration */ ++ list_for_each_entry(child, &desc->tx_list, list) { ++ if (i == 0) { /* Output */ ++ memcpy(&pxp->pxp_conf_state.out_param, ++ &child->layer_param.out_param, ++ sizeof(struct pxp_layer_param)); ++ } else { /* Overlay */ ++ memcpy(&pxp->pxp_conf_state.ol_param[i - 1], ++ &child->layer_param.ol_param, ++ sizeof(struct pxp_layer_param)); ++ } ++ ++ i++; ++ } ++ pr_debug("%s:%d S0 w/h %d/%d paddr %08x\n", __func__, __LINE__, ++ pxp->pxp_conf_state.s0_param.width, ++ pxp->pxp_conf_state.s0_param.height, ++ pxp->pxp_conf_state.s0_param.paddr); ++ pr_debug("%s:%d OUT w/h %d/%d paddr %08x\n", __func__, __LINE__, ++ pxp->pxp_conf_state.out_param.width, ++ pxp->pxp_conf_state.out_param.height, ++ pxp->pxp_conf_state.out_param.paddr); ++} ++ ++static void pxpdma_dostart_work(struct pxps *pxp) ++{ ++ struct pxp_channel *pxp_chan = NULL; ++ unsigned long flags; ++ struct pxp_tx_desc *desc = NULL; ++ ++ spin_lock_irqsave(&pxp->lock, flags); ++ ++ desc = list_entry(head.next, struct pxp_tx_desc, list); ++ pxp_chan = to_pxp_channel(desc->txd.chan); ++ ++ __pxpdma_dostart(pxp_chan); ++ ++ /* Configure PxP */ ++ pxp_config(pxp, pxp_chan); ++ ++ pxp_start(pxp); ++ ++ spin_unlock_irqrestore(&pxp->lock, flags); ++} ++ ++static void pxpdma_dequeue(struct pxp_channel *pxp_chan, struct pxps *pxp) ++{ ++ unsigned long flags; ++ struct pxp_tx_desc *desc = NULL; ++ ++ do { ++ desc = pxpdma_first_queued(pxp_chan); ++ spin_lock_irqsave(&pxp->lock, flags); ++ list_move_tail(&desc->list, &head); ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ } while (!list_empty(&pxp_chan->queue)); ++} ++ ++static dma_cookie_t pxp_tx_submit(struct dma_async_tx_descriptor *tx) ++{ ++ struct pxp_tx_desc *desc = to_tx_desc(tx); ++ struct pxp_channel *pxp_chan = to_pxp_channel(tx->chan); ++ dma_cookie_t cookie; ++ ++ dev_dbg(&pxp_chan->dma_chan.dev->device, "received TX\n"); ++ ++ /* pxp_chan->lock can be taken under ichan->lock, but not v.v. */ ++ spin_lock(&pxp_chan->lock); ++ ++ cookie = pxp_chan->dma_chan.cookie; ++ ++ if (++cookie < 0) ++ cookie = 1; ++ ++ /* from dmaengine.h: "last cookie value returned to client" */ ++ pxp_chan->dma_chan.cookie = cookie; ++ tx->cookie = cookie; ++ ++ /* Here we add the tx descriptor to our PxP task queue. */ ++ list_add_tail(&desc->list, &pxp_chan->queue); ++ ++ spin_unlock(&pxp_chan->lock); ++ ++ dev_dbg(&pxp_chan->dma_chan.dev->device, "done TX\n"); ++ ++ return cookie; ++} ++ ++/** ++ * pxp_init_channel() - initialize a PXP channel. ++ * @pxp_dma: PXP DMA context. ++ * @pchan: pointer to the channel object. ++ * @return 0 on success or negative error code on failure. ++ */ ++static int pxp_init_channel(struct pxp_dma *pxp_dma, ++ struct pxp_channel *pxp_chan) ++{ ++ int ret = 0; ++ ++ /* ++ * We are using _virtual_ channel here. ++ * Each channel contains all parameters of corresponding layers ++ * for one transaction; each layer is represented as one descriptor ++ * (i.e., pxp_tx_desc) here. ++ */ ++ ++ INIT_LIST_HEAD(&pxp_chan->queue); ++ ++ return ret; ++} ++ ++static irqreturn_t pxp_irq(int irq, void *dev_id) ++{ ++ struct pxps *pxp = dev_id; ++ struct pxp_channel *pxp_chan; ++ struct pxp_tx_desc *desc; ++ struct pxp_tx_desc *child, *_child; ++ dma_async_tx_callback callback; ++ void *callback_param; ++ unsigned long flags; ++ u32 hist_status; ++ ++ dump_pxp_reg(pxp); ++ ++ hist_status = ++ __raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS; ++ ++ __raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR); ++ ++ spin_lock_irqsave(&pxp->lock, flags); ++ ++ if (list_empty(&head)) { ++ pxp->pxp_ongoing = 0; ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ return IRQ_NONE; ++ } ++ ++ /* Get descriptor and call callback */ ++ desc = list_entry(head.next, struct pxp_tx_desc, list); ++ pxp_chan = to_pxp_channel(desc->txd.chan); ++ ++ pxp_chan->completed = desc->txd.cookie; ++ ++ callback = desc->txd.callback; ++ callback_param = desc->txd.callback_param; ++ ++ /* Send histogram status back to caller */ ++ desc->hist_status = hist_status; ++ ++ if ((desc->txd.flags & DMA_PREP_INTERRUPT) && callback) ++ callback(callback_param); ++ ++ pxp_chan->status = PXP_CHANNEL_INITIALIZED; ++ ++ list_for_each_entry_safe(child, _child, &desc->tx_list, list) { ++ list_del_init(&child->list); ++ kmem_cache_free(tx_desc_cache, (void *)child); ++ } ++ list_del_init(&desc->list); ++ kmem_cache_free(tx_desc_cache, (void *)desc); ++ ++ complete(&pxp->complete); ++ pxp->pxp_ongoing = 0; ++ mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(timeout_in_ms)); ++ ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ ++ return IRQ_HANDLED; ++} ++ ++/* allocate/free dma tx descriptor dynamically*/ ++static struct pxp_tx_desc *pxpdma_desc_alloc(struct pxp_channel *pxp_chan) ++{ ++ struct pxp_tx_desc *desc = NULL; ++ struct dma_async_tx_descriptor *txd = NULL; ++ ++ desc = kmem_cache_alloc(tx_desc_cache, GFP_KERNEL | __GFP_ZERO); ++ if (desc == NULL) ++ return NULL; ++ ++ INIT_LIST_HEAD(&desc->list); ++ INIT_LIST_HEAD(&desc->tx_list); ++ txd = &desc->txd; ++ dma_async_tx_descriptor_init(txd, &pxp_chan->dma_chan); ++ txd->tx_submit = pxp_tx_submit; ++ ++ return desc; ++} ++ ++/* Allocate and initialise a transfer descriptor. */ ++static struct dma_async_tx_descriptor *pxp_prep_slave_sg(struct dma_chan *chan, ++ struct scatterlist ++ *sgl, ++ unsigned int sg_len, ++ enum ++ dma_transfer_direction ++ direction, ++ unsigned long tx_flags, ++ void *context) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); ++ struct pxps *pxp = to_pxp(pxp_dma); ++ struct pxp_tx_desc *desc = NULL; ++ struct pxp_tx_desc *first = NULL, *prev = NULL; ++ struct scatterlist *sg; ++ dma_addr_t phys_addr; ++ int i; ++ ++ if (direction != DMA_DEV_TO_MEM && direction != DMA_MEM_TO_DEV) { ++ dev_err(chan->device->dev, "Invalid DMA direction %d!\n", ++ direction); ++ return NULL; ++ } ++ ++ if (unlikely(sg_len < 2)) ++ return NULL; ++ ++ for_each_sg(sgl, sg, sg_len, i) { ++ desc = pxpdma_desc_alloc(pxp_chan); ++ if (!desc) { ++ dev_err(chan->device->dev, "no enough memory to allocate tx descriptor\n"); ++ return NULL; ++ } ++ ++ phys_addr = sg_dma_address(sg); ++ ++ if (!first) { ++ first = desc; ++ ++ desc->layer_param.s0_param.paddr = phys_addr; ++ } else { ++ list_add_tail(&desc->list, &first->tx_list); ++ prev->next = desc; ++ desc->next = NULL; ++ ++ if (i == 1) ++ desc->layer_param.out_param.paddr = phys_addr; ++ else ++ desc->layer_param.ol_param.paddr = phys_addr; ++ } ++ ++ prev = desc; ++ } ++ ++ pxp->pxp_conf_state.layer_nr = sg_len; ++ first->txd.flags = tx_flags; ++ first->len = sg_len; ++ pr_debug("%s:%d first %p, first->len %d, flags %08x\n", ++ __func__, __LINE__, first, first->len, first->txd.flags); ++ ++ return &first->txd; ++} ++ ++static void pxp_issue_pending(struct dma_chan *chan) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); ++ struct pxps *pxp = to_pxp(pxp_dma); ++ ++ spin_lock(&pxp_chan->lock); ++ ++ if (list_empty(&pxp_chan->queue)) { ++ spin_unlock(&pxp_chan->lock); ++ return; ++ } ++ ++ pxpdma_dequeue(pxp_chan, pxp); ++ pxp_chan->status = PXP_CHANNEL_READY; ++ ++ spin_unlock(&pxp_chan->lock); ++ ++ pxp_clk_enable(pxp); ++ wake_up_interruptible(&pxp->thread_waitq); ++} ++ ++static void __pxp_terminate_all(struct dma_chan *chan) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ ++ pxp_chan->status = PXP_CHANNEL_INITIALIZED; ++} ++ ++static int pxp_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ++ unsigned long arg) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ ++ /* Only supports DMA_TERMINATE_ALL */ ++ if (cmd != DMA_TERMINATE_ALL) ++ return -ENXIO; ++ ++ spin_lock(&pxp_chan->lock); ++ __pxp_terminate_all(chan); ++ spin_unlock(&pxp_chan->lock); ++ ++ return 0; ++} ++ ++static int pxp_alloc_chan_resources(struct dma_chan *chan) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ struct pxp_dma *pxp_dma = to_pxp_dma(chan->device); ++ int ret; ++ ++ /* dmaengine.c now guarantees to only offer free channels */ ++ BUG_ON(chan->client_count > 1); ++ WARN_ON(pxp_chan->status != PXP_CHANNEL_FREE); ++ ++ chan->cookie = 1; ++ pxp_chan->completed = -ENXIO; ++ ++ pr_debug("%s dma_chan.chan_id %d\n", __func__, chan->chan_id); ++ ret = pxp_init_channel(pxp_dma, pxp_chan); ++ if (ret < 0) ++ goto err_chan; ++ ++ pxp_chan->status = PXP_CHANNEL_INITIALIZED; ++ ++ dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n", ++ chan->chan_id, pxp_chan->eof_irq); ++ ++ return ret; ++ ++err_chan: ++ return ret; ++} ++ ++static void pxp_free_chan_resources(struct dma_chan *chan) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ ++ spin_lock(&pxp_chan->lock); ++ ++ __pxp_terminate_all(chan); ++ ++ pxp_chan->status = PXP_CHANNEL_FREE; ++ ++ spin_unlock(&pxp_chan->lock); ++} ++ ++static enum dma_status pxp_tx_status(struct dma_chan *chan, ++ dma_cookie_t cookie, ++ struct dma_tx_state *txstate) ++{ ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ ++ if (cookie != chan->cookie) ++ return DMA_ERROR; ++ ++ if (txstate) { ++ txstate->last = pxp_chan->completed; ++ txstate->used = chan->cookie; ++ txstate->residue = 0; ++ } ++ return DMA_COMPLETE; ++} ++ ++static int pxp_hw_init(struct pxps *pxp) ++{ ++ struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state; ++ struct pxp_proc_data *proc_data = &pxp_conf->proc_data; ++ u32 reg_val; ++ ++ /* Pull PxP out of reset */ ++ __raw_writel(0, pxp->base + HW_PXP_CTRL); ++ ++ /* Config defaults */ ++ ++ /* Initialize non-channel-specific PxP parameters */ ++ proc_data->drect.left = proc_data->srect.left = 0; ++ proc_data->drect.top = proc_data->srect.top = 0; ++ proc_data->drect.width = proc_data->srect.width = 0; ++ proc_data->drect.height = proc_data->srect.height = 0; ++ proc_data->scaling = 0; ++ proc_data->hflip = 0; ++ proc_data->vflip = 0; ++ proc_data->rotate = 0; ++ proc_data->bgcolor = 0; ++ ++ /* Initialize S0 channel parameters */ ++ pxp_conf->s0_param.pixel_fmt = pxp_s0_formats[0]; ++ pxp_conf->s0_param.width = 0; ++ pxp_conf->s0_param.height = 0; ++ pxp_conf->s0_param.color_key = -1; ++ pxp_conf->s0_param.color_key_enable = false; ++ ++ /* Initialize OL channel parameters */ ++ pxp_conf->ol_param[0].combine_enable = false; ++ pxp_conf->ol_param[0].width = 0; ++ pxp_conf->ol_param[0].height = 0; ++ pxp_conf->ol_param[0].pixel_fmt = PXP_PIX_FMT_RGB565; ++ pxp_conf->ol_param[0].color_key_enable = false; ++ pxp_conf->ol_param[0].color_key = -1; ++ pxp_conf->ol_param[0].global_alpha_enable = false; ++ pxp_conf->ol_param[0].global_alpha = 0; ++ pxp_conf->ol_param[0].local_alpha_enable = false; ++ ++ /* Initialize Output channel parameters */ ++ pxp_conf->out_param.width = 0; ++ pxp_conf->out_param.height = 0; ++ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565; ++ ++ proc_data->overlay_state = 0; ++ ++ /* Write default h/w config */ ++ pxp_set_ctrl(pxp); ++ pxp_set_s0param(pxp); ++ pxp_set_s0crop(pxp); ++ /* ++ * simply program the ULC to a higher value than the LRC ++ * to avoid any AS pixels to show up in the output buffer. ++ */ ++ __raw_writel(0xFFFFFFFF, pxp->base + HW_PXP_OUT_AS_ULC); ++ pxp_set_olparam(0, pxp); ++ pxp_set_olcolorkey(0, pxp); ++ ++ pxp_set_s0colorkey(pxp); ++ pxp_set_csc(pxp); ++ pxp_set_bg(pxp); ++ pxp_set_lut(pxp); ++ ++ /* One-time histogram configuration */ ++ reg_val = ++ BF_PXP_HIST_CTRL_PANEL_MODE(BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST_CTRL); ++ ++ reg_val = BF_PXP_HIST2_PARAM_VALUE0(0x00) | ++ BF_PXP_HIST2_PARAM_VALUE1(0x00F); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST2_PARAM); ++ ++ reg_val = BF_PXP_HIST4_PARAM_VALUE0(0x00) | ++ BF_PXP_HIST4_PARAM_VALUE1(0x05) | ++ BF_PXP_HIST4_PARAM_VALUE2(0x0A) | BF_PXP_HIST4_PARAM_VALUE3(0x0F); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST4_PARAM); ++ ++ reg_val = BF_PXP_HIST8_PARAM0_VALUE0(0x00) | ++ BF_PXP_HIST8_PARAM0_VALUE1(0x02) | ++ BF_PXP_HIST8_PARAM0_VALUE2(0x04) | BF_PXP_HIST8_PARAM0_VALUE3(0x06); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM0); ++ reg_val = BF_PXP_HIST8_PARAM1_VALUE4(0x09) | ++ BF_PXP_HIST8_PARAM1_VALUE5(0x0B) | ++ BF_PXP_HIST8_PARAM1_VALUE6(0x0D) | BF_PXP_HIST8_PARAM1_VALUE7(0x0F); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST8_PARAM1); ++ ++ reg_val = BF_PXP_HIST16_PARAM0_VALUE0(0x00) | ++ BF_PXP_HIST16_PARAM0_VALUE1(0x01) | ++ BF_PXP_HIST16_PARAM0_VALUE2(0x02) | ++ BF_PXP_HIST16_PARAM0_VALUE3(0x03); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM0); ++ reg_val = BF_PXP_HIST16_PARAM1_VALUE4(0x04) | ++ BF_PXP_HIST16_PARAM1_VALUE5(0x05) | ++ BF_PXP_HIST16_PARAM1_VALUE6(0x06) | ++ BF_PXP_HIST16_PARAM1_VALUE7(0x07); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM1); ++ reg_val = BF_PXP_HIST16_PARAM2_VALUE8(0x08) | ++ BF_PXP_HIST16_PARAM2_VALUE9(0x09) | ++ BF_PXP_HIST16_PARAM2_VALUE10(0x0A) | ++ BF_PXP_HIST16_PARAM2_VALUE11(0x0B); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM2); ++ reg_val = BF_PXP_HIST16_PARAM3_VALUE12(0x0C) | ++ BF_PXP_HIST16_PARAM3_VALUE13(0x0D) | ++ BF_PXP_HIST16_PARAM3_VALUE14(0x0E) | ++ BF_PXP_HIST16_PARAM3_VALUE15(0x0F); ++ __raw_writel(reg_val, pxp->base + HW_PXP_HIST16_PARAM3); ++ ++ return 0; ++} ++ ++static int pxp_dma_init(struct pxps *pxp) ++{ ++ struct pxp_dma *pxp_dma = &pxp->pxp_dma; ++ struct dma_device *dma = &pxp_dma->dma; ++ int i; ++ ++ dma_cap_set(DMA_SLAVE, dma->cap_mask); ++ dma_cap_set(DMA_PRIVATE, dma->cap_mask); ++ ++ /* Compulsory common fields */ ++ dma->dev = pxp->dev; ++ dma->device_alloc_chan_resources = pxp_alloc_chan_resources; ++ dma->device_free_chan_resources = pxp_free_chan_resources; ++ dma->device_tx_status = pxp_tx_status; ++ dma->device_issue_pending = pxp_issue_pending; ++ ++ /* Compulsory for DMA_SLAVE fields */ ++ dma->device_prep_slave_sg = pxp_prep_slave_sg; ++ dma->device_control = pxp_control; ++ ++ /* Initialize PxP Channels */ ++ INIT_LIST_HEAD(&dma->channels); ++ for (i = 0; i < NR_PXP_VIRT_CHANNEL; i++) { ++ struct pxp_channel *pxp_chan = pxp->channel + i; ++ struct dma_chan *dma_chan = &pxp_chan->dma_chan; ++ ++ spin_lock_init(&pxp_chan->lock); ++ ++ /* Only one EOF IRQ for PxP, shared by all channels */ ++ pxp_chan->eof_irq = pxp->irq; ++ pxp_chan->status = PXP_CHANNEL_FREE; ++ pxp_chan->completed = -ENXIO; ++ snprintf(pxp_chan->eof_name, sizeof(pxp_chan->eof_name), ++ "PXP EOF %d", i); ++ ++ dma_chan->device = &pxp_dma->dma; ++ dma_chan->cookie = 1; ++ dma_chan->chan_id = i; ++ list_add_tail(&dma_chan->device_node, &dma->channels); ++ } ++ ++ return dma_async_device_register(&pxp_dma->dma); ++} ++ ++static ssize_t clk_off_timeout_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%d\n", timeout_in_ms); ++} ++ ++static ssize_t clk_off_timeout_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int val; ++ if (sscanf(buf, "%d", &val) > 0) { ++ timeout_in_ms = val; ++ return count; ++ } ++ return -EINVAL; ++} ++ ++static DEVICE_ATTR(clk_off_timeout, 0644, clk_off_timeout_show, ++ clk_off_timeout_store); ++ ++static ssize_t block_size_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%d\n", block_size); ++} ++ ++static ssize_t block_size_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ char **last = NULL; ++ ++ block_size = simple_strtoul(buf, last, 0); ++ if (block_size > 1) ++ block_size = 1; ++ ++ return count; ++} ++static DEVICE_ATTR(block_size, S_IWUSR | S_IRUGO, ++ block_size_show, block_size_store); ++ ++static const struct of_device_id imx_pxpdma_dt_ids[] = { ++ { .compatible = "fsl,imx6dl-pxp-dma", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, imx_pxpdma_dt_ids); ++ ++static int has_pending_task(struct pxps *pxp, struct pxp_channel *task) ++{ ++ int found; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&pxp->lock, flags); ++ found = !list_empty(&head); ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ ++ return found; ++} ++ ++static int pxp_dispatch_thread(void *argv) ++{ ++ struct pxps *pxp = (struct pxps *)argv; ++ struct pxp_channel *pending = NULL; ++ unsigned long flags; ++ ++ while (!kthread_should_stop()) { ++ int ret; ++ ret = wait_event_interruptible(pxp->thread_waitq, ++ has_pending_task(pxp, pending)); ++ if (signal_pending(current)) ++ continue; ++ ++ if (kthread_should_stop()) ++ break; ++ ++ spin_lock_irqsave(&pxp->lock, flags); ++ pxp->pxp_ongoing = 1; ++ spin_unlock_irqrestore(&pxp->lock, flags); ++ init_completion(&pxp->complete); ++ pxpdma_dostart_work(pxp); ++ ret = wait_for_completion_timeout(&pxp->complete, 2 * HZ); ++ if (ret == 0) { ++ printk(KERN_EMERG "%s: task is timeout\n\n", __func__); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int pxp_probe(struct platform_device *pdev) ++{ ++ struct pxps *pxp; ++ struct resource *res; ++ int irq; ++ int err = 0; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ if (!res || irq < 0) { ++ err = -ENODEV; ++ goto exit; ++ } ++ ++ pxp = devm_kzalloc(&pdev->dev, sizeof(*pxp), GFP_KERNEL); ++ if (!pxp) { ++ dev_err(&pdev->dev, "failed to allocate control object\n"); ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ pxp->dev = &pdev->dev; ++ ++ platform_set_drvdata(pdev, pxp); ++ pxp->irq = irq; ++ ++ pxp->pxp_ongoing = 0; ++ pxp->lut_state = 0; ++ ++ spin_lock_init(&pxp->lock); ++ mutex_init(&pxp->clk_mutex); ++ ++ pxp->base = devm_request_and_ioremap(&pdev->dev, res); ++ if (pxp->base == NULL) { ++ dev_err(&pdev->dev, "Couldn't ioremap regs\n"); ++ err = -ENODEV; ++ goto exit; ++ } ++ ++ pxp->pdev = pdev; ++ ++ pxp->clk = devm_clk_get(&pdev->dev, "pxp-axi"); ++ clk_prepare_enable(pxp->clk); ++ ++ err = pxp_hw_init(pxp); ++ clk_disable_unprepare(pxp->clk); ++ if (err) { ++ dev_err(&pdev->dev, "failed to initialize hardware\n"); ++ goto exit; ++ } ++ ++ err = devm_request_irq(&pdev->dev, pxp->irq, pxp_irq, 0, ++ "pxp-dmaengine", pxp); ++ if (err) ++ goto exit; ++ /* Initialize DMA engine */ ++ err = pxp_dma_init(pxp); ++ if (err < 0) ++ goto exit; ++ ++ if (device_create_file(&pdev->dev, &dev_attr_clk_off_timeout)) { ++ dev_err(&pdev->dev, ++ "Unable to create file from clk_off_timeout\n"); ++ goto exit; ++ } ++ ++ device_create_file(&pdev->dev, &dev_attr_block_size); ++ dump_pxp_reg(pxp); ++ ++ INIT_WORK(&pxp->work, clkoff_callback); ++ init_timer(&pxp->clk_timer); ++ pxp->clk_timer.function = pxp_clkoff_timer; ++ pxp->clk_timer.data = (unsigned long)pxp; ++ ++ /* allocate a kernel thread to dispatch pxp conf */ ++ pxp->dispatch = kthread_run(pxp_dispatch_thread, pxp, "pxp_dispatch"); ++ if (IS_ERR(pxp->dispatch)) { ++ err = PTR_ERR(pxp->dispatch); ++ goto exit; ++ } ++ init_waitqueue_head(&pxp->thread_waitq); ++ tx_desc_cache = kmem_cache_create("tx_desc", sizeof(struct pxp_tx_desc), ++ 0, SLAB_HWCACHE_ALIGN, NULL); ++ if (!tx_desc_cache) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ register_pxp_device(); ++ ++exit: ++ if (err) ++ dev_err(&pdev->dev, "Exiting (unsuccessfully) pxp_probe()\n"); ++ return err; ++} ++ ++static int pxp_remove(struct platform_device *pdev) ++{ ++ struct pxps *pxp = platform_get_drvdata(pdev); ++ ++ unregister_pxp_device(); ++ kmem_cache_destroy(tx_desc_cache); ++ kthread_stop(pxp->dispatch); ++ cancel_work_sync(&pxp->work); ++ del_timer_sync(&pxp->clk_timer); ++ clk_disable_unprepare(pxp->clk); ++ device_remove_file(&pdev->dev, &dev_attr_clk_off_timeout); ++ device_remove_file(&pdev->dev, &dev_attr_block_size); ++ dma_async_device_unregister(&(pxp->pxp_dma.dma)); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_PM ++static int pxp_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ struct pxps *pxp = platform_get_drvdata(pdev); ++ ++ pxp_clk_enable(pxp); ++ while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE) ++ ; ++ ++ __raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL); ++ pxp_clk_disable(pxp); ++ ++ return 0; ++} ++ ++static int pxp_resume(struct platform_device *pdev) ++{ ++ struct pxps *pxp = platform_get_drvdata(pdev); ++ ++ pxp_clk_enable(pxp); ++ /* Pull PxP out of reset */ ++ __raw_writel(0, pxp->base + HW_PXP_CTRL); ++ pxp_clk_disable(pxp); ++ ++ return 0; ++} ++#else ++#define pxp_suspend NULL ++#define pxp_resume NULL ++#endif ++ ++static struct platform_driver pxp_driver = { ++ .driver = { ++ .name = "imx-pxp", ++ .of_match_table = of_match_ptr(imx_pxpdma_dt_ids), ++ }, ++ .probe = pxp_probe, ++ .remove = pxp_remove, ++ .suspend = pxp_suspend, ++ .resume = pxp_resume, ++}; ++ ++module_platform_driver(pxp_driver); ++ ++ ++MODULE_DESCRIPTION("i.MX PxP driver"); ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/dma/pxp/regs-pxp_v2.h linux-imx6-3.14/drivers/dma/pxp/regs-pxp_v2.h +--- linux-3.14.14/drivers/dma/pxp/regs-pxp_v2.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/dma/pxp/regs-pxp_v2.h 2014-12-08 00:31:52.576418001 -0600 +@@ -0,0 +1,1152 @@ ++/* ++ * Freescale PXP Register Definitions ++ * ++ * Copyright (C) 2012-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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ * This file is created by xml file. Don't Edit it. ++ * ++ * Xml Revision: 1.29 ++ * Template revision: 1.3 ++ */ ++ ++#ifndef __ARCH_ARM___PXP_H ++#define __ARCH_ARM___PXP_H ++ ++#define HW_PXP_CTRL (0x00000000) ++#define HW_PXP_CTRL_SET (0x00000004) ++#define HW_PXP_CTRL_CLR (0x00000008) ++#define HW_PXP_CTRL_TOG (0x0000000c) ++ ++#define BM_PXP_CTRL_SFTRST 0x80000000 ++#define BM_PXP_CTRL_CLKGATE 0x40000000 ++#define BM_PXP_CTRL_RSVD4 0x20000000 ++#define BM_PXP_CTRL_EN_REPEAT 0x10000000 ++#define BP_PXP_CTRL_RSVD3 26 ++#define BM_PXP_CTRL_RSVD3 0x0C000000 ++#define BF_PXP_CTRL_RSVD3(v) \ ++ (((v) << 26) & BM_PXP_CTRL_RSVD3) ++#define BP_PXP_CTRL_INTERLACED_INPUT 24 ++#define BM_PXP_CTRL_INTERLACED_INPUT 0x03000000 ++#define BF_PXP_CTRL_INTERLACED_INPUT(v) \ ++ (((v) << 24) & BM_PXP_CTRL_INTERLACED_INPUT) ++#define BV_PXP_CTRL_INTERLACED_INPUT__PROGRESSIVE 0x0 ++#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD0 0x2 ++#define BV_PXP_CTRL_INTERLACED_INPUT__FIELD1 0x3 ++#define BM_PXP_CTRL_BLOCK_SIZE 0x00800000 ++#define BV_PXP_CTRL_BLOCK_SIZE__8X8 0x0 ++#define BV_PXP_CTRL_BLOCK_SIZE__16X16 0x1 ++#define BM_PXP_CTRL_ROT_POS 0x00400000 ++#define BM_PXP_CTRL_IN_PLACE 0x00200000 ++#define BP_PXP_CTRL_RSVD1 12 ++#define BM_PXP_CTRL_RSVD1 0x001FF000 ++#define BF_PXP_CTRL_RSVD1(v) \ ++ (((v) << 12) & BM_PXP_CTRL_RSVD1) ++#define BM_PXP_CTRL_VFLIP 0x00000800 ++#define BM_PXP_CTRL_HFLIP 0x00000400 ++#define BP_PXP_CTRL_ROTATE 8 ++#define BM_PXP_CTRL_ROTATE 0x00000300 ++#define BF_PXP_CTRL_ROTATE(v) \ ++ (((v) << 8) & BM_PXP_CTRL_ROTATE) ++#define BV_PXP_CTRL_ROTATE__ROT_0 0x0 ++#define BV_PXP_CTRL_ROTATE__ROT_90 0x1 ++#define BV_PXP_CTRL_ROTATE__ROT_180 0x2 ++#define BV_PXP_CTRL_ROTATE__ROT_270 0x3 ++#define BP_PXP_CTRL_RSVD0 5 ++#define BM_PXP_CTRL_RSVD0 0x000000E0 ++#define BF_PXP_CTRL_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_CTRL_RSVD0) ++#define BM_PXP_CTRL_ENABLE_LCD_HANDSHAKE 0x00000010 ++#define BM_PXP_CTRL_LUT_DMA_IRQ_ENABLE 0x00000008 ++#define BM_PXP_CTRL_NEXT_IRQ_ENABLE 0x00000004 ++#define BM_PXP_CTRL_IRQ_ENABLE 0x00000002 ++#define BM_PXP_CTRL_ENABLE 0x00000001 ++ ++#define HW_PXP_STAT (0x00000010) ++#define HW_PXP_STAT_SET (0x00000014) ++#define HW_PXP_STAT_CLR (0x00000018) ++#define HW_PXP_STAT_TOG (0x0000001c) ++ ++#define BP_PXP_STAT_BLOCKX 24 ++#define BM_PXP_STAT_BLOCKX 0xFF000000 ++#define BF_PXP_STAT_BLOCKX(v) \ ++ (((v) << 24) & BM_PXP_STAT_BLOCKX) ++#define BP_PXP_STAT_BLOCKY 16 ++#define BM_PXP_STAT_BLOCKY 0x00FF0000 ++#define BF_PXP_STAT_BLOCKY(v) \ ++ (((v) << 16) & BM_PXP_STAT_BLOCKY) ++#define BP_PXP_STAT_RSVD2 9 ++#define BM_PXP_STAT_RSVD2 0x0000FE00 ++#define BF_PXP_STAT_RSVD2(v) \ ++ (((v) << 9) & BM_PXP_STAT_RSVD2) ++#define BM_PXP_STAT_LUT_DMA_LOAD_DONE_IRQ 0x00000100 ++#define BP_PXP_STAT_AXI_ERROR_ID 4 ++#define BM_PXP_STAT_AXI_ERROR_ID 0x000000F0 ++#define BF_PXP_STAT_AXI_ERROR_ID(v) \ ++ (((v) << 4) & BM_PXP_STAT_AXI_ERROR_ID) ++#define BM_PXP_STAT_NEXT_IRQ 0x00000008 ++#define BM_PXP_STAT_AXI_READ_ERROR 0x00000004 ++#define BM_PXP_STAT_AXI_WRITE_ERROR 0x00000002 ++#define BM_PXP_STAT_IRQ 0x00000001 ++ ++#define HW_PXP_OUT_CTRL (0x00000020) ++#define HW_PXP_OUT_CTRL_SET (0x00000024) ++#define HW_PXP_OUT_CTRL_CLR (0x00000028) ++#define HW_PXP_OUT_CTRL_TOG (0x0000002c) ++ ++#define BP_PXP_OUT_CTRL_ALPHA 24 ++#define BM_PXP_OUT_CTRL_ALPHA 0xFF000000 ++#define BF_PXP_OUT_CTRL_ALPHA(v) \ ++ (((v) << 24) & BM_PXP_OUT_CTRL_ALPHA) ++#define BM_PXP_OUT_CTRL_ALPHA_OUTPUT 0x00800000 ++#define BP_PXP_OUT_CTRL_RSVD1 10 ++#define BM_PXP_OUT_CTRL_RSVD1 0x007FFC00 ++#define BF_PXP_OUT_CTRL_RSVD1(v) \ ++ (((v) << 10) & BM_PXP_OUT_CTRL_RSVD1) ++#define BP_PXP_OUT_CTRL_INTERLACED_OUTPUT 8 ++#define BM_PXP_OUT_CTRL_INTERLACED_OUTPUT 0x00000300 ++#define BF_PXP_OUT_CTRL_INTERLACED_OUTPUT(v) \ ++ (((v) << 8) & BM_PXP_OUT_CTRL_INTERLACED_OUTPUT) ++#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__PROGRESSIVE 0x0 ++#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD0 0x1 ++#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__FIELD1 0x2 ++#define BV_PXP_OUT_CTRL_INTERLACED_OUTPUT__INTERLACED 0x3 ++#define BP_PXP_OUT_CTRL_RSVD0 5 ++#define BM_PXP_OUT_CTRL_RSVD0 0x000000E0 ++#define BF_PXP_OUT_CTRL_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_OUT_CTRL_RSVD0) ++#define BP_PXP_OUT_CTRL_FORMAT 0 ++#define BM_PXP_OUT_CTRL_FORMAT 0x0000001F ++#define BF_PXP_OUT_CTRL_FORMAT(v) \ ++ (((v) << 0) & BM_PXP_OUT_CTRL_FORMAT) ++#define BV_PXP_OUT_CTRL_FORMAT__ARGB8888 0x0 ++#define BV_PXP_OUT_CTRL_FORMAT__RGB888 0x4 ++#define BV_PXP_OUT_CTRL_FORMAT__RGB888P 0x5 ++#define BV_PXP_OUT_CTRL_FORMAT__ARGB1555 0x8 ++#define BV_PXP_OUT_CTRL_FORMAT__ARGB4444 0x9 ++#define BV_PXP_OUT_CTRL_FORMAT__RGB555 0xC ++#define BV_PXP_OUT_CTRL_FORMAT__RGB444 0xD ++#define BV_PXP_OUT_CTRL_FORMAT__RGB565 0xE ++#define BV_PXP_OUT_CTRL_FORMAT__YUV1P444 0x10 ++#define BV_PXP_OUT_CTRL_FORMAT__UYVY1P422 0x12 ++#define BV_PXP_OUT_CTRL_FORMAT__VYUY1P422 0x13 ++#define BV_PXP_OUT_CTRL_FORMAT__Y8 0x14 ++#define BV_PXP_OUT_CTRL_FORMAT__Y4 0x15 ++#define BV_PXP_OUT_CTRL_FORMAT__YUV2P422 0x18 ++#define BV_PXP_OUT_CTRL_FORMAT__YUV2P420 0x19 ++#define BV_PXP_OUT_CTRL_FORMAT__YVU2P422 0x1A ++#define BV_PXP_OUT_CTRL_FORMAT__YVU2P420 0x1B ++ ++#define HW_PXP_OUT_BUF (0x00000030) ++ ++#define BP_PXP_OUT_BUF_ADDR 0 ++#define BM_PXP_OUT_BUF_ADDR 0xFFFFFFFF ++#define BF_PXP_OUT_BUF_ADDR(v) (v) ++ ++#define HW_PXP_OUT_BUF2 (0x00000040) ++ ++#define BP_PXP_OUT_BUF2_ADDR 0 ++#define BM_PXP_OUT_BUF2_ADDR 0xFFFFFFFF ++#define BF_PXP_OUT_BUF2_ADDR(v) (v) ++ ++#define HW_PXP_OUT_PITCH (0x00000050) ++ ++#define BP_PXP_OUT_PITCH_RSVD 16 ++#define BM_PXP_OUT_PITCH_RSVD 0xFFFF0000 ++#define BF_PXP_OUT_PITCH_RSVD(v) \ ++ (((v) << 16) & BM_PXP_OUT_PITCH_RSVD) ++#define BP_PXP_OUT_PITCH_PITCH 0 ++#define BM_PXP_OUT_PITCH_PITCH 0x0000FFFF ++#define BF_PXP_OUT_PITCH_PITCH(v) \ ++ (((v) << 0) & BM_PXP_OUT_PITCH_PITCH) ++ ++#define HW_PXP_OUT_LRC (0x00000060) ++ ++#define BP_PXP_OUT_LRC_RSVD1 30 ++#define BM_PXP_OUT_LRC_RSVD1 0xC0000000 ++#define BF_PXP_OUT_LRC_RSVD1(v) \ ++ (((v) << 30) & BM_PXP_OUT_LRC_RSVD1) ++#define BP_PXP_OUT_LRC_X 16 ++#define BM_PXP_OUT_LRC_X 0x3FFF0000 ++#define BF_PXP_OUT_LRC_X(v) \ ++ (((v) << 16) & BM_PXP_OUT_LRC_X) ++#define BP_PXP_OUT_LRC_RSVD0 14 ++#define BM_PXP_OUT_LRC_RSVD0 0x0000C000 ++#define BF_PXP_OUT_LRC_RSVD0(v) \ ++ (((v) << 14) & BM_PXP_OUT_LRC_RSVD0) ++#define BP_PXP_OUT_LRC_Y 0 ++#define BM_PXP_OUT_LRC_Y 0x00003FFF ++#define BF_PXP_OUT_LRC_Y(v) \ ++ (((v) << 0) & BM_PXP_OUT_LRC_Y) ++ ++#define HW_PXP_OUT_PS_ULC (0x00000070) ++ ++#define BP_PXP_OUT_PS_ULC_RSVD1 30 ++#define BM_PXP_OUT_PS_ULC_RSVD1 0xC0000000 ++#define BF_PXP_OUT_PS_ULC_RSVD1(v) \ ++ (((v) << 30) & BM_PXP_OUT_PS_ULC_RSVD1) ++#define BP_PXP_OUT_PS_ULC_X 16 ++#define BM_PXP_OUT_PS_ULC_X 0x3FFF0000 ++#define BF_PXP_OUT_PS_ULC_X(v) \ ++ (((v) << 16) & BM_PXP_OUT_PS_ULC_X) ++#define BP_PXP_OUT_PS_ULC_RSVD0 14 ++#define BM_PXP_OUT_PS_ULC_RSVD0 0x0000C000 ++#define BF_PXP_OUT_PS_ULC_RSVD0(v) \ ++ (((v) << 14) & BM_PXP_OUT_PS_ULC_RSVD0) ++#define BP_PXP_OUT_PS_ULC_Y 0 ++#define BM_PXP_OUT_PS_ULC_Y 0x00003FFF ++#define BF_PXP_OUT_PS_ULC_Y(v) \ ++ (((v) << 0) & BM_PXP_OUT_PS_ULC_Y) ++ ++#define HW_PXP_OUT_PS_LRC (0x00000080) ++ ++#define BP_PXP_OUT_PS_LRC_RSVD1 30 ++#define BM_PXP_OUT_PS_LRC_RSVD1 0xC0000000 ++#define BF_PXP_OUT_PS_LRC_RSVD1(v) \ ++ (((v) << 30) & BM_PXP_OUT_PS_LRC_RSVD1) ++#define BP_PXP_OUT_PS_LRC_X 16 ++#define BM_PXP_OUT_PS_LRC_X 0x3FFF0000 ++#define BF_PXP_OUT_PS_LRC_X(v) \ ++ (((v) << 16) & BM_PXP_OUT_PS_LRC_X) ++#define BP_PXP_OUT_PS_LRC_RSVD0 14 ++#define BM_PXP_OUT_PS_LRC_RSVD0 0x0000C000 ++#define BF_PXP_OUT_PS_LRC_RSVD0(v) \ ++ (((v) << 14) & BM_PXP_OUT_PS_LRC_RSVD0) ++#define BP_PXP_OUT_PS_LRC_Y 0 ++#define BM_PXP_OUT_PS_LRC_Y 0x00003FFF ++#define BF_PXP_OUT_PS_LRC_Y(v) \ ++ (((v) << 0) & BM_PXP_OUT_PS_LRC_Y) ++ ++#define HW_PXP_OUT_AS_ULC (0x00000090) ++ ++#define BP_PXP_OUT_AS_ULC_RSVD1 30 ++#define BM_PXP_OUT_AS_ULC_RSVD1 0xC0000000 ++#define BF_PXP_OUT_AS_ULC_RSVD1(v) \ ++ (((v) << 30) & BM_PXP_OUT_AS_ULC_RSVD1) ++#define BP_PXP_OUT_AS_ULC_X 16 ++#define BM_PXP_OUT_AS_ULC_X 0x3FFF0000 ++#define BF_PXP_OUT_AS_ULC_X(v) \ ++ (((v) << 16) & BM_PXP_OUT_AS_ULC_X) ++#define BP_PXP_OUT_AS_ULC_RSVD0 14 ++#define BM_PXP_OUT_AS_ULC_RSVD0 0x0000C000 ++#define BF_PXP_OUT_AS_ULC_RSVD0(v) \ ++ (((v) << 14) & BM_PXP_OUT_AS_ULC_RSVD0) ++#define BP_PXP_OUT_AS_ULC_Y 0 ++#define BM_PXP_OUT_AS_ULC_Y 0x00003FFF ++#define BF_PXP_OUT_AS_ULC_Y(v) \ ++ (((v) << 0) & BM_PXP_OUT_AS_ULC_Y) ++ ++#define HW_PXP_OUT_AS_LRC (0x000000a0) ++ ++#define BP_PXP_OUT_AS_LRC_RSVD1 30 ++#define BM_PXP_OUT_AS_LRC_RSVD1 0xC0000000 ++#define BF_PXP_OUT_AS_LRC_RSVD1(v) \ ++ (((v) << 30) & BM_PXP_OUT_AS_LRC_RSVD1) ++#define BP_PXP_OUT_AS_LRC_X 16 ++#define BM_PXP_OUT_AS_LRC_X 0x3FFF0000 ++#define BF_PXP_OUT_AS_LRC_X(v) \ ++ (((v) << 16) & BM_PXP_OUT_AS_LRC_X) ++#define BP_PXP_OUT_AS_LRC_RSVD0 14 ++#define BM_PXP_OUT_AS_LRC_RSVD0 0x0000C000 ++#define BF_PXP_OUT_AS_LRC_RSVD0(v) \ ++ (((v) << 14) & BM_PXP_OUT_AS_LRC_RSVD0) ++#define BP_PXP_OUT_AS_LRC_Y 0 ++#define BM_PXP_OUT_AS_LRC_Y 0x00003FFF ++#define BF_PXP_OUT_AS_LRC_Y(v) \ ++ (((v) << 0) & BM_PXP_OUT_AS_LRC_Y) ++ ++#define HW_PXP_PS_CTRL (0x000000b0) ++#define HW_PXP_PS_CTRL_SET (0x000000b4) ++#define HW_PXP_PS_CTRL_CLR (0x000000b8) ++#define HW_PXP_PS_CTRL_TOG (0x000000bc) ++ ++#define BP_PXP_PS_CTRL_RSVD1 12 ++#define BM_PXP_PS_CTRL_RSVD1 0xFFFFF000 ++#define BF_PXP_PS_CTRL_RSVD1(v) \ ++ (((v) << 12) & BM_PXP_PS_CTRL_RSVD1) ++#define BP_PXP_PS_CTRL_DECX 10 ++#define BM_PXP_PS_CTRL_DECX 0x00000C00 ++#define BF_PXP_PS_CTRL_DECX(v) \ ++ (((v) << 10) & BM_PXP_PS_CTRL_DECX) ++#define BV_PXP_PS_CTRL_DECX__DISABLE 0x0 ++#define BV_PXP_PS_CTRL_DECX__DECX2 0x1 ++#define BV_PXP_PS_CTRL_DECX__DECX4 0x2 ++#define BV_PXP_PS_CTRL_DECX__DECX8 0x3 ++#define BP_PXP_PS_CTRL_DECY 8 ++#define BM_PXP_PS_CTRL_DECY 0x00000300 ++#define BF_PXP_PS_CTRL_DECY(v) \ ++ (((v) << 8) & BM_PXP_PS_CTRL_DECY) ++#define BV_PXP_PS_CTRL_DECY__DISABLE 0x0 ++#define BV_PXP_PS_CTRL_DECY__DECY2 0x1 ++#define BV_PXP_PS_CTRL_DECY__DECY4 0x2 ++#define BV_PXP_PS_CTRL_DECY__DECY8 0x3 ++#define BP_PXP_PS_CTRL_SWAP 5 ++#define BM_PXP_PS_CTRL_SWAP 0x000000E0 ++#define BF_PXP_PS_CTRL_SWAP(v) \ ++ (((v) << 5) & BM_PXP_PS_CTRL_SWAP) ++#define BP_PXP_PS_CTRL_FORMAT 0 ++#define BM_PXP_PS_CTRL_FORMAT 0x0000001F ++#define BF_PXP_PS_CTRL_FORMAT(v) \ ++ (((v) << 0) & BM_PXP_PS_CTRL_FORMAT) ++#define BV_PXP_PS_CTRL_FORMAT__RGB888 0x4 ++#define BV_PXP_PS_CTRL_FORMAT__RGB555 0xC ++#define BV_PXP_PS_CTRL_FORMAT__RGB444 0xD ++#define BV_PXP_PS_CTRL_FORMAT__RGB565 0xE ++#define BV_PXP_PS_CTRL_FORMAT__YUV1P444 0x10 ++#define BV_PXP_PS_CTRL_FORMAT__UYVY1P422 0x12 ++#define BV_PXP_PS_CTRL_FORMAT__VYUY1P422 0x13 ++#define BV_PXP_PS_CTRL_FORMAT__Y8 0x14 ++#define BV_PXP_PS_CTRL_FORMAT__Y4 0x15 ++#define BV_PXP_PS_CTRL_FORMAT__YUV2P422 0x18 ++#define BV_PXP_PS_CTRL_FORMAT__YUV2P420 0x19 ++#define BV_PXP_PS_CTRL_FORMAT__YVU2P422 0x1A ++#define BV_PXP_PS_CTRL_FORMAT__YVU2P420 0x1B ++#define BV_PXP_PS_CTRL_FORMAT__YUV422 0x1E ++#define BV_PXP_PS_CTRL_FORMAT__YUV420 0x1F ++ ++#define HW_PXP_PS_BUF (0x000000c0) ++ ++#define BP_PXP_PS_BUF_ADDR 0 ++#define BM_PXP_PS_BUF_ADDR 0xFFFFFFFF ++#define BF_PXP_PS_BUF_ADDR(v) (v) ++ ++#define HW_PXP_PS_UBUF (0x000000d0) ++ ++#define BP_PXP_PS_UBUF_ADDR 0 ++#define BM_PXP_PS_UBUF_ADDR 0xFFFFFFFF ++#define BF_PXP_PS_UBUF_ADDR(v) (v) ++ ++#define HW_PXP_PS_VBUF (0x000000e0) ++ ++#define BP_PXP_PS_VBUF_ADDR 0 ++#define BM_PXP_PS_VBUF_ADDR 0xFFFFFFFF ++#define BF_PXP_PS_VBUF_ADDR(v) (v) ++ ++#define HW_PXP_PS_PITCH (0x000000f0) ++ ++#define BP_PXP_PS_PITCH_RSVD 16 ++#define BM_PXP_PS_PITCH_RSVD 0xFFFF0000 ++#define BF_PXP_PS_PITCH_RSVD(v) \ ++ (((v) << 16) & BM_PXP_PS_PITCH_RSVD) ++#define BP_PXP_PS_PITCH_PITCH 0 ++#define BM_PXP_PS_PITCH_PITCH 0x0000FFFF ++#define BF_PXP_PS_PITCH_PITCH(v) \ ++ (((v) << 0) & BM_PXP_PS_PITCH_PITCH) ++ ++#define HW_PXP_PS_BACKGROUND (0x00000100) ++ ++#define BP_PXP_PS_BACKGROUND_RSVD 24 ++#define BM_PXP_PS_BACKGROUND_RSVD 0xFF000000 ++#define BF_PXP_PS_BACKGROUND_RSVD(v) \ ++ (((v) << 24) & BM_PXP_PS_BACKGROUND_RSVD) ++#define BP_PXP_PS_BACKGROUND_COLOR 0 ++#define BM_PXP_PS_BACKGROUND_COLOR 0x00FFFFFF ++#define BF_PXP_PS_BACKGROUND_COLOR(v) \ ++ (((v) << 0) & BM_PXP_PS_BACKGROUND_COLOR) ++ ++#define HW_PXP_PS_SCALE (0x00000110) ++ ++#define BM_PXP_PS_SCALE_RSVD2 0x80000000 ++#define BP_PXP_PS_SCALE_YSCALE 16 ++#define BM_PXP_PS_SCALE_YSCALE 0x7FFF0000 ++#define BF_PXP_PS_SCALE_YSCALE(v) \ ++ (((v) << 16) & BM_PXP_PS_SCALE_YSCALE) ++#define BM_PXP_PS_SCALE_RSVD1 0x00008000 ++#define BP_PXP_PS_SCALE_XSCALE 0 ++#define BM_PXP_PS_SCALE_XSCALE 0x00007FFF ++#define BF_PXP_PS_SCALE_XSCALE(v) \ ++ (((v) << 0) & BM_PXP_PS_SCALE_XSCALE) ++ ++#define HW_PXP_PS_OFFSET (0x00000120) ++ ++#define BP_PXP_PS_OFFSET_RSVD2 28 ++#define BM_PXP_PS_OFFSET_RSVD2 0xF0000000 ++#define BF_PXP_PS_OFFSET_RSVD2(v) \ ++ (((v) << 28) & BM_PXP_PS_OFFSET_RSVD2) ++#define BP_PXP_PS_OFFSET_YOFFSET 16 ++#define BM_PXP_PS_OFFSET_YOFFSET 0x0FFF0000 ++#define BF_PXP_PS_OFFSET_YOFFSET(v) \ ++ (((v) << 16) & BM_PXP_PS_OFFSET_YOFFSET) ++#define BP_PXP_PS_OFFSET_RSVD1 12 ++#define BM_PXP_PS_OFFSET_RSVD1 0x0000F000 ++#define BF_PXP_PS_OFFSET_RSVD1(v) \ ++ (((v) << 12) & BM_PXP_PS_OFFSET_RSVD1) ++#define BP_PXP_PS_OFFSET_XOFFSET 0 ++#define BM_PXP_PS_OFFSET_XOFFSET 0x00000FFF ++#define BF_PXP_PS_OFFSET_XOFFSET(v) \ ++ (((v) << 0) & BM_PXP_PS_OFFSET_XOFFSET) ++ ++#define HW_PXP_PS_CLRKEYLOW (0x00000130) ++ ++#define BP_PXP_PS_CLRKEYLOW_RSVD1 24 ++#define BM_PXP_PS_CLRKEYLOW_RSVD1 0xFF000000 ++#define BF_PXP_PS_CLRKEYLOW_RSVD1(v) \ ++ (((v) << 24) & BM_PXP_PS_CLRKEYLOW_RSVD1) ++#define BP_PXP_PS_CLRKEYLOW_PIXEL 0 ++#define BM_PXP_PS_CLRKEYLOW_PIXEL 0x00FFFFFF ++#define BF_PXP_PS_CLRKEYLOW_PIXEL(v) \ ++ (((v) << 0) & BM_PXP_PS_CLRKEYLOW_PIXEL) ++ ++#define HW_PXP_PS_CLRKEYHIGH (0x00000140) ++ ++#define BP_PXP_PS_CLRKEYHIGH_RSVD1 24 ++#define BM_PXP_PS_CLRKEYHIGH_RSVD1 0xFF000000 ++#define BF_PXP_PS_CLRKEYHIGH_RSVD1(v) \ ++ (((v) << 24) & BM_PXP_PS_CLRKEYHIGH_RSVD1) ++#define BP_PXP_PS_CLRKEYHIGH_PIXEL 0 ++#define BM_PXP_PS_CLRKEYHIGH_PIXEL 0x00FFFFFF ++#define BF_PXP_PS_CLRKEYHIGH_PIXEL(v) \ ++ (((v) << 0) & BM_PXP_PS_CLRKEYHIGH_PIXEL) ++ ++#define HW_PXP_AS_CTRL (0x00000150) ++ ++#define BP_PXP_AS_CTRL_RSVD1 21 ++#define BM_PXP_AS_CTRL_RSVD1 0xFFE00000 ++#define BF_PXP_AS_CTRL_RSVD1(v) \ ++ (((v) << 21) & BM_PXP_AS_CTRL_RSVD1) ++#define BM_PXP_AS_CTRL_ALPHA_INVERT 0x00100000 ++#define BP_PXP_AS_CTRL_ROP 16 ++#define BM_PXP_AS_CTRL_ROP 0x000F0000 ++#define BF_PXP_AS_CTRL_ROP(v) \ ++ (((v) << 16) & BM_PXP_AS_CTRL_ROP) ++#define BV_PXP_AS_CTRL_ROP__MASKAS 0x0 ++#define BV_PXP_AS_CTRL_ROP__MASKNOTAS 0x1 ++#define BV_PXP_AS_CTRL_ROP__MASKASNOT 0x2 ++#define BV_PXP_AS_CTRL_ROP__MERGEAS 0x3 ++#define BV_PXP_AS_CTRL_ROP__MERGENOTAS 0x4 ++#define BV_PXP_AS_CTRL_ROP__MERGEASNOT 0x5 ++#define BV_PXP_AS_CTRL_ROP__NOTCOPYAS 0x6 ++#define BV_PXP_AS_CTRL_ROP__NOT 0x7 ++#define BV_PXP_AS_CTRL_ROP__NOTMASKAS 0x8 ++#define BV_PXP_AS_CTRL_ROP__NOTMERGEAS 0x9 ++#define BV_PXP_AS_CTRL_ROP__XORAS 0xA ++#define BV_PXP_AS_CTRL_ROP__NOTXORAS 0xB ++#define BP_PXP_AS_CTRL_ALPHA 8 ++#define BM_PXP_AS_CTRL_ALPHA 0x0000FF00 ++#define BF_PXP_AS_CTRL_ALPHA(v) \ ++ (((v) << 8) & BM_PXP_AS_CTRL_ALPHA) ++#define BP_PXP_AS_CTRL_FORMAT 4 ++#define BM_PXP_AS_CTRL_FORMAT 0x000000F0 ++#define BF_PXP_AS_CTRL_FORMAT(v) \ ++ (((v) << 4) & BM_PXP_AS_CTRL_FORMAT) ++#define BV_PXP_AS_CTRL_FORMAT__ARGB8888 0x0 ++#define BV_PXP_AS_CTRL_FORMAT__RGB888 0x4 ++#define BV_PXP_AS_CTRL_FORMAT__ARGB1555 0x8 ++#define BV_PXP_AS_CTRL_FORMAT__ARGB4444 0x9 ++#define BV_PXP_AS_CTRL_FORMAT__RGB555 0xC ++#define BV_PXP_AS_CTRL_FORMAT__RGB444 0xD ++#define BV_PXP_AS_CTRL_FORMAT__RGB565 0xE ++#define BM_PXP_AS_CTRL_ENABLE_COLORKEY 0x00000008 ++#define BP_PXP_AS_CTRL_ALPHA_CTRL 1 ++#define BM_PXP_AS_CTRL_ALPHA_CTRL 0x00000006 ++#define BF_PXP_AS_CTRL_ALPHA_CTRL(v) \ ++ (((v) << 1) & BM_PXP_AS_CTRL_ALPHA_CTRL) ++#define BV_PXP_AS_CTRL_ALPHA_CTRL__Embedded 0x0 ++#define BV_PXP_AS_CTRL_ALPHA_CTRL__Override 0x1 ++#define BV_PXP_AS_CTRL_ALPHA_CTRL__Multiply 0x2 ++#define BV_PXP_AS_CTRL_ALPHA_CTRL__ROPs 0x3 ++#define BM_PXP_AS_CTRL_RSVD0 0x00000001 ++ ++#define HW_PXP_AS_BUF (0x00000160) ++ ++#define BP_PXP_AS_BUF_ADDR 0 ++#define BM_PXP_AS_BUF_ADDR 0xFFFFFFFF ++#define BF_PXP_AS_BUF_ADDR(v) (v) ++ ++#define HW_PXP_AS_PITCH (0x00000170) ++ ++#define BP_PXP_AS_PITCH_RSVD 16 ++#define BM_PXP_AS_PITCH_RSVD 0xFFFF0000 ++#define BF_PXP_AS_PITCH_RSVD(v) \ ++ (((v) << 16) & BM_PXP_AS_PITCH_RSVD) ++#define BP_PXP_AS_PITCH_PITCH 0 ++#define BM_PXP_AS_PITCH_PITCH 0x0000FFFF ++#define BF_PXP_AS_PITCH_PITCH(v) \ ++ (((v) << 0) & BM_PXP_AS_PITCH_PITCH) ++ ++#define HW_PXP_AS_CLRKEYLOW (0x00000180) ++ ++#define BP_PXP_AS_CLRKEYLOW_RSVD1 24 ++#define BM_PXP_AS_CLRKEYLOW_RSVD1 0xFF000000 ++#define BF_PXP_AS_CLRKEYLOW_RSVD1(v) \ ++ (((v) << 24) & BM_PXP_AS_CLRKEYLOW_RSVD1) ++#define BP_PXP_AS_CLRKEYLOW_PIXEL 0 ++#define BM_PXP_AS_CLRKEYLOW_PIXEL 0x00FFFFFF ++#define BF_PXP_AS_CLRKEYLOW_PIXEL(v) \ ++ (((v) << 0) & BM_PXP_AS_CLRKEYLOW_PIXEL) ++ ++#define HW_PXP_AS_CLRKEYHIGH (0x00000190) ++ ++#define BP_PXP_AS_CLRKEYHIGH_RSVD1 24 ++#define BM_PXP_AS_CLRKEYHIGH_RSVD1 0xFF000000 ++#define BF_PXP_AS_CLRKEYHIGH_RSVD1(v) \ ++ (((v) << 24) & BM_PXP_AS_CLRKEYHIGH_RSVD1) ++#define BP_PXP_AS_CLRKEYHIGH_PIXEL 0 ++#define BM_PXP_AS_CLRKEYHIGH_PIXEL 0x00FFFFFF ++#define BF_PXP_AS_CLRKEYHIGH_PIXEL(v) \ ++ (((v) << 0) & BM_PXP_AS_CLRKEYHIGH_PIXEL) ++ ++#define HW_PXP_CSC1_COEF0 (0x000001a0) ++ ++#define BM_PXP_CSC1_COEF0_YCBCR_MODE 0x80000000 ++#define BM_PXP_CSC1_COEF0_BYPASS 0x40000000 ++#define BM_PXP_CSC1_COEF0_RSVD1 0x20000000 ++#define BP_PXP_CSC1_COEF0_C0 18 ++#define BM_PXP_CSC1_COEF0_C0 0x1FFC0000 ++#define BF_PXP_CSC1_COEF0_C0(v) \ ++ (((v) << 18) & BM_PXP_CSC1_COEF0_C0) ++#define BP_PXP_CSC1_COEF0_UV_OFFSET 9 ++#define BM_PXP_CSC1_COEF0_UV_OFFSET 0x0003FE00 ++#define BF_PXP_CSC1_COEF0_UV_OFFSET(v) \ ++ (((v) << 9) & BM_PXP_CSC1_COEF0_UV_OFFSET) ++#define BP_PXP_CSC1_COEF0_Y_OFFSET 0 ++#define BM_PXP_CSC1_COEF0_Y_OFFSET 0x000001FF ++#define BF_PXP_CSC1_COEF0_Y_OFFSET(v) \ ++ (((v) << 0) & BM_PXP_CSC1_COEF0_Y_OFFSET) ++ ++#define HW_PXP_CSC1_COEF1 (0x000001b0) ++ ++#define BP_PXP_CSC1_COEF1_RSVD1 27 ++#define BM_PXP_CSC1_COEF1_RSVD1 0xF8000000 ++#define BF_PXP_CSC1_COEF1_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC1_COEF1_RSVD1) ++#define BP_PXP_CSC1_COEF1_C1 16 ++#define BM_PXP_CSC1_COEF1_C1 0x07FF0000 ++#define BF_PXP_CSC1_COEF1_C1(v) \ ++ (((v) << 16) & BM_PXP_CSC1_COEF1_C1) ++#define BP_PXP_CSC1_COEF1_RSVD0 11 ++#define BM_PXP_CSC1_COEF1_RSVD0 0x0000F800 ++#define BF_PXP_CSC1_COEF1_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC1_COEF1_RSVD0) ++#define BP_PXP_CSC1_COEF1_C4 0 ++#define BM_PXP_CSC1_COEF1_C4 0x000007FF ++#define BF_PXP_CSC1_COEF1_C4(v) \ ++ (((v) << 0) & BM_PXP_CSC1_COEF1_C4) ++ ++#define HW_PXP_CSC1_COEF2 (0x000001c0) ++ ++#define BP_PXP_CSC1_COEF2_RSVD1 27 ++#define BM_PXP_CSC1_COEF2_RSVD1 0xF8000000 ++#define BF_PXP_CSC1_COEF2_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC1_COEF2_RSVD1) ++#define BP_PXP_CSC1_COEF2_C2 16 ++#define BM_PXP_CSC1_COEF2_C2 0x07FF0000 ++#define BF_PXP_CSC1_COEF2_C2(v) \ ++ (((v) << 16) & BM_PXP_CSC1_COEF2_C2) ++#define BP_PXP_CSC1_COEF2_RSVD0 11 ++#define BM_PXP_CSC1_COEF2_RSVD0 0x0000F800 ++#define BF_PXP_CSC1_COEF2_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC1_COEF2_RSVD0) ++#define BP_PXP_CSC1_COEF2_C3 0 ++#define BM_PXP_CSC1_COEF2_C3 0x000007FF ++#define BF_PXP_CSC1_COEF2_C3(v) \ ++ (((v) << 0) & BM_PXP_CSC1_COEF2_C3) ++ ++#define HW_PXP_CSC2_CTRL (0x000001d0) ++ ++#define BP_PXP_CSC2_CTRL_RSVD 3 ++#define BM_PXP_CSC2_CTRL_RSVD 0xFFFFFFF8 ++#define BF_PXP_CSC2_CTRL_RSVD(v) \ ++ (((v) << 3) & BM_PXP_CSC2_CTRL_RSVD) ++#define BP_PXP_CSC2_CTRL_CSC_MODE 1 ++#define BM_PXP_CSC2_CTRL_CSC_MODE 0x00000006 ++#define BF_PXP_CSC2_CTRL_CSC_MODE(v) \ ++ (((v) << 1) & BM_PXP_CSC2_CTRL_CSC_MODE) ++#define BV_PXP_CSC2_CTRL_CSC_MODE__YUV2RGB 0x0 ++#define BV_PXP_CSC2_CTRL_CSC_MODE__YCbCr2RGB 0x1 ++#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YUV 0x2 ++#define BV_PXP_CSC2_CTRL_CSC_MODE__RGB2YCbCr 0x3 ++#define BM_PXP_CSC2_CTRL_BYPASS 0x00000001 ++ ++#define HW_PXP_CSC2_COEF0 (0x000001e0) ++ ++#define BP_PXP_CSC2_COEF0_RSVD1 27 ++#define BM_PXP_CSC2_COEF0_RSVD1 0xF8000000 ++#define BF_PXP_CSC2_COEF0_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC2_COEF0_RSVD1) ++#define BP_PXP_CSC2_COEF0_A2 16 ++#define BM_PXP_CSC2_COEF0_A2 0x07FF0000 ++#define BF_PXP_CSC2_COEF0_A2(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF0_A2) ++#define BP_PXP_CSC2_COEF0_RSVD0 11 ++#define BM_PXP_CSC2_COEF0_RSVD0 0x0000F800 ++#define BF_PXP_CSC2_COEF0_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC2_COEF0_RSVD0) ++#define BP_PXP_CSC2_COEF0_A1 0 ++#define BM_PXP_CSC2_COEF0_A1 0x000007FF ++#define BF_PXP_CSC2_COEF0_A1(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF0_A1) ++ ++#define HW_PXP_CSC2_COEF1 (0x000001f0) ++ ++#define BP_PXP_CSC2_COEF1_RSVD1 27 ++#define BM_PXP_CSC2_COEF1_RSVD1 0xF8000000 ++#define BF_PXP_CSC2_COEF1_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC2_COEF1_RSVD1) ++#define BP_PXP_CSC2_COEF1_B1 16 ++#define BM_PXP_CSC2_COEF1_B1 0x07FF0000 ++#define BF_PXP_CSC2_COEF1_B1(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF1_B1) ++#define BP_PXP_CSC2_COEF1_RSVD0 11 ++#define BM_PXP_CSC2_COEF1_RSVD0 0x0000F800 ++#define BF_PXP_CSC2_COEF1_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC2_COEF1_RSVD0) ++#define BP_PXP_CSC2_COEF1_A3 0 ++#define BM_PXP_CSC2_COEF1_A3 0x000007FF ++#define BF_PXP_CSC2_COEF1_A3(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF1_A3) ++ ++#define HW_PXP_CSC2_COEF2 (0x00000200) ++ ++#define BP_PXP_CSC2_COEF2_RSVD1 27 ++#define BM_PXP_CSC2_COEF2_RSVD1 0xF8000000 ++#define BF_PXP_CSC2_COEF2_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC2_COEF2_RSVD1) ++#define BP_PXP_CSC2_COEF2_B3 16 ++#define BM_PXP_CSC2_COEF2_B3 0x07FF0000 ++#define BF_PXP_CSC2_COEF2_B3(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF2_B3) ++#define BP_PXP_CSC2_COEF2_RSVD0 11 ++#define BM_PXP_CSC2_COEF2_RSVD0 0x0000F800 ++#define BF_PXP_CSC2_COEF2_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC2_COEF2_RSVD0) ++#define BP_PXP_CSC2_COEF2_B2 0 ++#define BM_PXP_CSC2_COEF2_B2 0x000007FF ++#define BF_PXP_CSC2_COEF2_B2(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF2_B2) ++ ++#define HW_PXP_CSC2_COEF3 (0x00000210) ++ ++#define BP_PXP_CSC2_COEF3_RSVD1 27 ++#define BM_PXP_CSC2_COEF3_RSVD1 0xF8000000 ++#define BF_PXP_CSC2_COEF3_RSVD1(v) \ ++ (((v) << 27) & BM_PXP_CSC2_COEF3_RSVD1) ++#define BP_PXP_CSC2_COEF3_C2 16 ++#define BM_PXP_CSC2_COEF3_C2 0x07FF0000 ++#define BF_PXP_CSC2_COEF3_C2(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF3_C2) ++#define BP_PXP_CSC2_COEF3_RSVD0 11 ++#define BM_PXP_CSC2_COEF3_RSVD0 0x0000F800 ++#define BF_PXP_CSC2_COEF3_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC2_COEF3_RSVD0) ++#define BP_PXP_CSC2_COEF3_C1 0 ++#define BM_PXP_CSC2_COEF3_C1 0x000007FF ++#define BF_PXP_CSC2_COEF3_C1(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF3_C1) ++ ++#define HW_PXP_CSC2_COEF4 (0x00000220) ++ ++#define BP_PXP_CSC2_COEF4_RSVD1 25 ++#define BM_PXP_CSC2_COEF4_RSVD1 0xFE000000 ++#define BF_PXP_CSC2_COEF4_RSVD1(v) \ ++ (((v) << 25) & BM_PXP_CSC2_COEF4_RSVD1) ++#define BP_PXP_CSC2_COEF4_D1 16 ++#define BM_PXP_CSC2_COEF4_D1 0x01FF0000 ++#define BF_PXP_CSC2_COEF4_D1(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF4_D1) ++#define BP_PXP_CSC2_COEF4_RSVD0 11 ++#define BM_PXP_CSC2_COEF4_RSVD0 0x0000F800 ++#define BF_PXP_CSC2_COEF4_RSVD0(v) \ ++ (((v) << 11) & BM_PXP_CSC2_COEF4_RSVD0) ++#define BP_PXP_CSC2_COEF4_C3 0 ++#define BM_PXP_CSC2_COEF4_C3 0x000007FF ++#define BF_PXP_CSC2_COEF4_C3(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF4_C3) ++ ++#define HW_PXP_CSC2_COEF5 (0x00000230) ++ ++#define BP_PXP_CSC2_COEF5_RSVD1 25 ++#define BM_PXP_CSC2_COEF5_RSVD1 0xFE000000 ++#define BF_PXP_CSC2_COEF5_RSVD1(v) \ ++ (((v) << 25) & BM_PXP_CSC2_COEF5_RSVD1) ++#define BP_PXP_CSC2_COEF5_D3 16 ++#define BM_PXP_CSC2_COEF5_D3 0x01FF0000 ++#define BF_PXP_CSC2_COEF5_D3(v) \ ++ (((v) << 16) & BM_PXP_CSC2_COEF5_D3) ++#define BP_PXP_CSC2_COEF5_RSVD0 9 ++#define BM_PXP_CSC2_COEF5_RSVD0 0x0000FE00 ++#define BF_PXP_CSC2_COEF5_RSVD0(v) \ ++ (((v) << 9) & BM_PXP_CSC2_COEF5_RSVD0) ++#define BP_PXP_CSC2_COEF5_D2 0 ++#define BM_PXP_CSC2_COEF5_D2 0x000001FF ++#define BF_PXP_CSC2_COEF5_D2(v) \ ++ (((v) << 0) & BM_PXP_CSC2_COEF5_D2) ++ ++#define HW_PXP_LUT_CTRL (0x00000240) ++ ++#define BM_PXP_LUT_CTRL_BYPASS 0x80000000 ++#define BP_PXP_LUT_CTRL_RSVD3 26 ++#define BM_PXP_LUT_CTRL_RSVD3 0x7C000000 ++#define BF_PXP_LUT_CTRL_RSVD3(v) \ ++ (((v) << 26) & BM_PXP_LUT_CTRL_RSVD3) ++#define BP_PXP_LUT_CTRL_LOOKUP_MODE 24 ++#define BM_PXP_LUT_CTRL_LOOKUP_MODE 0x03000000 ++#define BF_PXP_LUT_CTRL_LOOKUP_MODE(v) \ ++ (((v) << 24) & BM_PXP_LUT_CTRL_LOOKUP_MODE) ++#define BV_PXP_LUT_CTRL_LOOKUP_MODE__CACHE_RGB565 0x0 ++#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_Y8 0x1 ++#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB444 0x2 ++#define BV_PXP_LUT_CTRL_LOOKUP_MODE__DIRECT_RGB454 0x3 ++#define BP_PXP_LUT_CTRL_RSVD2 18 ++#define BM_PXP_LUT_CTRL_RSVD2 0x00FC0000 ++#define BF_PXP_LUT_CTRL_RSVD2(v) \ ++ (((v) << 18) & BM_PXP_LUT_CTRL_RSVD2) ++#define BP_PXP_LUT_CTRL_OUT_MODE 16 ++#define BM_PXP_LUT_CTRL_OUT_MODE 0x00030000 ++#define BF_PXP_LUT_CTRL_OUT_MODE(v) \ ++ (((v) << 16) & BM_PXP_LUT_CTRL_OUT_MODE) ++#define BV_PXP_LUT_CTRL_OUT_MODE__RESERVED 0x0 ++#define BV_PXP_LUT_CTRL_OUT_MODE__Y8 0x1 ++#define BV_PXP_LUT_CTRL_OUT_MODE__RGBW4444CFA 0x2 ++#define BV_PXP_LUT_CTRL_OUT_MODE__RGB888 0x3 ++#define BP_PXP_LUT_CTRL_RSVD1 11 ++#define BM_PXP_LUT_CTRL_RSVD1 0x0000F800 ++#define BF_PXP_LUT_CTRL_RSVD1(v) \ ++ (((v) << 11) & BM_PXP_LUT_CTRL_RSVD1) ++#define BM_PXP_LUT_CTRL_SEL_8KB 0x00000400 ++#define BM_PXP_LUT_CTRL_LRU_UPD 0x00000200 ++#define BM_PXP_LUT_CTRL_INVALID 0x00000100 ++#define BP_PXP_LUT_CTRL_RSVD0 1 ++#define BM_PXP_LUT_CTRL_RSVD0 0x000000FE ++#define BF_PXP_LUT_CTRL_RSVD0(v) \ ++ (((v) << 1) & BM_PXP_LUT_CTRL_RSVD0) ++#define BM_PXP_LUT_CTRL_DMA_START 0x00000001 ++ ++#define HW_PXP_LUT_ADDR (0x00000250) ++ ++#define BM_PXP_LUT_ADDR_RSVD2 0x80000000 ++#define BP_PXP_LUT_ADDR_NUM_BYTES 16 ++#define BM_PXP_LUT_ADDR_NUM_BYTES 0x7FFF0000 ++#define BF_PXP_LUT_ADDR_NUM_BYTES(v) \ ++ (((v) << 16) & BM_PXP_LUT_ADDR_NUM_BYTES) ++#define BP_PXP_LUT_ADDR_RSVD1 14 ++#define BM_PXP_LUT_ADDR_RSVD1 0x0000C000 ++#define BF_PXP_LUT_ADDR_RSVD1(v) \ ++ (((v) << 14) & BM_PXP_LUT_ADDR_RSVD1) ++#define BP_PXP_LUT_ADDR_ADDR 0 ++#define BM_PXP_LUT_ADDR_ADDR 0x00003FFF ++#define BF_PXP_LUT_ADDR_ADDR(v) \ ++ (((v) << 0) & BM_PXP_LUT_ADDR_ADDR) ++ ++#define HW_PXP_LUT_DATA (0x00000260) ++ ++#define BP_PXP_LUT_DATA_DATA 0 ++#define BM_PXP_LUT_DATA_DATA 0xFFFFFFFF ++#define BF_PXP_LUT_DATA_DATA(v) (v) ++ ++#define HW_PXP_LUT_EXTMEM (0x00000270) ++ ++#define BP_PXP_LUT_EXTMEM_ADDR 0 ++#define BM_PXP_LUT_EXTMEM_ADDR 0xFFFFFFFF ++#define BF_PXP_LUT_EXTMEM_ADDR(v) (v) ++ ++#define HW_PXP_CFA (0x00000280) ++ ++#define BP_PXP_CFA_DATA 0 ++#define BM_PXP_CFA_DATA 0xFFFFFFFF ++#define BF_PXP_CFA_DATA(v) (v) ++ ++#define HW_PXP_HIST_CTRL (0x00000290) ++ ++#define BP_PXP_HIST_CTRL_RSVD 6 ++#define BM_PXP_HIST_CTRL_RSVD 0xFFFFFFC0 ++#define BF_PXP_HIST_CTRL_RSVD(v) \ ++ (((v) << 6) & BM_PXP_HIST_CTRL_RSVD) ++#define BP_PXP_HIST_CTRL_PANEL_MODE 4 ++#define BM_PXP_HIST_CTRL_PANEL_MODE 0x00000030 ++#define BF_PXP_HIST_CTRL_PANEL_MODE(v) \ ++ (((v) << 4) & BM_PXP_HIST_CTRL_PANEL_MODE) ++#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY4 0x0 ++#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY8 0x1 ++#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY16 0x2 ++#define BV_PXP_HIST_CTRL_PANEL_MODE__GRAY32 0x3 ++#define BP_PXP_HIST_CTRL_STATUS 0 ++#define BM_PXP_HIST_CTRL_STATUS 0x0000000F ++#define BF_PXP_HIST_CTRL_STATUS(v) \ ++ (((v) << 0) & BM_PXP_HIST_CTRL_STATUS) ++ ++#define HW_PXP_HIST2_PARAM (0x000002a0) ++ ++#define BP_PXP_HIST2_PARAM_RSVD 16 ++#define BM_PXP_HIST2_PARAM_RSVD 0xFFFF0000 ++#define BF_PXP_HIST2_PARAM_RSVD(v) \ ++ (((v) << 16) & BM_PXP_HIST2_PARAM_RSVD) ++#define BP_PXP_HIST2_PARAM_RSVD1 13 ++#define BM_PXP_HIST2_PARAM_RSVD1 0x0000E000 ++#define BF_PXP_HIST2_PARAM_RSVD1(v) \ ++ (((v) << 13) & BM_PXP_HIST2_PARAM_RSVD1) ++#define BP_PXP_HIST2_PARAM_VALUE1 8 ++#define BM_PXP_HIST2_PARAM_VALUE1 0x00001F00 ++#define BF_PXP_HIST2_PARAM_VALUE1(v) \ ++ (((v) << 8) & BM_PXP_HIST2_PARAM_VALUE1) ++#define BP_PXP_HIST2_PARAM_RSVD0 5 ++#define BM_PXP_HIST2_PARAM_RSVD0 0x000000E0 ++#define BF_PXP_HIST2_PARAM_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_HIST2_PARAM_RSVD0) ++#define BP_PXP_HIST2_PARAM_VALUE0 0 ++#define BM_PXP_HIST2_PARAM_VALUE0 0x0000001F ++#define BF_PXP_HIST2_PARAM_VALUE0(v) \ ++ (((v) << 0) & BM_PXP_HIST2_PARAM_VALUE0) ++ ++#define HW_PXP_HIST4_PARAM (0x000002b0) ++ ++#define BP_PXP_HIST4_PARAM_RSVD3 29 ++#define BM_PXP_HIST4_PARAM_RSVD3 0xE0000000 ++#define BF_PXP_HIST4_PARAM_RSVD3(v) \ ++ (((v) << 29) & BM_PXP_HIST4_PARAM_RSVD3) ++#define BP_PXP_HIST4_PARAM_VALUE3 24 ++#define BM_PXP_HIST4_PARAM_VALUE3 0x1F000000 ++#define BF_PXP_HIST4_PARAM_VALUE3(v) \ ++ (((v) << 24) & BM_PXP_HIST4_PARAM_VALUE3) ++#define BP_PXP_HIST4_PARAM_RSVD2 21 ++#define BM_PXP_HIST4_PARAM_RSVD2 0x00E00000 ++#define BF_PXP_HIST4_PARAM_RSVD2(v) \ ++ (((v) << 21) & BM_PXP_HIST4_PARAM_RSVD2) ++#define BP_PXP_HIST4_PARAM_VALUE2 16 ++#define BM_PXP_HIST4_PARAM_VALUE2 0x001F0000 ++#define BF_PXP_HIST4_PARAM_VALUE2(v) \ ++ (((v) << 16) & BM_PXP_HIST4_PARAM_VALUE2) ++#define BP_PXP_HIST4_PARAM_RSVD1 13 ++#define BM_PXP_HIST4_PARAM_RSVD1 0x0000E000 ++#define BF_PXP_HIST4_PARAM_RSVD1(v) \ ++ (((v) << 13) & BM_PXP_HIST4_PARAM_RSVD1) ++#define BP_PXP_HIST4_PARAM_VALUE1 8 ++#define BM_PXP_HIST4_PARAM_VALUE1 0x00001F00 ++#define BF_PXP_HIST4_PARAM_VALUE1(v) \ ++ (((v) << 8) & BM_PXP_HIST4_PARAM_VALUE1) ++#define BP_PXP_HIST4_PARAM_RSVD0 5 ++#define BM_PXP_HIST4_PARAM_RSVD0 0x000000E0 ++#define BF_PXP_HIST4_PARAM_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_HIST4_PARAM_RSVD0) ++#define BP_PXP_HIST4_PARAM_VALUE0 0 ++#define BM_PXP_HIST4_PARAM_VALUE0 0x0000001F ++#define BF_PXP_HIST4_PARAM_VALUE0(v) \ ++ (((v) << 0) & BM_PXP_HIST4_PARAM_VALUE0) ++ ++#define HW_PXP_HIST8_PARAM0 (0x000002c0) ++ ++#define BP_PXP_HIST8_PARAM0_RSVD3 29 ++#define BM_PXP_HIST8_PARAM0_RSVD3 0xE0000000 ++#define BF_PXP_HIST8_PARAM0_RSVD3(v) \ ++ (((v) << 29) & BM_PXP_HIST8_PARAM0_RSVD3) ++#define BP_PXP_HIST8_PARAM0_VALUE3 24 ++#define BM_PXP_HIST8_PARAM0_VALUE3 0x1F000000 ++#define BF_PXP_HIST8_PARAM0_VALUE3(v) \ ++ (((v) << 24) & BM_PXP_HIST8_PARAM0_VALUE3) ++#define BP_PXP_HIST8_PARAM0_RSVD2 21 ++#define BM_PXP_HIST8_PARAM0_RSVD2 0x00E00000 ++#define BF_PXP_HIST8_PARAM0_RSVD2(v) \ ++ (((v) << 21) & BM_PXP_HIST8_PARAM0_RSVD2) ++#define BP_PXP_HIST8_PARAM0_VALUE2 16 ++#define BM_PXP_HIST8_PARAM0_VALUE2 0x001F0000 ++#define BF_PXP_HIST8_PARAM0_VALUE2(v) \ ++ (((v) << 16) & BM_PXP_HIST8_PARAM0_VALUE2) ++#define BP_PXP_HIST8_PARAM0_RSVD1 13 ++#define BM_PXP_HIST8_PARAM0_RSVD1 0x0000E000 ++#define BF_PXP_HIST8_PARAM0_RSVD1(v) \ ++ (((v) << 13) & BM_PXP_HIST8_PARAM0_RSVD1) ++#define BP_PXP_HIST8_PARAM0_VALUE1 8 ++#define BM_PXP_HIST8_PARAM0_VALUE1 0x00001F00 ++#define BF_PXP_HIST8_PARAM0_VALUE1(v) \ ++ (((v) << 8) & BM_PXP_HIST8_PARAM0_VALUE1) ++#define BP_PXP_HIST8_PARAM0_RSVD0 5 ++#define BM_PXP_HIST8_PARAM0_RSVD0 0x000000E0 ++#define BF_PXP_HIST8_PARAM0_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_HIST8_PARAM0_RSVD0) ++#define BP_PXP_HIST8_PARAM0_VALUE0 0 ++#define BM_PXP_HIST8_PARAM0_VALUE0 0x0000001F ++#define BF_PXP_HIST8_PARAM0_VALUE0(v) \ ++ (((v) << 0) & BM_PXP_HIST8_PARAM0_VALUE0) ++ ++#define HW_PXP_HIST8_PARAM1 (0x000002d0) ++ ++#define BP_PXP_HIST8_PARAM1_RSVD7 29 ++#define BM_PXP_HIST8_PARAM1_RSVD7 0xE0000000 ++#define BF_PXP_HIST8_PARAM1_RSVD7(v) \ ++ (((v) << 29) & BM_PXP_HIST8_PARAM1_RSVD7) ++#define BP_PXP_HIST8_PARAM1_VALUE7 24 ++#define BM_PXP_HIST8_PARAM1_VALUE7 0x1F000000 ++#define BF_PXP_HIST8_PARAM1_VALUE7(v) \ ++ (((v) << 24) & BM_PXP_HIST8_PARAM1_VALUE7) ++#define BP_PXP_HIST8_PARAM1_RSVD6 21 ++#define BM_PXP_HIST8_PARAM1_RSVD6 0x00E00000 ++#define BF_PXP_HIST8_PARAM1_RSVD6(v) \ ++ (((v) << 21) & BM_PXP_HIST8_PARAM1_RSVD6) ++#define BP_PXP_HIST8_PARAM1_VALUE6 16 ++#define BM_PXP_HIST8_PARAM1_VALUE6 0x001F0000 ++#define BF_PXP_HIST8_PARAM1_VALUE6(v) \ ++ (((v) << 16) & BM_PXP_HIST8_PARAM1_VALUE6) ++#define BP_PXP_HIST8_PARAM1_RSVD5 13 ++#define BM_PXP_HIST8_PARAM1_RSVD5 0x0000E000 ++#define BF_PXP_HIST8_PARAM1_RSVD5(v) \ ++ (((v) << 13) & BM_PXP_HIST8_PARAM1_RSVD5) ++#define BP_PXP_HIST8_PARAM1_VALUE5 8 ++#define BM_PXP_HIST8_PARAM1_VALUE5 0x00001F00 ++#define BF_PXP_HIST8_PARAM1_VALUE5(v) \ ++ (((v) << 8) & BM_PXP_HIST8_PARAM1_VALUE5) ++#define BP_PXP_HIST8_PARAM1_RSVD4 5 ++#define BM_PXP_HIST8_PARAM1_RSVD4 0x000000E0 ++#define BF_PXP_HIST8_PARAM1_RSVD4(v) \ ++ (((v) << 5) & BM_PXP_HIST8_PARAM1_RSVD4) ++#define BP_PXP_HIST8_PARAM1_VALUE4 0 ++#define BM_PXP_HIST8_PARAM1_VALUE4 0x0000001F ++#define BF_PXP_HIST8_PARAM1_VALUE4(v) \ ++ (((v) << 0) & BM_PXP_HIST8_PARAM1_VALUE4) ++ ++#define HW_PXP_HIST16_PARAM0 (0x000002e0) ++ ++#define BP_PXP_HIST16_PARAM0_RSVD3 29 ++#define BM_PXP_HIST16_PARAM0_RSVD3 0xE0000000 ++#define BF_PXP_HIST16_PARAM0_RSVD3(v) \ ++ (((v) << 29) & BM_PXP_HIST16_PARAM0_RSVD3) ++#define BP_PXP_HIST16_PARAM0_VALUE3 24 ++#define BM_PXP_HIST16_PARAM0_VALUE3 0x1F000000 ++#define BF_PXP_HIST16_PARAM0_VALUE3(v) \ ++ (((v) << 24) & BM_PXP_HIST16_PARAM0_VALUE3) ++#define BP_PXP_HIST16_PARAM0_RSVD2 21 ++#define BM_PXP_HIST16_PARAM0_RSVD2 0x00E00000 ++#define BF_PXP_HIST16_PARAM0_RSVD2(v) \ ++ (((v) << 21) & BM_PXP_HIST16_PARAM0_RSVD2) ++#define BP_PXP_HIST16_PARAM0_VALUE2 16 ++#define BM_PXP_HIST16_PARAM0_VALUE2 0x001F0000 ++#define BF_PXP_HIST16_PARAM0_VALUE2(v) \ ++ (((v) << 16) & BM_PXP_HIST16_PARAM0_VALUE2) ++#define BP_PXP_HIST16_PARAM0_RSVD1 13 ++#define BM_PXP_HIST16_PARAM0_RSVD1 0x0000E000 ++#define BF_PXP_HIST16_PARAM0_RSVD1(v) \ ++ (((v) << 13) & BM_PXP_HIST16_PARAM0_RSVD1) ++#define BP_PXP_HIST16_PARAM0_VALUE1 8 ++#define BM_PXP_HIST16_PARAM0_VALUE1 0x00001F00 ++#define BF_PXP_HIST16_PARAM0_VALUE1(v) \ ++ (((v) << 8) & BM_PXP_HIST16_PARAM0_VALUE1) ++#define BP_PXP_HIST16_PARAM0_RSVD0 5 ++#define BM_PXP_HIST16_PARAM0_RSVD0 0x000000E0 ++#define BF_PXP_HIST16_PARAM0_RSVD0(v) \ ++ (((v) << 5) & BM_PXP_HIST16_PARAM0_RSVD0) ++#define BP_PXP_HIST16_PARAM0_VALUE0 0 ++#define BM_PXP_HIST16_PARAM0_VALUE0 0x0000001F ++#define BF_PXP_HIST16_PARAM0_VALUE0(v) \ ++ (((v) << 0) & BM_PXP_HIST16_PARAM0_VALUE0) ++ ++#define HW_PXP_HIST16_PARAM1 (0x000002f0) ++ ++#define BP_PXP_HIST16_PARAM1_RSVD7 29 ++#define BM_PXP_HIST16_PARAM1_RSVD7 0xE0000000 ++#define BF_PXP_HIST16_PARAM1_RSVD7(v) \ ++ (((v) << 29) & BM_PXP_HIST16_PARAM1_RSVD7) ++#define BP_PXP_HIST16_PARAM1_VALUE7 24 ++#define BM_PXP_HIST16_PARAM1_VALUE7 0x1F000000 ++#define BF_PXP_HIST16_PARAM1_VALUE7(v) \ ++ (((v) << 24) & BM_PXP_HIST16_PARAM1_VALUE7) ++#define BP_PXP_HIST16_PARAM1_RSVD6 21 ++#define BM_PXP_HIST16_PARAM1_RSVD6 0x00E00000 ++#define BF_PXP_HIST16_PARAM1_RSVD6(v) \ ++ (((v) << 21) & BM_PXP_HIST16_PARAM1_RSVD6) ++#define BP_PXP_HIST16_PARAM1_VALUE6 16 ++#define BM_PXP_HIST16_PARAM1_VALUE6 0x001F0000 ++#define BF_PXP_HIST16_PARAM1_VALUE6(v) \ ++ (((v) << 16) & BM_PXP_HIST16_PARAM1_VALUE6) ++#define BP_PXP_HIST16_PARAM1_RSVD5 13 ++#define BM_PXP_HIST16_PARAM1_RSVD5 0x0000E000 ++#define BF_PXP_HIST16_PARAM1_RSVD5(v) \ ++ (((v) << 13) & BM_PXP_HIST16_PARAM1_RSVD5) ++#define BP_PXP_HIST16_PARAM1_VALUE5 8 ++#define BM_PXP_HIST16_PARAM1_VALUE5 0x00001F00 ++#define BF_PXP_HIST16_PARAM1_VALUE5(v) \ ++ (((v) << 8) & BM_PXP_HIST16_PARAM1_VALUE5) ++#define BP_PXP_HIST16_PARAM1_RSVD4 5 ++#define BM_PXP_HIST16_PARAM1_RSVD4 0x000000E0 ++#define BF_PXP_HIST16_PARAM1_RSVD4(v) \ ++ (((v) << 5) & BM_PXP_HIST16_PARAM1_RSVD4) ++#define BP_PXP_HIST16_PARAM1_VALUE4 0 ++#define BM_PXP_HIST16_PARAM1_VALUE4 0x0000001F ++#define BF_PXP_HIST16_PARAM1_VALUE4(v) \ ++ (((v) << 0) & BM_PXP_HIST16_PARAM1_VALUE4) ++ ++#define HW_PXP_HIST16_PARAM2 (0x00000300) ++ ++#define BP_PXP_HIST16_PARAM2_RSVD11 29 ++#define BM_PXP_HIST16_PARAM2_RSVD11 0xE0000000 ++#define BF_PXP_HIST16_PARAM2_RSVD11(v) \ ++ (((v) << 29) & BM_PXP_HIST16_PARAM2_RSVD11) ++#define BP_PXP_HIST16_PARAM2_VALUE11 24 ++#define BM_PXP_HIST16_PARAM2_VALUE11 0x1F000000 ++#define BF_PXP_HIST16_PARAM2_VALUE11(v) \ ++ (((v) << 24) & BM_PXP_HIST16_PARAM2_VALUE11) ++#define BP_PXP_HIST16_PARAM2_RSVD10 21 ++#define BM_PXP_HIST16_PARAM2_RSVD10 0x00E00000 ++#define BF_PXP_HIST16_PARAM2_RSVD10(v) \ ++ (((v) << 21) & BM_PXP_HIST16_PARAM2_RSVD10) ++#define BP_PXP_HIST16_PARAM2_VALUE10 16 ++#define BM_PXP_HIST16_PARAM2_VALUE10 0x001F0000 ++#define BF_PXP_HIST16_PARAM2_VALUE10(v) \ ++ (((v) << 16) & BM_PXP_HIST16_PARAM2_VALUE10) ++#define BP_PXP_HIST16_PARAM2_RSVD9 13 ++#define BM_PXP_HIST16_PARAM2_RSVD9 0x0000E000 ++#define BF_PXP_HIST16_PARAM2_RSVD9(v) \ ++ (((v) << 13) & BM_PXP_HIST16_PARAM2_RSVD9) ++#define BP_PXP_HIST16_PARAM2_VALUE9 8 ++#define BM_PXP_HIST16_PARAM2_VALUE9 0x00001F00 ++#define BF_PXP_HIST16_PARAM2_VALUE9(v) \ ++ (((v) << 8) & BM_PXP_HIST16_PARAM2_VALUE9) ++#define BP_PXP_HIST16_PARAM2_RSVD8 5 ++#define BM_PXP_HIST16_PARAM2_RSVD8 0x000000E0 ++#define BF_PXP_HIST16_PARAM2_RSVD8(v) \ ++ (((v) << 5) & BM_PXP_HIST16_PARAM2_RSVD8) ++#define BP_PXP_HIST16_PARAM2_VALUE8 0 ++#define BM_PXP_HIST16_PARAM2_VALUE8 0x0000001F ++#define BF_PXP_HIST16_PARAM2_VALUE8(v) \ ++ (((v) << 0) & BM_PXP_HIST16_PARAM2_VALUE8) ++ ++#define HW_PXP_HIST16_PARAM3 (0x00000310) ++ ++#define BP_PXP_HIST16_PARAM3_RSVD15 29 ++#define BM_PXP_HIST16_PARAM3_RSVD15 0xE0000000 ++#define BF_PXP_HIST16_PARAM3_RSVD15(v) \ ++ (((v) << 29) & BM_PXP_HIST16_PARAM3_RSVD15) ++#define BP_PXP_HIST16_PARAM3_VALUE15 24 ++#define BM_PXP_HIST16_PARAM3_VALUE15 0x1F000000 ++#define BF_PXP_HIST16_PARAM3_VALUE15(v) \ ++ (((v) << 24) & BM_PXP_HIST16_PARAM3_VALUE15) ++#define BP_PXP_HIST16_PARAM3_RSVD14 21 ++#define BM_PXP_HIST16_PARAM3_RSVD14 0x00E00000 ++#define BF_PXP_HIST16_PARAM3_RSVD14(v) \ ++ (((v) << 21) & BM_PXP_HIST16_PARAM3_RSVD14) ++#define BP_PXP_HIST16_PARAM3_VALUE14 16 ++#define BM_PXP_HIST16_PARAM3_VALUE14 0x001F0000 ++#define BF_PXP_HIST16_PARAM3_VALUE14(v) \ ++ (((v) << 16) & BM_PXP_HIST16_PARAM3_VALUE14) ++#define BP_PXP_HIST16_PARAM3_RSVD13 13 ++#define BM_PXP_HIST16_PARAM3_RSVD13 0x0000E000 ++#define BF_PXP_HIST16_PARAM3_RSVD13(v) \ ++ (((v) << 13) & BM_PXP_HIST16_PARAM3_RSVD13) ++#define BP_PXP_HIST16_PARAM3_VALUE13 8 ++#define BM_PXP_HIST16_PARAM3_VALUE13 0x00001F00 ++#define BF_PXP_HIST16_PARAM3_VALUE13(v) \ ++ (((v) << 8) & BM_PXP_HIST16_PARAM3_VALUE13) ++#define BP_PXP_HIST16_PARAM3_RSVD12 5 ++#define BM_PXP_HIST16_PARAM3_RSVD12 0x000000E0 ++#define BF_PXP_HIST16_PARAM3_RSVD12(v) \ ++ (((v) << 5) & BM_PXP_HIST16_PARAM3_RSVD12) ++#define BP_PXP_HIST16_PARAM3_VALUE12 0 ++#define BM_PXP_HIST16_PARAM3_VALUE12 0x0000001F ++#define BF_PXP_HIST16_PARAM3_VALUE12(v) \ ++ (((v) << 0) & BM_PXP_HIST16_PARAM3_VALUE12) ++ ++#define HW_PXP_POWER (0x00000320) ++ ++#define BP_PXP_POWER_CTRL 12 ++#define BM_PXP_POWER_CTRL 0xFFFFF000 ++#define BF_PXP_POWER_CTRL(v) \ ++ (((v) << 12) & BM_PXP_POWER_CTRL) ++#define BP_PXP_POWER_ROT_MEM_LP_STATE 9 ++#define BM_PXP_POWER_ROT_MEM_LP_STATE 0x00000E00 ++#define BF_PXP_POWER_ROT_MEM_LP_STATE(v) \ ++ (((v) << 9) & BM_PXP_POWER_ROT_MEM_LP_STATE) ++#define BV_PXP_POWER_ROT_MEM_LP_STATE__NONE 0x0 ++#define BV_PXP_POWER_ROT_MEM_LP_STATE__LS 0x1 ++#define BV_PXP_POWER_ROT_MEM_LP_STATE__DS 0x2 ++#define BV_PXP_POWER_ROT_MEM_LP_STATE__SD 0x4 ++#define BP_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 6 ++#define BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN 0x000001C0 ++#define BF_PXP_POWER_LUT_LP_STATE_WAY1_BANKN(v) \ ++ (((v) << 6) & BM_PXP_POWER_LUT_LP_STATE_WAY1_BANKN) ++#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__NONE 0x0 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__LS 0x1 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__DS 0x2 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY1_BANKN__SD 0x4 ++#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 3 ++#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN 0x00000038 ++#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANKN(v) \ ++ (((v) << 3) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANKN) ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__NONE 0x0 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__LS 0x1 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__DS 0x2 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANKN__SD 0x4 ++#define BP_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0 ++#define BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0 0x00000007 ++#define BF_PXP_POWER_LUT_LP_STATE_WAY0_BANK0(v) \ ++ (((v) << 0) & BM_PXP_POWER_LUT_LP_STATE_WAY0_BANK0) ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__NONE 0x0 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__LS 0x1 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__DS 0x2 ++#define BV_PXP_POWER_LUT_LP_STATE_WAY0_BANK0__SD 0x4 ++ ++#define HW_PXP_NEXT (0x00000400) ++ ++#define BP_PXP_NEXT_POINTER 2 ++#define BM_PXP_NEXT_POINTER 0xFFFFFFFC ++#define BF_PXP_NEXT_POINTER(v) \ ++ (((v) << 2) & BM_PXP_NEXT_POINTER) ++#define BM_PXP_NEXT_RSVD 0x00000002 ++#define BM_PXP_NEXT_ENABLED 0x00000001 ++ ++#define HW_PXP_DEBUGCTRL (0x00000410) ++ ++#define BP_PXP_DEBUGCTRL_RSVD 12 ++#define BM_PXP_DEBUGCTRL_RSVD 0xFFFFF000 ++#define BF_PXP_DEBUGCTRL_RSVD(v) \ ++ (((v) << 12) & BM_PXP_DEBUGCTRL_RSVD) ++#define BP_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 8 ++#define BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT 0x00000F00 ++#define BF_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT(v) \ ++ (((v) << 8) & BM_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT) ++#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__NONE 0x0 ++#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MISS_CNT 0x1 ++#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__HIT_CNT 0x2 ++#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__LAT_CNT 0x4 ++#define BV_PXP_DEBUGCTRL_LUT_CLR_STAT_CNT__MAX_LAT 0x8 ++#define BP_PXP_DEBUGCTRL_SELECT 0 ++#define BM_PXP_DEBUGCTRL_SELECT 0x000000FF ++#define BF_PXP_DEBUGCTRL_SELECT(v) \ ++ (((v) << 0) & BM_PXP_DEBUGCTRL_SELECT) ++#define BV_PXP_DEBUGCTRL_SELECT__NONE 0x0 ++#define BV_PXP_DEBUGCTRL_SELECT__CTRL 0x1 ++#define BV_PXP_DEBUGCTRL_SELECT__PSBUF 0x2 ++#define BV_PXP_DEBUGCTRL_SELECT__PSBAX 0x3 ++#define BV_PXP_DEBUGCTRL_SELECT__PSBAY 0x4 ++#define BV_PXP_DEBUGCTRL_SELECT__ASBUF 0x5 ++#define BV_PXP_DEBUGCTRL_SELECT__ROTATION 0x6 ++#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF0 0x7 ++#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF1 0x8 ++#define BV_PXP_DEBUGCTRL_SELECT__OUTBUF2 0x9 ++#define BV_PXP_DEBUGCTRL_SELECT__LUT_STAT 0x10 ++#define BV_PXP_DEBUGCTRL_SELECT__LUT_MISS 0x11 ++#define BV_PXP_DEBUGCTRL_SELECT__LUT_HIT 0x12 ++#define BV_PXP_DEBUGCTRL_SELECT__LUT_LAT 0x13 ++#define BV_PXP_DEBUGCTRL_SELECT__LUT_MAX_LAT 0x14 ++ ++#define HW_PXP_DEBUG (0x00000420) ++ ++#define BP_PXP_DEBUG_DATA 0 ++#define BM_PXP_DEBUG_DATA 0xFFFFFFFF ++#define BF_PXP_DEBUG_DATA(v) (v) ++ ++#define HW_PXP_VERSION (0x00000430) ++ ++#define BP_PXP_VERSION_MAJOR 24 ++#define BM_PXP_VERSION_MAJOR 0xFF000000 ++#define BF_PXP_VERSION_MAJOR(v) \ ++ (((v) << 24) & BM_PXP_VERSION_MAJOR) ++#define BP_PXP_VERSION_MINOR 16 ++#define BM_PXP_VERSION_MINOR 0x00FF0000 ++#define BF_PXP_VERSION_MINOR(v) \ ++ (((v) << 16) & BM_PXP_VERSION_MINOR) ++#define BP_PXP_VERSION_STEP 0 ++#define BM_PXP_VERSION_STEP 0x0000FFFF ++#define BF_PXP_VERSION_STEP(v) \ ++ (((v) << 0) & BM_PXP_VERSION_STEP) ++#endif /* __ARCH_ARM___PXP_H */ +diff -Nur linux-3.14.14/drivers/gpio/gpio-pca953x.c linux-imx6-3.14/drivers/gpio/gpio-pca953x.c +--- linux-3.14.14/drivers/gpio/gpio-pca953x.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpio/gpio-pca953x.c 2014-12-08 00:31:52.600418001 -0600 +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + #ifdef CONFIG_OF_GPIO + #include +@@ -741,6 +742,10 @@ + + mutex_init(&chip->i2c_lock); + ++ ret = device_reset(&client->dev); ++ if (ret == -ENODEV) ++ return -EPROBE_DEFER; ++ + /* initialize cached registers from their original values. + * we can't share this chip with another i2c master. + */ +diff -Nur linux-3.14.14/drivers/gpu/drm/drm_crtc_helper.c linux-imx6-3.14/drivers/gpu/drm/drm_crtc_helper.c +--- linux-3.14.14/drivers/gpu/drm/drm_crtc_helper.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpu/drm/drm_crtc_helper.c 2014-12-08 00:31:52.608418001 -0600 +@@ -564,7 +564,7 @@ + * Caller must hold mode config lock. + * + * Setup a new configuration, provided by the upper layers (either an ioctl call +- * from userspace or internally e.g. from the fbdev suppport code) in @set, and ++ * from userspace or internally e.g. from the fbdev support code) in @set, and + * enable it. This is the main helper functions for drivers that implement + * kernel mode setting with the crtc helper functions and the assorted + * ->prepare(), ->modeset() and ->commit() helper callbacks. +diff -Nur linux-3.14.14/drivers/gpu/drm/drm_prime.c linux-imx6-3.14/drivers/gpu/drm/drm_prime.c +--- linux-3.14.14/drivers/gpu/drm/drm_prime.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpu/drm/drm_prime.c 2014-12-08 00:31:52.612418001 -0600 +@@ -471,7 +471,7 @@ + get_dma_buf(dma_buf); + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); +- if (IS_ERR_OR_NULL(sgt)) { ++ if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto fail_detach; + } +diff -Nur linux-3.14.14/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c linux-imx6-3.14/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +--- linux-3.14.14/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c 2014-12-08 00:31:52.616418001 -0600 +@@ -224,7 +224,7 @@ + get_dma_buf(dma_buf); + + sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); +- if (IS_ERR_OR_NULL(sgt)) { ++ if (IS_ERR(sgt)) { + ret = PTR_ERR(sgt); + goto err_buf_detach; + } +diff -Nur linux-3.14.14/drivers/gpu/drm/Kconfig linux-imx6-3.14/drivers/gpu/drm/Kconfig +--- linux-3.14.14/drivers/gpu/drm/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpu/drm/Kconfig 2014-12-08 00:31:52.604418001 -0600 +@@ -166,6 +166,13 @@ + Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister + chipset. If M is selected the module will be called savage. + ++config DRM_VIVANTE ++ tristate "Vivante GCCore" ++ depends on DRM ++ help ++ Choose this option if you have a Vivante graphics card. ++ If M is selected, the module will be called vivante. ++ + source "drivers/gpu/drm/exynos/Kconfig" + + source "drivers/gpu/drm/vmwgfx/Kconfig" +diff -Nur linux-3.14.14/drivers/gpu/drm/Makefile linux-imx6-3.14/drivers/gpu/drm/Makefile +--- linux-3.14.14/drivers/gpu/drm/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/gpu/drm/Makefile 2014-12-08 00:31:52.604418001 -0600 +@@ -1,3 +1,24 @@ ++############################################################################## ++# ++# Copyright (C) 2005 - 2013 by Vivante Corp. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the license, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not write to the Free Software ++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++# ++############################################################################## ++ ++ + # + # Makefile for the drm device driver. This driver provides support for the + # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. +@@ -35,6 +56,7 @@ + obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o + obj-$(CONFIG_DRM_USB) += drm_usb.o + obj-$(CONFIG_DRM_TTM) += ttm/ ++obj-$(CONFIG_DRM_VIVANTE) += vivante/ + obj-$(CONFIG_DRM_TDFX) += tdfx/ + obj-$(CONFIG_DRM_R128) += r128/ + obj-$(CONFIG_DRM_RADEON)+= radeon/ +diff -Nur linux-3.14.14/drivers/gpu/drm/vivante/Makefile linux-imx6-3.14/drivers/gpu/drm/vivante/Makefile +--- linux-3.14.14/drivers/gpu/drm/vivante/Makefile 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/gpu/drm/vivante/Makefile 2014-12-08 00:31:52.828418001 -0600 +@@ -0,0 +1,29 @@ ++############################################################################## ++# ++# Copyright (C) 2005 - 2013 by Vivante Corp. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the license, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not write to the Free Software ++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++# ++############################################################################## ++ ++ ++# ++# Makefile for the drm device driver. This driver provides support for the ++# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. ++ ++ccflags-y := -Iinclude/drm ++vivante-y := vivante_drv.o ++ ++obj-$(CONFIG_DRM_VIVANTE) += vivante.o +diff -Nur linux-3.14.14/drivers/gpu/drm/vivante/vivante_drv.c linux-imx6-3.14/drivers/gpu/drm/vivante/vivante_drv.c +--- linux-3.14.14/drivers/gpu/drm/vivante/vivante_drv.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/gpu/drm/vivante/vivante_drv.c 2014-12-08 00:31:52.828418001 -0600 +@@ -0,0 +1,108 @@ ++/**************************************************************************** ++* ++* Copyright (C) 2005 - 2013 by Vivante Corp. ++* ++* This program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2 of the license, or ++* (at your option) any later version. ++* ++* This program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License ++* along with this program; if not write to the Free Software ++* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++* ++*****************************************************************************/ ++ ++ ++/* vivante_drv.c -- vivante driver -*- linux-c -*- ++ * ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: ++ * Rickard E. (Rik) Faith ++ * Daryll Strauss ++ * Gareth Hughes ++ */ ++ ++#include ++#include ++ ++#include "drmP.h" ++#include "vivante_drv.h" ++ ++#include "drm_pciids.h" ++ ++static char platformdevicename[] = "Vivante GCCore"; ++static struct platform_device *pplatformdev; ++ ++static const struct file_operations viv_driver_fops = { ++ .owner = THIS_MODULE, ++ .open = drm_open, ++ .release = drm_release, ++ .unlocked_ioctl = drm_ioctl, ++ .mmap = drm_mmap, ++ .poll = drm_poll, ++ .llseek = noop_llseek, ++}; ++ ++static struct drm_driver driver = { ++ .fops = &viv_driver_fops, ++ .name = DRIVER_NAME, ++ .desc = DRIVER_DESC, ++ .date = DRIVER_DATE, ++ .major = DRIVER_MAJOR, ++ .minor = DRIVER_MINOR, ++ .patchlevel = DRIVER_PATCHLEVEL, ++}; ++ ++static int __init vivante_init(void) ++{ ++ int retcode; ++ ++ pplatformdev = platform_device_register_simple(platformdevicename, ++ -1, NULL, 0); ++ if (pplatformdev == NULL) ++ printk(KERN_ERR"Platform device is null\n"); ++ ++ retcode = drm_platform_init(&driver, pplatformdev); ++ ++ return retcode; ++} ++ ++static void __exit vivante_exit(void) ++{ ++ if (pplatformdev) { ++ platform_device_unregister(pplatformdev); ++ pplatformdev = NULL; ++ } ++} ++ ++module_init(vivante_init); ++module_exit(vivante_exit); ++ ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_LICENSE("GPL and additional rights"); +diff -Nur linux-3.14.14/drivers/gpu/drm/vivante/vivante_drv.h linux-imx6-3.14/drivers/gpu/drm/vivante/vivante_drv.h +--- linux-3.14.14/drivers/gpu/drm/vivante/vivante_drv.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/gpu/drm/vivante/vivante_drv.h 2014-12-08 00:31:52.828418001 -0600 +@@ -0,0 +1,66 @@ ++/**************************************************************************** ++* ++* Copyright (C) 2005 - 2013 by Vivante Corp. ++* ++* This program is free software; you can redistribute it and/or modify ++* it under the terms of the GNU General Public License as published by ++* the Free Software Foundation; either version 2 of the license, or ++* (at your option) any later version. ++* ++* This program is distributed in the hope that it will be useful, ++* but WITHOUT ANY WARRANTY; without even the implied warranty of ++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++* GNU General Public License for more details. ++* ++* You should have received a copy of the GNU General Public License ++* along with this program; if not write to the Free Software ++* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++* ++*****************************************************************************/ ++ ++ ++/* vivante_drv.h -- Vivante DRM template customization -*- linux-c -*- ++ * Created: Wed Feb 14 12:32:32 2012 by John Zhao ++ */ ++/* ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice (including the next ++ * paragraph) shall be included in all copies or substantial portions of the ++ * Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ * Authors: ++ * Gareth Hughes ++ */ ++ ++#ifndef __VIVANTE_DRV_H__ ++#define __VIVANTE_DRV_H__ ++ ++/* General customization: ++ */ ++ ++#define DRIVER_AUTHOR "Vivante Inc." ++ ++#define DRIVER_NAME "vivante" ++#define DRIVER_DESC "Vivante GCCore" ++#define DRIVER_DATE "20120216" ++ ++#define DRIVER_MAJOR 1 ++#define DRIVER_MINOR 0 ++#define DRIVER_PATCHLEVEL 0 ++ ++#endif +diff -Nur linux-3.14.14/drivers/hwmon/Kconfig linux-imx6-3.14/drivers/hwmon/Kconfig +--- linux-3.14.14/drivers/hwmon/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/hwmon/Kconfig 2014-12-08 00:31:52.852418001 -0600 +@@ -1584,4 +1584,19 @@ + + endif # ACPI + ++config SENSORS_MAG3110 ++ tristate "Freescale MAG3110 e-compass sensor" ++ depends on I2C && SYSFS ++ help ++ If you say yes here you get support for the Freescale MAG3110 ++ e-compass sensor. ++ This driver can also be built as a module. If so, the module ++ will be called mag3110. ++ ++config MXC_MMA8451 ++ tristate "MMA8451 device driver" ++ depends on I2C ++ depends on INPUT_POLLDEV ++ default y ++ + endif # HWMON +diff -Nur linux-3.14.14/drivers/hwmon/mag3110.c linux-imx6-3.14/drivers/hwmon/mag3110.c +--- linux-3.14.14/drivers/hwmon/mag3110.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/hwmon/mag3110.c 2014-12-08 00:31:52.868418001 -0600 +@@ -0,0 +1,611 @@ ++/* ++ * ++ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAG3110_DRV_NAME "mag3110" ++#define MAG3110_ID 0xC4 ++#define MAG3110_XYZ_DATA_LEN 6 ++#define MAG3110_STATUS_ZYXDR 0x08 ++ ++#define MAG3110_AC_MASK (0x01) ++#define MAG3110_AC_OFFSET 0 ++#define MAG3110_DR_MODE_MASK (0x7 << 5) ++#define MAG3110_DR_MODE_OFFSET 5 ++#define MAG3110_IRQ_USED 0 ++ ++#define POLL_INTERVAL_MAX 500 ++#define POLL_INTERVAL 100 ++#define INT_TIMEOUT 1000 ++#define DEFAULT_POSITION 2 ++/* register enum for mag3110 registers */ ++enum { ++ MAG3110_DR_STATUS = 0x00, ++ MAG3110_OUT_X_MSB, ++ MAG3110_OUT_X_LSB, ++ MAG3110_OUT_Y_MSB, ++ MAG3110_OUT_Y_LSB, ++ MAG3110_OUT_Z_MSB, ++ MAG3110_OUT_Z_LSB, ++ MAG3110_WHO_AM_I, ++ ++ MAG3110_OFF_X_MSB, ++ MAG3110_OFF_X_LSB, ++ MAG3110_OFF_Y_MSB, ++ MAG3110_OFF_Y_LSB, ++ MAG3110_OFF_Z_MSB, ++ MAG3110_OFF_Z_LSB, ++ ++ MAG3110_DIE_TEMP, ++ ++ MAG3110_CTRL_REG1 = 0x10, ++ MAG3110_CTRL_REG2, ++}; ++enum { ++ MAG_STANDBY, ++ MAG_ACTIVED ++}; ++struct mag3110_data { ++ struct i2c_client *client; ++ struct input_polled_dev *poll_dev; ++ struct device *hwmon_dev; ++ wait_queue_head_t waitq; ++ bool data_ready; ++ u8 ctl_reg1; ++ int active; ++ int position; ++}; ++static short MAGHAL[8][3][3] = { ++ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, ++ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, ++ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, ++ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, ++ ++ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, ++ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, ++ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, ++ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, ++}; ++ ++static struct mag3110_data *mag3110_pdata; ++/*! ++ * This function do one mag3110 register read. ++ */ ++static DEFINE_MUTEX(mag3110_lock); ++static int mag3110_adjust_position(short *x, short *y, short *z) ++{ ++ short rawdata[3], data[3]; ++ int i, j; ++ int position = mag3110_pdata->position; ++ if (position < 0 || position > 7) ++ position = 0; ++ rawdata[0] = *x; ++ rawdata[1] = *y; ++ rawdata[2] = *z; ++ for (i = 0; i < 3; i++) { ++ data[i] = 0; ++ for (j = 0; j < 3; j++) ++ data[i] += rawdata[j] * MAGHAL[position][i][j]; ++ } ++ *x = data[0]; ++ *y = data[1]; ++ *z = data[2]; ++ return 0; ++} ++ ++static int mag3110_read_reg(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++/*! ++ * This function do one mag3110 register write. ++ */ ++static int mag3110_write_reg(struct i2c_client *client, u8 reg, char value) ++{ ++ int ret; ++ ++ ret = i2c_smbus_write_byte_data(client, reg, value); ++ if (ret < 0) ++ dev_err(&client->dev, "i2c write failed\n"); ++ return ret; ++} ++ ++/*! ++ * This function do multiple mag3110 registers read. ++ */ ++static int mag3110_read_block_data(struct i2c_client *client, u8 reg, ++ int count, u8 *addr) ++{ ++ if (i2c_smbus_read_i2c_block_data(client, reg, count, addr) < count) { ++ dev_err(&client->dev, "i2c block read failed\n"); ++ return -1; ++ } ++ ++ return count; ++} ++ ++/* ++ * Initialization function ++ */ ++static int mag3110_init_client(struct i2c_client *client) ++{ ++ int val, ret; ++ ++ /* enable automatic resets */ ++ val = 0x80; ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG2, val); ++ ++ /* set default data rate to 10HZ */ ++ val = mag3110_read_reg(client, MAG3110_CTRL_REG1); ++ val |= (0x0 << MAG3110_DR_MODE_OFFSET); ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, val); ++ ++ return ret; ++} ++ ++/*************************************************************** ++* ++* read sensor data from mag3110 ++* ++***************************************************************/ ++static int mag3110_read_data(short *x, short *y, short *z) ++{ ++ struct mag3110_data *data; ++ int retry = 3; ++ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; ++ int result; ++ if (!mag3110_pdata || mag3110_pdata->active == MAG_STANDBY) ++ return -EINVAL; ++ ++ data = mag3110_pdata; ++#if MAG3110_IRQ_USED ++ if (!wait_event_interruptible_timeout ++ (data->waitq, data->data_ready != 0, ++ msecs_to_jiffies(INT_TIMEOUT))) { ++ dev_dbg(&data->client->dev, "interrupt not received\n"); ++ return -ETIME; ++ } ++#else ++ do { ++ msleep(1); ++ result = i2c_smbus_read_byte_data(data->client, ++ MAG3110_DR_STATUS); ++ retry--; ++ } while (!(result & MAG3110_STATUS_ZYXDR) && retry > 0); ++ /* Clear data_ready flag after data is read out */ ++ if (retry == 0) ++ return -EINVAL; ++#endif ++ ++ data->data_ready = 0; ++ ++ if (mag3110_read_block_data(data->client, ++ MAG3110_OUT_X_MSB, MAG3110_XYZ_DATA_LEN, ++ tmp_data) < 0) ++ return -1; ++ ++ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; ++ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; ++ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; ++ ++ return 0; ++} ++ ++static void report_abs(void) ++{ ++ struct input_dev *idev; ++ short x, y, z; ++ ++ mutex_lock(&mag3110_lock); ++ if (mag3110_read_data(&x, &y, &z) != 0) ++ goto out; ++ mag3110_adjust_position(&x, &y, &z); ++ idev = mag3110_pdata->poll_dev->input; ++ input_report_abs(idev, ABS_X, x); ++ input_report_abs(idev, ABS_Y, y); ++ input_report_abs(idev, ABS_Z, z); ++ input_sync(idev); ++out: ++ mutex_unlock(&mag3110_lock); ++} ++ ++static void mag3110_dev_poll(struct input_polled_dev *dev) ++{ ++ report_abs(); ++} ++ ++#if MAG3110_IRQ_USED ++static irqreturn_t mag3110_irq_handler(int irq, void *dev_id) ++{ ++ mag3110_pdata->data_ready = 1; ++ wake_up_interruptible(&mag3110_pdata->waitq); ++ ++ return IRQ_HANDLED; ++} ++#endif ++static ssize_t mag3110_enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client; ++ int val; ++ mutex_lock(&mag3110_lock); ++ client = mag3110_pdata->client; ++ val = mag3110_read_reg(client, MAG3110_CTRL_REG1) & MAG3110_AC_MASK; ++ ++ mutex_unlock(&mag3110_lock); ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t mag3110_enable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client; ++ int reg, ret; ++ long enable; ++ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; ++ ++ ret = strict_strtol(buf, 10, &enable); ++ if (ret) { ++ dev_err(dev, "string to long error\n"); ++ return ret; ++ } ++ ++ mutex_lock(&mag3110_lock); ++ client = mag3110_pdata->client; ++ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1); ++ if (enable && mag3110_pdata->active == MAG_STANDBY) { ++ reg |= MAG3110_AC_MASK; ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); ++ if (!ret) ++ mag3110_pdata->active = MAG_ACTIVED; ++ } else if (!enable && mag3110_pdata->active == MAG_ACTIVED) { ++ reg &= ~MAG3110_AC_MASK; ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); ++ if (!ret) ++ mag3110_pdata->active = MAG_STANDBY; ++ } ++ ++ if (mag3110_pdata->active == MAG_ACTIVED) { ++ msleep(100); ++ /* Read out MSB data to clear interrupt flag automatically */ ++ mag3110_read_block_data(client, MAG3110_OUT_X_MSB, ++ MAG3110_XYZ_DATA_LEN, tmp_data); ++ } ++ mutex_unlock(&mag3110_lock); ++ return count; ++} ++ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ mag3110_enable_show, mag3110_enable_store); ++ ++static ssize_t mag3110_dr_mode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client; ++ int val; ++ ++ client = mag3110_pdata->client; ++ val = (mag3110_read_reg(client, MAG3110_CTRL_REG1) ++ & MAG3110_DR_MODE_MASK) >> MAG3110_DR_MODE_OFFSET; ++ ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t mag3110_dr_mode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client; ++ int reg, ret; ++ unsigned long val; ++ ++ /* This must be done when mag3110 is disabled */ ++ if ((strict_strtoul(buf, 10, &val) < 0) || (val > 7)) ++ return -EINVAL; ++ ++ client = mag3110_pdata->client; ++ reg = mag3110_read_reg(client, MAG3110_CTRL_REG1) & ++ ~MAG3110_DR_MODE_MASK; ++ reg |= (val << MAG3110_DR_MODE_OFFSET); ++ /* MAG3110_CTRL_REG1 bit 5-7: data rate mode */ ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, reg); ++ if (ret < 0) ++ return ret; ++ ++ return count; ++} ++ ++static DEVICE_ATTR(dr_mode, S_IWUSR | S_IRUGO, ++ mag3110_dr_mode_show, mag3110_dr_mode_store); ++ ++static ssize_t mag3110_position_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int val; ++ mutex_lock(&mag3110_lock); ++ val = mag3110_pdata->position; ++ mutex_unlock(&mag3110_lock); ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t mag3110_position_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ long position; ++ int ret; ++ ret = strict_strtol(buf, 10, &position); ++ if (ret) { ++ dev_err(dev, "string to long error\n"); ++ return ret; ++ } ++ ++ mutex_lock(&mag3110_lock); ++ mag3110_pdata->position = (int)position; ++ mutex_unlock(&mag3110_lock); ++ return count; ++} ++ ++static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, ++ mag3110_position_show, mag3110_position_store); ++ ++static struct attribute *mag3110_attributes[] = { ++ &dev_attr_enable.attr, ++ &dev_attr_dr_mode.attr, ++ &dev_attr_position.attr, ++ NULL ++}; ++ ++static const struct attribute_group mag3110_attr_group = { ++ .attrs = mag3110_attributes, ++}; ++ ++static int mag3110_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adapter; ++ struct input_dev *idev; ++ struct mag3110_data *data; ++ int ret = 0; ++ struct regulator *vdd, *vdd_io; ++ u32 pos = 0; ++ struct device_node *of_node = client->dev.of_node; ++ vdd = NULL; ++ vdd_io = NULL; ++ ++ vdd = devm_regulator_get(&client->dev, "vdd"); ++ if (!IS_ERR(vdd)) { ++ ret = regulator_enable(vdd); ++ if (ret) { ++ dev_err(&client->dev, "vdd set voltage error\n"); ++ return ret; ++ } ++ } ++ ++ vdd_io = devm_regulator_get(&client->dev, "vddio"); ++ if (!IS_ERR(vdd_io)) { ++ ret = regulator_enable(vdd_io); ++ if (ret) { ++ dev_err(&client->dev, "vddio set voltage error\n"); ++ return ret; ++ } ++ } ++ ++ adapter = to_i2c_adapter(client->dev.parent); ++ if (!i2c_check_functionality(adapter, ++ I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_I2C_BLOCK)) ++ return -EIO; ++ ++ dev_info(&client->dev, "check mag3110 chip ID\n"); ++ ret = mag3110_read_reg(client, MAG3110_WHO_AM_I); ++ ++ if (MAG3110_ID != ret) { ++ dev_err(&client->dev, ++ "read chip ID 0x%x is not equal to 0x%x!\n", ret, ++ MAG3110_ID); ++ return -EINVAL; ++ } ++ data = kzalloc(sizeof(struct mag3110_data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ data->client = client; ++ i2c_set_clientdata(client, data); ++ /* Init queue */ ++ init_waitqueue_head(&data->waitq); ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ dev_err(&client->dev, "hwmon register failed!\n"); ++ ret = PTR_ERR(data->hwmon_dev); ++ goto error_rm_dev_sysfs; ++ } ++ ++ /*input poll device register */ ++ data->poll_dev = input_allocate_polled_device(); ++ if (!data->poll_dev) { ++ dev_err(&client->dev, "alloc poll device failed!\n"); ++ ret = -ENOMEM; ++ goto error_rm_hwmon_dev; ++ } ++ data->poll_dev->poll = mag3110_dev_poll; ++ data->poll_dev->poll_interval = POLL_INTERVAL; ++ data->poll_dev->poll_interval_max = POLL_INTERVAL_MAX; ++ idev = data->poll_dev->input; ++ idev->name = MAG3110_DRV_NAME; ++ idev->id.bustype = BUS_I2C; ++ idev->evbit[0] = BIT_MASK(EV_ABS); ++ input_set_abs_params(idev, ABS_X, -15000, 15000, 0, 0); ++ input_set_abs_params(idev, ABS_Y, -15000, 15000, 0, 0); ++ input_set_abs_params(idev, ABS_Z, -15000, 15000, 0, 0); ++ ret = input_register_polled_device(data->poll_dev); ++ if (ret) { ++ dev_err(&client->dev, "register poll device failed!\n"); ++ goto error_free_poll_dev; ++ } ++ ++ /*create device group in sysfs as user interface */ ++ ret = sysfs_create_group(&idev->dev.kobj, &mag3110_attr_group); ++ if (ret) { ++ dev_err(&client->dev, "create device file failed!\n"); ++ ret = -EINVAL; ++ goto error_rm_poll_dev; ++ } ++ /* set irq type to edge rising */ ++#if MAG3110_IRQ_USED ++ ret = request_irq(client->irq, mag3110_irq_handler, ++ IRQF_TRIGGER_RISING, client->dev.driver->name, idev); ++ if (ret < 0) { ++ dev_err(&client->dev, "failed to register irq %d!\n", ++ client->irq); ++ goto error_rm_dev_sysfs; ++ } ++#endif ++ /* Initialize mag3110 chip */ ++ mag3110_init_client(client); ++ mag3110_pdata = data; ++ mag3110_pdata->active = MAG_STANDBY; ++ ret = of_property_read_u32(of_node, "position", &pos); ++ if (ret) ++ pos = DEFAULT_POSITION; ++ mag3110_pdata->position = (int)pos; ++ dev_info(&client->dev, "mag3110 is probed\n"); ++ return 0; ++error_rm_dev_sysfs: ++ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); ++error_rm_poll_dev: ++ input_unregister_polled_device(data->poll_dev); ++error_free_poll_dev: ++ input_free_polled_device(data->poll_dev); ++error_rm_hwmon_dev: ++ hwmon_device_unregister(data->hwmon_dev); ++ ++ kfree(data); ++ mag3110_pdata = NULL; ++ ++ return ret; ++} ++ ++static int mag3110_remove(struct i2c_client *client) ++{ ++ struct mag3110_data *data; ++ int ret; ++ ++ data = i2c_get_clientdata(client); ++ ++ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, ++ data->ctl_reg1 & ~MAG3110_AC_MASK); ++ ++ free_irq(client->irq, data); ++ input_unregister_polled_device(data->poll_dev); ++ input_free_polled_device(data->poll_dev); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &mag3110_attr_group); ++ kfree(data); ++ mag3110_pdata = NULL; ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PM ++static int mag3110_suspend(struct i2c_client *client, pm_message_t mesg) ++{ ++ int ret = 0; ++ struct mag3110_data *data = i2c_get_clientdata(client); ++ if (data->active == MAG_ACTIVED) { ++ data->ctl_reg1 = mag3110_read_reg(client, MAG3110_CTRL_REG1); ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, ++ data->ctl_reg1 & ~MAG3110_AC_MASK); ++ } ++ return ret; ++} ++ ++static int mag3110_resume(struct i2c_client *client) ++{ ++ int ret = 0; ++ u8 tmp_data[MAG3110_XYZ_DATA_LEN]; ++ struct mag3110_data *data = i2c_get_clientdata(client); ++ if (data->active == MAG_ACTIVED) { ++ ret = mag3110_write_reg(client, MAG3110_CTRL_REG1, ++ data->ctl_reg1); ++ ++ if (data->ctl_reg1 & MAG3110_AC_MASK) { ++ /* Read out MSB data to clear interrupt ++ flag automatically */ ++ mag3110_read_block_data(client, MAG3110_OUT_X_MSB, ++ MAG3110_XYZ_DATA_LEN, tmp_data); ++ } ++ } ++ return ret; ++} ++ ++#else ++#define mag3110_suspend NULL ++#define mag3110_resume NULL ++#endif /* CONFIG_PM */ ++ ++static const struct i2c_device_id mag3110_id[] = { ++ {MAG3110_DRV_NAME, 0}, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mag3110_id); ++static struct i2c_driver mag3110_driver = { ++ .driver = {.name = MAG3110_DRV_NAME, ++ .owner = THIS_MODULE,}, ++ .suspend = mag3110_suspend, ++ .resume = mag3110_resume, ++ .probe = mag3110_probe, ++ .remove = mag3110_remove, ++ .id_table = mag3110_id, ++}; ++ ++static int __init mag3110_init(void) ++{ ++ return i2c_add_driver(&mag3110_driver); ++} ++ ++static void __exit mag3110_exit(void) ++{ ++ i2c_del_driver(&mag3110_driver); ++} ++ ++module_init(mag3110_init); ++module_exit(mag3110_exit); ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("Freescale mag3110 3-axis magnetometer driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/hwmon/Makefile linux-imx6-3.14/drivers/hwmon/Makefile +--- linux-3.14.14/drivers/hwmon/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/hwmon/Makefile 2014-12-08 00:31:52.852418001 -0600 +@@ -142,6 +142,8 @@ + obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o + obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o + obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o ++obj-$(CONFIG_SENSORS_MAG3110) += mag3110.o ++obj-$(CONFIG_MXC_MMA8451) += mxc_mma8451.o + + obj-$(CONFIG_PMBUS) += pmbus/ + +diff -Nur linux-3.14.14/drivers/hwmon/mxc_mma8451.c linux-imx6-3.14/drivers/hwmon/mxc_mma8451.c +--- linux-3.14.14/drivers/hwmon/mxc_mma8451.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/hwmon/mxc_mma8451.c 2014-12-08 00:31:52.868418001 -0600 +@@ -0,0 +1,598 @@ ++/* ++ * mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion ++ * Detection Sensor ++ * ++ * Copyright (C) 2010-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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MMA8451_I2C_ADDR 0x1C ++#define MMA8451_ID 0x1A ++#define MMA8452_ID 0x2A ++#define MMA8453_ID 0x3A ++ ++#define POLL_INTERVAL_MIN 1 ++#define POLL_INTERVAL_MAX 500 ++#define POLL_INTERVAL 100 /* msecs */ ++#define INPUT_FUZZ 32 ++#define INPUT_FLAT 32 ++#define MODE_CHANGE_DELAY_MS 100 ++ ++#define MMA8451_STATUS_ZYXDR 0x08 ++#define MMA8451_BUF_SIZE 7 ++#define DEFAULT_POSITION 0 ++ ++/* register enum for mma8451 registers */ ++enum { ++ MMA8451_STATUS = 0x00, ++ MMA8451_OUT_X_MSB, ++ MMA8451_OUT_X_LSB, ++ MMA8451_OUT_Y_MSB, ++ MMA8451_OUT_Y_LSB, ++ MMA8451_OUT_Z_MSB, ++ MMA8451_OUT_Z_LSB, ++ ++ MMA8451_F_SETUP = 0x09, ++ MMA8451_TRIG_CFG, ++ MMA8451_SYSMOD, ++ MMA8451_INT_SOURCE, ++ MMA8451_WHO_AM_I, ++ MMA8451_XYZ_DATA_CFG, ++ MMA8451_HP_FILTER_CUTOFF, ++ ++ MMA8451_PL_STATUS, ++ MMA8451_PL_CFG, ++ MMA8451_PL_COUNT, ++ MMA8451_PL_BF_ZCOMP, ++ MMA8451_P_L_THS_REG, ++ ++ MMA8451_FF_MT_CFG, ++ MMA8451_FF_MT_SRC, ++ MMA8451_FF_MT_THS, ++ MMA8451_FF_MT_COUNT, ++ ++ MMA8451_TRANSIENT_CFG = 0x1D, ++ MMA8451_TRANSIENT_SRC, ++ MMA8451_TRANSIENT_THS, ++ MMA8451_TRANSIENT_COUNT, ++ ++ MMA8451_PULSE_CFG, ++ MMA8451_PULSE_SRC, ++ MMA8451_PULSE_THSX, ++ MMA8451_PULSE_THSY, ++ MMA8451_PULSE_THSZ, ++ MMA8451_PULSE_TMLT, ++ MMA8451_PULSE_LTCY, ++ MMA8451_PULSE_WIND, ++ ++ MMA8451_ASLP_COUNT, ++ MMA8451_CTRL_REG1, ++ MMA8451_CTRL_REG2, ++ MMA8451_CTRL_REG3, ++ MMA8451_CTRL_REG4, ++ MMA8451_CTRL_REG5, ++ ++ MMA8451_OFF_X, ++ MMA8451_OFF_Y, ++ MMA8451_OFF_Z, ++ ++ MMA8451_REG_END, ++}; ++ ++/* The sensitivity is represented in counts/g. In 2g mode the ++sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512 ++counts/g and in 8g mode the sensitivity is 256 counts/g. ++ */ ++enum { ++ MODE_2G = 0, ++ MODE_4G, ++ MODE_8G, ++}; ++ ++enum { ++ MMA_STANDBY = 0, ++ MMA_ACTIVED, ++}; ++ ++/* mma8451 status */ ++struct mma8451_status { ++ u8 mode; ++ u8 ctl_reg1; ++ int active; ++ int position; ++}; ++ ++static struct mma8451_status mma_status; ++static struct input_polled_dev *mma8451_idev; ++static struct device *hwmon_dev; ++static struct i2c_client *mma8451_i2c_client; ++ ++static int senstive_mode = MODE_2G; ++static int ACCHAL[8][3][3] = { ++ { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} }, ++ { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} }, ++ { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} }, ++ { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} }, ++ ++ { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} }, ++ { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} }, ++ { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} }, ++ { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} }, ++}; ++ ++static DEFINE_MUTEX(mma8451_lock); ++static int mma8451_adjust_position(short *x, short *y, short *z) ++{ ++ short rawdata[3], data[3]; ++ int i, j; ++ int position = mma_status.position; ++ if (position < 0 || position > 7) ++ position = 0; ++ rawdata[0] = *x; ++ rawdata[1] = *y; ++ rawdata[2] = *z; ++ for (i = 0; i < 3; i++) { ++ data[i] = 0; ++ for (j = 0; j < 3; j++) ++ data[i] += rawdata[j] * ACCHAL[position][i][j]; ++ } ++ *x = data[0]; ++ *y = data[1]; ++ *z = data[2]; ++ return 0; ++} ++ ++static int mma8451_change_mode(struct i2c_client *client, int mode) ++{ ++ int result; ++ ++ mma_status.ctl_reg1 = 0; ++ result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0); ++ if (result < 0) ++ goto out; ++ mma_status.active = MMA_STANDBY; ++ ++ result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG, ++ mode); ++ if (result < 0) ++ goto out; ++ mdelay(MODE_CHANGE_DELAY_MS); ++ mma_status.mode = mode; ++ ++ return 0; ++out: ++ dev_err(&client->dev, "error when init mma8451:(%d)", result); ++ return result; ++} ++ ++static int mma8451_read_data(short *x, short *y, short *z) ++{ ++ u8 tmp_data[MMA8451_BUF_SIZE]; ++ int ret; ++ ++ ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client, ++ MMA8451_OUT_X_MSB, 7, tmp_data); ++ if (ret < MMA8451_BUF_SIZE) { ++ dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n"); ++ return -EIO; ++ } ++ ++ *x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1]; ++ *y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3]; ++ *z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5]; ++ return 0; ++} ++ ++static void report_abs(void) ++{ ++ short x, y, z; ++ int result; ++ int retry = 3; ++ ++ mutex_lock(&mma8451_lock); ++ if (mma_status.active == MMA_STANDBY) ++ goto out; ++ /* wait for the data ready */ ++ do { ++ result = i2c_smbus_read_byte_data(mma8451_i2c_client, ++ MMA8451_STATUS); ++ retry--; ++ msleep(1); ++ } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0); ++ if (retry == 0) ++ goto out; ++ if (mma8451_read_data(&x, &y, &z) != 0) ++ goto out; ++ mma8451_adjust_position(&x, &y, &z); ++ input_report_abs(mma8451_idev->input, ABS_X, x); ++ input_report_abs(mma8451_idev->input, ABS_Y, y); ++ input_report_abs(mma8451_idev->input, ABS_Z, z); ++ input_sync(mma8451_idev->input); ++out: ++ mutex_unlock(&mma8451_lock); ++} ++ ++static void mma8451_dev_poll(struct input_polled_dev *dev) ++{ ++ report_abs(); ++} ++ ++static ssize_t mma8451_enable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct i2c_client *client; ++ u8 val; ++ int enable; ++ ++ mutex_lock(&mma8451_lock); ++ client = mma8451_i2c_client; ++ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); ++ if ((val & 0x01) && mma_status.active == MMA_ACTIVED) ++ enable = 1; ++ else ++ enable = 0; ++ mutex_unlock(&mma8451_lock); ++ return sprintf(buf, "%d\n", enable); ++} ++ ++static ssize_t mma8451_enable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client; ++ int ret; ++ unsigned long enable; ++ u8 val = 0; ++ ++ ret = strict_strtoul(buf, 10, &enable); ++ if (ret) { ++ dev_err(dev, "string transform error\n"); ++ return ret; ++ } ++ ++ mutex_lock(&mma8451_lock); ++ client = mma8451_i2c_client; ++ enable = (enable > 0) ? 1 : 0; ++ if (enable && mma_status.active == MMA_STANDBY) { ++ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); ++ ret = ++ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, ++ val | 0x01); ++ if (!ret) ++ mma_status.active = MMA_ACTIVED; ++ ++ } else if (enable == 0 && mma_status.active == MMA_ACTIVED) { ++ val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1); ++ ret = ++ i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, ++ val & 0xFE); ++ if (!ret) ++ mma_status.active = MMA_STANDBY; ++ ++ } ++ mutex_unlock(&mma8451_lock); ++ return count; ++} ++ ++static ssize_t mma8451_position_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ int position = 0; ++ mutex_lock(&mma8451_lock); ++ position = mma_status.position; ++ mutex_unlock(&mma8451_lock); ++ return sprintf(buf, "%d\n", position); ++} ++ ++static ssize_t mma8451_position_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long position; ++ int ret; ++ ret = strict_strtoul(buf, 10, &position); ++ if (ret) { ++ dev_err(dev, "string transform error\n"); ++ return ret; ++ } ++ ++ mutex_lock(&mma8451_lock); ++ mma_status.position = (int)position; ++ mutex_unlock(&mma8451_lock); ++ return count; ++} ++ ++static ssize_t mma8451_scalemode_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int mode = 0; ++ mutex_lock(&mma8451_lock); ++ mode = (int)mma_status.mode; ++ mutex_unlock(&mma8451_lock); ++ ++ return sprintf(buf, "%d\n", mode); ++} ++ ++static ssize_t mma8451_scalemode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long mode; ++ int ret, active_save; ++ struct i2c_client *client = mma8451_i2c_client; ++ ++ ret = strict_strtoul(buf, 10, &mode); ++ if (ret) { ++ dev_err(dev, "string transform error\n"); ++ goto out; ++ } ++ ++ if (mode > MODE_8G) { ++ dev_warn(dev, "not supported mode\n"); ++ ret = count; ++ goto out; ++ } ++ ++ mutex_lock(&mma8451_lock); ++ if (mode == mma_status.mode) { ++ ret = count; ++ goto out_unlock; ++ } ++ ++ active_save = mma_status.active; ++ ret = mma8451_change_mode(client, mode); ++ if (ret) ++ goto out_unlock; ++ ++ if (active_save == MMA_ACTIVED) { ++ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 1); ++ ++ if (ret) ++ goto out_unlock; ++ mma_status.active = active_save; ++ } ++ ++out_unlock: ++ mutex_unlock(&mma8451_lock); ++out: ++ return ret; ++} ++ ++static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ++ mma8451_enable_show, mma8451_enable_store); ++static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, ++ mma8451_position_show, mma8451_position_store); ++static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, ++ mma8451_scalemode_show, mma8451_scalemode_store); ++ ++static struct attribute *mma8451_attributes[] = { ++ &dev_attr_enable.attr, ++ &dev_attr_position.attr, ++ &dev_attr_scalemode.attr, ++ NULL ++}; ++ ++static const struct attribute_group mma8451_attr_group = { ++ .attrs = mma8451_attributes, ++}; ++ ++static int mma8451_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int result, client_id; ++ struct input_dev *idev; ++ struct i2c_adapter *adapter; ++ u32 pos; ++ struct device_node *of_node = client->dev.of_node; ++ struct regulator *vdd, *vdd_io; ++ ++ mma8451_i2c_client = client; ++ ++ vdd = devm_regulator_get(&client->dev, "vdd"); ++ if (!IS_ERR(vdd)) { ++ result = regulator_enable(vdd); ++ if (result) { ++ dev_err(&client->dev, "vdd set voltage error\n"); ++ return result; ++ } ++ } ++ ++ vdd_io = devm_regulator_get(&client->dev, "vddio"); ++ if (!IS_ERR(vdd_io)) { ++ result = regulator_enable(vdd_io); ++ if (result) { ++ dev_err(&client->dev, "vddio set voltage error\n"); ++ return result; ++ } ++ } ++ ++ adapter = to_i2c_adapter(client->dev.parent); ++ result = i2c_check_functionality(adapter, ++ I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA); ++ if (!result) ++ goto err_out; ++ ++ client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I); ++ if (client_id != MMA8451_ID && client_id != MMA8452_ID ++ && client_id != MMA8453_ID) { ++ dev_err(&client->dev, ++ "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n", ++ result, MMA8451_ID, MMA8452_ID); ++ result = -EINVAL; ++ goto err_out; ++ } ++ ++ /* Initialize the MMA8451 chip */ ++ result = mma8451_change_mode(client, senstive_mode); ++ if (result) { ++ dev_err(&client->dev, ++ "error when init mma8451 chip:(%d)\n", result); ++ goto err_out; ++ } ++ ++ hwmon_dev = hwmon_device_register(&client->dev); ++ if (!hwmon_dev) { ++ result = -ENOMEM; ++ dev_err(&client->dev, "error when register hwmon device\n"); ++ goto err_out; ++ } ++ ++ mma8451_idev = input_allocate_polled_device(); ++ if (!mma8451_idev) { ++ result = -ENOMEM; ++ dev_err(&client->dev, "alloc poll device failed!\n"); ++ goto err_alloc_poll_device; ++ } ++ mma8451_idev->poll = mma8451_dev_poll; ++ mma8451_idev->poll_interval = POLL_INTERVAL; ++ mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN; ++ mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX; ++ idev = mma8451_idev->input; ++ idev->name = "mma845x"; ++ idev->id.bustype = BUS_I2C; ++ idev->evbit[0] = BIT_MASK(EV_ABS); ++ ++ input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); ++ input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); ++ input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); ++ ++ result = input_register_polled_device(mma8451_idev); ++ if (result) { ++ dev_err(&client->dev, "register poll device failed!\n"); ++ goto err_register_polled_device; ++ } ++ result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group); ++ if (result) { ++ dev_err(&client->dev, "create device file failed!\n"); ++ result = -EINVAL; ++ goto err_register_polled_device; ++ } ++ ++ result = of_property_read_u32(of_node, "position", &pos); ++ if (result) ++ pos = DEFAULT_POSITION; ++ mma_status.position = (int)pos; ++ ++ return 0; ++err_register_polled_device: ++ input_free_polled_device(mma8451_idev); ++err_alloc_poll_device: ++ hwmon_device_unregister(&client->dev); ++err_out: ++ return result; ++} ++ ++static int mma8451_stop_chip(struct i2c_client *client) ++{ ++ int ret = 0; ++ if (mma_status.active == MMA_ACTIVED) { ++ mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client, ++ MMA8451_CTRL_REG1); ++ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, ++ mma_status.ctl_reg1 & 0xFE); ++ } ++ return ret; ++} ++ ++static int mma8451_remove(struct i2c_client *client) ++{ ++ int ret; ++ ret = mma8451_stop_chip(client); ++ hwmon_device_unregister(hwmon_dev); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_PM_SLEEP ++static int mma8451_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ return mma8451_stop_chip(client); ++} ++ ++static int mma8451_resume(struct device *dev) ++{ ++ int ret = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ if (mma_status.active == MMA_ACTIVED) ++ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, ++ mma_status.ctl_reg1); ++ return ret; ++ ++} ++#endif ++ ++static const struct i2c_device_id mma8451_id[] = { ++ {"mma8451", 0}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, mma8451_id); ++ ++static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume); ++static struct i2c_driver mma8451_driver = { ++ .driver = { ++ .name = "mma8451", ++ .owner = THIS_MODULE, ++ .pm = &mma8451_pm_ops, ++ }, ++ .probe = mma8451_probe, ++ .remove = mma8451_remove, ++ .id_table = mma8451_id, ++}; ++ ++static int __init mma8451_init(void) ++{ ++ /* register driver */ ++ int res; ++ ++ res = i2c_add_driver(&mma8451_driver); ++ if (res < 0) { ++ printk(KERN_INFO "add mma8451 i2c driver failed\n"); ++ return -ENODEV; ++ } ++ return res; ++} ++ ++static void __exit mma8451_exit(void) ++{ ++ i2c_del_driver(&mma8451_driver); ++} ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("MMA8451 3-Axis Orientation/Motion Detection Sensor driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(mma8451_init); ++module_exit(mma8451_exit); +diff -Nur linux-3.14.14/drivers/i2c/busses/i2c-imx.c linux-imx6-3.14/drivers/i2c/busses/i2c-imx.c +--- linux-3.14.14/drivers/i2c/busses/i2c-imx.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/i2c/busses/i2c-imx.c 2014-12-08 00:31:52.884418001 -0600 +@@ -184,6 +184,9 @@ + int stopped; + unsigned int ifdr; /* IMX_I2C_IFDR */ + const struct imx_i2c_hwdata *hwdata; ++ ++ unsigned int cur_clk; ++ unsigned int bitrate; + }; + + static const struct imx_i2c_hwdata imx1_i2c_hwdata = { +@@ -305,6 +308,51 @@ + return 0; + } + ++static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) ++{ ++ struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; ++ unsigned ndivs = i2c_imx->hwdata->ndivs; ++ unsigned int i2c_clk_rate; ++ unsigned int div; ++ int i; ++ ++ /* Divider value calculation */ ++ i2c_clk_rate = clk_get_rate(i2c_imx->clk); ++ if (i2c_imx->cur_clk == i2c_clk_rate) ++ return; ++ else ++ i2c_imx->cur_clk = i2c_clk_rate; ++ ++ div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate; ++ if (div < i2c_clk_div[0].div) ++ i = 0; ++ else if (div > i2c_clk_div[ndivs - 1].div) ++ i = ndivs - 1; ++ else ++ for (i = 0; i2c_clk_div[i].div < div; i++) ++ ; ++ ++ /* Store divider value */ ++ i2c_imx->ifdr = imx_i2c_clk_div[i].val; ++ ++ /* ++ * There dummy delay is calculated. ++ * It should be about one I2C clock period long. ++ * This delay is used in I2C bus disable function ++ * to fix chip hardware bug. ++ */ ++ i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div ++ + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); ++ ++ /* dev_dbg() can't be used, because adapter is not yet registered */ ++#ifdef CONFIG_I2C_DEBUG_BUS ++ dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", ++ __func__, i2c_clk_rate, div); ++ dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", ++ __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); ++#endif ++} ++ + static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) + { + unsigned int temp = 0; +@@ -312,6 +360,7 @@ + + dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); + ++ i2c_imx_set_clk(i2c_imx); + result = clk_prepare_enable(i2c_imx->clk); + if (result) + return result; +@@ -367,45 +416,6 @@ + clk_disable_unprepare(i2c_imx->clk); + } + +-static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, +- unsigned int rate) +-{ +- struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; +- unsigned int i2c_clk_rate; +- unsigned int div; +- int i; +- +- /* Divider value calculation */ +- i2c_clk_rate = clk_get_rate(i2c_imx->clk); +- div = (i2c_clk_rate + rate - 1) / rate; +- if (div < i2c_clk_div[0].div) +- i = 0; +- else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) +- i = i2c_imx->hwdata->ndivs - 1; +- else +- for (i = 0; i2c_clk_div[i].div < div; i++); +- +- /* Store divider value */ +- i2c_imx->ifdr = i2c_clk_div[i].val; +- +- /* +- * There dummy delay is calculated. +- * It should be about one I2C clock period long. +- * This delay is used in I2C bus disable function +- * to fix chip hardware bug. +- */ +- i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div +- + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); +- +- /* dev_dbg() can't be used, because adapter is not yet registered */ +-#ifdef CONFIG_I2C_DEBUG_BUS +- dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", +- __func__, i2c_clk_rate, div); +- dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", +- __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); +-#endif +-} +- + static irqreturn_t i2c_imx_isr(int irq, void *dev_id) + { + struct imx_i2c_struct *i2c_imx = dev_id; +@@ -600,7 +610,6 @@ + struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); + void __iomem *base; + int irq, ret; +- u32 bitrate; + + dev_dbg(&pdev->dev, "<%s>\n", __func__); + +@@ -664,12 +673,12 @@ + i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); + + /* Set up clock divider */ +- bitrate = IMX_I2C_BIT_RATE; ++ i2c_imx->bitrate = IMX_I2C_BIT_RATE; + ret = of_property_read_u32(pdev->dev.of_node, +- "clock-frequency", &bitrate); ++ "clock-frequency", &i2c_imx->bitrate); + if (ret < 0 && pdata && pdata->bitrate) +- bitrate = pdata->bitrate; +- i2c_imx_set_clk(i2c_imx, bitrate); ++ i2c_imx->bitrate = pdata->bitrate; ++ i2c_imx_set_clk(i2c_imx); + + /* Set up chip registers to defaults */ + imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, +diff -Nur linux-3.14.14/drivers/input/keyboard/gpio_keys.c linux-imx6-3.14/drivers/input/keyboard/gpio_keys.c +--- linux-3.14.14/drivers/input/keyboard/gpio_keys.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/input/keyboard/gpio_keys.c 2014-12-08 00:31:52.992418001 -0600 +@@ -3,6 +3,7 @@ + * + * Copyright 2005 Phil Blundell + * Copyright 2010, 2011 David Jander ++ * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -473,6 +474,8 @@ + + isr = gpio_keys_gpio_isr; + irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; ++ if (bdata->button->wakeup) ++ irqflags |= IRQF_NO_SUSPEND; + + } else { + if (!button->irq) { +diff -Nur linux-3.14.14/drivers/input/keyboard/imx_keypad.c linux-imx6-3.14/drivers/input/keyboard/imx_keypad.c +--- linux-3.14.14/drivers/input/keyboard/imx_keypad.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/input/keyboard/imx_keypad.c 2014-12-08 00:31:52.992418001 -0600 +@@ -1,6 +1,7 @@ + /* + * Driver for the IMX keypad port. + * Copyright (C) 2009 Alberto Panizzo ++ * Copyright (C) 2013 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -548,6 +549,8 @@ + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(kbd->irq); ++ else ++ pinctrl_pm_select_sleep_state(dev); + + return 0; + } +@@ -561,6 +564,8 @@ + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(kbd->irq); ++ else ++ pinctrl_pm_select_default_state(dev); + + mutex_lock(&input_dev->mutex); + +diff -Nur linux-3.14.14/drivers/input/misc/mma8450.c linux-imx6-3.14/drivers/input/misc/mma8450.c +--- linux-3.14.14/drivers/input/misc/mma8450.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/input/misc/mma8450.c 2014-12-08 00:31:53.000418001 -0600 +@@ -1,7 +1,7 @@ + /* + * Driver for Freescale's 3-Axis Accelerometer MMA8450 + * +- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. ++ * 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 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #define MMA8450_DRV_NAME "mma8450" + +@@ -51,11 +52,22 @@ + + #define MMA8450_CTRL_REG1 0x38 + #define MMA8450_CTRL_REG2 0x39 ++#define MMA8450_ID 0xC6 ++#define MMA8450_WHO_AM_I 0x0F ++ ++enum { ++ MODE_STANDBY = 0, ++ MODE_2G, ++ MODE_4G, ++ MODE_8G, ++}; + + /* mma8450 status */ + struct mma8450 { + struct i2c_client *client; + struct input_polled_dev *idev; ++ struct mutex mma8450_lock; ++ u8 mode; + }; + + static int mma8450_read(struct mma8450 *m, unsigned off) +@@ -112,16 +124,19 @@ + int ret; + u8 buf[6]; + +- ret = mma8450_read(m, MMA8450_STATUS); +- if (ret < 0) +- return; ++ mutex_lock(&m->mma8450_lock); + +- if (!(ret & MMA8450_STATUS_ZXYDR)) ++ ret = mma8450_read(m, MMA8450_STATUS); ++ if (ret < 0 || !(ret & MMA8450_STATUS_ZXYDR)) { ++ mutex_unlock(&m->mma8450_lock); + return; ++ } + + ret = mma8450_read_block(m, MMA8450_OUT_X_LSB, buf, sizeof(buf)); +- if (ret < 0) ++ if (ret < 0) { ++ mutex_unlock(&m->mma8450_lock); + return; ++ } + + x = ((int)(s8)buf[1] << 4) | (buf[0] & 0xf); + y = ((int)(s8)buf[3] << 4) | (buf[2] & 0xf); +@@ -131,10 +146,12 @@ + input_report_abs(dev->input, ABS_Y, y); + input_report_abs(dev->input, ABS_Z, z); + input_sync(dev->input); ++ ++ mutex_unlock(&m->mma8450_lock); + } + + /* Initialize the MMA8450 chip */ +-static void mma8450_open(struct input_polled_dev *dev) ++static s32 mma8450_open(struct input_polled_dev *dev) + { + struct mma8450 *m = dev->private; + int err; +@@ -142,18 +159,20 @@ + /* enable all events from X/Y/Z, no FIFO */ + err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07); + if (err) +- return; ++ return err; + + /* + * Sleep mode poll rate - 50Hz + * System output data rate - 400Hz +- * Full scale selection - Active, +/- 2G ++ * Standby mode + */ +- err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01); +- if (err < 0) +- return; +- ++ err = mma8450_write(m, MMA8450_CTRL_REG1, MODE_STANDBY); ++ if (err) ++ return err; ++ m->mode = MODE_STANDBY; + msleep(MODE_CHANGE_DELAY_MS); ++ ++ return 0; + } + + static void mma8450_close(struct input_polled_dev *dev) +@@ -164,6 +183,76 @@ + mma8450_write(m, MMA8450_CTRL_REG2, 0x01); + } + ++static ssize_t mma8450_scalemode_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int mode = 0; ++ struct mma8450 *m; ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ m = i2c_get_clientdata(client); ++ ++ mutex_lock(&m->mma8450_lock); ++ mode = (int)m->mode; ++ mutex_unlock(&m->mma8450_lock); ++ ++ return sprintf(buf, "%d\n", mode); ++} ++ ++static ssize_t mma8450_scalemode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long mode; ++ int ret; ++ struct mma8450 *m = NULL; ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ ret = strict_strtoul(buf, 10, &mode); ++ if (ret) { ++ dev_err(dev, "string transform error\n"); ++ return ret; ++ } ++ ++ if (mode > MODE_8G) { ++ dev_warn(dev, "not supported mode %d\n", (int)mode); ++ return count; ++ } ++ ++ m = i2c_get_clientdata(client); ++ ++ mutex_lock(&m->mma8450_lock); ++ if (mode == m->mode) { ++ mutex_unlock(&m->mma8450_lock); ++ return count; ++ } ++ ++ ret = mma8450_write(m, MMA8450_CTRL_REG1, mode); ++ if (ret < 0) { ++ mutex_unlock(&m->mma8450_lock); ++ return ret; ++ } ++ ++ msleep(MODE_CHANGE_DELAY_MS); ++ m->mode = (u8)mode; ++ mutex_unlock(&m->mma8450_lock); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(scalemode, S_IWUSR | S_IRUGO, ++ mma8450_scalemode_show, mma8450_scalemode_store); ++ ++static struct attribute *mma8450_attributes[] = { ++ &dev_attr_scalemode.attr, ++ NULL ++}; ++ ++static const struct attribute_group mma8450_attr_group = { ++ .attrs = mma8450_attributes, ++}; ++ + /* + * I2C init/probing/exit functions + */ +@@ -172,7 +261,25 @@ + { + struct input_polled_dev *idev; + struct mma8450 *m; +- int err; ++ int err, client_id; ++ struct i2c_adapter *adapter = NULL; ++ ++ adapter = to_i2c_adapter(c->dev.parent); ++ err = i2c_check_functionality(adapter, ++ I2C_FUNC_SMBUS_BYTE | ++ I2C_FUNC_SMBUS_BYTE_DATA); ++ if (!err) ++ goto err_out; ++ ++ client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I); ++ ++ if (MMA8450_ID != client_id) { ++ dev_err(&c->dev, ++ "read chip ID 0x%x is not equal to 0x%x!\n", client_id, ++ MMA8450_ID); ++ err = -EINVAL; ++ goto err_out; ++ } + + m = kzalloc(sizeof(struct mma8450), GFP_KERNEL); + idev = input_allocate_polled_device(); +@@ -183,6 +290,7 @@ + + m->client = c; + m->idev = idev; ++ i2c_set_clientdata(c, m); + + idev->private = m; + idev->input->name = MMA8450_DRV_NAME; +@@ -190,8 +298,6 @@ + idev->poll = mma8450_poll; + idev->poll_interval = POLL_INTERVAL; + idev->poll_interval_max = POLL_INTERVAL_MAX; +- idev->open = mma8450_open; +- idev->close = mma8450_close; + + __set_bit(EV_ABS, idev->input->evbit); + input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32); +@@ -206,11 +312,32 @@ + + i2c_set_clientdata(c, m); + ++ mutex_init(&m->mma8450_lock); ++ ++ err = mma8450_open(idev); ++ if (err) { ++ dev_err(&c->dev, "failed to initialize mma8450\n"); ++ goto err_unreg_dev; ++ } ++ ++ err = sysfs_create_group(&c->dev.kobj, &mma8450_attr_group); ++ if (err) { ++ dev_err(&c->dev, "create device file failed!\n"); ++ err = -EINVAL; ++ goto err_close; ++ } ++ + return 0; + ++err_close: ++ mma8450_close(idev); ++err_unreg_dev: ++ mutex_destroy(&m->mma8450_lock); ++ input_unregister_polled_device(idev); + err_free_mem: + input_free_polled_device(idev); + kfree(m); ++err_out: + return err; + } + +@@ -219,6 +346,9 @@ + struct mma8450 *m = i2c_get_clientdata(c); + struct input_polled_dev *idev = m->idev; + ++ sysfs_remove_group(&c->dev.kobj, &mma8450_attr_group); ++ mma8450_close(idev); ++ mutex_destroy(&m->mma8450_lock); + input_unregister_polled_device(idev); + input_free_polled_device(idev); + kfree(m); +diff -Nur linux-3.14.14/drivers/input/sparse-keymap.c linux-imx6-3.14/drivers/input/sparse-keymap.c +--- linux-3.14.14/drivers/input/sparse-keymap.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/input/sparse-keymap.c 2014-12-08 00:31:53.012418001 -0600 +@@ -236,7 +236,7 @@ + * in an input device that was set up by sparse_keymap_setup(). + * NOTE: It is safe to cal this function while input device is + * still registered (however the drivers should care not to try to +- * use freed keymap and thus have to shut off interrups/polling ++ * use freed keymap and thus have to shut off interrupts/polling + * before freeing the keymap). + */ + void sparse_keymap_free(struct input_dev *dev) +diff -Nur linux-3.14.14/drivers/Kconfig linux-imx6-3.14/drivers/Kconfig +--- linux-3.14.14/drivers/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/Kconfig 2014-12-08 00:31:52.392418001 -0600 +@@ -96,6 +96,8 @@ + + source "drivers/memstick/Kconfig" + ++source "drivers/mxc/Kconfig" ++ + source "drivers/leds/Kconfig" + + source "drivers/accessibility/Kconfig" +diff -Nur linux-3.14.14/drivers/leds/leds-gpio.c linux-imx6-3.14/drivers/leds/leds-gpio.c +--- linux-3.14.14/drivers/leds/leds-gpio.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/leds/leds-gpio.c 2014-12-08 00:31:53.080418001 -0600 +@@ -3,7 +3,7 @@ + * + * Copyright (C) 2007 8D Technologies inc. + * Raphael Assenat +- * Copyright (C) 2008 Freescale Semiconductor, Inc. ++ * Copyright (C) 2008, 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -203,6 +203,8 @@ + else + led.default_state = LEDS_GPIO_DEFSTATE_OFF; + } ++ if (of_get_property(child, "retain-state-suspended", NULL)) ++ led.retain_state_suspended = 1; + + ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], + &pdev->dev, NULL); +diff -Nur linux-3.14.14/drivers/leds/leds-pwm.c linux-imx6-3.14/drivers/leds/leds-pwm.c +--- linux-3.14.14/drivers/leds/leds-pwm.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/leds/leds-pwm.c 2014-12-08 00:31:53.080418001 -0600 +@@ -70,6 +70,10 @@ + + duty *= brightness; + do_div(duty, max); ++ ++ if (led_dat->active_low) ++ duty = led_dat->period - duty; ++ + led_dat->duty = duty; + + if (led_dat->can_sleep) +@@ -93,55 +97,75 @@ + } + } + +-static int led_pwm_create_of(struct platform_device *pdev, +- struct led_pwm_priv *priv) ++static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, ++ struct led_pwm *led, struct device_node *child) + { +- struct device_node *child; ++ struct led_pwm_data *led_data = &priv->leds[priv->num_leds]; + int ret; + +- for_each_child_of_node(pdev->dev.of_node, child) { +- struct led_pwm_data *led_dat = &priv->leds[priv->num_leds]; ++ led_data->active_low = led->active_low; ++ led_data->period = led->pwm_period_ns; ++ led_data->cdev.name = led->name; ++ led_data->cdev.default_trigger = led->default_trigger; ++ led_data->cdev.brightness_set = led_pwm_set; ++ led_data->cdev.brightness = LED_OFF; ++ led_data->cdev.max_brightness = led->max_brightness; ++ led_data->cdev.flags = LED_CORE_SUSPENDRESUME; ++ ++ if (child) ++ led_data->pwm = devm_of_pwm_get(dev, child, NULL); ++ else ++ led_data->pwm = devm_pwm_get(dev, led->name); ++ if (IS_ERR(led_data->pwm)) { ++ ret = PTR_ERR(led_data->pwm); ++ dev_err(dev, "unable to request PWM for %s: %d\n", ++ led->name, ret); ++ return ret; ++ } + +- led_dat->cdev.name = of_get_property(child, "label", +- NULL) ? : child->name; ++ if (child) ++ led_data->period = pwm_get_period(led_data->pwm); + +- led_dat->pwm = devm_of_pwm_get(&pdev->dev, child, NULL); +- if (IS_ERR(led_dat->pwm)) { +- dev_err(&pdev->dev, "unable to request PWM for %s\n", +- led_dat->cdev.name); +- ret = PTR_ERR(led_dat->pwm); +- goto err; +- } +- /* Get the period from PWM core when n*/ +- led_dat->period = pwm_get_period(led_dat->pwm); ++ led_data->can_sleep = pwm_can_sleep(led_data->pwm); ++ if (led_data->can_sleep) ++ INIT_WORK(&led_data->work, led_pwm_work); + +- led_dat->cdev.default_trigger = of_get_property(child, ++ ret = led_classdev_register(dev, &led_data->cdev); ++ if (ret == 0) { ++ priv->num_leds++; ++ } else { ++ dev_err(dev, "failed to register PWM led for %s: %d\n", ++ led->name, ret); ++ } ++ ++ return ret; ++} ++ ++static int led_pwm_create_of(struct device *dev, struct led_pwm_priv *priv) ++{ ++ struct device_node *child; ++ struct led_pwm led; ++ int ret = 0; ++ ++ memset(&led, 0, sizeof(led)); ++ ++ for_each_child_of_node(dev->of_node, child) { ++ led.name = of_get_property(child, "label", NULL) ? : ++ child->name; ++ ++ led.default_trigger = of_get_property(child, + "linux,default-trigger", NULL); ++ led.active_low = of_property_read_bool(child, "active-low"); + of_property_read_u32(child, "max-brightness", +- &led_dat->cdev.max_brightness); ++ &led.max_brightness); + +- led_dat->cdev.brightness_set = led_pwm_set; +- led_dat->cdev.brightness = LED_OFF; +- led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; +- +- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); +- if (led_dat->can_sleep) +- INIT_WORK(&led_dat->work, led_pwm_work); +- +- ret = led_classdev_register(&pdev->dev, &led_dat->cdev); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to register for %s\n", +- led_dat->cdev.name); ++ ret = led_pwm_add(dev, priv, &led, child); ++ if (ret) { + of_node_put(child); +- goto err; ++ break; + } +- priv->num_leds++; + } + +- return 0; +-err: +- led_pwm_cleanup(priv); +- + return ret; + } + +@@ -167,51 +191,23 @@ + + if (pdata) { + for (i = 0; i < count; i++) { +- struct led_pwm *cur_led = &pdata->leds[i]; +- struct led_pwm_data *led_dat = &priv->leds[i]; +- +- led_dat->pwm = devm_pwm_get(&pdev->dev, cur_led->name); +- if (IS_ERR(led_dat->pwm)) { +- ret = PTR_ERR(led_dat->pwm); +- dev_err(&pdev->dev, +- "unable to request PWM for %s\n", +- cur_led->name); +- goto err; +- } +- +- led_dat->cdev.name = cur_led->name; +- led_dat->cdev.default_trigger = cur_led->default_trigger; +- led_dat->active_low = cur_led->active_low; +- led_dat->period = cur_led->pwm_period_ns; +- led_dat->cdev.brightness_set = led_pwm_set; +- led_dat->cdev.brightness = LED_OFF; +- led_dat->cdev.max_brightness = cur_led->max_brightness; +- led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; +- +- led_dat->can_sleep = pwm_can_sleep(led_dat->pwm); +- if (led_dat->can_sleep) +- INIT_WORK(&led_dat->work, led_pwm_work); +- +- ret = led_classdev_register(&pdev->dev, &led_dat->cdev); +- if (ret < 0) +- goto err; ++ ret = led_pwm_add(&pdev->dev, priv, &pdata->leds[i], ++ NULL); ++ if (ret) ++ break; + } +- priv->num_leds = count; + } else { +- ret = led_pwm_create_of(pdev, priv); +- if (ret) +- return ret; ++ ret = led_pwm_create_of(&pdev->dev, priv); ++ } ++ ++ if (ret) { ++ led_pwm_cleanup(priv); ++ return ret; + } + + platform_set_drvdata(pdev, priv); + + return 0; +- +-err: +- priv->num_leds = i; +- led_pwm_cleanup(priv); +- +- return ret; + } + + static int led_pwm_remove(struct platform_device *pdev) +diff -Nur linux-3.14.14/drivers/mailbox/mailbox.c linux-imx6-3.14/drivers/mailbox/mailbox.c +--- linux-3.14.14/drivers/mailbox/mailbox.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/mailbox/mailbox.c 2014-12-08 00:31:53.092418001 -0600 +@@ -0,0 +1,488 @@ ++/* ++ * Mailbox: Common code for Mailbox controllers and users ++ * ++ * Copyright (C) 2014 Linaro Ltd. ++ * Author: Jassi Brar ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TXDONE_BY_IRQ (1 << 0) /* controller has remote RTR irq */ ++#define TXDONE_BY_POLL (1 << 1) /* controller can read status of last TX */ ++#define TXDONE_BY_ACK (1 << 2) /* S/W ACK recevied by Client ticks the TX */ ++ ++static LIST_HEAD(mbox_cons); ++static DEFINE_MUTEX(con_mutex); ++ ++static int _add_to_rbuf(struct mbox_chan *chan, void *mssg) ++{ ++ int idx; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ ++ /* See if there is any space left */ ++ if (chan->msg_count == MBOX_TX_QUEUE_LEN) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return -ENOMEM; ++ } ++ ++ idx = chan->msg_free; ++ chan->msg_data[idx] = mssg; ++ chan->msg_count++; ++ ++ if (idx == MBOX_TX_QUEUE_LEN - 1) ++ chan->msg_free = 0; ++ else ++ chan->msg_free++; ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ return idx; ++} ++ ++static void _msg_submit(struct mbox_chan *chan) ++{ ++ unsigned count, idx; ++ unsigned long flags; ++ void *data; ++ int err; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ ++ if (!chan->msg_count || chan->active_req) { ++ spin_unlock_irqrestore(&chan->lock, flags); ++ return; ++ } ++ ++ count = chan->msg_count; ++ idx = chan->msg_free; ++ if (idx >= count) ++ idx -= count; ++ else ++ idx += MBOX_TX_QUEUE_LEN - count; ++ ++ data = chan->msg_data[idx]; ++ ++ /* Try to submit a message to the MBOX controller */ ++ err = chan->mbox->ops->send_data(chan, data); ++ if (!err) { ++ chan->active_req = data; ++ chan->msg_count--; ++ } ++ ++ spin_unlock_irqrestore(&chan->lock, flags); ++} ++ ++static void tx_tick(struct mbox_chan *chan, int r) ++{ ++ unsigned long flags; ++ void *mssg; ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ mssg = chan->active_req; ++ chan->active_req = NULL; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ /* Submit next message */ ++ _msg_submit(chan); ++ ++ /* Notify the client */ ++ if (chan->cl->tx_block) ++ complete(&chan->tx_complete); ++ else if (mssg && chan->cl->tx_done) ++ chan->cl->tx_done(chan->cl, mssg, r); ++} ++ ++static void poll_txdone(unsigned long data) ++{ ++ struct mbox_controller *mbox = (struct mbox_controller *)data; ++ bool txdone, resched = false; ++ int i; ++ ++ for (i = 0; i < mbox->num_chans; i++) { ++ struct mbox_chan *chan = &mbox->chans[i]; ++ ++ if (chan->active_req && chan->cl) { ++ resched = true; ++ txdone = chan->mbox->ops->last_tx_done(chan); ++ if (txdone) ++ tx_tick(chan, 0); ++ } ++ } ++ ++ if (resched) ++ mod_timer(&mbox->poll, ++ jiffies + msecs_to_jiffies(mbox->period)); ++} ++ ++/** ++ * mbox_chan_received_data - A way for controller driver to push data ++ * received from remote to the upper layer. ++ * @chan: Pointer to the mailbox channel on which RX happened. ++ * @data: Client specific message typecasted as void * ++ * ++ * After startup and before shutdown any data received on the chan ++ * is passed on to the API via atomic mbox_chan_received_data(). ++ * The controller should ACK the RX only after this call returns. ++ */ ++void mbox_chan_received_data(struct mbox_chan *chan, void *mssg) ++{ ++ /* No buffering the received data */ ++ if (chan->cl->rx_callback) ++ chan->cl->rx_callback(chan->cl, mssg); ++} ++EXPORT_SYMBOL_GPL(mbox_chan_received_data); ++ ++/** ++ * mbox_chan_txdone - A way for controller driver to notify the ++ * framework that the last TX has completed. ++ * @chan: Pointer to the mailbox chan on which TX happened. ++ * @r: Status of last TX - OK or ERROR ++ * ++ * The controller that has IRQ for TX ACK calls this atomic API ++ * to tick the TX state machine. It works only if txdone_irq ++ * is set by the controller. ++ */ ++void mbox_chan_txdone(struct mbox_chan *chan, int r) ++{ ++ if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) { ++ pr_err("Controller can't run the TX ticker\n"); ++ return; ++ } ++ ++ tx_tick(chan, r); ++} ++EXPORT_SYMBOL_GPL(mbox_chan_txdone); ++ ++/** ++ * mbox_client_txdone - The way for a client to run the TX state machine. ++ * @chan: Mailbox channel assigned to this client. ++ * @r: Success status of last transmission. ++ * ++ * The client/protocol had received some 'ACK' packet and it notifies ++ * the API that the last packet was sent successfully. This only works ++ * if the controller can't sense TX-Done. ++ */ ++void mbox_client_txdone(struct mbox_chan *chan, int r) ++{ ++ if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) { ++ pr_err("Client can't run the TX ticker\n"); ++ return; ++ } ++ ++ tx_tick(chan, r); ++} ++EXPORT_SYMBOL_GPL(mbox_client_txdone); ++ ++/** ++ * mbox_client_peek_data - A way for client driver to pull data ++ * received from remote by the controller. ++ * @chan: Mailbox channel assigned to this client. ++ * ++ * A poke to controller driver for any received data. ++ * The data is actually passed onto client via the ++ * mbox_chan_received_data() ++ * The call can be made from atomic context, so the controller's ++ * implementation of peek_data() must not sleep. ++ * ++ * Return: True, if controller has, and is going to push after this, ++ * some data. ++ * False, if controller doesn't have any data to be read. ++ */ ++bool mbox_client_peek_data(struct mbox_chan *chan) ++{ ++ if (chan->mbox->ops->peek_data) ++ return chan->mbox->ops->peek_data(chan); ++ ++ return false; ++} ++EXPORT_SYMBOL_GPL(mbox_client_peek_data); ++ ++/** ++ * mbox_send_message - For client to submit a message to be ++ * sent to the remote. ++ * @chan: Mailbox channel assigned to this client. ++ * @mssg: Client specific message typecasted. ++ * ++ * For client to submit data to the controller destined for a remote ++ * processor. If the client had set 'tx_block', the call will return ++ * either when the remote receives the data or when 'tx_tout' millisecs ++ * run out. ++ * In non-blocking mode, the requests are buffered by the API and a ++ * non-negative token is returned for each queued request. If the request ++ * is not queued, a negative token is returned. Upon failure or successful ++ * TX, the API calls 'tx_done' from atomic context, from which the client ++ * could submit yet another request. ++ * In blocking mode, 'tx_done' is not called, effectively making the ++ * queue length 1. ++ * The pointer to message should be preserved until it is sent ++ * over the chan, i.e, tx_done() is made. ++ * This function could be called from atomic context as it simply ++ * queues the data and returns a token against the request. ++ * ++ * Return: Non-negative integer for successful submission (non-blocking mode) ++ * or transmission over chan (blocking mode). ++ * Negative value denotes failure. ++ */ ++int mbox_send_message(struct mbox_chan *chan, void *mssg) ++{ ++ int t; ++ ++ if (!chan || !chan->cl) ++ return -EINVAL; ++ ++ t = _add_to_rbuf(chan, mssg); ++ if (t < 0) { ++ pr_err("Try increasing MBOX_TX_QUEUE_LEN\n"); ++ return t; ++ } ++ ++ _msg_submit(chan); ++ ++ reinit_completion(&chan->tx_complete); ++ ++ if (chan->txdone_method == TXDONE_BY_POLL) ++ poll_txdone((unsigned long)chan->mbox); ++ ++ if (chan->cl->tx_block && chan->active_req) { ++ unsigned long wait; ++ int ret; ++ ++ if (!chan->cl->tx_tout) /* wait for ever */ ++ wait = msecs_to_jiffies(3600000); ++ else ++ wait = msecs_to_jiffies(chan->cl->tx_tout); ++ ++ ret = wait_for_completion_timeout(&chan->tx_complete, wait); ++ if (ret == 0) { ++ t = -EIO; ++ tx_tick(chan, -EIO); ++ } ++ } ++ ++ return t; ++} ++EXPORT_SYMBOL_GPL(mbox_send_message); ++ ++/** ++ * mbox_request_channel - Request a mailbox channel. ++ * @cl: Identity of the client requesting the channel. ++ * ++ * The Client specifies its requirements and capabilities while asking for ++ * a mailbox channel. It can't be called from atomic context. ++ * The channel is exclusively allocated and can't be used by another ++ * client before the owner calls mbox_free_channel. ++ * After assignment, any packet received on this channel will be ++ * handed over to the client via the 'rx_callback'. ++ * The framework holds reference to the client, so the mbox_client ++ * structure shouldn't be modified until the mbox_free_channel returns. ++ * ++ * Return: Pointer to the channel assigned to the client if successful. ++ * ERR_PTR for request failure. ++ */ ++struct mbox_chan *mbox_request_channel(struct mbox_client *cl) ++{ ++ struct device *dev = cl->dev; ++ struct mbox_controller *mbox; ++ struct of_phandle_args spec; ++ struct mbox_chan *chan; ++ unsigned long flags; ++ int count, i, ret; ++ ++ if (!dev || !dev->of_node) { ++ pr_err("%s: No owner device node\n", __func__); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ count = of_property_count_strings(dev->of_node, "mbox-names"); ++ if (count < 0) { ++ pr_err("%s: mbox-names property of node '%s' missing\n", ++ __func__, dev->of_node->full_name); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ mutex_lock(&con_mutex); ++ ++ ret = -ENODEV; ++ for (i = 0; i < count; i++) { ++ const char *s; ++ ++ if (of_property_read_string_index(dev->of_node, ++ "mbox-names", i, &s)) ++ continue; ++ ++ if (strcmp(cl->chan_name, s)) ++ continue; ++ ++ if (of_parse_phandle_with_args(dev->of_node, ++ "mbox", "#mbox-cells", i, &spec)) ++ continue; ++ ++ chan = NULL; ++ list_for_each_entry(mbox, &mbox_cons, node) ++ if (mbox->dev->of_node == spec.np) { ++ chan = mbox->of_xlate(mbox, &spec); ++ break; ++ } ++ ++ of_node_put(spec.np); ++ ++ if (!chan) ++ continue; ++ ++ ret = -EBUSY; ++ if (!chan->cl && try_module_get(mbox->dev->driver->owner)) ++ break; ++ } ++ ++ if (i == count) { ++ mutex_unlock(&con_mutex); ++ return ERR_PTR(ret); ++ } ++ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->msg_free = 0; ++ chan->msg_count = 0; ++ chan->active_req = NULL; ++ chan->cl = cl; ++ init_completion(&chan->tx_complete); ++ ++ if (chan->txdone_method == TXDONE_BY_POLL ++ && cl->knows_txdone) ++ chan->txdone_method |= TXDONE_BY_ACK; ++ spin_unlock_irqrestore(&chan->lock, flags); ++ ++ ret = chan->mbox->ops->startup(chan); ++ if (ret) { ++ pr_err("Unable to startup the chan (%d)\n", ret); ++ mbox_free_channel(chan); ++ chan = ERR_PTR(ret); ++ } ++ ++ mutex_unlock(&con_mutex); ++ return chan; ++} ++EXPORT_SYMBOL_GPL(mbox_request_channel); ++ ++/** ++ * mbox_free_channel - The client relinquishes control of a mailbox ++ * channel by this call. ++ * @chan: The mailbox channel to be freed. ++ */ ++void mbox_free_channel(struct mbox_chan *chan) ++{ ++ unsigned long flags; ++ ++ if (!chan || !chan->cl) ++ return; ++ ++ chan->mbox->ops->shutdown(chan); ++ ++ /* The queued TX requests are simply aborted, no callbacks are made */ ++ spin_lock_irqsave(&chan->lock, flags); ++ chan->cl = NULL; ++ chan->active_req = NULL; ++ if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK)) ++ chan->txdone_method = TXDONE_BY_POLL; ++ ++ module_put(chan->mbox->dev->driver->owner); ++ spin_unlock_irqrestore(&chan->lock, flags); ++} ++EXPORT_SYMBOL_GPL(mbox_free_channel); ++ ++static struct mbox_chan * ++of_mbox_index_xlate(struct mbox_controller *mbox, ++ const struct of_phandle_args *sp) ++{ ++ int ind = sp->args[0]; ++ ++ if (ind >= mbox->num_chans) ++ return NULL; ++ ++ return &mbox->chans[ind]; ++} ++ ++/** ++ * mbox_controller_register - Register the mailbox controller ++ * @mbox: Pointer to the mailbox controller. ++ * ++ * The controller driver registers its communication chans ++ */ ++int mbox_controller_register(struct mbox_controller *mbox) ++{ ++ int i, txdone; ++ ++ /* Sanity check */ ++ if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans) ++ return -EINVAL; ++ ++ if (mbox->txdone_irq) ++ txdone = TXDONE_BY_IRQ; ++ else if (mbox->txdone_poll) ++ txdone = TXDONE_BY_POLL; ++ else /* It has to be ACK then */ ++ txdone = TXDONE_BY_ACK; ++ ++ if (txdone == TXDONE_BY_POLL) { ++ mbox->poll.function = &poll_txdone; ++ mbox->poll.data = (unsigned long)mbox; ++ init_timer(&mbox->poll); ++ } ++ ++ for (i = 0; i < mbox->num_chans; i++) { ++ struct mbox_chan *chan = &mbox->chans[i]; ++ chan->cl = NULL; ++ chan->mbox = mbox; ++ chan->txdone_method = txdone; ++ spin_lock_init(&chan->lock); ++ } ++ ++ if (!mbox->of_xlate) ++ mbox->of_xlate = of_mbox_index_xlate; ++ ++ mutex_lock(&con_mutex); ++ list_add_tail(&mbox->node, &mbox_cons); ++ mutex_unlock(&con_mutex); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(mbox_controller_register); ++ ++/** ++ * mbox_controller_unregister - UnRegister the mailbox controller ++ * @mbox: Pointer to the mailbox controller. ++ */ ++void mbox_controller_unregister(struct mbox_controller *mbox) ++{ ++ int i; ++ ++ if (!mbox) ++ return; ++ ++ mutex_lock(&con_mutex); ++ ++ list_del(&mbox->node); ++ ++ for (i = 0; i < mbox->num_chans; i++) ++ mbox_free_channel(&mbox->chans[i]); ++ ++ if (mbox->txdone_poll) ++ del_timer_sync(&mbox->poll); ++ ++ mutex_unlock(&con_mutex); ++} ++EXPORT_SYMBOL_GPL(mbox_controller_unregister); +diff -Nur linux-3.14.14/drivers/mailbox/Makefile linux-imx6-3.14/drivers/mailbox/Makefile +--- linux-3.14.14/drivers/mailbox/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mailbox/Makefile 2014-12-08 00:31:53.092418001 -0600 +@@ -1,3 +1,7 @@ ++# Generic MAILBOX API ++ ++obj-$(CONFIG_MAILBOX) += mailbox.o ++ + obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o + + obj-$(CONFIG_OMAP_MBOX) += omap-mailbox.o +diff -Nur linux-3.14.14/drivers/mailbox/pl320-ipc.c linux-imx6-3.14/drivers/mailbox/pl320-ipc.c +--- linux-3.14.14/drivers/mailbox/pl320-ipc.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mailbox/pl320-ipc.c 2014-12-08 00:31:53.092418001 -0600 +@@ -26,7 +26,7 @@ + #include + #include + +-#include ++#include + + #define IPCMxSOURCE(m) ((m) * 0x40) + #define IPCMxDSET(m) (((m) * 0x40) + 0x004) +diff -Nur linux-3.14.14/drivers/Makefile linux-imx6-3.14/drivers/Makefile +--- linux-3.14.14/drivers/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/Makefile 2014-12-08 00:31:52.392418001 -0600 +@@ -111,6 +111,7 @@ + obj-$(CONFIG_CPU_FREQ) += cpufreq/ + obj-$(CONFIG_CPU_IDLE) += cpuidle/ + obj-y += mmc/ ++obj-$(CONFIG_ARCH_MXC) += mxc/ + obj-$(CONFIG_MEMSTICK) += memstick/ + obj-y += leds/ + obj-$(CONFIG_INFINIBAND) += infiniband/ +diff -Nur linux-3.14.14/drivers/media/platform/Kconfig linux-imx6-3.14/drivers/media/platform/Kconfig +--- linux-3.14.14/drivers/media/platform/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/media/platform/Kconfig 2014-12-08 00:31:53.232418001 -0600 +@@ -115,6 +115,21 @@ + To compile this driver as a module, choose M here: the module + will be called s3c-camif. + ++config VIDEO_MXC_OUTPUT ++ tristate "MXC Video For Linux Video Output" ++ depends on VIDEO_DEV && ARCH_MXC && FB_MXC ++ select VIDEOBUF_DMA_CONTIG ++ ---help--- ++ This is the video4linux2 output driver based on MXC module. ++ ++config VIDEO_MXC_CAPTURE ++ tristate "MXC Video For Linux Video Capture" ++ depends on VIDEO_V4L2 && VIDEO_V4L2_INT_DEVICE ++ ---help--- ++ This is the video4linux2 capture driver based on i.MX video-in module. ++ ++source "drivers/media/platform/mxc/capture/Kconfig" ++source "drivers/media/platform/mxc/output/Kconfig" + source "drivers/media/platform/soc_camera/Kconfig" + source "drivers/media/platform/exynos4-is/Kconfig" + source "drivers/media/platform/s5p-tv/Kconfig" +diff -Nur linux-3.14.14/drivers/media/platform/Makefile linux-imx6-3.14/drivers/media/platform/Makefile +--- linux-3.14.14/drivers/media/platform/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/media/platform/Makefile 2014-12-08 00:31:53.232418001 -0600 +@@ -51,4 +51,7 @@ + + obj-$(CONFIG_ARCH_OMAP) += omap/ + ++obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc/capture/ ++obj-$(CONFIG_VIDEO_MXC_OUTPUT) += mxc/output/ ++ + ccflags-y += -I$(srctree)/drivers/media/i2c +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/adv7180.c linux-imx6-3.14/drivers/media/platform/mxc/capture/adv7180.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/adv7180.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/adv7180.c 2014-12-08 00:31:53.252418001 -0600 +@@ -0,0 +1,1344 @@ ++/* ++ * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file adv7180.c ++ * ++ * @brief Analog Device ADV7180 video decoder functions ++ * ++ * @ingroup Camera ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++ ++#define ADV7180_VOLTAGE_ANALOG 1800000 ++#define ADV7180_VOLTAGE_DIGITAL_CORE 1800000 ++#define ADV7180_VOLTAGE_DIGITAL_IO 3300000 ++#define ADV7180_VOLTAGE_PLL 1800000 ++ ++static struct regulator *dvddio_regulator; ++static struct regulator *dvdd_regulator; ++static struct regulator *avdd_regulator; ++static struct regulator *pvdd_regulator; ++static int pwn_gpio; ++ ++static int adv7180_probe(struct i2c_client *adapter, ++ const struct i2c_device_id *id); ++static int adv7180_detach(struct i2c_client *client); ++ ++static const struct i2c_device_id adv7180_id[] = { ++ {"adv7180", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, adv7180_id); ++ ++static struct i2c_driver adv7180_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "adv7180", ++ }, ++ .probe = adv7180_probe, ++ .remove = adv7180_detach, ++ .id_table = adv7180_id, ++}; ++ ++/*! ++ * Maintains the information on the current state of the sensor. ++ */ ++struct sensor { ++ struct sensor_data sen; ++ v4l2_std_id std_id; ++} adv7180_data; ++ ++ ++/*! List of input video formats supported. The video formats is corresponding ++ * with v4l2 id in video_fmt_t ++ */ ++typedef enum { ++ ADV7180_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ ++ ADV7180_PAL, /*!< (B, G, H, I, N)PAL video signal. */ ++ ADV7180_NOT_LOCKED, /*!< Not locked on a signal. */ ++} video_fmt_idx; ++ ++/*! Number of video standards supported (including 'not locked' signal). */ ++#define ADV7180_STD_MAX (ADV7180_PAL + 1) ++ ++/*! Video format structure. */ ++typedef struct { ++ int v4l2_id; /*!< Video for linux ID. */ ++ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ ++ u16 raw_width; /*!< Raw width. */ ++ u16 raw_height; /*!< Raw height. */ ++ u16 active_width; /*!< Active width. */ ++ u16 active_height; /*!< Active height. */ ++} video_fmt_t; ++ ++/*! Description of video formats supported. ++ * ++ * PAL: raw=720x625, active=720x576. ++ * NTSC: raw=720x525, active=720x480. ++ */ ++static video_fmt_t video_fmts[] = { ++ { /*! NTSC */ ++ .v4l2_id = V4L2_STD_NTSC, ++ .name = "NTSC", ++ .raw_width = 720, /* SENS_FRM_WIDTH */ ++ .raw_height = 525, /* SENS_FRM_HEIGHT */ ++ .active_width = 720, /* ACT_FRM_WIDTH plus 1 */ ++ .active_height = 480, /* ACT_FRM_WIDTH plus 1 */ ++ }, ++ { /*! (B, G, H, I, N) PAL */ ++ .v4l2_id = V4L2_STD_PAL, ++ .name = "PAL", ++ .raw_width = 720, ++ .raw_height = 625, ++ .active_width = 720, ++ .active_height = 576, ++ }, ++ { /*! Unlocked standard */ ++ .v4l2_id = V4L2_STD_ALL, ++ .name = "Autodetect", ++ .raw_width = 720, ++ .raw_height = 625, ++ .active_width = 720, ++ .active_height = 576, ++ }, ++}; ++ ++/*!* Standard index of ADV7180. */ ++static video_fmt_idx video_idx = ADV7180_PAL; ++ ++/*! @brief This mutex is used to provide mutual exclusion. ++ * ++ * Create a mutex that can be used to provide mutually exclusive ++ * read/write access to the globally accessible data structures ++ * and variables that were defined above. ++ */ ++static DEFINE_MUTEX(mutex); ++ ++#define IF_NAME "adv7180" ++#define ADV7180_INPUT_CTL 0x00 /* Input Control */ ++#define ADV7180_STATUS_1 0x10 /* Status #1 */ ++#define ADV7180_BRIGHTNESS 0x0a /* Brightness */ ++#define ADV7180_IDENT 0x11 /* IDENT */ ++#define ADV7180_VSYNC_FIELD_CTL_1 0x31 /* VSYNC Field Control #1 */ ++#define ADV7180_MANUAL_WIN_CTL 0x3d /* Manual Window Control */ ++#define ADV7180_SD_SATURATION_CB 0xe3 /* SD Saturation Cb */ ++#define ADV7180_SD_SATURATION_CR 0xe4 /* SD Saturation Cr */ ++#define ADV7180_PWR_MNG 0x0f /* Power Management */ ++ ++/* supported controls */ ++/* This hasn't been fully implemented yet. ++ * This is how it should work, though. */ ++static struct v4l2_queryctrl adv7180_qctrl[] = { ++ { ++ .id = V4L2_CID_BRIGHTNESS, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Brightness", ++ .minimum = 0, /* check this value */ ++ .maximum = 255, /* check this value */ ++ .step = 1, /* check this value */ ++ .default_value = 127, /* check this value */ ++ .flags = 0, ++ }, { ++ .id = V4L2_CID_SATURATION, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Saturation", ++ .minimum = 0, /* check this value */ ++ .maximum = 255, /* check this value */ ++ .step = 0x1, /* check this value */ ++ .default_value = 127, /* check this value */ ++ .flags = 0, ++ } ++}; ++ ++static inline void adv7180_power_down(int enable) ++{ ++ gpio_set_value_cansleep(pwn_gpio, !enable); ++ msleep(2); ++} ++ ++static int adv7180_regulator_enable(struct device *dev) ++{ ++ int ret = 0; ++ ++ dvddio_regulator = devm_regulator_get(dev, "DOVDD"); ++ ++ if (!IS_ERR(dvddio_regulator)) { ++ regulator_set_voltage(dvddio_regulator, ++ ADV7180_VOLTAGE_DIGITAL_IO, ++ ADV7180_VOLTAGE_DIGITAL_IO); ++ ret = regulator_enable(dvddio_regulator); ++ if (ret) { ++ dev_err(dev, "set io voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set io voltage ok\n"); ++ } ++ } else { ++ dev_warn(dev, "cannot get io voltage\n"); ++ } ++ ++ dvdd_regulator = devm_regulator_get(dev, "DVDD"); ++ if (!IS_ERR(dvdd_regulator)) { ++ regulator_set_voltage(dvdd_regulator, ++ ADV7180_VOLTAGE_DIGITAL_CORE, ++ ADV7180_VOLTAGE_DIGITAL_CORE); ++ ret = regulator_enable(dvdd_regulator); ++ if (ret) { ++ dev_err(dev, "set core voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set core voltage ok\n"); ++ } ++ } else { ++ dev_warn(dev, "cannot get core voltage\n"); ++ } ++ ++ avdd_regulator = devm_regulator_get(dev, "AVDD"); ++ if (!IS_ERR(avdd_regulator)) { ++ regulator_set_voltage(avdd_regulator, ++ ADV7180_VOLTAGE_ANALOG, ++ ADV7180_VOLTAGE_ANALOG); ++ ret = regulator_enable(avdd_regulator); ++ if (ret) { ++ dev_err(dev, "set analog voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set analog voltage ok\n"); ++ } ++ } else { ++ dev_warn(dev, "cannot get analog voltage\n"); ++ } ++ ++ pvdd_regulator = devm_regulator_get(dev, "PVDD"); ++ if (!IS_ERR(pvdd_regulator)) { ++ regulator_set_voltage(pvdd_regulator, ++ ADV7180_VOLTAGE_PLL, ++ ADV7180_VOLTAGE_PLL); ++ ret = regulator_enable(pvdd_regulator); ++ if (ret) { ++ dev_err(dev, "set pll voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set pll voltage ok\n"); ++ } ++ } else { ++ dev_warn(dev, "cannot get pll voltage\n"); ++ } ++ ++ return ret; ++} ++ ++ ++/*********************************************************************** ++ * I2C transfert. ++ ***********************************************************************/ ++ ++/*! Read one register from a ADV7180 i2c slave device. ++ * ++ * @param *reg register in the device we wish to access. ++ * ++ * @return 0 if success, an error code otherwise. ++ */ ++static inline int adv7180_read(u8 reg) ++{ ++ int val; ++ ++ val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg); ++ if (val < 0) { ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "%s:read reg error: reg=%2x\n", __func__, reg); ++ return -1; ++ } ++ return val; ++} ++ ++/*! Write one register of a ADV7180 i2c slave device. ++ * ++ * @param *reg register in the device we wish to access. ++ * ++ * @return 0 if success, an error code otherwise. ++ */ ++static int adv7180_write_reg(u8 reg, u8 val) ++{ ++ s32 ret; ++ ++ ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val); ++ if (ret < 0) { ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "%s:write reg error:reg=%2x,val=%2x\n", __func__, ++ reg, val); ++ return -1; ++ } ++ return 0; ++} ++ ++/*********************************************************************** ++ * mxc_v4l2_capture interface. ++ ***********************************************************************/ ++ ++/*! ++ * Return attributes of current video standard. ++ * Since this device autodetects the current standard, this function also ++ * sets the values that need to be changed if the standard changes. ++ * There is no set std equivalent function. ++ * ++ * @return None. ++ */ ++static void adv7180_get_std(v4l2_std_id *std) ++{ ++ int tmp; ++ int idx; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n"); ++ ++ /* Read the AD_RESULT to get the detect output video standard */ ++ tmp = adv7180_read(ADV7180_STATUS_1) & 0x70; ++ ++ mutex_lock(&mutex); ++ if (tmp == 0x40) { ++ /* PAL */ ++ *std = V4L2_STD_PAL; ++ idx = ADV7180_PAL; ++ } else if (tmp == 0) { ++ /*NTSC*/ ++ *std = V4L2_STD_NTSC; ++ idx = ADV7180_NTSC; ++ } else { ++ *std = V4L2_STD_ALL; ++ idx = ADV7180_NOT_LOCKED; ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "Got invalid video standard!\n"); ++ } ++ mutex_unlock(&mutex); ++ ++ /* This assumes autodetect which this device uses. */ ++ if (*std != adv7180_data.std_id) { ++ video_idx = idx; ++ adv7180_data.std_id = *std; ++ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; ++ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; ++ } ++} ++ ++/*********************************************************************** ++ * IOCTL Functions from v4l2_int_ioctl_desc. ++ ***********************************************************************/ ++ ++/*! ++ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num ++ * s: pointer to standard V4L2 device structure ++ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure ++ * ++ * Gets slave interface parameters. ++ * Calculates the required xclk value to support the requested ++ * clock parameters in p. This value is returned in the p ++ * parameter. ++ * ++ * vidioc_int_g_ifparm returns platform-specific information about the ++ * interface settings used by the sensor. ++ * ++ * Called on open. ++ */ ++static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n"); ++ ++ if (s == NULL) { ++ pr_err(" ERROR!! no slave device set!\n"); ++ return -1; ++ } ++ ++ /* Initialize structure to 0s then set any non-0 values. */ ++ memset(p, 0, sizeof(*p)); ++ p->if_type = V4L2_IF_TYPE_BT656; /* This is the only possibility. */ ++ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; ++ p->u.bt656.nobt_hs_inv = 1; ++ p->u.bt656.bt_sync_correct = 1; ++ ++ /* ADV7180 has a dedicated clock so no clock settings needed. */ ++ ++ return 0; ++} ++ ++/*! ++ * Sets the camera power. ++ * ++ * s pointer to the camera device ++ * on if 1, power is to be turned on. 0 means power is to be turned off ++ * ++ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num ++ * @s: pointer to standard V4L2 device structure ++ * @on: power state to which device is to be set ++ * ++ * Sets devices power state to requrested state, if possible. ++ * This is called on open, close, suspend and resume. ++ */ ++static int ioctl_s_power(struct v4l2_int_device *s, int on) ++{ ++ struct sensor *sensor = s->priv; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n"); ++ ++ if (on && !sensor->sen.on) { ++ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x04) != 0) ++ return -EIO; ++ ++ /* ++ * FIXME:Additional 400ms to wait the chip to be stable? ++ * This is a workaround for preview scrolling issue. ++ */ ++ msleep(400); ++ } else if (!on && sensor->sen.on) { ++ if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0) ++ return -EIO; ++ } ++ ++ sensor->sen.on = on; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure ++ * ++ * Returns the sensor's video CAPTURE parameters. ++ */ ++static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor *sensor = s->priv; ++ struct v4l2_captureparm *cparm = &a->parm.capture; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n"); ++ ++ switch (a->type) { ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ++ memset(a, 0, sizeof(*a)); ++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ cparm->capability = sensor->sen.streamcap.capability; ++ cparm->timeperframe = sensor->sen.streamcap.timeperframe; ++ cparm->capturemode = sensor->sen.streamcap.capturemode; ++ break; ++ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ break; ++ ++ default: ++ pr_debug("ioctl_g_parm:type is unknown %d\n", a->type); ++ break; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure ++ * ++ * Configures the sensor to use the input parameters, if possible. If ++ * not possible, reverts to the old parameters and returns the ++ * appropriate error code. ++ * ++ * This driver cannot change these settings. ++ */ ++static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n"); ++ ++ switch (a->type) { ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ break; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap ++ * @s: pointer to standard V4L2 device structure ++ * @f: pointer to standard V4L2 v4l2_format structure ++ * ++ * Returns the sensor's current pixel format in the v4l2_format ++ * parameter. ++ */ ++static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) ++{ ++ struct sensor *sensor = s->priv; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n"); ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" Returning size of %dx%d\n", ++ sensor->sen.pix.width, sensor->sen.pix.height); ++ f->fmt.pix = sensor->sen.pix; ++ break; ++ ++ case V4L2_BUF_TYPE_PRIVATE: { ++ v4l2_std_id std; ++ adv7180_get_std(&std); ++ f->fmt.pix.pixelformat = (u32)std; ++ } ++ break; ++ ++ default: ++ f->fmt.pix = sensor->sen.pix; ++ break; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure ++ * ++ * If the requested control is supported, returns the control information ++ * from the video_control[] array. Otherwise, returns -EINVAL if the ++ * control is not supported. ++ */ ++static int ioctl_queryctrl(struct v4l2_int_device *s, ++ struct v4l2_queryctrl *qc) ++{ ++ int i; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n"); ++ ++ for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++) ++ if (qc->id && qc->id == adv7180_qctrl[i].id) { ++ memcpy(qc, &(adv7180_qctrl[i]), ++ sizeof(*qc)); ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++/*! ++ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure ++ * ++ * If the requested control is supported, returns the control's current ++ * value from the video_control[] array. Otherwise, returns -EINVAL ++ * if the control is not supported. ++ */ ++static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int ret = 0; ++ int sat = 0; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n"); ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_BRIGHTNESS\n"); ++ adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS); ++ vc->value = adv7180_data.sen.brightness; ++ break; ++ case V4L2_CID_CONTRAST: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_CONTRAST\n"); ++ vc->value = adv7180_data.sen.contrast; ++ break; ++ case V4L2_CID_SATURATION: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_SATURATION\n"); ++ sat = adv7180_read(ADV7180_SD_SATURATION_CB); ++ adv7180_data.sen.saturation = sat; ++ vc->value = adv7180_data.sen.saturation; ++ break; ++ case V4L2_CID_HUE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_HUE\n"); ++ vc->value = adv7180_data.sen.hue; ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_AUTO_WHITE_BALANCE\n"); ++ break; ++ case V4L2_CID_DO_WHITE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_DO_WHITE_BALANCE\n"); ++ break; ++ case V4L2_CID_RED_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_RED_BALANCE\n"); ++ vc->value = adv7180_data.sen.red; ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_BLUE_BALANCE\n"); ++ vc->value = adv7180_data.sen.blue; ++ break; ++ case V4L2_CID_GAMMA: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_GAMMA\n"); ++ break; ++ case V4L2_CID_EXPOSURE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_EXPOSURE\n"); ++ vc->value = adv7180_data.sen.ae_mode; ++ break; ++ case V4L2_CID_AUTOGAIN: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_AUTOGAIN\n"); ++ break; ++ case V4L2_CID_GAIN: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_GAIN\n"); ++ break; ++ case V4L2_CID_HFLIP: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_HFLIP\n"); ++ break; ++ case V4L2_CID_VFLIP: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_VFLIP\n"); ++ break; ++ default: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " Default case\n"); ++ vc->value = 0; ++ ret = -EPERM; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure ++ * ++ * If the requested control is supported, sets the control's current ++ * value in HW (and updates the video_control[] array). Otherwise, ++ * returns -EINVAL if the control is not supported. ++ */ ++static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int retval = 0; ++ u8 tmp; ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n"); ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_BRIGHTNESS\n"); ++ tmp = vc->value; ++ adv7180_write_reg(ADV7180_BRIGHTNESS, tmp); ++ adv7180_data.sen.brightness = vc->value; ++ break; ++ case V4L2_CID_CONTRAST: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_CONTRAST\n"); ++ break; ++ case V4L2_CID_SATURATION: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_SATURATION\n"); ++ tmp = vc->value; ++ adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp); ++ adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp); ++ adv7180_data.sen.saturation = vc->value; ++ break; ++ case V4L2_CID_HUE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_HUE\n"); ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_AUTO_WHITE_BALANCE\n"); ++ break; ++ case V4L2_CID_DO_WHITE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_DO_WHITE_BALANCE\n"); ++ break; ++ case V4L2_CID_RED_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_RED_BALANCE\n"); ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_BLUE_BALANCE\n"); ++ break; ++ case V4L2_CID_GAMMA: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_GAMMA\n"); ++ break; ++ case V4L2_CID_EXPOSURE: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_EXPOSURE\n"); ++ break; ++ case V4L2_CID_AUTOGAIN: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_AUTOGAIN\n"); ++ break; ++ case V4L2_CID_GAIN: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_GAIN\n"); ++ break; ++ case V4L2_CID_HFLIP: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_HFLIP\n"); ++ break; ++ case V4L2_CID_VFLIP: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " V4L2_CID_VFLIP\n"); ++ break; ++ default: ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ " Default case\n"); ++ retval = -EPERM; ++ break; ++ } ++ ++ return retval; ++} ++ ++/*! ++ * ioctl_enum_framesizes - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMESIZES ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_framesizes(struct v4l2_int_device *s, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ if (fsize->index >= 1) ++ return -EINVAL; ++ ++ fsize->discrete.width = video_fmts[video_idx].active_width; ++ fsize->discrete.height = video_fmts[video_idx].active_height; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_chip_ident - V4L2 sensor interface handler for ++ * VIDIOC_DBG_G_CHIP_IDENT ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @id: pointer to int ++ * ++ * Return 0. ++ */ ++static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) ++{ ++ ((struct v4l2_dbg_chip_ident *)id)->match.type = ++ V4L2_CHIP_MATCH_I2C_DRIVER; ++ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, ++ "adv7180_decoder"); ++ ((struct v4l2_dbg_chip_ident *)id)->ident = V4L2_IDENT_ADV7180; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT ++ * @s: pointer to standard V4L2 device structure ++ */ ++static int ioctl_init(struct v4l2_int_device *s) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n"); ++ return 0; ++} ++ ++/*! ++ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Initialise the device when slave attaches to the master. ++ */ ++static int ioctl_dev_init(struct v4l2_int_device *s) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n"); ++ return 0; ++} ++ ++/*! ++ * This structure defines all the ioctls for this module. ++ */ ++static struct v4l2_int_ioctl_desc adv7180_ioctl_desc[] = { ++ ++ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func*)ioctl_dev_init}, ++ ++ /*! ++ * Delinitialise the dev. at slave detach. ++ * The complement of ioctl_dev_init. ++ */ ++/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *)ioctl_dev_exit}, */ ++ ++ {vidioc_int_s_power_num, (v4l2_int_ioctl_func*)ioctl_s_power}, ++ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func*)ioctl_g_ifparm}, ++/* {vidioc_int_g_needs_reset_num, ++ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ ++/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ ++ {vidioc_int_init_num, (v4l2_int_ioctl_func*)ioctl_init}, ++ ++ /*! ++ * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type. ++ */ ++/* {vidioc_int_enum_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */ ++ ++ /*! ++ * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. ++ * This ioctl is used to negotiate the image capture size and ++ * pixel format without actually making it take effect. ++ */ ++/* {vidioc_int_try_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ ++ ++ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func*)ioctl_g_fmt_cap}, ++ ++ /*! ++ * If the requested format is supported, configures the HW to use that ++ * format, returns error code if format not supported or HW can't be ++ * correctly configured. ++ */ ++/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */ ++ ++ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func*)ioctl_g_parm}, ++ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm}, ++ {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func*)ioctl_queryctrl}, ++ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func*)ioctl_g_ctrl}, ++ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl}, ++ {vidioc_int_enum_framesizes_num, ++ (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, ++ {vidioc_int_g_chip_ident_num, ++ (v4l2_int_ioctl_func *)ioctl_g_chip_ident}, ++}; ++ ++static struct v4l2_int_slave adv7180_slave = { ++ .ioctls = adv7180_ioctl_desc, ++ .num_ioctls = ARRAY_SIZE(adv7180_ioctl_desc), ++}; ++ ++static struct v4l2_int_device adv7180_int_device = { ++ .module = THIS_MODULE, ++ .name = "adv7180", ++ .type = v4l2_int_type_slave, ++ .u = { ++ .slave = &adv7180_slave, ++ }, ++}; ++ ++ ++/*********************************************************************** ++ * I2C client and driver. ++ ***********************************************************************/ ++ ++/*! ADV7180 Reset function. ++ * ++ * @return None. ++ */ ++static void adv7180_hard_reset(bool cvbs) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "In adv7180:adv7180_hard_reset\n"); ++ ++ if (cvbs) { ++ /* Set CVBS input on AIN1 */ ++ adv7180_write_reg(ADV7180_INPUT_CTL, 0x00); ++ } else { ++ /* ++ * Set YPbPr input on AIN1,4,5 and normal ++ * operations(autodection of all stds). ++ */ ++ adv7180_write_reg(ADV7180_INPUT_CTL, 0x09); ++ } ++ ++ /* Datasheet recommends */ ++ adv7180_write_reg(0x01, 0xc8); ++ adv7180_write_reg(0x02, 0x04); ++ adv7180_write_reg(0x03, 0x00); ++ adv7180_write_reg(0x04, 0x45); ++ adv7180_write_reg(0x05, 0x00); ++ adv7180_write_reg(0x06, 0x02); ++ adv7180_write_reg(0x07, 0x7F); ++ adv7180_write_reg(0x08, 0x80); ++ adv7180_write_reg(0x0A, 0x00); ++ adv7180_write_reg(0x0B, 0x00); ++ adv7180_write_reg(0x0C, 0x36); ++ adv7180_write_reg(0x0D, 0x7C); ++ adv7180_write_reg(0x0E, 0x00); ++ adv7180_write_reg(0x0F, 0x00); ++ adv7180_write_reg(0x13, 0x00); ++ adv7180_write_reg(0x14, 0x12); ++ adv7180_write_reg(0x15, 0x00); ++ adv7180_write_reg(0x16, 0x00); ++ adv7180_write_reg(0x17, 0x01); ++ adv7180_write_reg(0x18, 0x93); ++ adv7180_write_reg(0xF1, 0x19); ++ adv7180_write_reg(0x1A, 0x00); ++ adv7180_write_reg(0x1B, 0x00); ++ adv7180_write_reg(0x1C, 0x00); ++ adv7180_write_reg(0x1D, 0x40); ++ adv7180_write_reg(0x1E, 0x00); ++ adv7180_write_reg(0x1F, 0x00); ++ adv7180_write_reg(0x20, 0x00); ++ adv7180_write_reg(0x21, 0x00); ++ adv7180_write_reg(0x22, 0x00); ++ adv7180_write_reg(0x23, 0xC0); ++ adv7180_write_reg(0x24, 0x00); ++ adv7180_write_reg(0x25, 0x00); ++ adv7180_write_reg(0x26, 0x00); ++ adv7180_write_reg(0x27, 0x58); ++ adv7180_write_reg(0x28, 0x00); ++ adv7180_write_reg(0x29, 0x00); ++ adv7180_write_reg(0x2A, 0x00); ++ adv7180_write_reg(0x2B, 0xE1); ++ adv7180_write_reg(0x2C, 0xAE); ++ adv7180_write_reg(0x2D, 0xF4); ++ adv7180_write_reg(0x2E, 0x00); ++ adv7180_write_reg(0x2F, 0xF0); ++ adv7180_write_reg(0x30, 0x00); ++ adv7180_write_reg(0x31, 0x12); ++ adv7180_write_reg(0x32, 0x41); ++ adv7180_write_reg(0x33, 0x84); ++ adv7180_write_reg(0x34, 0x00); ++ adv7180_write_reg(0x35, 0x02); ++ adv7180_write_reg(0x36, 0x00); ++ adv7180_write_reg(0x37, 0x01); ++ adv7180_write_reg(0x38, 0x80); ++ adv7180_write_reg(0x39, 0xC0); ++ adv7180_write_reg(0x3A, 0x10); ++ adv7180_write_reg(0x3B, 0x05); ++ adv7180_write_reg(0x3C, 0x58); ++ adv7180_write_reg(0x3D, 0xB2); ++ adv7180_write_reg(0x3E, 0x64); ++ adv7180_write_reg(0x3F, 0xE4); ++ adv7180_write_reg(0x40, 0x90); ++ adv7180_write_reg(0x41, 0x01); ++ adv7180_write_reg(0x42, 0x7E); ++ adv7180_write_reg(0x43, 0xA4); ++ adv7180_write_reg(0x44, 0xFF); ++ adv7180_write_reg(0x45, 0xB6); ++ adv7180_write_reg(0x46, 0x12); ++ adv7180_write_reg(0x48, 0x00); ++ adv7180_write_reg(0x49, 0x00); ++ adv7180_write_reg(0x4A, 0x00); ++ adv7180_write_reg(0x4B, 0x00); ++ adv7180_write_reg(0x4C, 0x00); ++ adv7180_write_reg(0x4D, 0xEF); ++ adv7180_write_reg(0x4E, 0x08); ++ adv7180_write_reg(0x4F, 0x08); ++ adv7180_write_reg(0x50, 0x08); ++ adv7180_write_reg(0x51, 0x24); ++ adv7180_write_reg(0x52, 0x0B); ++ adv7180_write_reg(0x53, 0x4E); ++ adv7180_write_reg(0x54, 0x80); ++ adv7180_write_reg(0x55, 0x00); ++ adv7180_write_reg(0x56, 0x10); ++ adv7180_write_reg(0x57, 0x00); ++ adv7180_write_reg(0x58, 0x00); ++ adv7180_write_reg(0x59, 0x00); ++ adv7180_write_reg(0x5A, 0x00); ++ adv7180_write_reg(0x5B, 0x00); ++ adv7180_write_reg(0x5C, 0x00); ++ adv7180_write_reg(0x5D, 0x00); ++ adv7180_write_reg(0x5E, 0x00); ++ adv7180_write_reg(0x5F, 0x00); ++ adv7180_write_reg(0x60, 0x00); ++ adv7180_write_reg(0x61, 0x00); ++ adv7180_write_reg(0x62, 0x20); ++ adv7180_write_reg(0x63, 0x00); ++ adv7180_write_reg(0x64, 0x00); ++ adv7180_write_reg(0x65, 0x00); ++ adv7180_write_reg(0x66, 0x00); ++ adv7180_write_reg(0x67, 0x03); ++ adv7180_write_reg(0x68, 0x01); ++ adv7180_write_reg(0x69, 0x00); ++ adv7180_write_reg(0x6A, 0x00); ++ adv7180_write_reg(0x6B, 0xC0); ++ adv7180_write_reg(0x6C, 0x00); ++ adv7180_write_reg(0x6D, 0x00); ++ adv7180_write_reg(0x6E, 0x00); ++ adv7180_write_reg(0x6F, 0x00); ++ adv7180_write_reg(0x70, 0x00); ++ adv7180_write_reg(0x71, 0x00); ++ adv7180_write_reg(0x72, 0x00); ++ adv7180_write_reg(0x73, 0x10); ++ adv7180_write_reg(0x74, 0x04); ++ adv7180_write_reg(0x75, 0x01); ++ adv7180_write_reg(0x76, 0x00); ++ adv7180_write_reg(0x77, 0x3F); ++ adv7180_write_reg(0x78, 0xFF); ++ adv7180_write_reg(0x79, 0xFF); ++ adv7180_write_reg(0x7A, 0xFF); ++ adv7180_write_reg(0x7B, 0x1E); ++ adv7180_write_reg(0x7C, 0xC0); ++ adv7180_write_reg(0x7D, 0x00); ++ adv7180_write_reg(0x7E, 0x00); ++ adv7180_write_reg(0x7F, 0x00); ++ adv7180_write_reg(0x80, 0x00); ++ adv7180_write_reg(0x81, 0xC0); ++ adv7180_write_reg(0x82, 0x04); ++ adv7180_write_reg(0x83, 0x00); ++ adv7180_write_reg(0x84, 0x0C); ++ adv7180_write_reg(0x85, 0x02); ++ adv7180_write_reg(0x86, 0x03); ++ adv7180_write_reg(0x87, 0x63); ++ adv7180_write_reg(0x88, 0x5A); ++ adv7180_write_reg(0x89, 0x08); ++ adv7180_write_reg(0x8A, 0x10); ++ adv7180_write_reg(0x8B, 0x00); ++ adv7180_write_reg(0x8C, 0x40); ++ adv7180_write_reg(0x8D, 0x00); ++ adv7180_write_reg(0x8E, 0x40); ++ adv7180_write_reg(0x8F, 0x00); ++ adv7180_write_reg(0x90, 0x00); ++ adv7180_write_reg(0x91, 0x50); ++ adv7180_write_reg(0x92, 0x00); ++ adv7180_write_reg(0x93, 0x00); ++ adv7180_write_reg(0x94, 0x00); ++ adv7180_write_reg(0x95, 0x00); ++ adv7180_write_reg(0x96, 0x00); ++ adv7180_write_reg(0x97, 0xF0); ++ adv7180_write_reg(0x98, 0x00); ++ adv7180_write_reg(0x99, 0x00); ++ adv7180_write_reg(0x9A, 0x00); ++ adv7180_write_reg(0x9B, 0x00); ++ adv7180_write_reg(0x9C, 0x00); ++ adv7180_write_reg(0x9D, 0x00); ++ adv7180_write_reg(0x9E, 0x00); ++ adv7180_write_reg(0x9F, 0x00); ++ adv7180_write_reg(0xA0, 0x00); ++ adv7180_write_reg(0xA1, 0x00); ++ adv7180_write_reg(0xA2, 0x00); ++ adv7180_write_reg(0xA3, 0x00); ++ adv7180_write_reg(0xA4, 0x00); ++ adv7180_write_reg(0xA5, 0x00); ++ adv7180_write_reg(0xA6, 0x00); ++ adv7180_write_reg(0xA7, 0x00); ++ adv7180_write_reg(0xA8, 0x00); ++ adv7180_write_reg(0xA9, 0x00); ++ adv7180_write_reg(0xAA, 0x00); ++ adv7180_write_reg(0xAB, 0x00); ++ adv7180_write_reg(0xAC, 0x00); ++ adv7180_write_reg(0xAD, 0x00); ++ adv7180_write_reg(0xAE, 0x60); ++ adv7180_write_reg(0xAF, 0x00); ++ adv7180_write_reg(0xB0, 0x00); ++ adv7180_write_reg(0xB1, 0x60); ++ adv7180_write_reg(0xB2, 0x1C); ++ adv7180_write_reg(0xB3, 0x54); ++ adv7180_write_reg(0xB4, 0x00); ++ adv7180_write_reg(0xB5, 0x00); ++ adv7180_write_reg(0xB6, 0x00); ++ adv7180_write_reg(0xB7, 0x13); ++ adv7180_write_reg(0xB8, 0x03); ++ adv7180_write_reg(0xB9, 0x33); ++ adv7180_write_reg(0xBF, 0x02); ++ adv7180_write_reg(0xC0, 0x00); ++ adv7180_write_reg(0xC1, 0x00); ++ adv7180_write_reg(0xC2, 0x00); ++ adv7180_write_reg(0xC3, 0x00); ++ adv7180_write_reg(0xC4, 0x00); ++ adv7180_write_reg(0xC5, 0x81); ++ adv7180_write_reg(0xC6, 0x00); ++ adv7180_write_reg(0xC7, 0x00); ++ adv7180_write_reg(0xC8, 0x00); ++ adv7180_write_reg(0xC9, 0x04); ++ adv7180_write_reg(0xCC, 0x69); ++ adv7180_write_reg(0xCD, 0x00); ++ adv7180_write_reg(0xCE, 0x01); ++ adv7180_write_reg(0xCF, 0xB4); ++ adv7180_write_reg(0xD0, 0x00); ++ adv7180_write_reg(0xD1, 0x10); ++ adv7180_write_reg(0xD2, 0xFF); ++ adv7180_write_reg(0xD3, 0xFF); ++ adv7180_write_reg(0xD4, 0x7F); ++ adv7180_write_reg(0xD5, 0x7F); ++ adv7180_write_reg(0xD6, 0x3E); ++ adv7180_write_reg(0xD7, 0x08); ++ adv7180_write_reg(0xD8, 0x3C); ++ adv7180_write_reg(0xD9, 0x08); ++ adv7180_write_reg(0xDA, 0x3C); ++ adv7180_write_reg(0xDB, 0x9B); ++ adv7180_write_reg(0xDC, 0xAC); ++ adv7180_write_reg(0xDD, 0x4C); ++ adv7180_write_reg(0xDE, 0x00); ++ adv7180_write_reg(0xDF, 0x00); ++ adv7180_write_reg(0xE0, 0x14); ++ adv7180_write_reg(0xE1, 0x80); ++ adv7180_write_reg(0xE2, 0x80); ++ adv7180_write_reg(0xE3, 0x80); ++ adv7180_write_reg(0xE4, 0x80); ++ adv7180_write_reg(0xE5, 0x25); ++ adv7180_write_reg(0xE6, 0x44); ++ adv7180_write_reg(0xE7, 0x63); ++ adv7180_write_reg(0xE8, 0x65); ++ adv7180_write_reg(0xE9, 0x14); ++ adv7180_write_reg(0xEA, 0x63); ++ adv7180_write_reg(0xEB, 0x55); ++ adv7180_write_reg(0xEC, 0x55); ++ adv7180_write_reg(0xEE, 0x00); ++ adv7180_write_reg(0xEF, 0x4A); ++ adv7180_write_reg(0xF0, 0x44); ++ adv7180_write_reg(0xF1, 0x0C); ++ adv7180_write_reg(0xF2, 0x32); ++ adv7180_write_reg(0xF3, 0x00); ++ adv7180_write_reg(0xF4, 0x3F); ++ adv7180_write_reg(0xF5, 0xE0); ++ adv7180_write_reg(0xF6, 0x69); ++ adv7180_write_reg(0xF7, 0x10); ++ adv7180_write_reg(0xF8, 0x00); ++ adv7180_write_reg(0xF9, 0x03); ++ adv7180_write_reg(0xFA, 0xFA); ++ adv7180_write_reg(0xFB, 0x40); ++} ++ ++/*! ADV7180 I2C attach function. ++ * ++ * @param *adapter struct i2c_adapter *. ++ * ++ * @return Error code indicating success or failure. ++ */ ++ ++/*! ++ * ADV7180 I2C probe function. ++ * Function set in i2c_driver struct. ++ * Called by insmod. ++ * ++ * @param *adapter I2C adapter descriptor. ++ * ++ * @return Error code indicating success or failure. ++ */ ++static int adv7180_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ int rev_id; ++ int ret = 0; ++ u32 cvbs = true; ++ struct pinctrl *pinctrl; ++ struct device *dev = &client->dev; ++ ++ printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data); ++ ++ /* ov5640 pinctrl */ ++ pinctrl = devm_pinctrl_get_select_default(dev); ++ if (IS_ERR(pinctrl)) { ++ dev_err(dev, "setup pinctrl failed\n"); ++ return PTR_ERR(pinctrl); ++ } ++ ++ /* request power down pin */ ++ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); ++ if (!gpio_is_valid(pwn_gpio)) { ++ dev_err(dev, "no sensor pwdn pin available\n"); ++ return -ENODEV; ++ } ++ ret = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, ++ "adv7180_pwdn"); ++ if (ret < 0) { ++ dev_err(dev, "no power pin available!\n"); ++ return ret; ++ } ++ ++ adv7180_regulator_enable(dev); ++ ++ adv7180_power_down(0); ++ ++ msleep(1); ++ ++ /* Set initial values for the sensor struct. */ ++ memset(&adv7180_data, 0, sizeof(adv7180_data)); ++ adv7180_data.sen.i2c_client = client; ++ adv7180_data.sen.streamcap.timeperframe.denominator = 30; ++ adv7180_data.sen.streamcap.timeperframe.numerator = 1; ++ adv7180_data.std_id = V4L2_STD_ALL; ++ video_idx = ADV7180_NOT_LOCKED; ++ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width; ++ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height; ++ adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */ ++ adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */ ++ adv7180_data.sen.on = true; ++ ++ adv7180_data.sen.sensor_clk = devm_clk_get(dev, "csi_mclk"); ++ if (IS_ERR(adv7180_data.sen.sensor_clk)) { ++ dev_err(dev, "get mclk failed\n"); ++ return PTR_ERR(adv7180_data.sen.sensor_clk); ++ } ++ ++ ret = of_property_read_u32(dev->of_node, "mclk", ++ &adv7180_data.sen.mclk); ++ if (ret) { ++ dev_err(dev, "mclk frequency is invalid\n"); ++ return ret; ++ } ++ ++ ret = of_property_read_u32( ++ dev->of_node, "mclk_source", ++ (u32 *) &(adv7180_data.sen.mclk_source)); ++ if (ret) { ++ dev_err(dev, "mclk_source invalid\n"); ++ return ret; ++ } ++ ++ ret = of_property_read_u32(dev->of_node, "csi_id", ++ &(adv7180_data.sen.csi)); ++ if (ret) { ++ dev_err(dev, "csi_id invalid\n"); ++ return ret; ++ } ++ ++ clk_prepare_enable(adv7180_data.sen.sensor_clk); ++ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "%s:adv7180 probe i2c address is 0x%02X\n", ++ __func__, adv7180_data.sen.i2c_client->addr); ++ ++ /*! Read the revision ID of the tvin chip */ ++ rev_id = adv7180_read(ADV7180_IDENT); ++ dev_dbg(dev, ++ "%s:Analog Device adv7%2X0 detected!\n", __func__, ++ rev_id); ++ ++ ret = of_property_read_u32(dev->of_node, "cvbs", &(cvbs)); ++ if (ret) { ++ dev_err(dev, "cvbs setting is not found\n"); ++ cvbs = true; ++ } ++ ++ /*! ADV7180 initialization. */ ++ adv7180_hard_reset(cvbs); ++ ++ pr_debug(" type is %d (expect %d)\n", ++ adv7180_int_device.type, v4l2_int_type_slave); ++ pr_debug(" num ioctls is %d\n", ++ adv7180_int_device.u.slave->num_ioctls); ++ ++ /* This function attaches this structure to the /dev/video0 device. ++ * The pointer in priv points to the adv7180_data structure here.*/ ++ adv7180_int_device.priv = &adv7180_data; ++ ret = v4l2_int_device_register(&adv7180_int_device); ++ ++ clk_disable_unprepare(adv7180_data.sen.sensor_clk); ++ ++ return ret; ++} ++ ++/*! ++ * ADV7180 I2C detach function. ++ * Called on rmmod. ++ * ++ * @param *client struct i2c_client*. ++ * ++ * @return Error code indicating success or failure. ++ */ ++static int adv7180_detach(struct i2c_client *client) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, ++ "%s:Removing %s video decoder @ 0x%02X from adapter %s\n", ++ __func__, IF_NAME, client->addr << 1, client->adapter->name); ++ ++ /* Power down via i2c */ ++ adv7180_write_reg(ADV7180_PWR_MNG, 0x24); ++ ++ if (dvddio_regulator) ++ regulator_disable(dvddio_regulator); ++ ++ if (dvdd_regulator) ++ regulator_disable(dvdd_regulator); ++ ++ if (avdd_regulator) ++ regulator_disable(avdd_regulator); ++ ++ if (pvdd_regulator) ++ regulator_disable(pvdd_regulator); ++ ++ v4l2_int_device_unregister(&adv7180_int_device); ++ ++ return 0; ++} ++ ++/*! ++ * ADV7180 init function. ++ * Called on insmod. ++ * ++ * @return Error code indicating success or failure. ++ */ ++static __init int adv7180_init(void) ++{ ++ u8 err = 0; ++ ++ pr_debug("In adv7180_init\n"); ++ ++ /* Tells the i2c driver what functions to call for this driver. */ ++ err = i2c_add_driver(&adv7180_i2c_driver); ++ if (err != 0) ++ pr_err("%s:driver registration failed, error=%d\n", ++ __func__, err); ++ ++ return err; ++} ++ ++/*! ++ * ADV7180 cleanup function. ++ * Called on rmmod. ++ * ++ * @return Error code indicating success or failure. ++ */ ++static void __exit adv7180_clean(void) ++{ ++ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n"); ++ i2c_del_driver(&adv7180_i2c_driver); ++} ++ ++module_init(adv7180_init); ++module_exit(adv7180_clean); ++ ++MODULE_AUTHOR("Freescale Semiconductor"); ++MODULE_DESCRIPTION("Anolog Device ADV7180 video decoder driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/csi_v4l2_capture.c linux-imx6-3.14/drivers/media/platform/mxc/capture/csi_v4l2_capture.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/csi_v4l2_capture.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,2047 @@ ++/* ++ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file drivers/media/video/mxc/capture/csi_v4l2_capture.c ++ * This file is derived from mxc_v4l2_capture.c ++ * ++ * @brief Video For Linux 2 capture driver ++ * ++ * @ingroup MXC_V4L2_CAPTURE ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "fsl_csi.h" ++ ++static int video_nr = -1; ++static cam_data *g_cam; ++static int req_buf_number; ++ ++static int csi_v4l2_master_attach(struct v4l2_int_device *slave); ++static void csi_v4l2_master_detach(struct v4l2_int_device *slave); ++static u8 camera_power(cam_data *cam, bool cameraOn); ++struct v4l2_crop crop_current; ++struct v4l2_window win_current; ++ ++/*! Information about this driver. */ ++static struct v4l2_int_master csi_v4l2_master = { ++ .attach = csi_v4l2_master_attach, ++ .detach = csi_v4l2_master_detach, ++}; ++ ++static struct v4l2_int_device csi_v4l2_int_device = { ++ .module = THIS_MODULE, ++ .name = "csi_v4l2_cap", ++ .type = v4l2_int_type_master, ++ .u = { ++ .master = &csi_v4l2_master, ++ }, ++}; ++ ++static struct v4l2_queryctrl pxp_controls[] = { ++ { ++ .id = V4L2_CID_HFLIP, ++ .type = V4L2_CTRL_TYPE_BOOLEAN, ++ .name = "Horizontal Flip", ++ .minimum = 0, ++ .maximum = 1, ++ .step = 1, ++ .default_value = 0, ++ .flags = 0, ++ }, { ++ .id = V4L2_CID_VFLIP, ++ .type = V4L2_CTRL_TYPE_BOOLEAN, ++ .name = "Vertical Flip", ++ .minimum = 0, ++ .maximum = 1, ++ .step = 1, ++ .default_value = 0, ++ .flags = 0, ++ }, { ++ .id = V4L2_CID_PRIVATE_BASE, ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .name = "Rotation", ++ .minimum = 0, ++ .maximum = 270, ++ .step = 90, ++ .default_value = 0, ++ .flags = 0, ++ }, ++}; ++ ++/* Callback function triggered after PxP receives an EOF interrupt */ ++static void pxp_dma_done(void *arg) ++{ ++ struct pxp_tx_desc *tx_desc = to_tx_desc(arg); ++ struct dma_chan *chan = tx_desc->txd.chan; ++ struct pxp_channel *pxp_chan = to_pxp_channel(chan); ++ cam_data *cam = pxp_chan->client; ++ ++ /* This call will signal wait_for_completion_timeout() */ ++ complete(&cam->pxp_tx_cmpl); ++} ++ ++static bool chan_filter(struct dma_chan *chan, void *arg) ++{ ++ if (imx_dma_is_pxp(chan)) ++ return true; ++ else ++ return false; ++} ++ ++/* Function to request PXP DMA channel */ ++static int pxp_chan_init(cam_data *cam) ++{ ++ dma_cap_mask_t mask; ++ struct dma_chan *chan; ++ ++ /* Request a free channel */ ++ dma_cap_zero(mask); ++ dma_cap_set(DMA_SLAVE, mask); ++ dma_cap_set(DMA_PRIVATE, mask); ++ chan = dma_request_channel(mask, chan_filter, NULL); ++ if (!chan) { ++ pr_err("Unsuccessfully request channel!\n"); ++ return -EBUSY; ++ } ++ ++ cam->pxp_chan = to_pxp_channel(chan); ++ cam->pxp_chan->client = cam; ++ ++ init_completion(&cam->pxp_tx_cmpl); ++ ++ return 0; ++} ++ ++/* ++ * Function to call PxP DMA driver and send our new V4L2 buffer ++ * through the PxP. ++ * Note: This is a blocking call, so upon return the PxP tx should be complete. ++ */ ++static int pxp_process_update(cam_data *cam) ++{ ++ dma_cookie_t cookie; ++ struct scatterlist *sg = cam->sg; ++ struct dma_chan *dma_chan; ++ struct pxp_tx_desc *desc; ++ struct dma_async_tx_descriptor *txd; ++ struct pxp_config_data *pxp_conf = &cam->pxp_conf; ++ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; ++ int i, ret; ++ int length; ++ ++ pr_debug("Starting PxP Send Buffer\n"); ++ ++ /* First, check to see that we have acquired a PxP Channel object */ ++ if (cam->pxp_chan == NULL) { ++ /* ++ * PxP Channel has not yet been created and initialized, ++ * so let's go ahead and try ++ */ ++ ret = pxp_chan_init(cam); ++ if (ret) { ++ /* ++ * PxP channel init failed, and we can't use the ++ * PxP until the PxP DMA driver has loaded, so we abort ++ */ ++ pr_err("PxP chan init failed\n"); ++ return -ENODEV; ++ } ++ } ++ ++ /* ++ * Init completion, so that we can be properly informed of ++ * the completion of the PxP task when it is done. ++ */ ++ init_completion(&cam->pxp_tx_cmpl); ++ ++ dma_chan = &cam->pxp_chan->dma_chan; ++ ++ txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg, 2, ++ DMA_TO_DEVICE, ++ DMA_PREP_INTERRUPT, ++ NULL); ++ if (!txd) { ++ pr_err("Error preparing a DMA transaction descriptor.\n"); ++ return -EIO; ++ } ++ ++ txd->callback_param = txd; ++ txd->callback = pxp_dma_done; ++ ++ /* ++ * Configure PxP for processing of new v4l2 buf ++ */ ++ pxp_conf->s0_param.pixel_fmt = PXP_PIX_FMT_UYVY; ++ pxp_conf->s0_param.color_key = -1; ++ pxp_conf->s0_param.color_key_enable = false; ++ pxp_conf->s0_param.width = cam->v2f.fmt.pix.width; ++ pxp_conf->s0_param.height = cam->v2f.fmt.pix.height; ++ ++ pxp_conf->ol_param[0].combine_enable = false; ++ ++ proc_data->srect.top = 0; ++ proc_data->srect.left = 0; ++ proc_data->srect.width = pxp_conf->s0_param.width; ++ proc_data->srect.height = pxp_conf->s0_param.height; ++ ++ if (crop_current.c.top != 0) ++ proc_data->srect.top = crop_current.c.top; ++ if (crop_current.c.left != 0) ++ proc_data->srect.left = crop_current.c.left; ++ if (crop_current.c.width != 0) ++ proc_data->srect.width = crop_current.c.width; ++ if (crop_current.c.height != 0) ++ proc_data->srect.height = crop_current.c.height; ++ ++ proc_data->drect.left = 0; ++ proc_data->drect.top = 0; ++ proc_data->drect.width = proc_data->srect.width; ++ proc_data->drect.height = proc_data->srect.height; ++ ++ if (win_current.w.left != 0) ++ proc_data->drect.left = win_current.w.left; ++ if (win_current.w.top != 0) ++ proc_data->drect.top = win_current.w.top; ++ if (win_current.w.width != 0) ++ proc_data->drect.width = win_current.w.width; ++ if (win_current.w.height != 0) ++ proc_data->drect.height = win_current.w.height; ++ ++ pr_debug("srect l: %d, t: %d, w: %d, h: %d; " ++ "drect l: %d, t: %d, w: %d, h: %d\n", ++ proc_data->srect.left, proc_data->srect.top, ++ proc_data->srect.width, proc_data->srect.height, ++ proc_data->drect.left, proc_data->drect.top, ++ proc_data->drect.width, proc_data->drect.height); ++ ++ pxp_conf->out_param.pixel_fmt = PXP_PIX_FMT_RGB565; ++ pxp_conf->out_param.width = proc_data->drect.width; ++ pxp_conf->out_param.height = proc_data->drect.height; ++ ++ if (cam->rotation % 180) ++ pxp_conf->out_param.stride = pxp_conf->out_param.height; ++ else ++ pxp_conf->out_param.stride = pxp_conf->out_param.width; ++ ++ desc = to_tx_desc(txd); ++ length = desc->len; ++ for (i = 0; i < length; i++) { ++ if (i == 0) {/* S0 */ ++ memcpy(&desc->proc_data, proc_data, ++ sizeof(struct pxp_proc_data)); ++ pxp_conf->s0_param.paddr = sg_dma_address(&sg[0]); ++ memcpy(&desc->layer_param.s0_param, &pxp_conf->s0_param, ++ sizeof(struct pxp_layer_param)); ++ } else if (i == 1) { ++ pxp_conf->out_param.paddr = sg_dma_address(&sg[1]); ++ memcpy(&desc->layer_param.out_param, ++ &pxp_conf->out_param, ++ sizeof(struct pxp_layer_param)); ++ } ++ ++ desc = desc->next; ++ } ++ ++ /* Submitting our TX starts the PxP processing task */ ++ cookie = txd->tx_submit(txd); ++ if (cookie < 0) { ++ pr_err("Error sending FB through PxP\n"); ++ return -EIO; ++ } ++ ++ cam->txd = txd; ++ ++ /* trigger PxP */ ++ dma_async_issue_pending(dma_chan); ++ ++ return 0; ++} ++ ++static int pxp_complete_update(cam_data *cam) ++{ ++ int ret; ++ /* ++ * Wait for completion event, which will be set ++ * through our TX callback function. ++ */ ++ ret = wait_for_completion_timeout(&cam->pxp_tx_cmpl, HZ / 10); ++ if (ret <= 0) { ++ pr_warning("PxP operation failed due to %s\n", ++ ret < 0 ? "user interrupt" : "timeout"); ++ dma_release_channel(&cam->pxp_chan->dma_chan); ++ cam->pxp_chan = NULL; ++ return ret ? : -ETIMEDOUT; ++ } ++ ++ dma_release_channel(&cam->pxp_chan->dma_chan); ++ cam->pxp_chan = NULL; ++ ++ pr_debug("TX completed\n"); ++ ++ return 0; ++} ++ ++/*! ++ * Camera V4l2 callback function. ++ * ++ * @param mask u32 ++ * @param dev void device structure ++ * ++ * @return none ++ */ ++static void camera_callback(u32 mask, void *dev) ++{ ++ struct mxc_v4l_frame *done_frame; ++ struct mxc_v4l_frame *ready_frame; ++ cam_data *cam; ++ ++ cam = (cam_data *) dev; ++ if (cam == NULL) ++ return; ++ ++ spin_lock(&cam->queue_int_lock); ++ spin_lock(&cam->dqueue_int_lock); ++ if (!list_empty(&cam->working_q)) { ++ done_frame = list_entry(cam->working_q.next, ++ struct mxc_v4l_frame, queue); ++ ++ if (done_frame->csi_buf_num != cam->ping_pong_csi) ++ goto next; ++ ++ if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { ++ done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; ++ done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; ++ ++ /* Added to the done queue */ ++ list_del(cam->working_q.next); ++ list_add_tail(&done_frame->queue, &cam->done_q); ++ cam->enc_counter++; ++ wake_up_interruptible(&cam->enc_queue); ++ } else { ++ pr_err("ERROR: v4l2 capture: %s: " ++ "buffer not queued\n", __func__); ++ } ++ } ++ ++next: ++ if (!list_empty(&cam->ready_q)) { ++ ready_frame = list_entry(cam->ready_q.next, ++ struct mxc_v4l_frame, queue); ++ list_del(cam->ready_q.next); ++ list_add_tail(&ready_frame->queue, &cam->working_q); ++ ++ __raw_writel(ready_frame->paddress, ++ cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : ++ CSI_CSIDMASA_FB2); ++ ready_frame->csi_buf_num = cam->ping_pong_csi; ++ } else { ++ __raw_writel(cam->dummy_frame.paddress, ++ cam->ping_pong_csi == 1 ? CSI_CSIDMASA_FB1 : ++ CSI_CSIDMASA_FB2); ++ } ++ spin_unlock(&cam->dqueue_int_lock); ++ spin_unlock(&cam->queue_int_lock); ++ ++ return; ++} ++ ++/*! ++ * Make csi ready for capture image. ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 success ++ */ ++static int csi_cap_image(cam_data *cam) ++{ ++ unsigned int value; ++ ++ value = __raw_readl(CSI_CSICR3); ++ __raw_writel(value | BIT_FRMCNT_RST, CSI_CSICR3); ++ value = __raw_readl(CSI_CSISR); ++ __raw_writel(value, CSI_CSISR); ++ ++ return 0; ++} ++ ++/*************************************************************************** ++ * Functions for handling Frame buffers. ++ **************************************************************************/ ++ ++/*! ++ * Free frame buffers ++ * ++ * @param cam Structure cam_data * ++ * ++ * @return status 0 success. ++ */ ++static int csi_free_frame_buf(cam_data *cam) ++{ ++ int i; ++ ++ pr_debug("MVC: In %s\n", __func__); ++ ++ for (i = 0; i < FRAME_NUM; i++) { ++ if (cam->frame[i].vaddress != 0) { ++ dma_free_coherent(0, cam->frame[i].buffer.length, ++ cam->frame[i].vaddress, ++ cam->frame[i].paddress); ++ cam->frame[i].vaddress = 0; ++ } ++ } ++ ++ if (cam->dummy_frame.vaddress != 0) { ++ dma_free_coherent(0, cam->dummy_frame.buffer.length, ++ cam->dummy_frame.vaddress, ++ cam->dummy_frame.paddress); ++ cam->dummy_frame.vaddress = 0; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Allocate frame buffers ++ * ++ * @param cam Structure cam_data * ++ * @param count int number of buffer need to allocated ++ * ++ * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. ++ */ ++static int csi_allocate_frame_buf(cam_data *cam, int count) ++{ ++ int i; ++ ++ pr_debug("In MVC:%s- size=%d\n", ++ __func__, cam->v2f.fmt.pix.sizeimage); ++ for (i = 0; i < count; i++) { ++ cam->frame[i].vaddress = dma_alloc_coherent(0, PAGE_ALIGN ++ (cam->v2f.fmt. ++ pix.sizeimage), ++ &cam->frame[i]. ++ paddress, ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->frame[i].vaddress == 0) { ++ pr_err("ERROR: v4l2 capture: " ++ "%s failed.\n", __func__); ++ csi_free_frame_buf(cam); ++ return -ENOBUFS; ++ } ++ cam->frame[i].buffer.index = i; ++ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ cam->frame[i].buffer.length = cam->v2f.fmt.pix.sizeimage; ++ cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; ++ cam->frame[i].buffer.m.offset = cam->frame[i].paddress; ++ cam->frame[i].index = i; ++ cam->frame[i].csi_buf_num = 0; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Free frame buffers status ++ * ++ * @param cam Structure cam_data * ++ * ++ * @return none ++ */ ++static void csi_free_frames(cam_data *cam) ++{ ++ int i; ++ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ for (i = 0; i < FRAME_NUM; i++) ++ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ ++ cam->enc_counter = 0; ++ INIT_LIST_HEAD(&cam->ready_q); ++ INIT_LIST_HEAD(&cam->working_q); ++ INIT_LIST_HEAD(&cam->done_q); ++ ++ return; ++} ++ ++/*! ++ * Return the buffer status ++ * ++ * @param cam Structure cam_data * ++ * @param buf Structure v4l2_buffer * ++ * ++ * @return status 0 success, EINVAL failed. ++ */ ++static int csi_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ if (buf->index < 0 || buf->index >= FRAME_NUM) { ++ pr_err("ERROR: v4l2 capture: %s buffers " ++ "not allocated\n", __func__); ++ return -EINVAL; ++ } ++ ++ memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); ++ ++ return 0; ++} ++ ++static int csi_v4l2_release_bufs(cam_data *cam) ++{ ++ pr_debug("In MVC:csi_v4l2_release_bufs\n"); ++ return 0; ++} ++ ++static int csi_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ pr_debug("In MVC:csi_v4l2_prepare_bufs\n"); ++ ++ if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < ++ cam->v2f.fmt.pix.sizeimage) { ++ pr_err("ERROR: v4l2 capture: csi_v4l2_prepare_bufs buffers " ++ "not allocated,index=%d, length=%d\n", buf->index, ++ buf->length); ++ return -EINVAL; ++ } ++ ++ cam->frame[buf->index].buffer.index = buf->index; ++ cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ cam->frame[buf->index].buffer.length = buf->length; ++ cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress ++ = buf->m.offset; ++ cam->frame[buf->index].buffer.type = buf->type; ++ cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; ++ cam->frame[buf->index].index = buf->index; ++ ++ return 0; ++} ++ ++/*! ++ * Indicates whether the palette is supported. ++ * ++ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_UYVY or V4L2_PIX_FMT_YUV420 ++ * ++ * @return 0 if failed ++ */ ++static inline int valid_mode(u32 palette) ++{ ++ return (palette == V4L2_PIX_FMT_RGB565) || ++ (palette == V4L2_PIX_FMT_YUYV) || ++ (palette == V4L2_PIX_FMT_UYVY) || (palette == V4L2_PIX_FMT_YUV420); ++} ++ ++/*! ++ * Start stream I/O ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int csi_streamon(cam_data *cam) ++{ ++ struct mxc_v4l_frame *frame; ++ unsigned long flags; ++ unsigned long val; ++ int timeout, timeout2; ++ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ if (NULL == cam) { ++ pr_err("ERROR: v4l2 capture: %s cam parameter is NULL\n", ++ __func__); ++ return -1; ++ } ++ cam->dummy_frame.vaddress = dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->dummy_frame.paddress, ++ GFP_DMA | GFP_KERNEL); ++ if (cam->dummy_frame.vaddress == 0) { ++ pr_err("ERROR: v4l2 capture: Allocate dummy frame " ++ "failed.\n"); ++ return -ENOBUFS; ++ } ++ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; ++ cam->dummy_frame.buffer.length = cam->v2f.fmt.pix.sizeimage; ++ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; ++ ++ spin_lock_irqsave(&cam->queue_int_lock, flags); ++ /* move the frame from readyq to workingq */ ++ if (list_empty(&cam->ready_q)) { ++ pr_err("ERROR: v4l2 capture: %s: " ++ "ready_q queue empty\n", __func__); ++ spin_unlock_irqrestore(&cam->queue_int_lock, flags); ++ return -1; ++ } ++ frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->ready_q.next); ++ list_add_tail(&frame->queue, &cam->working_q); ++ __raw_writel(frame->paddress, CSI_CSIDMASA_FB1); ++ frame->csi_buf_num = 1; ++ ++ if (list_empty(&cam->ready_q)) { ++ pr_err("ERROR: v4l2 capture: %s: " ++ "ready_q queue empty\n", __func__); ++ spin_unlock_irqrestore(&cam->queue_int_lock, flags); ++ return -1; ++ } ++ frame = list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->ready_q.next); ++ list_add_tail(&frame->queue, &cam->working_q); ++ __raw_writel(frame->paddress, CSI_CSIDMASA_FB2); ++ frame->csi_buf_num = 2; ++ spin_unlock_irqrestore(&cam->queue_int_lock, flags); ++ ++ cam->capture_pid = current->pid; ++ cam->capture_on = true; ++ csi_cap_image(cam); ++ ++ local_irq_save(flags); ++ for (timeout = 1000000; timeout > 0; timeout--) { ++ if (__raw_readl(CSI_CSISR) & BIT_SOF_INT) { ++ val = __raw_readl(CSI_CSICR3); ++ __raw_writel(val | BIT_DMA_REFLASH_RFF, CSI_CSICR3); ++ for (timeout2 = 1000000; timeout2 > 0; timeout2--) { ++ if (__raw_readl(CSI_CSICR3) & ++ BIT_DMA_REFLASH_RFF) ++ cpu_relax(); ++ else ++ break; ++ } ++ if (timeout2 <= 0) { ++ pr_err("timeout when wait for reflash done.\n"); ++ local_irq_restore(flags); ++ return -ETIME; ++ } ++ ++ csi_dmareq_rff_enable(); ++ csi_enable_int(1); ++ break; ++ } else ++ cpu_relax(); ++ } ++ if (timeout <= 0) { ++ pr_err("timeout when wait for SOF\n"); ++ local_irq_restore(flags); ++ return -ETIME; ++ } ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++/*! ++ * Stop stream I/O ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int csi_streamoff(cam_data *cam) ++{ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ if (cam->capture_on == false) ++ return 0; ++ ++ csi_dmareq_rff_disable(); ++ csi_disable_int(); ++ cam->capture_on = false; ++ ++ /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ ++ __raw_writel(0, CSI_CSIDMASA_FB1); ++ __raw_writel(0, CSI_CSIDMASA_FB2); ++ ++ csi_free_frames(cam); ++ csi_free_frame_buf(cam); ++ ++ return 0; ++} ++ ++/*! ++ * start the viewfinder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int start_preview(cam_data *cam) ++{ ++ unsigned long fb_addr = (unsigned long)cam->v4l2_fb.base; ++ ++ __raw_writel(fb_addr, CSI_CSIDMASA_FB1); ++ __raw_writel(fb_addr, CSI_CSIDMASA_FB2); ++ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3); ++ ++ csi_enable_int(0); ++ ++ return 0; ++} ++ ++/*! ++ * shut down the viewfinder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int stop_preview(cam_data *cam) ++{ ++ csi_disable_int(); ++ ++ /* set CSI_CSIDMASA_FB1 and CSI_CSIDMASA_FB2 to default value */ ++ __raw_writel(0, CSI_CSIDMASA_FB1); ++ __raw_writel(0, CSI_CSIDMASA_FB2); ++ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, CSI_CSICR3); ++ ++ return 0; ++} ++ ++/*************************************************************************** ++ * VIDIOC Functions. ++ **************************************************************************/ ++ ++/*! ++ * ++ * @param cam structure cam_data * ++ * ++ * @param f structure v4l2_format * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int csi_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) ++{ ++ int retval = 0; ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ++ f->fmt.pix = cam->v2f.fmt.pix; ++ break; ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); ++ f->fmt.win = cam->win; ++ break; ++ default: ++ pr_debug(" type is invalid\n"); ++ retval = -EINVAL; ++ } ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ ++ return retval; ++} ++ ++/*! ++ * V4L2 - csi_v4l2_s_fmt function ++ * ++ * @param cam structure cam_data * ++ * ++ * @param f structure v4l2_format * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int csi_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) ++{ ++ int retval = 0; ++ int size = 0; ++ int bytesperline = 0; ++ int *width, *height; ++ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ++ if (!valid_mode(f->fmt.pix.pixelformat)) { ++ pr_err("ERROR: v4l2 capture: %s: format " ++ "not supported\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Handle case where size requested is larger than cuurent ++ * camera setting. */ ++ if ((f->fmt.pix.width > cam->crop_bounds.width) ++ || (f->fmt.pix.height > cam->crop_bounds.height)) { ++ /* Need the logic here, calling vidioc_s_param if ++ * camera can change. */ ++ pr_debug("csi_v4l2_s_fmt size changed\n"); ++ } ++ if (cam->rotation % 180) { ++ height = &f->fmt.pix.width; ++ width = &f->fmt.pix.height; ++ } else { ++ width = &f->fmt.pix.width; ++ height = &f->fmt.pix.height; ++ } ++ ++ if ((cam->crop_bounds.width / *width > 8) || ++ ((cam->crop_bounds.width / *width == 8) && ++ (cam->crop_bounds.width % *width))) { ++ *width = cam->crop_bounds.width / 8; ++ if (*width % 8) ++ *width += 8 - *width % 8; ++ pr_err("ERROR: v4l2 capture: width exceeds limit " ++ "resize to %d.\n", *width); ++ } ++ ++ if ((cam->crop_bounds.height / *height > 8) || ++ ((cam->crop_bounds.height / *height == 8) && ++ (cam->crop_bounds.height % *height))) { ++ *height = cam->crop_bounds.height / 8; ++ if (*height % 8) ++ *height += 8 - *height % 8; ++ pr_err("ERROR: v4l2 capture: height exceeds limit " ++ "resize to %d.\n", *height); ++ } ++ ++ switch (f->fmt.pix.pixelformat) { ++ case V4L2_PIX_FMT_RGB565: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ csi_init_format(V4L2_PIX_FMT_UYVY); ++ csi_set_16bit_imagpara(f->fmt.pix.width, ++ f->fmt.pix.height); ++ bytesperline = f->fmt.pix.width * 2; ++ break; ++ case V4L2_PIX_FMT_UYVY: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ csi_init_format(f->fmt.pix.pixelformat); ++ csi_set_16bit_imagpara(f->fmt.pix.width, ++ f->fmt.pix.height); ++ bytesperline = f->fmt.pix.width * 2; ++ break; ++ case V4L2_PIX_FMT_YUYV: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ csi_init_format(f->fmt.pix.pixelformat); ++ csi_set_16bit_imagpara(f->fmt.pix.width, ++ f->fmt.pix.height); ++ bytesperline = f->fmt.pix.width * 2; ++ break; ++ case V4L2_PIX_FMT_YUV420: ++ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; ++ csi_set_12bit_imagpara(f->fmt.pix.width, ++ f->fmt.pix.height); ++ bytesperline = f->fmt.pix.width; ++ break; ++ case V4L2_PIX_FMT_YUV422P: ++ case V4L2_PIX_FMT_RGB24: ++ case V4L2_PIX_FMT_BGR24: ++ case V4L2_PIX_FMT_BGR32: ++ case V4L2_PIX_FMT_RGB32: ++ case V4L2_PIX_FMT_NV12: ++ default: ++ pr_debug(" case not supported\n"); ++ break; ++ } ++ ++ if (f->fmt.pix.bytesperline < bytesperline) ++ f->fmt.pix.bytesperline = bytesperline; ++ else ++ bytesperline = f->fmt.pix.bytesperline; ++ ++ if (f->fmt.pix.sizeimage < size) ++ f->fmt.pix.sizeimage = size; ++ else ++ size = f->fmt.pix.sizeimage; ++ ++ cam->v2f.fmt.pix = f->fmt.pix; ++ ++ if (cam->v2f.fmt.pix.priv != 0) { ++ if (copy_from_user(&cam->offset, ++ (void *)cam->v2f.fmt.pix.priv, ++ sizeof(cam->offset))) { ++ retval = -EFAULT; ++ break; ++ } ++ } ++ break; ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); ++ cam->win = f->fmt.win; ++ win_current = f->fmt.win; ++ size = win_current.w.width * win_current.w.height * 2; ++ if (cam->v2f.fmt.pix.sizeimage < size) ++ cam->v2f.fmt.pix.sizeimage = size; ++ ++ break; ++ default: ++ retval = -EINVAL; ++ } ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ ++ return retval; ++} ++ ++/*! ++ * V4L2 - csi_v4l2_s_param function ++ * Allows setting of capturemode and frame rate. ++ * ++ * @param cam structure cam_data * ++ * @param parm structure v4l2_streamparm * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int csi_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) ++{ ++ struct v4l2_ifparm ifparm; ++ struct v4l2_format cam_fmt; ++ struct v4l2_streamparm currentparm; ++ int err = 0; ++ ++ pr_debug("In %s\n", __func__); ++ ++ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ pr_err(KERN_ERR "%s invalid type\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Stop the viewfinder */ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ /* First check that this device can support the changes requested. */ ++ err = vidioc_int_g_parm(cam->sensor, ¤tparm); ++ if (err) { ++ pr_err("%s: vidioc_int_g_parm returned an error %d\n", ++ __func__, err); ++ goto exit; ++ } ++ ++ pr_debug(" Current capabilities are %x\n", ++ currentparm.parm.capture.capability); ++ pr_debug(" Current capturemode is %d change to %d\n", ++ currentparm.parm.capture.capturemode, ++ parm->parm.capture.capturemode); ++ pr_debug(" Current framerate is %d change to %d\n", ++ currentparm.parm.capture.timeperframe.denominator, ++ parm->parm.capture.timeperframe.denominator); ++ ++ err = vidioc_int_s_parm(cam->sensor, parm); ++ if (err) { ++ pr_err("%s: vidioc_int_s_parm returned an error %d\n", ++ __func__, err); ++ goto exit; ++ } ++ ++ vidioc_int_g_ifparm(cam->sensor, &ifparm); ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); ++ pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", ++ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); ++ ++ cam->crop_bounds.top = cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = cam_fmt.fmt.pix.width; ++ cam->crop_bounds.height = cam_fmt.fmt.pix.height; ++ cam->crop_current.width = cam->crop_bounds.width; ++ cam->crop_current.height = cam->crop_bounds.height; ++ ++exit: ++ return err; ++} ++ ++static int pxp_set_cstate(cam_data *cam, struct v4l2_control *vc) ++{ ++ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; ++ ++ if (vc->id == V4L2_CID_HFLIP) { ++ proc_data->hflip = vc->value; ++ } else if (vc->id == V4L2_CID_VFLIP) { ++ proc_data->vflip = vc->value; ++ } else if (vc->id == V4L2_CID_PRIVATE_BASE) { ++ if (vc->value % 90) ++ return -ERANGE; ++ proc_data->rotate = vc->value; ++ cam->rotation = vc->value; ++ } ++ ++ return 0; ++} ++ ++static int pxp_get_cstate(cam_data *cam, struct v4l2_control *vc) ++{ ++ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; ++ ++ if (vc->id == V4L2_CID_HFLIP) ++ vc->value = proc_data->hflip; ++ else if (vc->id == V4L2_CID_VFLIP) ++ vc->value = proc_data->vflip; ++ else if (vc->id == V4L2_CID_PRIVATE_BASE) ++ vc->value = proc_data->rotate; ++ ++ return 0; ++} ++ ++ ++/*! ++ * Dequeue one V4L capture buffer ++ * ++ * @param cam structure cam_data * ++ * @param buf structure v4l2_buffer * ++ * ++ * @return status 0 success, EINVAL invalid frame number ++ * ETIME timeout, ERESTARTSYS interrupted by user ++ */ ++static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ int retval = 0; ++ struct mxc_v4l_frame *frame; ++ unsigned long lock_flags; ++ ++ if (!wait_event_interruptible_timeout(cam->enc_queue, ++ cam->enc_counter != 0, 10 * HZ)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " ++ "enc_counter %x\n", cam->enc_counter); ++ return -ETIME; ++ } else if (signal_pending(current)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " ++ "interrupt received\n"); ++ return -ERESTARTSYS; ++ } ++ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EBUSY; ++ ++ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); ++ ++ if (list_empty(&cam->done_q)) { ++ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); ++ up(&cam->busy_lock); ++ return -EINVAL; ++ } ++ ++ cam->enc_counter--; ++ ++ frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->done_q.next); ++ ++ if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { ++ frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; ++ } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " ++ "Buffer not filled.\n"); ++ frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; ++ retval = -EINVAL; ++ } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " ++ "Buffer not queued.\n"); ++ retval = -EINVAL; ++ } ++ ++ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); ++ ++ buf->bytesused = cam->v2f.fmt.pix.sizeimage; ++ buf->index = frame->index; ++ buf->flags = frame->buffer.flags; ++ buf->m = cam->frame[frame->index].buffer.m; ++ ++ /* ++ * Note: ++ * If want to do preview on LCD, use PxP CSC to convert from UYVY ++ * to RGB565; but for encoding, usually we don't use RGB format. ++ */ ++ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { ++ sg_dma_address(&cam->sg[0]) = buf->m.offset; ++ sg_dma_address(&cam->sg[1]) = ++ cam->frame[req_buf_number].paddress; ++ retval = pxp_process_update(cam); ++ if (retval) { ++ pr_err("Unable to submit PxP update task.\n"); ++ return retval; ++ } ++ pxp_complete_update(cam); ++ if (cam->frame[buf->index].vaddress) ++ memcpy(cam->frame[buf->index].vaddress, ++ cam->frame[req_buf_number].vaddress, ++ cam->v2f.fmt.pix.sizeimage); ++ } ++ up(&cam->busy_lock); ++ ++ return retval; ++} ++ ++/*! ++ * V4L interface - open function ++ * ++ * @param file structure file * ++ * ++ * @return status 0 success, ENODEV invalid device instance, ++ * ENODEV timeout, ERESTARTSYS interrupted by user ++ */ ++static int csi_v4l_open(struct file *file) ++{ ++ struct v4l2_ifparm ifparm; ++ struct v4l2_format cam_fmt; ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ struct sensor_data *sensor; ++ int err = 0; ++ ++ pr_debug(" device name is %s\n", dev->name); ++ ++ if (!cam) { ++ pr_err("%s: Internal error, cam_data not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ if (!cam->sensor) { ++ pr_err("%s: Internal error, camera is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ sensor = cam->sensor->priv; ++ if (!sensor) { ++ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ down(&cam->busy_lock); ++ err = 0; ++ if (signal_pending(current)) ++ goto oops; ++ ++ if (cam->open_count++ == 0) { ++ wait_event_interruptible(cam->power_queue, ++ cam->low_power == false); ++ ++ cam->enc_counter = 0; ++ INIT_LIST_HEAD(&cam->ready_q); ++ INIT_LIST_HEAD(&cam->working_q); ++ INIT_LIST_HEAD(&cam->done_q); ++ ++ vidioc_int_g_ifparm(cam->sensor, &ifparm); ++ ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ clk_prepare_enable(sensor->sensor_clk); ++ vidioc_int_s_power(cam->sensor, 1); ++ vidioc_int_init(cam->sensor); ++ vidioc_int_dev_init(cam->sensor); ++ } ++ ++ file->private_data = dev; ++ ++oops: ++ up(&cam->busy_lock); ++ return err; ++} ++ ++/*! ++ * V4L interface - close function ++ * ++ * @param file struct file * ++ * ++ * @return 0 success ++ */ ++static int csi_v4l_close(struct file *file) ++{ ++ struct video_device *dev = video_devdata(file); ++ int err = 0; ++ cam_data *cam = video_get_drvdata(dev); ++ struct sensor_data *sensor; ++ ++ pr_debug("In MVC:%s\n", __func__); ++ ++ if (!cam) { ++ pr_err("%s: Internal error, cam_data not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ if (!cam->sensor) { ++ pr_err("%s: Internal error, camera is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ sensor = cam->sensor->priv; ++ if (!sensor) { ++ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ /* for the case somebody hit the ctrl C */ ++ if (cam->overlay_pid == current->pid) { ++ err = stop_preview(cam); ++ cam->overlay_on = false; ++ } ++ ++ if (--cam->open_count == 0) { ++ wait_event_interruptible(cam->power_queue, ++ cam->low_power == false); ++ file->private_data = NULL; ++ vidioc_int_s_power(cam->sensor, 0); ++ clk_disable_unprepare(sensor->sensor_clk); ++ } ++ ++ return err; ++} ++ ++/* ++ * V4L interface - read function ++ * ++ * @param file struct file * ++ * @param read buf char * ++ * @param count size_t ++ * @param ppos structure loff_t * ++ * ++ * @return bytes read ++ */ ++static ssize_t csi_v4l_read(struct file *file, char *buf, size_t count, ++ loff_t *ppos) ++{ ++ int err = 0; ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EINTR; ++ ++ /* Stop the viewfinder */ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ if (cam->still_buf_vaddr == NULL) { ++ cam->still_buf_vaddr = dma_alloc_coherent(0, ++ PAGE_ALIGN ++ (cam->v2f.fmt. ++ pix.sizeimage), ++ &cam-> ++ still_buf[0], ++ GFP_DMA | GFP_KERNEL); ++ if (cam->still_buf_vaddr == NULL) { ++ pr_err("alloc dma memory failed\n"); ++ return -ENOMEM; ++ } ++ cam->still_counter = 0; ++ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB2); ++ __raw_writel(cam->still_buf[0], CSI_CSIDMASA_FB1); ++ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_DMA_REFLASH_RFF, ++ CSI_CSICR3); ++ __raw_writel(__raw_readl(CSI_CSISR), CSI_CSISR); ++ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, ++ CSI_CSICR3); ++ csi_enable_int(1); ++ } ++ ++ wait_event_interruptible(cam->still_queue, cam->still_counter); ++ csi_disable_int(); ++ err = copy_to_user(buf, cam->still_buf_vaddr, ++ cam->v2f.fmt.pix.sizeimage); ++ ++ if (cam->still_buf_vaddr != NULL) { ++ dma_free_coherent(0, PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ cam->still_buf_vaddr, cam->still_buf[0]); ++ cam->still_buf[0] = 0; ++ cam->still_buf_vaddr = NULL; ++ } ++ ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ ++ up(&cam->busy_lock); ++ if (err < 0) ++ return err; ++ ++ return cam->v2f.fmt.pix.sizeimage - err; ++} ++ ++/*! ++ * V4L interface - ioctl function ++ * ++ * @param file struct file* ++ * ++ * @param ioctlnr unsigned int ++ * ++ * @param arg void* ++ * ++ * @return 0 success, ENODEV for invalid device instance, ++ * -1 for other errors. ++ */ ++static long csi_v4l_do_ioctl(struct file *file, ++ unsigned int ioctlnr, void *arg) ++{ ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ int retval = 0; ++ unsigned long lock_flags; ++ ++ pr_debug("In MVC: %s, %x\n", __func__, ioctlnr); ++ wait_event_interruptible(cam->power_queue, cam->low_power == false); ++ /* make this _really_ smp-safe */ ++ if (ioctlnr != VIDIOC_DQBUF) ++ if (down_interruptible(&cam->busy_lock)) ++ return -EBUSY; ++ ++ switch (ioctlnr) { ++ /*! ++ * V4l2 VIDIOC_G_FMT ioctl ++ */ ++ case VIDIOC_G_FMT:{ ++ struct v4l2_format *gf = arg; ++ pr_debug(" case VIDIOC_G_FMT\n"); ++ retval = csi_v4l2_g_fmt(cam, gf); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_FMT ioctl ++ */ ++ case VIDIOC_S_FMT:{ ++ struct v4l2_format *sf = arg; ++ pr_debug(" case VIDIOC_S_FMT\n"); ++ retval = csi_v4l2_s_fmt(cam, sf); ++ vidioc_int_s_fmt_cap(cam->sensor, sf); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_OVERLAY ioctl ++ */ ++ case VIDIOC_OVERLAY:{ ++ int *on = arg; ++ pr_debug(" case VIDIOC_OVERLAY\n"); ++ if (*on) { ++ cam->overlay_on = true; ++ cam->overlay_pid = current->pid; ++ start_preview(cam); ++ } ++ if (!*on) { ++ stop_preview(cam); ++ cam->overlay_on = false; ++ } ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_G_FBUF ioctl ++ */ ++ case VIDIOC_G_FBUF:{ ++ struct v4l2_framebuffer *fb = arg; ++ *fb = cam->v4l2_fb; ++ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_FBUF ioctl ++ */ ++ case VIDIOC_S_FBUF:{ ++ struct v4l2_framebuffer *fb = arg; ++ cam->v4l2_fb = *fb; ++ break; ++ } ++ ++ case VIDIOC_G_PARM:{ ++ struct v4l2_streamparm *parm = arg; ++ pr_debug(" case VIDIOC_G_PARM\n"); ++ vidioc_int_g_parm(cam->sensor, parm); ++ break; ++ } ++ ++ case VIDIOC_S_PARM:{ ++ struct v4l2_streamparm *parm = arg; ++ pr_debug(" case VIDIOC_S_PARM\n"); ++ retval = csi_v4l2_s_param(cam, parm); ++ break; ++ } ++ ++ case VIDIOC_QUERYCAP:{ ++ struct v4l2_capability *cap = arg; ++ pr_debug(" case VIDIOC_QUERYCAP\n"); ++ strcpy(cap->driver, "csi_v4l2"); ++ cap->version = KERNEL_VERSION(0, 1, 11); ++ cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | ++ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | ++ V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_READWRITE; ++ cap->card[0] = '\0'; ++ cap->bus_info[0] = '\0'; ++ break; ++ } ++ ++ case VIDIOC_CROPCAP: ++ { ++ struct v4l2_cropcap *cap = arg; ++ ++ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { ++ retval = -EINVAL; ++ break; ++ } ++ cap->bounds = cam->crop_bounds; ++ cap->defrect = cam->crop_defrect; ++ break; ++ } ++ case VIDIOC_S_CROP: ++ { ++ struct v4l2_crop *crop = arg; ++ struct v4l2_rect *b = &cam->crop_bounds; ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ retval = -EINVAL; ++ break; ++ } ++ ++ crop->c.top = (crop->c.top < b->top) ? b->top ++ : crop->c.top; ++ if (crop->c.top > b->top + b->height) ++ crop->c.top = b->top + b->height - 1; ++ if (crop->c.height > b->top + b->height - crop->c.top) ++ crop->c.height = ++ b->top + b->height - crop->c.top; ++ ++ crop->c.left = (crop->c.left < b->left) ? b->left ++ : crop->c.left; ++ if (crop->c.left > b->left + b->width) ++ crop->c.left = b->left + b->width - 1; ++ if (crop->c.width > b->left - crop->c.left + b->width) ++ crop->c.width = ++ b->left - crop->c.left + b->width; ++ ++ crop->c.width -= crop->c.width % 8; ++ crop->c.height -= crop->c.height % 8; ++ ++ crop_current.c = crop->c; ++ ++ break; ++ } ++ case VIDIOC_G_CROP: ++ { ++ struct v4l2_crop *crop = arg; ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ retval = -EINVAL; ++ break; ++ } ++ crop->c = crop_current.c; ++ ++ break; ++ ++ } ++ case VIDIOC_REQBUFS: { ++ struct v4l2_requestbuffers *req = arg; ++ pr_debug(" case VIDIOC_REQBUFS\n"); ++ ++ if (req->count > FRAME_NUM) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " ++ "not enough buffers\n"); ++ req->count = FRAME_NUM; ++ } ++ ++ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " ++ "wrong buffer type\n"); ++ retval = -EINVAL; ++ break; ++ } ++ ++ csi_streamoff(cam); ++ if (req->memory & V4L2_MEMORY_MMAP) { ++ csi_free_frame_buf(cam); ++ retval = csi_allocate_frame_buf(cam, req->count + 1); ++ req_buf_number = req->count; ++ } ++ break; ++ } ++ ++ case VIDIOC_QUERYBUF: { ++ struct v4l2_buffer *buf = arg; ++ int index = buf->index; ++ pr_debug(" case VIDIOC_QUERYBUF\n"); ++ ++ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ retval = -EINVAL; ++ break; ++ } ++ ++ if (buf->memory & V4L2_MEMORY_MMAP) { ++ memset(buf, 0, sizeof(buf)); ++ buf->index = index; ++ } ++ ++ down(&cam->param_lock); ++ if (buf->memory & V4L2_MEMORY_USERPTR) { ++ csi_v4l2_release_bufs(cam); ++ retval = csi_v4l2_prepare_bufs(cam, buf); ++ } ++ if (buf->memory & V4L2_MEMORY_MMAP) ++ retval = csi_v4l2_buffer_status(cam, buf); ++ up(&cam->param_lock); ++ break; ++ } ++ ++ case VIDIOC_QBUF: { ++ struct v4l2_buffer *buf = arg; ++ int index = buf->index; ++ pr_debug(" case VIDIOC_QBUF\n"); ++ ++ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); ++ cam->frame[index].buffer.m.offset = buf->m.offset; ++ if ((cam->frame[index].buffer.flags & 0x7) == ++ V4L2_BUF_FLAG_MAPPED) { ++ cam->frame[index].buffer.flags |= V4L2_BUF_FLAG_QUEUED; ++ list_add_tail(&cam->frame[index].queue, &cam->ready_q); ++ } else if (cam->frame[index].buffer.flags & ++ V4L2_BUF_FLAG_QUEUED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " ++ "buffer already queued\n"); ++ retval = -EINVAL; ++ } else if (cam->frame[index].buffer. ++ flags & V4L2_BUF_FLAG_DONE) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " ++ "overwrite done buffer.\n"); ++ cam->frame[index].buffer.flags &= ++ ~V4L2_BUF_FLAG_DONE; ++ cam->frame[index].buffer.flags |= ++ V4L2_BUF_FLAG_QUEUED; ++ retval = -EINVAL; ++ } ++ buf->flags = cam->frame[index].buffer.flags; ++ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); ++ ++ break; ++ } ++ ++ case VIDIOC_DQBUF: { ++ struct v4l2_buffer *buf = arg; ++ pr_debug(" case VIDIOC_DQBUF\n"); ++ ++ retval = csi_v4l_dqueue(cam, buf); ++ ++ break; ++ } ++ ++ case VIDIOC_STREAMON: { ++ pr_debug(" case VIDIOC_STREAMON\n"); ++ retval = csi_streamon(cam); ++ break; ++ } ++ ++ case VIDIOC_STREAMOFF: { ++ pr_debug(" case VIDIOC_STREAMOFF\n"); ++ retval = csi_streamoff(cam); ++ break; ++ } ++ case VIDIOC_ENUM_FMT: { ++ struct v4l2_fmtdesc *fmt = arg; ++ if (cam->sensor) ++ retval = vidioc_int_enum_fmt_cap(cam->sensor, fmt); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_ENUM_FRAMESIZES: { ++ struct v4l2_frmsizeenum *fsize = arg; ++ if (cam->sensor) ++ retval = vidioc_int_enum_framesizes(cam->sensor, fsize); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_ENUM_FRAMEINTERVALS: { ++ struct v4l2_frmivalenum *fival = arg; ++ if (cam->sensor) ++ retval = vidioc_int_enum_frameintervals(cam->sensor, ++ fival); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_DBG_G_CHIP_IDENT: { ++ struct v4l2_dbg_chip_ident *p = arg; ++ p->ident = V4L2_IDENT_NONE; ++ p->revision = 0; ++ if (cam->sensor) ++ retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ ++ case VIDIOC_S_CTRL: ++ { ++ struct v4l2_control *vc = arg; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) ++ if (vc->id == pxp_controls[i].id) { ++ if (vc->value < pxp_controls[i].minimum || ++ vc->value > pxp_controls[i].maximum) { ++ retval = -ERANGE; ++ break; ++ } ++ retval = pxp_set_cstate(cam, vc); ++ break; ++ } ++ ++ if (i >= ARRAY_SIZE(pxp_controls)) ++ retval = -EINVAL; ++ break; ++ ++ } ++ case VIDIOC_G_CTRL: ++ { ++ struct v4l2_control *vc = arg; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) ++ if (vc->id == pxp_controls[i].id) { ++ retval = pxp_get_cstate(cam, vc); ++ break; ++ } ++ ++ if (i >= ARRAY_SIZE(pxp_controls)) ++ retval = -EINVAL; ++ break; ++ } ++ case VIDIOC_QUERYCTRL: ++ { ++ struct v4l2_queryctrl *qc = arg; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(pxp_controls); i++) ++ if (qc->id && qc->id == pxp_controls[i].id) { ++ memcpy(qc, &(pxp_controls[i]), sizeof(*qc)); ++ break; ++ } ++ ++ if (i >= ARRAY_SIZE(pxp_controls)) ++ retval = -EINVAL; ++ break; ++ } ++ case VIDIOC_G_STD: ++ case VIDIOC_G_OUTPUT: ++ case VIDIOC_S_OUTPUT: ++ case VIDIOC_ENUMSTD: ++ case VIDIOC_S_STD: ++ case VIDIOC_TRY_FMT: ++ case VIDIOC_ENUMINPUT: ++ case VIDIOC_G_INPUT: ++ case VIDIOC_S_INPUT: ++ case VIDIOC_G_TUNER: ++ case VIDIOC_S_TUNER: ++ case VIDIOC_G_FREQUENCY: ++ case VIDIOC_S_FREQUENCY: ++ case VIDIOC_ENUMOUTPUT: ++ default: ++ pr_debug(" case not supported\n"); ++ retval = -EINVAL; ++ break; ++ } ++ ++ if (ioctlnr != VIDIOC_DQBUF) ++ up(&cam->busy_lock); ++ return retval; ++} ++ ++/* ++ * V4L interface - ioctl function ++ * ++ * @return None ++ */ ++static long csi_v4l_ioctl(struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return video_usercopy(file, cmd, arg, csi_v4l_do_ioctl); ++} ++ ++/*! ++ * V4L interface - mmap function ++ * ++ * @param file structure file * ++ * ++ * @param vma structure vm_area_struct * ++ * ++ * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error ++ */ ++static int csi_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct video_device *dev = video_devdata(file); ++ unsigned long size; ++ int res = 0; ++ cam_data *cam = video_get_drvdata(dev); ++ ++ pr_debug("%s\n", __func__); ++ pr_debug("\npgoff=0x%lx, start=0x%lx, end=0x%lx\n", ++ vma->vm_pgoff, vma->vm_start, vma->vm_end); ++ ++ /* make this _really_ smp-safe */ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EINTR; ++ ++ size = vma->vm_end - vma->vm_start; ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ ++ if (remap_pfn_range(vma, vma->vm_start, ++ vma->vm_pgoff, size, vma->vm_page_prot)) { ++ pr_err("ERROR: v4l2 capture: %s : " ++ "remap_pfn_range failed\n", __func__); ++ res = -ENOBUFS; ++ goto csi_mmap_exit; ++ } ++ ++ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ ++ ++csi_mmap_exit: ++ up(&cam->busy_lock); ++ return res; ++} ++ ++/*! ++ * This structure defines the functions to be called in this driver. ++ */ ++static struct v4l2_file_operations csi_v4l_fops = { ++ .owner = THIS_MODULE, ++ .open = csi_v4l_open, ++ .release = csi_v4l_close, ++ .read = csi_v4l_read, ++ .ioctl = csi_v4l_ioctl, ++ .mmap = csi_mmap, ++}; ++ ++static struct video_device csi_v4l_template = { ++ .name = "Mx25 Camera", ++ .fops = &csi_v4l_fops, ++ .release = video_device_release, ++}; ++ ++/*! ++ * initialize cam_data structure ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static void init_camera_struct(cam_data *cam) ++{ ++ struct pxp_proc_data *proc_data = &cam->pxp_conf.proc_data; ++ pr_debug("In MVC: %s\n", __func__); ++ ++ proc_data->hflip = 0; ++ proc_data->vflip = 0; ++ proc_data->rotate = 0; ++ proc_data->bgcolor = 0; ++ ++ /* Default everything to 0 */ ++ memset(cam, 0, sizeof(cam_data)); ++ ++ sema_init(&cam->param_lock, 1); ++ sema_init(&cam->busy_lock, 1); ++ ++ cam->video_dev = video_device_alloc(); ++ if (cam->video_dev == NULL) ++ return; ++ ++ *(cam->video_dev) = csi_v4l_template; ++ ++ video_set_drvdata(cam->video_dev, cam); ++ cam->video_dev->minor = -1; ++ ++ init_waitqueue_head(&cam->enc_queue); ++ init_waitqueue_head(&cam->still_queue); ++ ++ cam->streamparm.parm.capture.capturemode = 0; ++ ++ cam->standard.index = 0; ++ cam->standard.id = V4L2_STD_UNKNOWN; ++ cam->standard.frameperiod.denominator = 30; ++ cam->standard.frameperiod.numerator = 1; ++ cam->standard.framelines = 480; ++ cam->standard_autodetect = true; ++ cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; ++ cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; ++ cam->overlay_on = false; ++ cam->capture_on = false; ++ cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; ++ ++ cam->v2f.fmt.pix.sizeimage = 480 * 640 * 2; ++ cam->v2f.fmt.pix.bytesperline = 640 * 2; ++ cam->v2f.fmt.pix.width = 640; ++ cam->v2f.fmt.pix.height = 480; ++ cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; ++ cam->win.w.width = 160; ++ cam->win.w.height = 160; ++ cam->win.w.left = 0; ++ cam->win.w.top = 0; ++ cam->still_counter = 0; ++ /* setup cropping */ ++ cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = 640; ++ cam->crop_bounds.top = 0; ++ cam->crop_bounds.height = 480; ++ cam->crop_current = cam->crop_defrect = cam->crop_bounds; ++ ++ cam->enc_callback = camera_callback; ++ csi_start_callback(cam); ++ init_waitqueue_head(&cam->power_queue); ++ spin_lock_init(&cam->queue_int_lock); ++ spin_lock_init(&cam->dqueue_int_lock); ++} ++ ++/*! ++ * camera_power function ++ * Turns Sensor power On/Off ++ * ++ * @param cam cam data struct ++ * @param cameraOn true to turn camera on, false to turn off power. ++ * ++ * @return status ++ */ ++static u8 camera_power(cam_data *cam, bool cameraOn) ++{ ++ pr_debug("In MVC: %s on=%d\n", __func__, cameraOn); ++ ++ if (cameraOn == true) { ++ vidioc_int_s_power(cam->sensor, 1); ++ } else { ++ vidioc_int_s_power(cam->sensor, 0); ++ } ++ return 0; ++} ++ ++static const struct of_device_id imx_csi_v4l2_dt_ids[] = { ++ { .compatible = "fsl,imx6sl-csi-v4l2", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, imx_csi_v4l2_dt_ids); ++ ++static int csi_v4l2_probe(struct platform_device *pdev) ++{ ++ struct scatterlist *sg; ++ u8 err = 0; ++ ++ /* Create g_cam and initialize it. */ ++ g_cam = kmalloc(sizeof(cam_data), GFP_KERNEL); ++ if (g_cam == NULL) { ++ pr_err("ERROR: v4l2 capture: failed to register camera\n"); ++ err = -ENOMEM; ++ goto out; ++ } ++ memset(&crop_current, 0, sizeof(crop_current)); ++ memset(&win_current, 0, sizeof(win_current)); ++ init_camera_struct(g_cam); ++ platform_set_drvdata(pdev, (void *)g_cam); ++ ++ /* Set up the v4l2 device and register it */ ++ csi_v4l2_int_device.priv = g_cam; ++ /* This function contains a bug that won't let this be rmmod'd. */ ++ v4l2_int_device_register(&csi_v4l2_int_device); ++ ++ /* register v4l video device */ ++ if (video_register_device(g_cam->video_dev, VFL_TYPE_GRABBER, video_nr) ++ == -1) { ++ kfree(g_cam); ++ g_cam = NULL; ++ pr_err("ERROR: v4l2 capture: video_register_device failed\n"); ++ err = -ENODEV; ++ goto out; ++ } ++ pr_debug(" Video device registered: %s #%d\n", ++ g_cam->video_dev->name, g_cam->video_dev->minor); ++ ++ g_cam->pxp_chan = NULL; ++ /* Initialize Scatter-gather list containing 2 buffer addresses. */ ++ sg = g_cam->sg; ++ sg_init_table(sg, 2); ++ ++out: ++ return err; ++} ++ ++static int csi_v4l2_remove(struct platform_device *pdev) ++{ ++ if (g_cam->open_count) { ++ pr_err("ERROR: v4l2 capture:camera open " ++ "-- setting ops to NULL\n"); ++ } else { ++ pr_info("V4L2 freeing image input device\n"); ++ v4l2_int_device_unregister(&csi_v4l2_int_device); ++ csi_stop_callback(g_cam); ++ video_unregister_device(g_cam->video_dev); ++ platform_set_drvdata(pdev, NULL); ++ ++ kfree(g_cam); ++ g_cam = NULL; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * This function is called to put the sensor in a low power state. ++ * Refer to the document driver-model/driver.txt in the kernel source tree ++ * for more information. ++ * ++ * @param pdev the device structure used to give information on which I2C ++ * to suspend ++ * @param state the power state the device is entering ++ * ++ * @return The function returns 0 on success and -1 on failure. ++ */ ++static int csi_v4l2_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ cam_data *cam = platform_get_drvdata(pdev); ++ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ if (cam == NULL) ++ return -1; ++ ++ cam->low_power = true; ++ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ if (cam->capture_on == true || cam->overlay_on == true) ++ camera_power(cam, false); ++ ++ return 0; ++} ++ ++/*! ++ * This function is called to bring the sensor back from a low power state. ++ * Refer to the document driver-model/driver.txt in the kernel source tree ++ * for more information. ++ * ++ * @param pdev the device structure ++ * ++ * @return The function returns 0 on success and -1 on failure ++ */ ++static int csi_v4l2_resume(struct platform_device *pdev) ++{ ++ cam_data *cam = platform_get_drvdata(pdev); ++ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ if (cam == NULL) ++ return -1; ++ ++ cam->low_power = false; ++ wake_up_interruptible(&cam->power_queue); ++ if (cam->capture_on == true || cam->overlay_on == true) ++ camera_power(cam, true); ++ ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ ++ return 0; ++} ++ ++/*! ++ * This structure contains pointers to the power management callback functions. ++ */ ++static struct platform_driver csi_v4l2_driver = { ++ .driver = { ++ .name = "csi_v4l2", ++ .of_match_table = of_match_ptr(imx_csi_v4l2_dt_ids), ++ }, ++ .probe = csi_v4l2_probe, ++ .remove = csi_v4l2_remove, ++#ifdef CONFIG_PM ++ .suspend = csi_v4l2_suspend, ++ .resume = csi_v4l2_resume, ++#endif ++ .shutdown = NULL, ++}; ++ ++/*! ++ * Initializes the camera driver. ++ */ ++static int csi_v4l2_master_attach(struct v4l2_int_device *slave) ++{ ++ cam_data *cam = slave->u.slave->master->priv; ++ struct v4l2_format cam_fmt; ++ ++ pr_debug("In MVC: %s\n", __func__); ++ pr_debug(" slave.name = %s\n", slave->name); ++ pr_debug(" master.name = %s\n", slave->u.slave->master->name); ++ ++ cam->sensor = slave; ++ if (slave == NULL) { ++ pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); ++ return -1; ++ } ++ ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); ++ ++ /* Used to detect TV in (type 1) vs. camera (type 0) */ ++ cam->device_type = cam_fmt.fmt.pix.priv; ++ ++ cam->crop_bounds.top = cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = cam_fmt.fmt.pix.width; ++ cam->crop_bounds.height = cam_fmt.fmt.pix.height; ++ ++ /* This also is the max crop size for this device. */ ++ cam->crop_defrect.top = cam->crop_defrect.left = 0; ++ cam->crop_defrect.width = cam_fmt.fmt.pix.width; ++ cam->crop_defrect.height = cam_fmt.fmt.pix.height; ++ ++ /* At this point, this is also the current image size. */ ++ cam->crop_current.top = cam->crop_current.left = 0; ++ cam->crop_current.width = cam_fmt.fmt.pix.width; ++ cam->crop_current.height = cam_fmt.fmt.pix.height; ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ ++ return 0; ++} ++ ++/*! ++ * Disconnects the camera driver. ++ */ ++static void csi_v4l2_master_detach(struct v4l2_int_device *slave) ++{ ++ pr_debug("In MVC: %s\n", __func__); ++ ++ vidioc_int_dev_exit(slave); ++} ++ ++module_platform_driver(csi_v4l2_driver); ++ ++module_param(video_nr, int, 0444); ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("V4L2 capture driver for Mx25 based cameras"); ++MODULE_LICENSE("GPL"); ++MODULE_SUPPORTED_DEVICE("video"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/fsl_csi.c linux-imx6-3.14/drivers/media/platform/mxc/capture/fsl_csi.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/fsl_csi.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/fsl_csi.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,302 @@ ++/* ++ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file fsl_csi.c, this file is derived from mx27_csi.c ++ * ++ * @brief mx25 CMOS Sensor interface functions ++ * ++ * @ingroup CSI ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mxc_v4l2_capture.h" ++#include "fsl_csi.h" ++ ++void __iomem *csi_regbase; ++EXPORT_SYMBOL(csi_regbase); ++static int irq_nr; ++static csi_irq_callback_t g_callback; ++static void *g_callback_data; ++ ++static irqreturn_t csi_irq_handler(int irq, void *data) ++{ ++ cam_data *cam = (cam_data *) data; ++ unsigned long status = __raw_readl(CSI_CSISR); ++ ++ __raw_writel(status, CSI_CSISR); ++ ++ if (status & BIT_HRESP_ERR_INT) ++ pr_warning("Hresponse error is detected.\n"); ++ ++ if (status & BIT_DMA_TSF_DONE_FB1) { ++ if (cam->capture_on) { ++ spin_lock(&cam->queue_int_lock); ++ cam->ping_pong_csi = 1; ++ spin_unlock(&cam->queue_int_lock); ++ cam->enc_callback(0, cam); ++ } else { ++ cam->still_counter++; ++ wake_up_interruptible(&cam->still_queue); ++ } ++ } ++ ++ if (status & BIT_DMA_TSF_DONE_FB2) { ++ if (cam->capture_on) { ++ spin_lock(&cam->queue_int_lock); ++ cam->ping_pong_csi = 2; ++ spin_unlock(&cam->queue_int_lock); ++ cam->enc_callback(0, cam); ++ } else { ++ cam->still_counter++; ++ wake_up_interruptible(&cam->still_queue); ++ } ++ } ++ ++ if (g_callback) ++ g_callback(g_callback_data, status); ++ ++ pr_debug("CSI status = 0x%08lX\n", status); ++ ++ return IRQ_HANDLED; ++} ++ ++static void csihw_reset_frame_count(void) ++{ ++ __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, CSI_CSICR3); ++} ++ ++static void csihw_reset(void) ++{ ++ csihw_reset_frame_count(); ++ __raw_writel(CSICR1_RESET_VAL, CSI_CSICR1); ++ __raw_writel(CSICR2_RESET_VAL, CSI_CSICR2); ++ __raw_writel(CSICR3_RESET_VAL, CSI_CSICR3); ++} ++ ++/*! ++ * csi_init_interface ++ * Init csi interface ++ */ ++void csi_init_interface(void) ++{ ++ unsigned int val = 0; ++ unsigned int imag_para; ++ ++ val |= BIT_SOF_POL; ++ val |= BIT_REDGE; ++ val |= BIT_GCLK_MODE; ++ val |= BIT_HSYNC_POL; ++ val |= BIT_PACK_DIR; ++ val |= BIT_FCC; ++ val |= BIT_SWAP16_EN; ++ val |= 1 << SHIFT_MCLKDIV; ++ val |= BIT_MCLKEN; ++ __raw_writel(val, CSI_CSICR1); ++ ++ imag_para = (640 << 16) | 960; ++ __raw_writel(imag_para, CSI_CSIIMAG_PARA); ++ ++ val = 0x1010; ++ val |= BIT_DMA_REFLASH_RFF; ++ __raw_writel(val, CSI_CSICR3); ++} ++EXPORT_SYMBOL(csi_init_interface); ++ ++void csi_init_format(int fmt) ++{ ++ unsigned int val; ++ ++ val = __raw_readl(CSI_CSICR1); ++ if (fmt == V4L2_PIX_FMT_YUYV) { ++ val &= ~BIT_PACK_DIR; ++ val &= ~BIT_SWAP16_EN; ++ } else if (fmt == V4L2_PIX_FMT_UYVY) { ++ val |= BIT_PACK_DIR; ++ val |= BIT_SWAP16_EN; ++ } else ++ pr_warning("unsupported format, old format remains.\n"); ++ ++ __raw_writel(val, CSI_CSICR1); ++} ++EXPORT_SYMBOL(csi_init_format); ++ ++/*! ++ * csi_read_mclk_flag ++ * ++ * @return gcsi_mclk_source ++ */ ++int csi_read_mclk_flag(void) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(csi_read_mclk_flag); ++ ++void csi_start_callback(void *data) ++{ ++ cam_data *cam = (cam_data *) data; ++ ++ if (request_irq(irq_nr, csi_irq_handler, 0, "csi", cam) < 0) ++ pr_debug("CSI error: irq request fail\n"); ++ ++} ++EXPORT_SYMBOL(csi_start_callback); ++ ++void csi_stop_callback(void *data) ++{ ++ cam_data *cam = (cam_data *) data; ++ ++ free_irq(irq_nr, cam); ++} ++EXPORT_SYMBOL(csi_stop_callback); ++ ++void csi_enable_int(int arg) ++{ ++ unsigned long cr1 = __raw_readl(CSI_CSICR1); ++ ++ cr1 |= BIT_SOF_INTEN; ++ if (arg == 1) { ++ /* still capture needs DMA intterrupt */ ++ cr1 |= BIT_FB1_DMA_DONE_INTEN; ++ cr1 |= BIT_FB2_DMA_DONE_INTEN; ++ } ++ __raw_writel(cr1, CSI_CSICR1); ++} ++EXPORT_SYMBOL(csi_enable_int); ++ ++void csi_disable_int(void) ++{ ++ unsigned long cr1 = __raw_readl(CSI_CSICR1); ++ ++ cr1 &= ~BIT_SOF_INTEN; ++ cr1 &= ~BIT_FB1_DMA_DONE_INTEN; ++ cr1 &= ~BIT_FB2_DMA_DONE_INTEN; ++ __raw_writel(cr1, CSI_CSICR1); ++} ++EXPORT_SYMBOL(csi_disable_int); ++ ++void csi_set_16bit_imagpara(int width, int height) ++{ ++ int imag_para = 0; ++ unsigned long cr3 = __raw_readl(CSI_CSICR3); ++ ++ imag_para = (width << 16) | (height * 2); ++ __raw_writel(imag_para, CSI_CSIIMAG_PARA); ++ ++ /* reflash the embeded DMA controller */ ++ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); ++} ++EXPORT_SYMBOL(csi_set_16bit_imagpara); ++ ++void csi_set_12bit_imagpara(int width, int height) ++{ ++ int imag_para = 0; ++ unsigned long cr3 = __raw_readl(CSI_CSICR3); ++ ++ imag_para = (width << 16) | (height * 3 / 2); ++ __raw_writel(imag_para, CSI_CSIIMAG_PARA); ++ ++ /* reflash the embeded DMA controller */ ++ __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); ++} ++EXPORT_SYMBOL(csi_set_12bit_imagpara); ++ ++void csi_dmareq_rff_enable(void) ++{ ++ unsigned long cr3 = __raw_readl(CSI_CSICR3); ++ ++ cr3 |= BIT_DMA_REQ_EN_RFF; ++ cr3 |= BIT_HRESP_ERR_EN; ++ __raw_writel(cr3, CSI_CSICR3); ++} ++EXPORT_SYMBOL(csi_dmareq_rff_enable); ++ ++void csi_dmareq_rff_disable(void) ++{ ++ unsigned long cr3 = __raw_readl(CSI_CSICR3); ++ ++ cr3 &= ~BIT_DMA_REQ_EN_RFF; ++ cr3 &= ~BIT_HRESP_ERR_EN; ++ __raw_writel(cr3, CSI_CSICR3); ++} ++EXPORT_SYMBOL(csi_dmareq_rff_disable); ++ ++static const struct of_device_id fsl_csi_dt_ids[] = { ++ { .compatible = "fsl,imx6sl-csi", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, fsl_csi_dt_ids); ++ ++static int csi_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "No csi irq found.\n"); ++ ret = -ENODEV; ++ goto err; ++ } ++ irq_nr = res->start; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "No csi base address found.\n"); ++ ret = -ENODEV; ++ goto err; ++ } ++ csi_regbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (!csi_regbase) { ++ dev_err(&pdev->dev, "ioremap failed with csi base\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ csihw_reset(); ++ csi_init_interface(); ++ csi_dmareq_rff_disable(); ++ ++err: ++ return ret; ++} ++ ++static int csi_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static struct platform_driver csi_driver = { ++ .driver = { ++ .name = "fsl_csi", ++ .of_match_table = of_match_ptr(fsl_csi_dt_ids), ++ }, ++ .probe = csi_probe, ++ .remove = csi_remove, ++}; ++ ++module_platform_driver(csi_driver); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("fsl CSI driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/fsl_csi.h linux-imx6-3.14/drivers/media/platform/mxc/capture/fsl_csi.h +--- linux-3.14.14/drivers/media/platform/mxc/capture/fsl_csi.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/fsl_csi.h 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,198 @@ ++/* ++ * Copyright 2009-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file fsl_csi.h ++ * ++ * @brief mx25 CMOS Sensor interface functions ++ * ++ * @ingroup CSI ++ */ ++ ++#ifndef MX25_CSI_H ++#define MX25_CSI_H ++ ++#include ++ ++/* reset values */ ++#define CSICR1_RESET_VAL 0x40000800 ++#define CSICR2_RESET_VAL 0x0 ++#define CSICR3_RESET_VAL 0x0 ++ ++/* csi control reg 1 */ ++#define BIT_SWAP16_EN (0x1 << 31) ++#define BIT_EXT_VSYNC (0x1 << 30) ++#define BIT_EOF_INT_EN (0x1 << 29) ++#define BIT_PRP_IF_EN (0x1 << 28) ++#define BIT_CCIR_MODE (0x1 << 27) ++#define BIT_COF_INT_EN (0x1 << 26) ++#define BIT_SF_OR_INTEN (0x1 << 25) ++#define BIT_RF_OR_INTEN (0x1 << 24) ++#define BIT_SFF_DMA_DONE_INTEN (0x1 << 22) ++#define BIT_STATFF_INTEN (0x1 << 21) ++#define BIT_FB2_DMA_DONE_INTEN (0x1 << 20) ++#define BIT_FB1_DMA_DONE_INTEN (0x1 << 19) ++#define BIT_RXFF_INTEN (0x1 << 18) ++#define BIT_SOF_POL (0x1 << 17) ++#define BIT_SOF_INTEN (0x1 << 16) ++#define BIT_MCLKDIV (0xF << 12) ++#define BIT_HSYNC_POL (0x1 << 11) ++#define BIT_CCIR_EN (0x1 << 10) ++#define BIT_MCLKEN (0x1 << 9) ++#define BIT_FCC (0x1 << 8) ++#define BIT_PACK_DIR (0x1 << 7) ++#define BIT_CLR_STATFIFO (0x1 << 6) ++#define BIT_CLR_RXFIFO (0x1 << 5) ++#define BIT_GCLK_MODE (0x1 << 4) ++#define BIT_INV_DATA (0x1 << 3) ++#define BIT_INV_PCLK (0x1 << 2) ++#define BIT_REDGE (0x1 << 1) ++#define BIT_PIXEL_BIT (0x1 << 0) ++ ++#define SHIFT_MCLKDIV 12 ++ ++/* control reg 3 */ ++#define BIT_FRMCNT (0xFFFF << 16) ++#define BIT_FRMCNT_RST (0x1 << 15) ++#define BIT_DMA_REFLASH_RFF (0x1 << 14) ++#define BIT_DMA_REFLASH_SFF (0x1 << 13) ++#define BIT_DMA_REQ_EN_RFF (0x1 << 12) ++#define BIT_DMA_REQ_EN_SFF (0x1 << 11) ++#define BIT_STATFF_LEVEL (0x7 << 8) ++#define BIT_HRESP_ERR_EN (0x1 << 7) ++#define BIT_RXFF_LEVEL (0x7 << 4) ++#define BIT_TWO_8BIT_SENSOR (0x1 << 3) ++#define BIT_ZERO_PACK_EN (0x1 << 2) ++#define BIT_ECC_INT_EN (0x1 << 1) ++#define BIT_ECC_AUTO_EN (0x1 << 0) ++ ++#define SHIFT_FRMCNT 16 ++ ++/* csi status reg */ ++#define BIT_SFF_OR_INT (0x1 << 25) ++#define BIT_RFF_OR_INT (0x1 << 24) ++#define BIT_DMA_TSF_DONE_SFF (0x1 << 22) ++#define BIT_STATFF_INT (0x1 << 21) ++#define BIT_DMA_TSF_DONE_FB2 (0x1 << 20) ++#define BIT_DMA_TSF_DONE_FB1 (0x1 << 19) ++#define BIT_RXFF_INT (0x1 << 18) ++#define BIT_EOF_INT (0x1 << 17) ++#define BIT_SOF_INT (0x1 << 16) ++#define BIT_F2_INT (0x1 << 15) ++#define BIT_F1_INT (0x1 << 14) ++#define BIT_COF_INT (0x1 << 13) ++#define BIT_HRESP_ERR_INT (0x1 << 7) ++#define BIT_ECC_INT (0x1 << 1) ++#define BIT_DRDY (0x1 << 0) ++ ++#define CSI_MCLK_VF 1 ++#define CSI_MCLK_ENC 2 ++#define CSI_MCLK_RAW 4 ++#define CSI_MCLK_I2C 8 ++#endif ++ ++extern void __iomem *csi_regbase; ++#define CSI_CSICR1 (csi_regbase) ++#define CSI_CSICR2 (csi_regbase + 0x4) ++#define CSI_CSICR3 (csi_regbase + 0x8) ++#define CSI_STATFIFO (csi_regbase + 0xC) ++#define CSI_CSIRXFIFO (csi_regbase + 0x10) ++#define CSI_CSIRXCNT (csi_regbase + 0x14) ++#define CSI_CSISR (csi_regbase + 0x18) ++ ++#define CSI_CSIDBG (csi_regbase + 0x1C) ++#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20) ++#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24) ++#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28) ++#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C) ++#define CSI_CSIFBUF_PARA (csi_regbase + 0x30) ++#define CSI_CSIIMAG_PARA (csi_regbase + 0x34) ++ ++static inline void csi_clear_status(unsigned long status) ++{ ++ __raw_writel(status, CSI_CSISR); ++} ++ ++struct csi_signal_cfg_t { ++ unsigned data_width:3; ++ unsigned clk_mode:2; ++ unsigned ext_vsync:1; ++ unsigned Vsync_pol:1; ++ unsigned Hsync_pol:1; ++ unsigned pixclk_pol:1; ++ unsigned data_pol:1; ++ unsigned sens_clksrc:1; ++}; ++ ++struct csi_config_t { ++ /* control reg 1 */ ++ unsigned int swap16_en:1; ++ unsigned int ext_vsync:1; ++ unsigned int eof_int_en:1; ++ unsigned int prp_if_en:1; ++ unsigned int ccir_mode:1; ++ unsigned int cof_int_en:1; ++ unsigned int sf_or_inten:1; ++ unsigned int rf_or_inten:1; ++ unsigned int sff_dma_done_inten:1; ++ unsigned int statff_inten:1; ++ unsigned int fb2_dma_done_inten:1; ++ unsigned int fb1_dma_done_inten:1; ++ unsigned int rxff_inten:1; ++ unsigned int sof_pol:1; ++ unsigned int sof_inten:1; ++ unsigned int mclkdiv:4; ++ unsigned int hsync_pol:1; ++ unsigned int ccir_en:1; ++ unsigned int mclken:1; ++ unsigned int fcc:1; ++ unsigned int pack_dir:1; ++ unsigned int gclk_mode:1; ++ unsigned int inv_data:1; ++ unsigned int inv_pclk:1; ++ unsigned int redge:1; ++ unsigned int pixel_bit:1; ++ ++ /* control reg 3 */ ++ unsigned int frmcnt:16; ++ unsigned int frame_reset:1; ++ unsigned int dma_reflash_rff:1; ++ unsigned int dma_reflash_sff:1; ++ unsigned int dma_req_en_rff:1; ++ unsigned int dma_req_en_sff:1; ++ unsigned int statff_level:3; ++ unsigned int hresp_err_en:1; ++ unsigned int rxff_level:3; ++ unsigned int two_8bit_sensor:1; ++ unsigned int zero_pack_en:1; ++ unsigned int ecc_int_en:1; ++ unsigned int ecc_auto_en:1; ++ /* fifo counter */ ++ unsigned int rxcnt; ++}; ++ ++typedef void (*csi_irq_callback_t) (void *data, unsigned long status); ++ ++void csi_init_interface(void); ++void csi_init_format(int fmt); ++void csi_set_16bit_imagpara(int width, int height); ++void csi_set_12bit_imagpara(int width, int height); ++int csi_read_mclk_flag(void); ++void csi_start_callback(void *data); ++void csi_stop_callback(void *data); ++void csi_enable_int(int arg); ++void csi_disable_int(void); ++void csi_mclk_enable(void); ++void csi_mclk_disable(void); ++void csi_dmareq_rff_enable(void); ++void csi_dmareq_rff_disable(void); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_bg_overlay_sdc.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,546 @@ ++ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_bg_overlay_sdc_bg.c ++ * ++ * @brief IPU Use case for PRP-VF back-ground ++ * ++ * @ingroup IPU ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++static int csi_buffer_num; ++static u32 bpp, csi_mem_bufsize = 3; ++static u32 out_format; ++static struct ipu_soc *disp_ipu; ++static u32 offset; ++ ++static void csi_buf_work_func(struct work_struct *work) ++{ ++ int err = 0; ++ cam_data *cam = ++ container_of(work, struct _cam_data, csi_work_struct); ++ ++ struct ipu_task task; ++ memset(&task, 0, sizeof(task)); ++ ++ if (csi_buffer_num) ++ task.input.paddr = cam->vf_bufs[0]; ++ else ++ task.input.paddr = cam->vf_bufs[1]; ++ task.input.width = cam->crop_current.width; ++ task.input.height = cam->crop_current.height; ++ task.input.format = IPU_PIX_FMT_UYVY; ++ ++ task.output.paddr = offset; ++ task.output.width = cam->overlay_fb->var.xres; ++ task.output.height = cam->overlay_fb->var.yres; ++ task.output.format = out_format; ++ task.output.rotate = cam->rotation; ++ task.output.crop.pos.x = cam->win.w.left; ++ task.output.crop.pos.y = cam->win.w.top; ++ if (cam->win.w.width > 1024 || cam->win.w.height > 1024) { ++ task.output.crop.w = cam->overlay_fb->var.xres; ++ task.output.crop.h = cam->overlay_fb->var.yres; ++ } else { ++ task.output.crop.w = cam->win.w.width; ++ task.output.crop.h = cam->win.w.height; ++ } ++again: ++ err = ipu_check_task(&task); ++ if (err != IPU_CHECK_OK) { ++ if (err > IPU_CHECK_ERR_MIN) { ++ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) { ++ task.input.crop.w -= 8; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) { ++ task.input.crop.h -= 8; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { ++ task.output.width -= 8; ++ task.output.crop.w = task.output.width; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { ++ task.output.height -= 8; ++ task.output.crop.h = task.output.height; ++ goto again; ++ } ++ printk(KERN_ERR "check ipu taks fail\n"); ++ return; ++ } ++ printk(KERN_ERR "check ipu taks fail\n"); ++ return; ++ } ++ err = ipu_queue_task(&task); ++ if (err < 0) ++ printk(KERN_ERR "queue ipu task error\n"); ++} ++ ++static void get_disp_ipu(cam_data *cam) ++{ ++ if (cam->output > 2) ++ disp_ipu = ipu_get_soc(1); /* using DISP4 */ ++ else ++ disp_ipu = ipu_get_soc(0); ++} ++ ++ ++/*! ++ * csi ENC callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t csi_enc_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = (cam_data *) dev_id; ++ ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num); ++ schedule_work(&cam->csi_work_struct); ++ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0; ++ return IRQ_HANDLED; ++} ++ ++static int csi_enc_setup(cam_data *cam) ++{ ++ ipu_channel_params_t params; ++ u32 pixel_fmt; ++ int err = 0, sensor_protocol = 0; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (!cam) { ++ printk(KERN_ERR "cam private is NULL\n"); ++ return -ENXIO; ++ } ++ ++ memset(¶ms, 0, sizeof(ipu_channel_params_t)); ++ params.csi_mem.csi = cam->csi; ++ ++ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); ++ switch (sensor_protocol) { ++ case IPU_CSI_CLK_MODE_GATED_CLK: ++ case IPU_CSI_CLK_MODE_NONGATED_CLK: ++ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: ++ params.csi_mem.interlaced = false; ++ break; ++ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: ++ params.csi_mem.interlaced = true; ++ break; ++ default: ++ printk(KERN_ERR "sensor protocol unsupported\n"); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ params.csi_mem.mipi_en = true; ++ params.csi_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ params.csi_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ } ++ csi_mem_bufsize = ++ cam->crop_current.width * cam->crop_current.height * 2; ++ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize); ++ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[0], ++ (dma_addr_t *) & ++ cam->vf_bufs[0], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[0] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_2; ++ } ++ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize); ++ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[1], ++ (dma_addr_t *) & ++ cam->vf_bufs[1], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[1] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_1; ++ } ++ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); ++ ++ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); ++ if (err != 0) { ++ printk(KERN_ERR "ipu_init_channel %d\n", err); ++ goto out_1; ++ } ++ ++ pixel_fmt = IPU_PIX_FMT_UYVY; ++ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ pixel_fmt, cam->crop_current.width, ++ cam->crop_current.height, ++ cam->crop_current.width, IPU_ROTATE_NONE, ++ cam->vf_bufs[0], cam->vf_bufs[1], 0, ++ cam->offset.u_offset, cam->offset.u_offset); ++ if (err != 0) { ++ printk(KERN_ERR "CSI_MEM output buffer\n"); ++ goto out_1; ++ } ++ err = ipu_enable_channel(cam->ipu, CSI_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); ++ goto out_1; ++ } ++ ++ csi_buffer_num = 0; ++ ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1); ++ return err; ++out_1: ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++out_2: ++ return err; ++} ++ ++/*! ++ * Enable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_enabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, ++ csi_enc_callback, 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n"); ++ return err; ++ } ++ ++ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func); ++ ++ err = csi_enc_setup(cam); ++ if (err != 0) { ++ printk(KERN_ERR "csi_enc_setup %d\n", err); ++ goto out1; ++ } ++ ++ return err; ++out1: ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++ return err; ++} ++ ++/*! ++ * bg_overlay_start - start the overlay task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int bg_overlay_start(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ if (!cam) { ++ printk(KERN_ERR "private is NULL\n"); ++ return -EIO; ++ } ++ ++ if (cam->overlay_active == true) { ++ pr_debug("already start.\n"); ++ return 0; ++ } ++ ++ get_disp_ipu(cam); ++ ++ out_format = cam->v4l2_fb.fmt.pixelformat; ++ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) { ++ bpp = 3, csi_mem_bufsize = 3; ++ pr_info("BGR24\n"); ++ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) { ++ bpp = 2, csi_mem_bufsize = 2; ++ pr_info("RGB565\n"); ++ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) { ++ bpp = 4, csi_mem_bufsize = 4; ++ pr_info("BGR32\n"); ++ } else { ++ printk(KERN_ERR ++ "unsupported fix format from the framebuffer.\n"); ++ return -EINVAL; ++ } ++ ++ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top + ++ csi_mem_bufsize * cam->win.w.left; ++ ++ if (cam->v4l2_fb.base == 0) ++ printk(KERN_ERR "invalid frame buffer address.\n"); ++ else ++ offset += (u32) cam->v4l2_fb.base; ++ ++ csi_mem_bufsize = cam->win.w.width * cam->win.w.height ++ * csi_mem_bufsize; ++ ++ err = csi_enc_enabling_tasks(cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error csi enc enable fail\n"); ++ return err; ++ } ++ ++ cam->overlay_active = true; ++ return err; ++} ++ ++/*! ++ * bg_overlay_stop - stop the overlay task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int bg_overlay_stop(void *private) ++{ ++ int err = 0; ++ cam_data *cam = (cam_data *) private; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (cam->overlay_active == false) ++ return 0; ++ ++ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); ++ ++ ipu_uninit_channel(cam->ipu, CSI_MEM); ++ ++ csi_buffer_num = 0; ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ flush_work(&cam->csi_work_struct); ++ cancel_work_sync(&cam->csi_work_struct); ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[0], ++ cam->rot_vf_bufs_vaddr[0], ++ cam->rot_vf_bufs[0]); ++ cam->rot_vf_bufs_vaddr[0] = NULL; ++ cam->rot_vf_bufs[0] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[1], ++ cam->rot_vf_bufs_vaddr[1], ++ cam->rot_vf_bufs[1]); ++ cam->rot_vf_bufs_vaddr[1] = NULL; ++ cam->rot_vf_bufs[1] = 0; ++ } ++ ++ cam->overlay_active = false; ++ return err; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int bg_overlay_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int bg_overlay_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select bg as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int bg_overlay_sdc_select(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ if (cam) { ++ cam->vf_start_sdc = bg_overlay_start; ++ cam->vf_stop_sdc = bg_overlay_stop; ++ cam->vf_enable_csi = bg_overlay_enable_csi; ++ cam->vf_disable_csi = bg_overlay_disable_csi; ++ cam->overlay_active = false; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(bg_overlay_sdc_select); ++ ++/*! ++ * function to de-select bg as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int bg_overlay_sdc_deselect(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ if (cam) { ++ cam->vf_start_sdc = NULL; ++ cam->vf_stop_sdc = NULL; ++ cam->vf_enable_csi = NULL; ++ cam->vf_disable_csi = NULL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(bg_overlay_sdc_deselect); ++ ++/*! ++ * Init background overlay task. ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int bg_overlay_sdc_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit background overlay task. ++ * ++ * @return Error code indicating success or failure ++ */ ++void __exit bg_overlay_sdc_exit(void) ++{ ++} ++ ++module_init(bg_overlay_sdc_init); ++module_exit(bg_overlay_sdc_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_csi_enc.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_csi_enc.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_csi_enc.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_csi_enc.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,418 @@ ++/* ++ * Copyright 2009-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_csi_enc.c ++ * ++ * @brief CSI Use case for video capture ++ * ++ * @ingroup IPU ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++#ifdef CAMERA_DBG ++ #define CAMERA_TRACE(x) (printk)x ++#else ++ #define CAMERA_TRACE(x) ++#endif ++ ++/* ++ * Function definitions ++ */ ++ ++/*! ++ * csi ENC callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t csi_enc_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = (cam_data *) dev_id; ++ ++ if (cam->enc_callback == NULL) ++ return IRQ_HANDLED; ++ ++ cam->enc_callback(irq, dev_id); ++ return IRQ_HANDLED; ++} ++ ++/*! ++ * CSI ENC enable channel setup function ++ * ++ * @param cam struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_setup(cam_data *cam) ++{ ++ ipu_channel_params_t params; ++ u32 pixel_fmt; ++ int err = 0, sensor_protocol = 0; ++ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ CAMERA_TRACE("In csi_enc_setup\n"); ++ if (!cam) { ++ printk(KERN_ERR "cam private is NULL\n"); ++ return -ENXIO; ++ } ++ ++ memset(¶ms, 0, sizeof(ipu_channel_params_t)); ++ params.csi_mem.csi = cam->csi; ++ ++ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); ++ switch (sensor_protocol) { ++ case IPU_CSI_CLK_MODE_GATED_CLK: ++ case IPU_CSI_CLK_MODE_NONGATED_CLK: ++ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: ++ params.csi_mem.interlaced = false; ++ break; ++ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: ++ params.csi_mem.interlaced = true; ++ break; ++ default: ++ printk(KERN_ERR "sensor protocol unsupported\n"); ++ return -EINVAL; ++ } ++ ++ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) ++ pixel_fmt = IPU_PIX_FMT_YUV420P; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) ++ pixel_fmt = IPU_PIX_FMT_YVU420P; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) ++ pixel_fmt = IPU_PIX_FMT_YUV422P; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) ++ pixel_fmt = IPU_PIX_FMT_UYVY; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) ++ pixel_fmt = IPU_PIX_FMT_YUYV; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) ++ pixel_fmt = IPU_PIX_FMT_NV12; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) ++ pixel_fmt = IPU_PIX_FMT_BGR24; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) ++ pixel_fmt = IPU_PIX_FMT_RGB24; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) ++ pixel_fmt = IPU_PIX_FMT_RGB565; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) ++ pixel_fmt = IPU_PIX_FMT_BGR32; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) ++ pixel_fmt = IPU_PIX_FMT_RGB32; ++ else { ++ printk(KERN_ERR "format not supported\n"); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ params.csi_mem.mipi_en = true; ++ params.csi_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ params.csi_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); ++ if (err != 0) { ++ printk(KERN_ERR "ipu_init_channel %d\n", err); ++ return err; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ pixel_fmt, cam->v2f.fmt.pix.width, ++ cam->v2f.fmt.pix.height, ++ cam->v2f.fmt.pix.bytesperline, ++ IPU_ROTATE_NONE, ++ dummy, dummy, 0, ++ cam->offset.u_offset, ++ cam->offset.v_offset); ++ if (err != 0) { ++ printk(KERN_ERR "CSI_MEM output buffer\n"); ++ return err; ++ } ++ err = ipu_enable_channel(cam->ipu, CSI_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); ++ return err; ++ } ++ ++ return err; ++} ++ ++/*! ++ * function to update physical buffer address for encorder IDMA channel ++ * ++ * @param eba physical buffer address for encorder IDMA channel ++ * @param buffer_num int buffer 0 or buffer 1 ++ * ++ * @return status ++ */ ++static int csi_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba, ++ int *buffer_num) ++{ ++ int err = 0; ++ ++ pr_debug("eba %x\n", eba); ++ err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ *buffer_num, eba); ++ if (err != 0) { ++ ipu_clear_buffer_ready(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ *buffer_num); ++ ++ err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ *buffer_num, eba); ++ if (err != 0) { ++ pr_err("ERROR: v4l2 capture: fail to update " ++ "buf%d\n", *buffer_num); ++ return err; ++ } ++ } ++ ++ ipu_select_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num); ++ ++ *buffer_num = (*buffer_num == 0) ? 1 : 0; ++ ++ return 0; ++} ++ ++/*! ++ * Enable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_enabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n"); ++ ++ cam->dummy_frame.vaddress = dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->dummy_frame.paddress, ++ GFP_DMA | GFP_KERNEL); ++ if (cam->dummy_frame.vaddress == 0) { ++ pr_err("ERROR: v4l2 capture: Allocate dummy frame " ++ "failed.\n"); ++ return -ENOBUFS; ++ } ++ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; ++ cam->dummy_frame.buffer.length = ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); ++ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, ++ csi_enc_callback, 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering rot irq\n"); ++ return err; ++ } ++ ++ err = csi_enc_setup(cam); ++ if (err != 0) { ++ printk(KERN_ERR "csi_enc_setup %d\n", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++/*! ++ * Disable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++static int csi_enc_disabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); ++ ++ ipu_uninit_channel(cam->ipu, CSI_MEM); ++ ++ if (cam->dummy_frame.vaddress != 0) { ++ dma_free_coherent(0, cam->dummy_frame.buffer.length, ++ cam->dummy_frame.vaddress, ++ cam->dummy_frame.paddress); ++ cam->dummy_frame.vaddress = 0; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ return err; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select CSI ENC as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++int csi_enc_select(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ if (cam) { ++ cam->enc_update_eba = csi_enc_eba_update; ++ cam->enc_enable = csi_enc_enabling_tasks; ++ cam->enc_disable = csi_enc_disabling_tasks; ++ cam->enc_enable_csi = csi_enc_enable_csi; ++ cam->enc_disable_csi = csi_enc_disable_csi; ++ } else { ++ err = -EIO; ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(csi_enc_select); ++ ++/*! ++ * function to de-select CSI ENC as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++int csi_enc_deselect(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ if (cam) { ++ cam->enc_update_eba = NULL; ++ cam->enc_enable = NULL; ++ cam->enc_disable = NULL; ++ cam->enc_enable_csi = NULL; ++ cam->enc_disable_csi = NULL; ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(csi_enc_deselect); ++ ++/*! ++ * Init the Encorder channels ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int csi_enc_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit the Encorder channels ++ * ++ */ ++void __exit csi_enc_exit(void) ++{ ++} ++ ++module_init(csi_enc_init); ++module_exit(csi_enc_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("CSI ENC Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_fg_overlay_sdc.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,634 @@ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++/* * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_foreground_sdc.c ++ * ++ * @brief IPU Use case for PRP-VF ++ * ++ * @ingroup IPU ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++#ifdef CAMERA_DBG ++ #define CAMERA_TRACE(x) (printk)x ++#else ++ #define CAMERA_TRACE(x) ++#endif ++ ++static int csi_buffer_num, buffer_num; ++static u32 csi_mem_bufsize; ++static struct ipu_soc *disp_ipu; ++static struct fb_info *fbi; ++static struct fb_var_screeninfo fbvar; ++static u32 vf_out_format; ++static void csi_buf_work_func(struct work_struct *work) ++{ ++ int err = 0; ++ cam_data *cam = ++ container_of(work, struct _cam_data, csi_work_struct); ++ ++ struct ipu_task task; ++ memset(&task, 0, sizeof(task)); ++ ++ if (csi_buffer_num) ++ task.input.paddr = cam->vf_bufs[0]; ++ else ++ task.input.paddr = cam->vf_bufs[1]; ++ task.input.width = cam->crop_current.width; ++ task.input.height = cam->crop_current.height; ++ task.input.format = IPU_PIX_FMT_NV12; ++ ++ if (buffer_num == 0) ++ task.output.paddr = fbi->fix.smem_start + ++ (fbi->fix.line_length * fbvar.yres); ++ else ++ task.output.paddr = fbi->fix.smem_start; ++ task.output.width = cam->win.w.width; ++ task.output.height = cam->win.w.height; ++ task.output.format = vf_out_format; ++ task.output.rotate = cam->rotation; ++again: ++ err = ipu_check_task(&task); ++ if (err != IPU_CHECK_OK) { ++ if (err > IPU_CHECK_ERR_MIN) { ++ if (err == IPU_CHECK_ERR_SPLIT_INPUTW_OVER) { ++ task.input.crop.w -= 8; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_INPUTH_OVER) { ++ task.input.crop.h -= 8; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { ++ task.output.width -= 8; ++ task.output.crop.w = task.output.width; ++ goto again; ++ } ++ if (err == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { ++ task.output.height -= 8; ++ task.output.crop.h = task.output.height; ++ goto again; ++ } ++ printk(KERN_ERR "check ipu taks fail\n"); ++ return; ++ } ++ printk(KERN_ERR "check ipu taks fail\n"); ++ return; ++ } ++ err = ipu_queue_task(&task); ++ if (err < 0) ++ printk(KERN_ERR "queue ipu task error\n"); ++ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num); ++ buffer_num = (buffer_num == 0) ? 1 : 0; ++} ++ ++static void get_disp_ipu(cam_data *cam) ++{ ++ if (cam->output > 2) ++ disp_ipu = ipu_get_soc(1); /* using DISP4 */ ++ else ++ disp_ipu = ipu_get_soc(0); ++} ++ ++/*! ++ * csi ENC callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t csi_enc_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = (cam_data *) dev_id; ++ ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, csi_buffer_num); ++ if ((cam->crop_current.width != cam->win.w.width) || ++ (cam->crop_current.height != cam->win.w.height) || ++ (vf_out_format != IPU_PIX_FMT_NV12) || ++ (cam->rotation >= IPU_ROTATE_VERT_FLIP)) ++ schedule_work(&cam->csi_work_struct); ++ csi_buffer_num = (csi_buffer_num == 0) ? 1 : 0; ++ return IRQ_HANDLED; ++} ++ ++static int csi_enc_setup(cam_data *cam) ++{ ++ ipu_channel_params_t params; ++ int err = 0, sensor_protocol = 0; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ CAMERA_TRACE("In csi_enc_setup\n"); ++ if (!cam) { ++ printk(KERN_ERR "cam private is NULL\n"); ++ return -ENXIO; ++ } ++ ++ memset(¶ms, 0, sizeof(ipu_channel_params_t)); ++ params.csi_mem.csi = cam->csi; ++ ++ sensor_protocol = ipu_csi_get_sensor_protocol(cam->ipu, cam->csi); ++ switch (sensor_protocol) { ++ case IPU_CSI_CLK_MODE_GATED_CLK: ++ case IPU_CSI_CLK_MODE_NONGATED_CLK: ++ case IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR: ++ params.csi_mem.interlaced = false; ++ break; ++ case IPU_CSI_CLK_MODE_CCIR656_INTERLACED: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR: ++ case IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR: ++ params.csi_mem.interlaced = true; ++ break; ++ default: ++ printk(KERN_ERR "sensor protocol unsupported\n"); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ params.csi_mem.mipi_en = true; ++ params.csi_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ params.csi_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } else { ++ params.csi_mem.mipi_en = false; ++ params.csi_mem.mipi_vc = 0; ++ params.csi_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ } ++ csi_mem_bufsize = cam->crop_current.width * ++ cam->crop_current.height * 3/2; ++ cam->vf_bufs_size[0] = PAGE_ALIGN(csi_mem_bufsize); ++ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[0], ++ (dma_addr_t *) & ++ cam->vf_bufs[0], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[0] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_2; ++ } ++ cam->vf_bufs_size[1] = PAGE_ALIGN(csi_mem_bufsize); ++ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[1], ++ (dma_addr_t *) & ++ cam->vf_bufs[1], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[1] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_1; ++ } ++ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); ++ ++ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); ++ if (err != 0) { ++ printk(KERN_ERR "ipu_init_channel %d\n", err); ++ goto out_1; ++ } ++ ++ if ((cam->crop_current.width == cam->win.w.width) && ++ (cam->crop_current.height == cam->win.w.height) && ++ (vf_out_format == IPU_PIX_FMT_NV12) && ++ (cam->rotation < IPU_ROTATE_VERT_FLIP)) { ++ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, ++ IPU_OUTPUT_BUFFER, ++ IPU_PIX_FMT_NV12, ++ cam->crop_current.width, ++ cam->crop_current.height, ++ cam->crop_current.width, IPU_ROTATE_NONE, ++ fbi->fix.smem_start + ++ (fbi->fix.line_length * fbvar.yres), ++ fbi->fix.smem_start, 0, ++ cam->offset.u_offset, cam->offset.u_offset); ++ } else { ++ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, ++ IPU_OUTPUT_BUFFER, ++ IPU_PIX_FMT_NV12, ++ cam->crop_current.width, ++ cam->crop_current.height, ++ cam->crop_current.width, IPU_ROTATE_NONE, ++ cam->vf_bufs[0], cam->vf_bufs[1], 0, ++ cam->offset.u_offset, cam->offset.u_offset); ++ } ++ if (err != 0) { ++ printk(KERN_ERR "CSI_MEM output buffer\n"); ++ goto out_1; ++ } ++ err = ipu_enable_channel(cam->ipu, CSI_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel CSI_MEM\n"); ++ goto out_1; ++ } ++ ++ csi_buffer_num = 0; ++ ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 1); ++ return err; ++out_1: ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++out_2: ++ return err; ++} ++ ++/*! ++ * Enable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int csi_enc_enabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n"); ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, ++ csi_enc_callback, 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering CSI0_OUT_EOF irq\n"); ++ return err; ++ } ++ ++ INIT_WORK(&cam->csi_work_struct, csi_buf_work_func); ++ ++ err = csi_enc_setup(cam); ++ if (err != 0) { ++ printk(KERN_ERR "csi_enc_setup %d\n", err); ++ goto out1; ++ } ++ ++ return err; ++out1: ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++ return err; ++} ++ ++/* ++ * Function definitions ++ */ ++ ++/*! ++ * foreground_start - start the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int foreground_start(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0, i = 0, screen_size; ++ char *base; ++ ++ if (!cam) { ++ printk(KERN_ERR "private is NULL\n"); ++ return -EIO; ++ } ++ ++ if (cam->overlay_active == true) { ++ pr_debug("already started.\n"); ++ return 0; ++ } ++ ++ get_disp_ipu(cam); ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ char *idstr = registered_fb[i]->fix.id; ++ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || ++ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { ++ fbi = registered_fb[i]; ++ break; ++ } ++ } ++ ++ if (fbi == NULL) { ++ printk(KERN_ERR "DISP FG fb not found\n"); ++ return -EPERM; ++ } ++ ++ fbvar = fbi->var; ++ ++ /* Store the overlay frame buffer's original std */ ++ cam->fb_origin_std = fbvar.nonstd; ++ ++ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { ++ /* Use DP to do CSC so that we can get better performance */ ++ vf_out_format = IPU_PIX_FMT_NV12; ++ fbvar.nonstd = vf_out_format; ++ } else { ++ vf_out_format = IPU_PIX_FMT_RGB565; ++ fbvar.nonstd = 0; ++ } ++ ++ fbvar.bits_per_pixel = 16; ++ fbvar.xres = fbvar.xres_virtual = cam->win.w.width; ++ fbvar.yres = cam->win.w.height; ++ fbvar.yres_virtual = cam->win.w.height * 2; ++ fbvar.yoffset = 0; ++ fbvar.vmode &= ~FB_VMODE_YWRAP; ++ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG; ++ fbvar.activate |= FB_ACTIVATE_FORCE; ++ fb_set_var(fbi, &fbvar); ++ ++ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left, ++ cam->win.w.top); ++ ++ /* Fill black color for framebuffer */ ++ base = (char *) fbi->screen_base; ++ screen_size = fbi->var.xres * fbi->var.yres; ++ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { ++ memset(base, 0, screen_size); ++ base += screen_size; ++ for (i = 0; i < screen_size / 2; i++, base++) ++ *base = 0x80; ++ } else { ++ for (i = 0; i < screen_size * 2; i++, base++) ++ *base = 0x00; ++ } ++ ++ console_lock(); ++ fb_blank(fbi, FB_BLANK_UNBLANK); ++ console_unlock(); ++ ++ /* correct display ch buffer address */ ++ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, ++ 0, fbi->fix.smem_start + ++ (fbi->fix.line_length * fbvar.yres)); ++ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, ++ 1, fbi->fix.smem_start); ++ ++ err = csi_enc_enabling_tasks(cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error csi enc enable fail\n"); ++ return err; ++ } ++ ++ cam->overlay_active = true; ++ return err; ++ ++} ++ ++/*! ++ * foreground_stop - stop the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int foreground_stop(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0, i = 0; ++ struct fb_info *fbi = NULL; ++ struct fb_var_screeninfo fbvar; ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (cam->overlay_active == false) ++ return 0; ++ ++ err = ipu_disable_channel(cam->ipu, CSI_MEM, true); ++ ++ ipu_uninit_channel(cam->ipu, CSI_MEM); ++ ++ csi_buffer_num = 0; ++ buffer_num = 0; ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ char *idstr = registered_fb[i]->fix.id; ++ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || ++ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { ++ fbi = registered_fb[i]; ++ break; ++ } ++ } ++ ++ if (fbi == NULL) { ++ printk(KERN_ERR "DISP FG fb not found\n"); ++ return -EPERM; ++ } ++ ++ console_lock(); ++ fb_blank(fbi, FB_BLANK_POWERDOWN); ++ console_unlock(); ++ ++ /* Set the overlay frame buffer std to what it is used to be */ ++ fbvar = fbi->var; ++ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG; ++ fbvar.nonstd = cam->fb_origin_std; ++ fbvar.activate |= FB_ACTIVATE_FORCE; ++ fb_set_var(fbi, &fbvar); ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ flush_work(&cam->csi_work_struct); ++ cancel_work_sync(&cam->csi_work_struct); ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++ ++ cam->overlay_active = false; ++ return err; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int foreground_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int foreground_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select foreground as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int foreground_sdc_select(void *private) ++{ ++ cam_data *cam; ++ int err = 0; ++ if (private) { ++ cam = (cam_data *) private; ++ cam->vf_start_sdc = foreground_start; ++ cam->vf_stop_sdc = foreground_stop; ++ cam->vf_enable_csi = foreground_enable_csi; ++ cam->vf_disable_csi = foreground_disable_csi; ++ cam->overlay_active = false; ++ } else ++ err = -EIO; ++ ++ return err; ++} ++EXPORT_SYMBOL(foreground_sdc_select); ++ ++/*! ++ * function to de-select foreground as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return int ++ */ ++int foreground_sdc_deselect(void *private) ++{ ++ cam_data *cam; ++ ++ if (private) { ++ cam = (cam_data *) private; ++ cam->vf_start_sdc = NULL; ++ cam->vf_stop_sdc = NULL; ++ cam->vf_enable_csi = NULL; ++ cam->vf_disable_csi = NULL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(foreground_sdc_deselect); ++ ++/*! ++ * Init viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int foreground_sdc_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++void __exit foreground_sdc_exit(void) ++{ ++} ++ ++module_init(foreground_sdc_init); ++module_exit(foreground_sdc_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP VF SDC Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_enc.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_enc.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_enc.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_enc.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,595 @@ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_prp_enc.c ++ * ++ * @brief IPU Use case for PRP-ENC ++ * ++ * @ingroup IPU ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++#ifdef CAMERA_DBG ++ #define CAMERA_TRACE(x) (printk)x ++#else ++ #define CAMERA_TRACE(x) ++#endif ++ ++static ipu_rotate_mode_t grotation = IPU_ROTATE_NONE; ++ ++/* ++ * Function definitions ++ */ ++ ++/*! ++ * IPU ENC callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t prp_enc_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = (cam_data *) dev_id; ++ ++ if (cam->enc_callback == NULL) ++ return IRQ_HANDLED; ++ ++ cam->enc_callback(irq, dev_id); ++ ++ return IRQ_HANDLED; ++} ++ ++/*! ++ * PrpENC enable channel setup function ++ * ++ * @param cam struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_enc_setup(cam_data *cam) ++{ ++ ipu_channel_params_t enc; ++ int err = 0; ++ dma_addr_t dummy = cam->dummy_frame.buffer.m.offset; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ CAMERA_TRACE("In prp_enc_setup\n"); ++ if (!cam) { ++ printk(KERN_ERR "cam private is NULL\n"); ++ return -ENXIO; ++ } ++ memset(&enc, 0, sizeof(ipu_channel_params_t)); ++ ++ ipu_csi_get_window_size(cam->ipu, &enc.csi_prp_enc_mem.in_width, ++ &enc.csi_prp_enc_mem.in_height, cam->csi); ++ ++ enc.csi_prp_enc_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; ++ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.width; ++ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.height; ++ enc.csi_prp_enc_mem.csi = cam->csi; ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ enc.csi_prp_enc_mem.out_width = cam->v2f.fmt.pix.height; ++ enc.csi_prp_enc_mem.out_height = cam->v2f.fmt.pix.width; ++ } ++ ++ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV420P; ++ pr_info("YUV420\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YVU420) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YVU420P; ++ pr_info("YVU420\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUV422P; ++ pr_info("YUV422P\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_YUYV; ++ pr_info("YUYV\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_UYVY; ++ pr_info("UYVY\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_NV12; ++ pr_info("NV12\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR24; ++ pr_info("BGR24\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB24; ++ pr_info("RGB24\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB565; ++ pr_info("RGB565\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_BGR32; ++ pr_info("BGR32\n"); ++ } else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) { ++ enc.csi_prp_enc_mem.out_pixel_fmt = IPU_PIX_FMT_RGB32; ++ pr_info("RGB32\n"); ++ } else { ++ printk(KERN_ERR "format not supported\n"); ++ return -EINVAL; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ enc.csi_prp_enc_mem.mipi_en = true; ++ enc.csi_prp_enc_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ enc.csi_prp_enc_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ enc.csi_prp_enc_mem.mipi_en = false; ++ enc.csi_prp_enc_mem.mipi_vc = 0; ++ enc.csi_prp_enc_mem.mipi_id = 0; ++ } ++ } else { ++ enc.csi_prp_enc_mem.mipi_en = false; ++ enc.csi_prp_enc_mem.mipi_vc = 0; ++ enc.csi_prp_enc_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ err = ipu_init_channel(cam->ipu, CSI_PRP_ENC_MEM, &enc); ++ if (err != 0) { ++ printk(KERN_ERR "ipu_init_channel %d\n", err); ++ return err; ++ } ++ ++ grotation = cam->rotation; ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ if (cam->rot_enc_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->rot_enc_buf_size[0], ++ cam->rot_enc_bufs_vaddr[0], ++ cam->rot_enc_bufs[0]); ++ } ++ if (cam->rot_enc_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_enc_buf_size[1], ++ cam->rot_enc_bufs_vaddr[1], ++ cam->rot_enc_bufs[1]); ++ } ++ cam->rot_enc_buf_size[0] = ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); ++ cam->rot_enc_bufs_vaddr[0] = ++ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[0], ++ &cam->rot_enc_bufs[0], ++ GFP_DMA | GFP_KERNEL); ++ if (!cam->rot_enc_bufs_vaddr[0]) { ++ printk(KERN_ERR "alloc enc_bufs0\n"); ++ return -ENOMEM; ++ } ++ cam->rot_enc_buf_size[1] = ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); ++ cam->rot_enc_bufs_vaddr[1] = ++ (void *)dma_alloc_coherent(0, cam->rot_enc_buf_size[1], ++ &cam->rot_enc_bufs[1], ++ GFP_DMA | GFP_KERNEL); ++ if (!cam->rot_enc_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_enc_buf_size[0], ++ cam->rot_enc_bufs_vaddr[0], ++ cam->rot_enc_bufs[0]); ++ cam->rot_enc_bufs_vaddr[0] = NULL; ++ cam->rot_enc_bufs[0] = 0; ++ printk(KERN_ERR "alloc enc_bufs1\n"); ++ return -ENOMEM; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ enc.csi_prp_enc_mem.out_pixel_fmt, ++ enc.csi_prp_enc_mem.out_width, ++ enc.csi_prp_enc_mem.out_height, ++ enc.csi_prp_enc_mem.out_width, ++ IPU_ROTATE_NONE, ++ cam->rot_enc_bufs[0], ++ cam->rot_enc_bufs[1], 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "CSI_PRP_ENC_MEM err\n"); ++ return err; ++ } ++ ++ err = ipu_init_channel(cam->ipu, MEM_ROT_ENC_MEM, NULL); ++ if (err != 0) { ++ printk(KERN_ERR "MEM_ROT_ENC_MEM channel err\n"); ++ return err; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, ++ IPU_INPUT_BUFFER, ++ enc.csi_prp_enc_mem.out_pixel_fmt, ++ enc.csi_prp_enc_mem.out_width, ++ enc.csi_prp_enc_mem.out_height, ++ enc.csi_prp_enc_mem.out_width, ++ cam->rotation, ++ cam->rot_enc_bufs[0], ++ cam->rot_enc_bufs[1], 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "MEM_ROT_ENC_MEM input buffer\n"); ++ return err; ++ } ++ ++ err = ++ ipu_init_channel_buffer(cam->ipu, MEM_ROT_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ enc.csi_prp_enc_mem.out_pixel_fmt, ++ enc.csi_prp_enc_mem.out_height, ++ enc.csi_prp_enc_mem.out_width, ++ cam->v2f.fmt.pix.bytesperline / ++ bytes_per_pixel(enc.csi_prp_enc_mem. ++ out_pixel_fmt), ++ IPU_ROTATE_NONE, ++ dummy, dummy, 0, ++ cam->offset.u_offset, ++ cam->offset.v_offset); ++ if (err != 0) { ++ printk(KERN_ERR "MEM_ROT_ENC_MEM output buffer\n"); ++ return err; ++ } ++ ++ err = ipu_link_channels(cam->ipu, ++ CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); ++ if (err < 0) { ++ printk(KERN_ERR ++ "link CSI_PRP_ENC_MEM-MEM_ROT_ENC_MEM\n"); ++ return err; ++ } ++ ++ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); ++ return err; ++ } ++ err = ipu_enable_channel(cam->ipu, MEM_ROT_ENC_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel MEM_ROT_ENC_MEM\n"); ++ return err; ++ } ++ ++ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, 0); ++ ipu_select_buffer(cam->ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, 1); ++ } else { ++ err = ++ ipu_init_channel_buffer(cam->ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ enc.csi_prp_enc_mem.out_pixel_fmt, ++ enc.csi_prp_enc_mem.out_width, ++ enc.csi_prp_enc_mem.out_height, ++ cam->v2f.fmt.pix.bytesperline / ++ bytes_per_pixel(enc.csi_prp_enc_mem. ++ out_pixel_fmt), ++ cam->rotation, ++ dummy, dummy, 0, ++ cam->offset.u_offset, ++ cam->offset.v_offset); ++ if (err != 0) { ++ printk(KERN_ERR "CSI_PRP_ENC_MEM output buffer\n"); ++ return err; ++ } ++ err = ipu_enable_channel(cam->ipu, CSI_PRP_ENC_MEM); ++ if (err < 0) { ++ printk(KERN_ERR "ipu_enable_channel CSI_PRP_ENC_MEM\n"); ++ return err; ++ } ++ } ++ ++ return err; ++} ++ ++/*! ++ * function to update physical buffer address for encorder IDMA channel ++ * ++ * @param eba physical buffer address for encorder IDMA channel ++ * @param buffer_num int buffer 0 or buffer 1 ++ * ++ * @return status ++ */ ++static int prp_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba, ++ int *buffer_num) ++{ ++ int err = 0; ++ ++ pr_debug("eba %x\n", eba); ++ if (grotation >= IPU_ROTATE_90_RIGHT) { ++ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM, ++ IPU_OUTPUT_BUFFER, *buffer_num, ++ eba); ++ } else { ++ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, *buffer_num, ++ eba); ++ } ++ if (err != 0) { ++ if (grotation >= IPU_ROTATE_90_RIGHT) { ++ ipu_clear_buffer_ready(ipu, MEM_ROT_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ *buffer_num); ++ err = ipu_update_channel_buffer(ipu, MEM_ROT_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ *buffer_num, ++ eba); ++ } else { ++ ipu_clear_buffer_ready(ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ *buffer_num); ++ err = ipu_update_channel_buffer(ipu, CSI_PRP_ENC_MEM, ++ IPU_OUTPUT_BUFFER, ++ *buffer_num, ++ eba); ++ } ++ ++ if (err != 0) { ++ pr_err("ERROR: v4l2 capture: fail to update " ++ "buf%d\n", *buffer_num); ++ return err; ++ } ++ } ++ ++ if (grotation >= IPU_ROTATE_90_RIGHT) { ++ ipu_select_buffer(ipu, MEM_ROT_ENC_MEM, IPU_OUTPUT_BUFFER, ++ *buffer_num); ++ } else { ++ ipu_select_buffer(ipu, CSI_PRP_ENC_MEM, IPU_OUTPUT_BUFFER, ++ *buffer_num); ++ } ++ ++ *buffer_num = (*buffer_num == 0) ? 1 : 0; ++ return 0; ++} ++ ++/*! ++ * Enable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_enc_enabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ CAMERA_TRACE("IPU:In prp_enc_enabling_tasks\n"); ++ ++ cam->dummy_frame.vaddress = dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->dummy_frame.paddress, ++ GFP_DMA | GFP_KERNEL); ++ if (cam->dummy_frame.vaddress == 0) { ++ pr_err("ERROR: v4l2 capture: Allocate dummy frame " ++ "failed.\n"); ++ return -ENOBUFS; ++ } ++ cam->dummy_frame.buffer.type = V4L2_BUF_TYPE_PRIVATE; ++ cam->dummy_frame.buffer.length = ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); ++ cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress; ++ ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, ++ prp_enc_callback, 0, "Mxc Camera", cam); ++ } else { ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, ++ prp_enc_callback, 0, "Mxc Camera", cam); ++ } ++ if (err != 0) { ++ printk(KERN_ERR "Error registering rot irq\n"); ++ return err; ++ } ++ ++ err = prp_enc_setup(cam); ++ if (err != 0) { ++ printk(KERN_ERR "prp_enc_setup %d\n", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++/*! ++ * Disable encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++static int prp_enc_disabling_tasks(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_ROT_OUT_EOF, cam); ++ ipu_unlink_channels(cam->ipu, CSI_PRP_ENC_MEM, MEM_ROT_ENC_MEM); ++ } ++ ++ err = ipu_disable_channel(cam->ipu, CSI_PRP_ENC_MEM, true); ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) ++ err |= ipu_disable_channel(cam->ipu, MEM_ROT_ENC_MEM, true); ++ ++ ipu_uninit_channel(cam->ipu, CSI_PRP_ENC_MEM); ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) ++ ipu_uninit_channel(cam->ipu, MEM_ROT_ENC_MEM); ++ ++ if (cam->dummy_frame.vaddress != 0) { ++ dma_free_coherent(0, cam->dummy_frame.buffer.length, ++ cam->dummy_frame.vaddress, ++ cam->dummy_frame.paddress); ++ cam->dummy_frame.vaddress = 0; ++ } ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ return err; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_enc_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_enc_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ if (cam->rotation < IPU_ROTATE_90_RIGHT) ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_ENC_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select PRP-ENC as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++int prp_enc_select(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ if (cam) { ++ cam->enc_update_eba = prp_enc_eba_update; ++ cam->enc_enable = prp_enc_enabling_tasks; ++ cam->enc_disable = prp_enc_disabling_tasks; ++ cam->enc_enable_csi = prp_enc_enable_csi; ++ cam->enc_disable_csi = prp_enc_disable_csi; ++ } else { ++ err = -EIO; ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(prp_enc_select); ++ ++/*! ++ * function to de-select PRP-ENC as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return int ++ */ ++int prp_enc_deselect(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ if (cam) { ++ cam->enc_update_eba = NULL; ++ cam->enc_enable = NULL; ++ cam->enc_disable = NULL; ++ cam->enc_enable_csi = NULL; ++ cam->enc_disable_csi = NULL; ++ if (cam->rot_enc_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->rot_enc_buf_size[0], ++ cam->rot_enc_bufs_vaddr[0], ++ cam->rot_enc_bufs[0]); ++ cam->rot_enc_bufs_vaddr[0] = NULL; ++ cam->rot_enc_bufs[0] = 0; ++ } ++ if (cam->rot_enc_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_enc_buf_size[1], ++ cam->rot_enc_bufs_vaddr[1], ++ cam->rot_enc_bufs[1]); ++ cam->rot_enc_bufs_vaddr[1] = NULL; ++ cam->rot_enc_bufs[1] = 0; ++ } ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(prp_enc_deselect); ++ ++/*! ++ * Init the Encorder channels ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int prp_enc_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit the Encorder channels ++ * ++ */ ++void __exit prp_enc_exit(void) ++{ ++} ++ ++module_init(prp_enc_init); ++module_exit(prp_enc_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP ENC Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_sw.h linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_sw.h +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_sw.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_sw.h 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_prp_sw.h ++ * ++ * @brief This file contains the IPU PRP use case driver header. ++ * ++ * @ingroup IPU ++ */ ++ ++#ifndef _INCLUDE_IPU__PRP_SW_H_ ++#define _INCLUDE_IPU__PRP_SW_H_ ++ ++int csi_enc_select(void *private); ++int csi_enc_deselect(void *private); ++int prp_enc_select(void *private); ++int prp_enc_deselect(void *private); ++#ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++int prp_vf_sdc_select(void *private); ++int prp_vf_sdc_deselect(void *private); ++int prp_vf_sdc_select_bg(void *private); ++int prp_vf_sdc_deselect_bg(void *private); ++#else ++int foreground_sdc_select(void *private); ++int foreground_sdc_deselect(void *private); ++int bg_overlay_sdc_select(void *private); ++int bg_overlay_sdc_deselect(void *private); ++#endif ++int prp_still_select(void *private); ++int prp_still_deselect(void *private); ++ ++#endif +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc_bg.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,521 @@ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_prp_vf_sdc_bg.c ++ * ++ * @brief IPU Use case for PRP-VF back-ground ++ * ++ * @ingroup IPU ++ */ ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++static int buffer_num; ++static int buffer_ready; ++static struct ipu_soc *disp_ipu; ++ ++static void get_disp_ipu(cam_data *cam) ++{ ++ if (cam->output > 2) ++ disp_ipu = ipu_get_soc(1); /* using DISP4 */ ++ else ++ disp_ipu = ipu_get_soc(0); ++} ++ ++/* ++ * Function definitions ++ */ ++ ++/*! ++ * SDC V-Sync callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = dev_id; ++ if (buffer_ready > 0) { ++ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, 0); ++ buffer_ready--; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/*! ++ * VF EOF callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = dev_id; ++ pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num); ++ ++ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_INPUT_BUFFER, buffer_num); ++ buffer_num = (buffer_num == 0) ? 1 : 0; ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, buffer_num); ++ buffer_ready++; ++ return IRQ_HANDLED; ++} ++ ++/*! ++ * prpvf_start - start the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int prpvf_start(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ipu_channel_params_t vf; ++ u32 format; ++ u32 offset; ++ u32 bpp, size = 3; ++ int err = 0; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (!cam) { ++ printk(KERN_ERR "private is NULL\n"); ++ return -EIO; ++ } ++ ++ if (cam->overlay_active == true) { ++ pr_debug("already start.\n"); ++ return 0; ++ } ++ ++ get_disp_ipu(cam); ++ ++ format = cam->v4l2_fb.fmt.pixelformat; ++ if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) { ++ bpp = 3, size = 3; ++ pr_info("BGR24\n"); ++ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_RGB565) { ++ bpp = 2, size = 2; ++ pr_info("RGB565\n"); ++ } else if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR32) { ++ bpp = 4, size = 4; ++ pr_info("BGR32\n"); ++ } else { ++ printk(KERN_ERR ++ "unsupported fix format from the framebuffer.\n"); ++ return -EINVAL; ++ } ++ ++ offset = cam->v4l2_fb.fmt.bytesperline * cam->win.w.top + ++ size * cam->win.w.left; ++ ++ if (cam->v4l2_fb.base == 0) ++ printk(KERN_ERR "invalid frame buffer address.\n"); ++ else ++ offset += (u32) cam->v4l2_fb.base; ++ ++ memset(&vf, 0, sizeof(ipu_channel_params_t)); ++ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width, ++ &vf.csi_prp_vf_mem.in_height, cam->csi); ++ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; ++ vf.csi_prp_vf_mem.out_width = cam->win.w.width; ++ vf.csi_prp_vf_mem.out_height = cam->win.w.height; ++ vf.csi_prp_vf_mem.csi = cam->csi; ++ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { ++ vf.csi_prp_vf_mem.out_width = cam->win.w.height; ++ vf.csi_prp_vf_mem.out_height = cam->win.w.width; ++ } ++ vf.csi_prp_vf_mem.out_pixel_fmt = format; ++ size = cam->win.w.width * cam->win.w.height * size; ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ vf.csi_prp_vf_mem.mipi_en = true; ++ vf.csi_prp_vf_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ vf.csi_prp_vf_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ vf.csi_prp_vf_mem.mipi_en = false; ++ vf.csi_prp_vf_mem.mipi_vc = 0; ++ vf.csi_prp_vf_mem.mipi_id = 0; ++ } ++ } else { ++ vf.csi_prp_vf_mem.mipi_en = false; ++ vf.csi_prp_vf_mem.mipi_vc = 0; ++ vf.csi_prp_vf_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); ++ if (err != 0) ++ goto out_4; ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); ++ } ++ cam->vf_bufs_size[0] = PAGE_ALIGN(size); ++ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[0], ++ &cam->vf_bufs[0], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[0] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_3; ++ } ++ cam->vf_bufs_size[1] = PAGE_ALIGN(size); ++ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[1], ++ &cam->vf_bufs[1], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[1] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_3; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ format, vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ IPU_ROTATE_NONE, ++ cam->vf_bufs[0], ++ cam->vf_bufs[1], ++ 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n"); ++ goto out_3; ++ } ++ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL); ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n"); ++ goto out_3; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_INPUT_BUFFER, ++ format, vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ cam->vf_rotation, ++ cam->vf_bufs[0], ++ cam->vf_bufs[1], ++ 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n"); ++ goto out_2; ++ } ++ ++ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ format, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ cam->overlay_fb->var.xres * bpp, ++ IPU_ROTATE_NONE, ++ offset, 0, 0, 0, 0); ++ ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); ++ goto out_2; ++ } ++ } else { ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ format, ++ vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ cam->overlay_fb->var.xres * bpp, ++ IPU_ROTATE_NONE, ++ offset, 0, 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); ++ goto out_2; ++ } ++ } ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, ++ prpvf_vf_eof_callback, ++ 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR ++ "Error registering IPU_IRQ_PRP_VF_OUT_EOF irq.\n"); ++ goto out_2; ++ } ++ ++ ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END); ++ err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END, ++ prpvf_sdc_vsync_callback, ++ 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n"); ++ goto out_1; ++ } ++ ++ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); ++ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM); ++ ++ buffer_num = 0; ++ buffer_ready = 0; ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0); ++ ++ cam->overlay_active = true; ++ return err; ++ ++out_1: ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL); ++out_2: ++ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); ++out_3: ++ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); ++out_4: ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[0], ++ cam->rot_vf_bufs_vaddr[0], ++ cam->rot_vf_bufs[0]); ++ cam->rot_vf_bufs_vaddr[0] = NULL; ++ cam->rot_vf_bufs[0] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[1], ++ cam->rot_vf_bufs_vaddr[1], ++ cam->rot_vf_bufs[1]); ++ cam->rot_vf_bufs_vaddr[1] = NULL; ++ cam->rot_vf_bufs[1] = 0; ++ } ++ return err; ++} ++ ++/*! ++ * prpvf_stop - stop the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int prpvf_stop(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (cam->overlay_active == false) ++ return 0; ++ ++ ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam); ++ ++ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true); ++ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true); ++ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); ++ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[0], ++ cam->rot_vf_bufs_vaddr[0], ++ cam->rot_vf_bufs[0]); ++ cam->rot_vf_bufs_vaddr[0] = NULL; ++ cam->rot_vf_bufs[0] = 0; ++ } ++ if (cam->rot_vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->rot_vf_buf_size[1], ++ cam->rot_vf_bufs_vaddr[1], ++ cam->rot_vf_bufs[1]); ++ cam->rot_vf_bufs_vaddr[1] = NULL; ++ cam->rot_vf_bufs[1] = 0; ++ } ++ ++ buffer_num = 0; ++ buffer_ready = 0; ++ cam->overlay_active = false; ++ return 0; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_vf_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_vf_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select PRP-VF as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int prp_vf_sdc_select_bg(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ if (cam) { ++ cam->vf_start_sdc = prpvf_start; ++ cam->vf_stop_sdc = prpvf_stop; ++ cam->vf_enable_csi = prp_vf_enable_csi; ++ cam->vf_disable_csi = prp_vf_disable_csi; ++ cam->overlay_active = false; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(prp_vf_sdc_select_bg); ++ ++/*! ++ * function to de-select PRP-VF as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int prp_vf_sdc_deselect_bg(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ if (cam) { ++ cam->vf_start_sdc = NULL; ++ cam->vf_stop_sdc = NULL; ++ cam->vf_enable_csi = NULL; ++ cam->vf_disable_csi = NULL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(prp_vf_sdc_deselect_bg); ++ ++/*! ++ * Init viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int prp_vf_sdc_init_bg(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++void __exit prp_vf_sdc_exit_bg(void) ++{ ++} ++ ++module_init(prp_vf_sdc_init_bg); ++module_exit(prp_vf_sdc_exit_bg); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP VF SDC Backgroud Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_prp_vf_sdc.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,582 @@ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++/* * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_prp_vf_sdc.c ++ * ++ * @brief IPU Use case for PRP-VF ++ * ++ * @ingroup IPU ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++static int buffer_num; ++static struct ipu_soc *disp_ipu; ++ ++static void get_disp_ipu(cam_data *cam) ++{ ++ if (cam->output > 2) ++ disp_ipu = ipu_get_soc(1); /* using DISP4 */ ++ else ++ disp_ipu = ipu_get_soc(0); ++} ++ ++static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = dev_id; ++ pr_debug("buffer_num %d\n", buffer_num); ++ ++ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { ++ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, ++ IPU_INPUT_BUFFER, buffer_num); ++ buffer_num = (buffer_num == 0) ? 1 : 0; ++ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, buffer_num); ++ } else { ++ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, ++ IPU_INPUT_BUFFER, buffer_num); ++ buffer_num = (buffer_num == 0) ? 1 : 0; ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, buffer_num); ++ } ++ return IRQ_HANDLED; ++} ++/* ++ * Function definitions ++ */ ++ ++/*! ++ * prpvf_start - start the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int prpvf_start(void *private) ++{ ++ struct fb_var_screeninfo fbvar; ++ struct fb_info *fbi = NULL; ++ cam_data *cam = (cam_data *) private; ++ ipu_channel_params_t vf; ++ u32 vf_out_format = 0; ++ u32 size = 2, temp = 0; ++ int err = 0, i = 0; ++ short *tmp, color; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (!cam) { ++ printk(KERN_ERR "private is NULL\n"); ++ return -EIO; ++ } ++ ++ if (cam->overlay_active == true) { ++ pr_debug("already started.\n"); ++ return 0; ++ } ++ ++ get_disp_ipu(cam); ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ char *idstr = registered_fb[i]->fix.id; ++ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || ++ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { ++ fbi = registered_fb[i]; ++ break; ++ } ++ } ++ ++ if (fbi == NULL) { ++ printk(KERN_ERR "DISP FG fb not found\n"); ++ return -EPERM; ++ } ++ ++ fbvar = fbi->var; ++ ++ /* Store the overlay frame buffer's original std */ ++ cam->fb_origin_std = fbvar.nonstd; ++ ++ if (cam->devtype == IMX5_V4L2 || cam->devtype == IMX6_V4L2) { ++ /* Use DP to do CSC so that we can get better performance */ ++ vf_out_format = IPU_PIX_FMT_UYVY; ++ fbvar.nonstd = vf_out_format; ++ color = 0x80; ++ } else { ++ vf_out_format = IPU_PIX_FMT_RGB565; ++ fbvar.nonstd = 0; ++ color = 0x0; ++ } ++ ++ fbvar.bits_per_pixel = 16; ++ fbvar.xres = fbvar.xres_virtual = cam->win.w.width; ++ fbvar.yres = cam->win.w.height; ++ fbvar.yres_virtual = cam->win.w.height * 2; ++ fbvar.yoffset = 0; ++ fbvar.accel_flags = FB_ACCEL_DOUBLE_FLAG; ++ fbvar.activate |= FB_ACTIVATE_FORCE; ++ fb_set_var(fbi, &fbvar); ++ ++ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left, ++ cam->win.w.top); ++ ++ /* Fill black color for framebuffer */ ++ tmp = (short *) fbi->screen_base; ++ for (i = 0; i < (fbi->fix.line_length * fbi->var.yres)/2; ++ i++, tmp++) ++ *tmp = color; ++ ++ console_lock(); ++ fb_blank(fbi, FB_BLANK_UNBLANK); ++ console_unlock(); ++ ++ /* correct display ch buffer address */ ++ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, ++ 0, fbi->fix.smem_start + ++ (fbi->fix.line_length * fbvar.yres)); ++ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, ++ 1, fbi->fix.smem_start); ++ ++ memset(&vf, 0, sizeof(ipu_channel_params_t)); ++ ipu_csi_get_window_size(cam->ipu, &vf.csi_prp_vf_mem.in_width, ++ &vf.csi_prp_vf_mem.in_height, cam->csi); ++ vf.csi_prp_vf_mem.in_pixel_fmt = IPU_PIX_FMT_UYVY; ++ vf.csi_prp_vf_mem.out_width = cam->win.w.width; ++ vf.csi_prp_vf_mem.out_height = cam->win.w.height; ++ vf.csi_prp_vf_mem.csi = cam->csi; ++ if (cam->vf_rotation >= IPU_ROTATE_90_RIGHT) { ++ vf.csi_prp_vf_mem.out_width = cam->win.w.height; ++ vf.csi_prp_vf_mem.out_height = cam->win.w.width; ++ } ++ vf.csi_prp_vf_mem.out_pixel_fmt = vf_out_format; ++ size = cam->win.w.width * cam->win.w.height * size; ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) { ++ vf.csi_prp_vf_mem.mipi_en = true; ++ vf.csi_prp_vf_mem.mipi_vc = ++ mipi_csi2_get_virtual_channel(mipi_csi2_info); ++ vf.csi_prp_vf_mem.mipi_id = ++ mipi_csi2_get_datatype(mipi_csi2_info); ++ ++ mipi_csi2_pixelclk_enable(mipi_csi2_info); ++ } else { ++ vf.csi_prp_vf_mem.mipi_en = false; ++ vf.csi_prp_vf_mem.mipi_vc = 0; ++ vf.csi_prp_vf_mem.mipi_id = 0; ++ } ++ } else { ++ vf.csi_prp_vf_mem.mipi_en = false; ++ vf.csi_prp_vf_mem.mipi_vc = 0; ++ vf.csi_prp_vf_mem.mipi_id = 0; ++ } ++ } ++#endif ++ ++ err = ipu_init_channel(cam->ipu, CSI_PRP_VF_MEM, &vf); ++ if (err != 0) ++ goto out_5; ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ } ++ cam->vf_bufs_size[0] = PAGE_ALIGN(size); ++ cam->vf_bufs_vaddr[0] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[0], ++ (dma_addr_t *) & ++ cam->vf_bufs[0], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[0] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_4; ++ } ++ cam->vf_bufs_size[1] = PAGE_ALIGN(size); ++ cam->vf_bufs_vaddr[1] = (void *)dma_alloc_coherent(0, ++ cam->vf_bufs_size[1], ++ (dma_addr_t *) & ++ cam->vf_bufs[1], ++ GFP_DMA | ++ GFP_KERNEL); ++ if (cam->vf_bufs_vaddr[1] == NULL) { ++ printk(KERN_ERR "Error to allocate vf buffer\n"); ++ err = -ENOMEM; ++ goto out_3; ++ } ++ pr_debug("vf_bufs %x %x\n", cam->vf_bufs[0], cam->vf_bufs[1]); ++ ++ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { ++ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ vf_out_format, ++ vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ IPU_ROTATE_NONE, ++ cam->vf_bufs[0], cam->vf_bufs[1], ++ 0, 0, 0); ++ if (err != 0) ++ goto out_3; ++ ++ err = ipu_init_channel(cam->ipu, MEM_ROT_VF_MEM, NULL); ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM channel\n"); ++ goto out_3; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_INPUT_BUFFER, ++ vf_out_format, ++ vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ cam->vf_rotation, ++ cam->vf_bufs[0], ++ cam->vf_bufs[1], ++ 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM input buffer\n"); ++ goto out_2; ++ } ++ ++ if (cam->vf_rotation < IPU_ROTATE_90_RIGHT) { ++ temp = vf.csi_prp_vf_mem.out_width; ++ vf.csi_prp_vf_mem.out_width = ++ vf.csi_prp_vf_mem.out_height; ++ vf.csi_prp_vf_mem.out_height = temp; ++ } ++ ++ err = ipu_init_channel_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ vf_out_format, ++ vf.csi_prp_vf_mem.out_height, ++ vf.csi_prp_vf_mem.out_width, ++ vf.csi_prp_vf_mem.out_height, ++ IPU_ROTATE_NONE, ++ fbi->fix.smem_start + ++ (fbi->fix.line_length * ++ fbi->var.yres), ++ fbi->fix.smem_start, 0, 0, 0); ++ ++ if (err != 0) { ++ printk(KERN_ERR "Error MEM_ROT_VF_MEM output buffer\n"); ++ goto out_2; ++ } ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, ++ prpvf_rot_eof_callback, ++ 0, "Mxc Camera", cam); ++ if (err < 0) { ++ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n"); ++ goto out_2; ++ } ++ ++ err = ipu_link_channels(cam->ipu, ++ CSI_PRP_VF_MEM, MEM_ROT_VF_MEM); ++ if (err < 0) { ++ printk(KERN_ERR ++ "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n"); ++ goto out_1; ++ } ++ ++ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); ++ ipu_enable_channel(cam->ipu, MEM_ROT_VF_MEM); ++ ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, 0); ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, 1); ++ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, ++ IPU_OUTPUT_BUFFER, 0); ++ } else { ++ err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, ++ vf_out_format, cam->win.w.width, ++ cam->win.w.height, ++ cam->win.w.width, ++ cam->vf_rotation, ++ fbi->fix.smem_start + ++ (fbi->fix.line_length * ++ fbi->var.yres), ++ fbi->fix.smem_start, 0, 0, 0); ++ if (err != 0) { ++ printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n"); ++ goto out_4; ++ } ++ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, ++ prpvf_rot_eof_callback, ++ 0, "Mxc Camera", cam); ++ if (err < 0) { ++ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n"); ++ goto out_4; ++ } ++ ++ ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM); ++ ++ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, ++ IPU_OUTPUT_BUFFER, 0); ++ } ++ ++ cam->overlay_active = true; ++ return err; ++ ++out_1: ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL); ++out_2: ++ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) ++ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); ++out_3: ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++out_4: ++ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); ++out_5: ++ return err; ++} ++ ++/*! ++ * prpvf_stop - stop the vf task ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ */ ++static int prpvf_stop(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0, i = 0; ++ struct fb_info *fbi = NULL; ++ struct fb_var_screeninfo fbvar; ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ void *mipi_csi2_info; ++ int ipu_id; ++ int csi_id; ++#endif ++ ++ if (cam->overlay_active == false) ++ return 0; ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ char *idstr = registered_fb[i]->fix.id; ++ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) || ++ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) { ++ fbi = registered_fb[i]; ++ break; ++ } ++ } ++ ++ if (fbi == NULL) { ++ printk(KERN_ERR "DISP FG fb not found\n"); ++ return -EPERM; ++ } ++ ++ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { ++ ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM); ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam); ++ } ++ buffer_num = 0; ++ ++ ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true); ++ ++ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) { ++ ipu_disable_channel(cam->ipu, MEM_ROT_VF_MEM, true); ++ ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM); ++ } ++ ipu_uninit_channel(cam->ipu, CSI_PRP_VF_MEM); ++ ++ console_lock(); ++ fb_blank(fbi, FB_BLANK_POWERDOWN); ++ console_unlock(); ++ ++ /* Set the overlay frame buffer std to what it is used to be */ ++ fbvar = fbi->var; ++ fbvar.accel_flags = FB_ACCEL_TRIPLE_FLAG; ++ fbvar.nonstd = cam->fb_origin_std; ++ fbvar.activate |= FB_ACTIVATE_FORCE; ++ fb_set_var(fbi, &fbvar); ++ ++#ifdef CONFIG_MXC_MIPI_CSI2 ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ if (mipi_csi2_info) { ++ if (mipi_csi2_get_status(mipi_csi2_info)) { ++ ipu_id = mipi_csi2_get_bind_ipu(mipi_csi2_info); ++ csi_id = mipi_csi2_get_bind_csi(mipi_csi2_info); ++ ++ if (cam->ipu == ipu_get_soc(ipu_id) ++ && cam->csi == csi_id) ++ mipi_csi2_pixelclk_disable(mipi_csi2_info); ++ } ++ } ++#endif ++ ++ if (cam->vf_bufs_vaddr[0]) { ++ dma_free_coherent(0, cam->vf_bufs_size[0], ++ cam->vf_bufs_vaddr[0], ++ (dma_addr_t) cam->vf_bufs[0]); ++ cam->vf_bufs_vaddr[0] = NULL; ++ cam->vf_bufs[0] = 0; ++ } ++ if (cam->vf_bufs_vaddr[1]) { ++ dma_free_coherent(0, cam->vf_bufs_size[1], ++ cam->vf_bufs_vaddr[1], ++ (dma_addr_t) cam->vf_bufs[1]); ++ cam->vf_bufs_vaddr[1] = NULL; ++ cam->vf_bufs[1] = 0; ++ } ++ ++ cam->overlay_active = false; ++ return err; ++} ++ ++/*! ++ * Enable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_vf_enable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ return ipu_enable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * Disable csi ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_vf_disable_csi(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ /* free csi eof irq firstly. ++ * when disable csi, wait for idmac eof. ++ * it requests eof irq again */ ++ if (cam->vf_rotation < IPU_ROTATE_VERT_FLIP) ++ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam); ++ ++ return ipu_disable_csi(cam->ipu, cam->csi); ++} ++ ++/*! ++ * function to select PRP-VF as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return status ++ */ ++int prp_vf_sdc_select(void *private) ++{ ++ cam_data *cam; ++ int err = 0; ++ if (private) { ++ cam = (cam_data *) private; ++ cam->vf_start_sdc = prpvf_start; ++ cam->vf_stop_sdc = prpvf_stop; ++ cam->vf_enable_csi = prp_vf_enable_csi; ++ cam->vf_disable_csi = prp_vf_disable_csi; ++ cam->overlay_active = false; ++ } else ++ err = -EIO; ++ ++ return err; ++} ++EXPORT_SYMBOL(prp_vf_sdc_select); ++ ++/*! ++ * function to de-select PRP-VF as the working path ++ * ++ * @param private cam_data * mxc v4l2 main structure ++ * ++ * @return int ++ */ ++int prp_vf_sdc_deselect(void *private) ++{ ++ cam_data *cam; ++ ++ if (private) { ++ cam = (cam_data *) private; ++ cam->vf_start_sdc = NULL; ++ cam->vf_stop_sdc = NULL; ++ cam->vf_enable_csi = NULL; ++ cam->vf_disable_csi = NULL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(prp_vf_sdc_deselect); ++ ++/*! ++ * Init viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int prp_vf_sdc_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit viewfinder task. ++ * ++ * @return Error code indicating success or failure ++ */ ++void __exit prp_vf_sdc_exit(void) ++{ ++} ++ ++module_init(prp_vf_sdc_init); ++module_exit(prp_vf_sdc_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP VF SDC Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ipu_still.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_still.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ipu_still.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ipu_still.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,268 @@ ++/* ++ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file ipu_still.c ++ * ++ * @brief IPU Use case for still image capture ++ * ++ * @ingroup IPU ++ */ ++ ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++static int callback_eof_flag; ++#ifndef CONFIG_MXC_IPU_V1 ++static int buffer_num; ++#endif ++ ++#ifdef CONFIG_MXC_IPU_V1 ++static int callback_flag; ++/* ++ * Function definitions ++ */ ++/*! ++ * CSI EOF callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t prp_csi_eof_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = devid; ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ callback_flag%2 ? 1 : 0); ++ if (callback_flag == 0) ++ ipu_enable_channel(cam->ipu, CSI_MEM); ++ ++ callback_flag++; ++ return IRQ_HANDLED; ++} ++#endif ++ ++/*! ++ * CSI callback function. ++ * ++ * @param irq int irq line ++ * @param dev_id void * device id ++ * ++ * @return status IRQ_HANDLED for handled ++ */ ++static irqreturn_t prp_still_callback(int irq, void *dev_id) ++{ ++ cam_data *cam = (cam_data *) dev_id; ++ ++ callback_eof_flag++; ++ if (callback_eof_flag < 5) { ++#ifndef CONFIG_MXC_IPU_V1 ++ buffer_num = (buffer_num == 0) ? 1 : 0; ++ ipu_select_buffer(cam->ipu, CSI_MEM, ++ IPU_OUTPUT_BUFFER, buffer_num); ++#endif ++ } else { ++ cam->still_counter++; ++ wake_up_interruptible(&cam->still_queue); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/*! ++ * start csi->mem task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_still_start(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ u32 pixel_fmt; ++ int err; ++ ipu_channel_params_t params; ++ ++ if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) ++ pixel_fmt = IPU_PIX_FMT_YUV420P; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) ++ pixel_fmt = IPU_PIX_FMT_NV12; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) ++ pixel_fmt = IPU_PIX_FMT_YUV422P; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY) ++ pixel_fmt = IPU_PIX_FMT_UYVY; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) ++ pixel_fmt = IPU_PIX_FMT_YUYV; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) ++ pixel_fmt = IPU_PIX_FMT_BGR24; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) ++ pixel_fmt = IPU_PIX_FMT_RGB24; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) ++ pixel_fmt = IPU_PIX_FMT_RGB565; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_BGR32) ++ pixel_fmt = IPU_PIX_FMT_BGR32; ++ else if (cam->v2f.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB32) ++ pixel_fmt = IPU_PIX_FMT_RGB32; ++ else { ++ printk(KERN_ERR "format not supported\n"); ++ return -EINVAL; ++ } ++ ++ memset(¶ms, 0, sizeof(params)); ++ err = ipu_init_channel(cam->ipu, CSI_MEM, ¶ms); ++ if (err != 0) ++ return err; ++ ++ err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, ++ pixel_fmt, cam->v2f.fmt.pix.width, ++ cam->v2f.fmt.pix.height, ++ cam->v2f.fmt.pix.width, IPU_ROTATE_NONE, ++ cam->still_buf[0], cam->still_buf[1], 0, ++ 0, 0); ++ if (err != 0) ++ return err; ++ ++#ifdef CONFIG_MXC_IPU_V1 ++ ipu_clear_irq(IPU_IRQ_SENSOR_OUT_EOF); ++ err = ipu_request_irq(IPU_IRQ_SENSOR_OUT_EOF, prp_still_callback, ++ 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering irq.\n"); ++ return err; ++ } ++ callback_flag = 0; ++ callback_eof_flag = 0; ++ ipu_clear_irq(IPU_IRQ_SENSOR_EOF); ++ err = ipu_request_irq(IPU_IRQ_SENSOR_EOF, prp_csi_eof_callback, ++ 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error IPU_IRQ_SENSOR_EOF\n"); ++ return err; ++ } ++#else ++ callback_eof_flag = 0; ++ buffer_num = 0; ++ ++ ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF); ++ err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, ++ prp_still_callback, ++ 0, "Mxc Camera", cam); ++ if (err != 0) { ++ printk(KERN_ERR "Error registering irq.\n"); ++ return err; ++ } ++ ++ ipu_select_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER, 0); ++ ipu_enable_channel(cam->ipu, CSI_MEM); ++ ipu_enable_csi(cam->ipu, cam->csi); ++#endif ++ ++ return err; ++} ++ ++/*! ++ * stop csi->mem encoder task ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++static int prp_still_stop(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++#ifdef CONFIG_MXC_IPU_V1 ++ ipu_free_irq(IPU_IRQ_SENSOR_EOF, NULL); ++ ipu_free_irq(IPU_IRQ_SENSOR_OUT_EOF, cam); ++#else ++ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam); ++#endif ++ ++ ipu_disable_csi(cam->ipu, cam->csi); ++ ipu_disable_channel(cam->ipu, CSI_MEM, true); ++ ipu_uninit_channel(cam->ipu, CSI_MEM); ++ ++ return err; ++} ++ ++/*! ++ * function to select CSI_MEM as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++int prp_still_select(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ ++ if (cam) { ++ cam->csi_start = prp_still_start; ++ cam->csi_stop = prp_still_stop; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(prp_still_select); ++ ++/*! ++ * function to de-select CSI_MEM as the working path ++ * ++ * @param private struct cam_data * mxc capture instance ++ * ++ * @return status ++ */ ++int prp_still_deselect(void *private) ++{ ++ cam_data *cam = (cam_data *) private; ++ int err = 0; ++ ++ err = prp_still_stop(cam); ++ ++ if (cam) { ++ cam->csi_start = NULL; ++ cam->csi_stop = NULL; ++ } ++ ++ return err; ++} ++EXPORT_SYMBOL(prp_still_deselect); ++ ++/*! ++ * Init the Encorder channels ++ * ++ * @return Error code indicating success or failure ++ */ ++__init int prp_still_init(void) ++{ ++ return 0; ++} ++ ++/*! ++ * Deinit the Encorder channels ++ * ++ */ ++void __exit prp_still_exit(void) ++{ ++} ++ ++module_init(prp_still_init); ++module_exit(prp_still_exit); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("IPU PRP STILL IMAGE Driver"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/Kconfig linux-imx6-3.14/drivers/media/platform/mxc/capture/Kconfig +--- linux-3.14.14/drivers/media/platform/mxc/capture/Kconfig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/Kconfig 2014-12-08 00:31:53.252418001 -0600 +@@ -0,0 +1,86 @@ ++if VIDEO_MXC_CAPTURE ++ ++menu "MXC Camera/V4L2 PRP Features support" ++config VIDEO_MXC_IPU_CAMERA ++ bool ++ depends on VIDEO_MXC_CAPTURE && MXC_IPU ++ default y ++ ++config VIDEO_MXC_CSI_CAMERA ++ tristate "CSI camera support" ++ depends on VIDEO_MXC_CAPTURE && VIDEO_V4L2 ++ ---help--- ++ This is the video4linux2 capture driver based on CSI module. ++ ++config MXC_CAMERA_OV5640 ++ tristate "OmniVision ov5640 camera support" ++ depends on !VIDEO_MXC_EMMA_CAMERA && I2C ++ ---help--- ++ If you plan to use the ov5640 Camera with your MXC system, say Y here. ++ ++config MXC_CAMERA_OV5642 ++ tristate "OmniVision ov5642 camera support" ++ depends on !VIDEO_MXC_EMMA_CAMERA && I2C ++ ---help--- ++ If you plan to use the ov5642 Camera with your MXC system, say Y here. ++ ++config MXC_CAMERA_OV5640_MIPI ++ tristate "OmniVision ov5640 camera support using mipi" ++ depends on !VIDEO_MXC_EMMA_CAMERA && I2C ++ ---help--- ++ If you plan to use the ov5640 Camera with mipi interface in your MXC system, say Y here. ++ ++config MXC_TVIN_ADV7180 ++ tristate "Analog Device adv7180 TV Decoder Input support" ++ depends on !VIDEO_MXC_EMMA_CAMERA && I2C ++ ---help--- ++ If you plan to use the adv7180 video decoder with your MXC system, say Y here. ++ ++choice ++ prompt "Select Overlay Rounting" ++ default MXC_IPU_DEVICE_QUEUE_SDC ++ depends on VIDEO_MXC_IPU_CAMERA && FB_MXC_SYNC_PANEL ++ ++config MXC_IPU_DEVICE_QUEUE_SDC ++ tristate "Queue ipu device for overlay library" ++ depends on VIDEO_MXC_IPU_CAMERA ++ ---help--- ++ Use case CSI->MEM->IPU DEVICE->SDC: ++ Images from sensor will be frist recieved in memory,then ++ queue to ipu device for processing if needed, and displaying ++ it on synchronous display with SDC use case. ++ ++config MXC_IPU_PRP_VF_SDC ++ bool "Pre-Processor VF SDC library" ++ depends on VIDEO_MXC_IPU_CAMERA ++ ---help--- ++ Use case PRP_VF_SDC: ++ Preprocessing image from smart sensor for viewfinder and ++ displaying it on synchronous display with SDC use case. ++ If SDC BG is selected, Rotation will not be supported. ++ CSI -> IC (PRP VF) -> MEM ++ MEM -> IC (ROT) -> MEM ++ MEM -> SDC (FG/BG) ++ ++endchoice ++ ++config MXC_IPU_PRP_ENC ++ tristate "Pre-processor Encoder library" ++ depends on VIDEO_MXC_IPU_CAMERA ++ default y ++ ---help--- ++ Use case PRP_ENC: ++ Preprocessing image from smart sensor for encoder. ++ CSI -> IC (PRP ENC) -> MEM ++ ++config MXC_IPU_CSI_ENC ++ tristate "IPU CSI Encoder library" ++ depends on VIDEO_MXC_IPU_CAMERA ++ default y ++ ---help--- ++ Use case IPU_CSI_ENC: ++ Get raw image with CSI from smart sensor for encoder. ++ CSI -> MEM ++endmenu ++ ++endif +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/Makefile linux-imx6-3.14/drivers/media/platform/mxc/capture/Makefile +--- linux-3.14.14/drivers/media/platform/mxc/capture/Makefile 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/Makefile 2014-12-08 00:31:53.252418001 -0600 +@@ -0,0 +1,21 @@ ++obj-$(CONFIG_VIDEO_MXC_CSI_CAMERA) += fsl_csi.o csi_v4l2_capture.o ++ ++ifeq ($(CONFIG_VIDEO_MXC_IPU_CAMERA),y) ++ obj-$(CONFIG_VIDEO_MXC_CAPTURE) += mxc_v4l2_capture.o ++ obj-$(CONFIG_MXC_IPU_PRP_VF_SDC) += ipu_prp_vf_sdc.o ipu_prp_vf_sdc_bg.o ++ obj-$(CONFIG_MXC_IPU_DEVICE_QUEUE_SDC) += ipu_fg_overlay_sdc.o ipu_bg_overlay_sdc.o ++ obj-$(CONFIG_MXC_IPU_PRP_ENC) += ipu_prp_enc.o ipu_still.o ++ obj-$(CONFIG_MXC_IPU_CSI_ENC) += ipu_csi_enc.o ipu_still.o ++endif ++ ++ov5640_camera-objs := ov5640.o ++obj-$(CONFIG_MXC_CAMERA_OV5640) += ov5640_camera.o ++ ++ov5642_camera-objs := ov5642.o ++obj-$(CONFIG_MXC_CAMERA_OV5642) += ov5642_camera.o ++ ++ov5640_camera_mipi-objs := ov5640_mipi.o ++obj-$(CONFIG_MXC_CAMERA_OV5640_MIPI) += ov5640_camera_mipi.o ++ ++adv7180_tvin-objs := adv7180.o ++obj-$(CONFIG_MXC_TVIN_ADV7180) += adv7180_tvin.o +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c linux-imx6-3.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,3102 @@ ++/* ++ * Copyright 2004-2014 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @file drivers/media/video/mxc/capture/mxc_v4l2_capture.c ++ * ++ * @brief Mxc Video For Linux 2 driver ++ * ++ * @ingroup MXC_V4L2_CAPTURE ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++#include "ipu_prp_sw.h" ++ ++#define init_MUTEX(sem) sema_init(sem, 1) ++ ++static struct platform_device_id imx_v4l2_devtype[] = { ++ { ++ .name = "v4l2-capture-imx5", ++ .driver_data = IMX5_V4L2, ++ }, { ++ .name = "v4l2-capture-imx6", ++ .driver_data = IMX6_V4L2, ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(platform, imx_v4l2_devtype); ++ ++static const struct of_device_id mxc_v4l2_dt_ids[] = { ++ { ++ .compatible = "fsl,imx6q-v4l2-capture", ++ .data = &imx_v4l2_devtype[IMX6_V4L2], ++ }, { ++ /* sentinel */ ++ } ++}; ++MODULE_DEVICE_TABLE(of, mxc_v4l2_dt_ids); ++ ++static int video_nr = -1; ++ ++/*! This data is used for the output to the display. */ ++#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 6 ++#define MXC_V4L2_CAPTURE_NUM_INPUTS 2 ++static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = { ++ { ++ .index = 0, ++ .name = "DISP3 BG", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++ { ++ .index = 1, ++ .name = "DISP3 BG - DI1", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++ { ++ .index = 2, ++ .name = "DISP3 FG", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++ { ++ .index = 3, ++ .name = "DISP4 BG", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++ { ++ .index = 4, ++ .name = "DISP4 BG - DI1", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++ { ++ .index = 5, ++ .name = "DISP4 FG", ++ .type = V4L2_OUTPUT_TYPE_ANALOG, ++ .audioset = 0, ++ .modulator = 0, ++ .std = V4L2_STD_UNKNOWN, ++ }, ++}; ++ ++static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = { ++ { ++ .index = 0, ++ .name = "CSI IC MEM", ++ .type = V4L2_INPUT_TYPE_CAMERA, ++ .audioset = 0, ++ .tuner = 0, ++ .std = V4L2_STD_UNKNOWN, ++ .status = 0, ++ }, ++ { ++ .index = 1, ++ .name = "CSI MEM", ++ .type = V4L2_INPUT_TYPE_CAMERA, ++ .audioset = 0, ++ .tuner = 0, ++ .std = V4L2_STD_UNKNOWN, ++ .status = V4L2_IN_ST_NO_POWER, ++ }, ++}; ++ ++/*! List of TV input video formats supported. The video formats is corresponding ++ * to the v4l2_id in video_fmt_t. ++ * Currently, only PAL and NTSC is supported. Needs to be expanded in the ++ * future. ++ */ ++typedef enum { ++ TV_NTSC = 0, /*!< Locked on (M) NTSC video signal. */ ++ TV_PAL, /*!< (B, G, H, I, N)PAL video signal. */ ++ TV_NOT_LOCKED, /*!< Not locked on a signal. */ ++} video_fmt_idx; ++ ++/*! Number of video standards supported (including 'not locked' signal). */ ++#define TV_STD_MAX (TV_NOT_LOCKED + 1) ++ ++/*! Video format structure. */ ++typedef struct { ++ int v4l2_id; /*!< Video for linux ID. */ ++ char name[16]; /*!< Name (e.g., "NTSC", "PAL", etc.) */ ++ u16 raw_width; /*!< Raw width. */ ++ u16 raw_height; /*!< Raw height. */ ++ u16 active_width; /*!< Active width. */ ++ u16 active_height; /*!< Active height. */ ++ u16 active_top; /*!< Active top. */ ++ u16 active_left; /*!< Active left. */ ++} video_fmt_t; ++ ++/*! ++ * Description of video formats supported. ++ * ++ * PAL: raw=720x625, active=720x576. ++ * NTSC: raw=720x525, active=720x480. ++ */ ++static video_fmt_t video_fmts[] = { ++ { /*! NTSC */ ++ .v4l2_id = V4L2_STD_NTSC, ++ .name = "NTSC", ++ .raw_width = 720, /* SENS_FRM_WIDTH */ ++ .raw_height = 525, /* SENS_FRM_HEIGHT */ ++ .active_width = 720, /* ACT_FRM_WIDTH */ ++ .active_height = 480, /* ACT_FRM_HEIGHT */ ++ .active_top = 13, ++ .active_left = 0, ++ }, ++ { /*! (B, G, H, I, N) PAL */ ++ .v4l2_id = V4L2_STD_PAL, ++ .name = "PAL", ++ .raw_width = 720, ++ .raw_height = 625, ++ .active_width = 720, ++ .active_height = 576, ++ .active_top = 0, ++ .active_left = 0, ++ }, ++ { /*! Unlocked standard */ ++ .v4l2_id = V4L2_STD_ALL, ++ .name = "Autodetect", ++ .raw_width = 720, ++ .raw_height = 625, ++ .active_width = 720, ++ .active_height = 576, ++ .active_top = 0, ++ .active_left = 0, ++ }, ++}; ++ ++/*!* Standard index of TV. */ ++static video_fmt_idx video_index = TV_NOT_LOCKED; ++ ++static int mxc_v4l2_master_attach(struct v4l2_int_device *slave); ++static void mxc_v4l2_master_detach(struct v4l2_int_device *slave); ++static int start_preview(cam_data *cam); ++static int stop_preview(cam_data *cam); ++ ++/*! Information about this driver. */ ++static struct v4l2_int_master mxc_v4l2_master = { ++ .attach = mxc_v4l2_master_attach, ++ .detach = mxc_v4l2_master_detach, ++}; ++ ++/*************************************************************************** ++ * Functions for handling Frame buffers. ++ **************************************************************************/ ++ ++/*! ++ * Free frame buffers ++ * ++ * @param cam Structure cam_data * ++ * ++ * @return status 0 success. ++ */ ++static int mxc_free_frame_buf(cam_data *cam) ++{ ++ int i; ++ ++ pr_debug("MVC: In mxc_free_frame_buf\n"); ++ ++ for (i = 0; i < FRAME_NUM; i++) { ++ if (cam->frame[i].vaddress != 0) { ++ dma_free_coherent(0, cam->frame[i].buffer.length, ++ cam->frame[i].vaddress, ++ cam->frame[i].paddress); ++ cam->frame[i].vaddress = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Allocate frame buffers ++ * ++ * @param cam Structure cam_data* ++ * @param count int number of buffer need to allocated ++ * ++ * @return status -0 Successfully allocated a buffer, -ENOBUFS failed. ++ */ ++static int mxc_allocate_frame_buf(cam_data *cam, int count) ++{ ++ int i; ++ ++ pr_debug("In MVC:mxc_allocate_frame_buf - size=%d\n", ++ cam->v2f.fmt.pix.sizeimage); ++ ++ for (i = 0; i < count; i++) { ++ cam->frame[i].vaddress = ++ dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->frame[i].paddress, ++ GFP_DMA | GFP_KERNEL); ++ if (cam->frame[i].vaddress == 0) { ++ pr_err("ERROR: v4l2 capture: " ++ "mxc_allocate_frame_buf failed.\n"); ++ mxc_free_frame_buf(cam); ++ return -ENOBUFS; ++ } ++ cam->frame[i].buffer.index = i; ++ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ cam->frame[i].buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ cam->frame[i].buffer.length = ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage); ++ cam->frame[i].buffer.memory = V4L2_MEMORY_MMAP; ++ cam->frame[i].buffer.m.offset = cam->frame[i].paddress; ++ cam->frame[i].index = i; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Free frame buffers status ++ * ++ * @param cam Structure cam_data * ++ * ++ * @return none ++ */ ++static void mxc_free_frames(cam_data *cam) ++{ ++ int i; ++ ++ pr_debug("In MVC:mxc_free_frames\n"); ++ ++ for (i = 0; i < FRAME_NUM; i++) ++ cam->frame[i].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ ++ cam->enc_counter = 0; ++ INIT_LIST_HEAD(&cam->ready_q); ++ INIT_LIST_HEAD(&cam->working_q); ++ INIT_LIST_HEAD(&cam->done_q); ++} ++ ++/*! ++ * Return the buffer status ++ * ++ * @param cam Structure cam_data * ++ * @param buf Structure v4l2_buffer * ++ * ++ * @return status 0 success, EINVAL failed. ++ */ ++static int mxc_v4l2_buffer_status(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ pr_debug("In MVC:mxc_v4l2_buffer_status\n"); ++ ++ if (buf->index < 0 || buf->index >= FRAME_NUM) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l2_buffer_status buffers " ++ "not allocated\n"); ++ return -EINVAL; ++ } ++ ++ memcpy(buf, &(cam->frame[buf->index].buffer), sizeof(*buf)); ++ return 0; ++} ++ ++static int mxc_v4l2_release_bufs(cam_data *cam) ++{ ++ pr_debug("In MVC:mxc_v4l2_release_bufs\n"); ++ return 0; ++} ++ ++static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ pr_debug("In MVC:mxc_v4l2_prepare_bufs\n"); ++ ++ if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length < ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers " ++ "not allocated,index=%d, length=%d\n", buf->index, ++ buf->length); ++ return -EINVAL; ++ } ++ ++ cam->frame[buf->index].buffer.index = buf->index; ++ cam->frame[buf->index].buffer.flags = V4L2_BUF_FLAG_MAPPED; ++ cam->frame[buf->index].buffer.length = buf->length; ++ cam->frame[buf->index].buffer.m.offset = cam->frame[buf->index].paddress ++ = buf->m.offset; ++ cam->frame[buf->index].buffer.type = buf->type; ++ cam->frame[buf->index].buffer.memory = V4L2_MEMORY_USERPTR; ++ cam->frame[buf->index].index = buf->index; ++ ++ return 0; ++} ++ ++/*************************************************************************** ++ * Functions for handling the video stream. ++ **************************************************************************/ ++ ++/*! ++ * Indicates whether the palette is supported. ++ * ++ * @param palette V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32 ++ * ++ * @return 0 if failed ++ */ ++static inline int valid_mode(u32 palette) ++{ ++ return ((palette == V4L2_PIX_FMT_RGB565) || ++ (palette == V4L2_PIX_FMT_BGR24) || ++ (palette == V4L2_PIX_FMT_RGB24) || ++ (palette == V4L2_PIX_FMT_BGR32) || ++ (palette == V4L2_PIX_FMT_RGB32) || ++ (palette == V4L2_PIX_FMT_YUV422P) || ++ (palette == V4L2_PIX_FMT_UYVY) || ++ (palette == V4L2_PIX_FMT_YUYV) || ++ (palette == V4L2_PIX_FMT_YUV420) || ++ (palette == V4L2_PIX_FMT_YVU420) || ++ (palette == V4L2_PIX_FMT_NV12)); ++} ++ ++/*! ++ * Start the encoder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int mxc_streamon(cam_data *cam) ++{ ++ struct mxc_v4l_frame *frame; ++ unsigned long lock_flags; ++ int err = 0; ++ ++ pr_debug("In MVC:mxc_streamon\n"); ++ ++ if (NULL == cam) { ++ pr_err("ERROR! cam parameter is NULL\n"); ++ return -1; ++ } ++ ++ if (cam->capture_on) { ++ pr_err("ERROR: v4l2 capture: Capture stream has been turned " ++ " on\n"); ++ return -1; ++ } ++ ++ if (list_empty(&cam->ready_q)) { ++ pr_err("ERROR: v4l2 capture: mxc_streamon buffer has not been " ++ "queued yet\n"); ++ return -EINVAL; ++ } ++ if (cam->enc_update_eba && ++ cam->ready_q.prev == cam->ready_q.next) { ++ pr_err("ERROR: v4l2 capture: mxc_streamon buffer need " ++ "ping pong at least two buffers\n"); ++ return -EINVAL; ++ } ++ ++ cam->capture_pid = current->pid; ++ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ if (cam->enc_enable) { ++ err = cam->enc_enable(cam); ++ if (err != 0) ++ return err; ++ } ++ ++ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); ++ cam->ping_pong_csi = 0; ++ cam->local_buf_num = 0; ++ if (cam->enc_update_eba) { ++ frame = ++ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->ready_q.next); ++ list_add_tail(&frame->queue, &cam->working_q); ++ frame->ipu_buf_num = cam->ping_pong_csi; ++ err = cam->enc_update_eba(cam->ipu, frame->buffer.m.offset, ++ &cam->ping_pong_csi); ++ ++ frame = ++ list_entry(cam->ready_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->ready_q.next); ++ list_add_tail(&frame->queue, &cam->working_q); ++ frame->ipu_buf_num = cam->ping_pong_csi; ++ err |= cam->enc_update_eba(cam->ipu, frame->buffer.m.offset, ++ &cam->ping_pong_csi); ++ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); ++ } else { ++ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); ++ return -EINVAL; ++ } ++ ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ ++ if (cam->enc_enable_csi) { ++ err = cam->enc_enable_csi(cam); ++ if (err != 0) ++ return err; ++ } ++ ++ cam->capture_on = true; ++ ++ return err; ++} ++ ++/*! ++ * Shut down the encoder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int mxc_streamoff(cam_data *cam) ++{ ++ int err = 0; ++ ++ pr_debug("In MVC:mxc_streamoff\n"); ++ ++ if (cam->capture_on == false) ++ return 0; ++ ++ /* For both CSI--MEM and CSI--IC--MEM ++ * 1. wait for idmac eof ++ * 2. disable csi first ++ * 3. disable idmac ++ * 4. disable smfc (CSI--MEM channel) ++ */ ++ if (mxc_capture_inputs[cam->current_input].name != NULL) { ++ if (cam->enc_disable_csi) { ++ err = cam->enc_disable_csi(cam); ++ if (err != 0) ++ return err; ++ } ++ if (cam->enc_disable) { ++ err = cam->enc_disable(cam); ++ if (err != 0) ++ return err; ++ } ++ } ++ ++ mxc_free_frames(cam); ++ mxc_capture_inputs[cam->current_input].status |= V4L2_IN_ST_NO_POWER; ++ cam->capture_on = false; ++ return err; ++} ++ ++/*! ++ * Valid and adjust the overlay window size, position ++ * ++ * @param cam structure cam_data * ++ * @param win struct v4l2_window * ++ * ++ * @return 0 ++ */ ++static int verify_preview(cam_data *cam, struct v4l2_window *win) ++{ ++ int i = 0, width_bound = 0, height_bound = 0; ++ int *width, *height; ++ unsigned int ipu_ch = CHAN_NONE; ++ struct fb_info *bg_fbi = NULL, *fbi = NULL; ++ bool foregound_fb = false; ++ mm_segment_t old_fs; ++ ++ pr_debug("In MVC: verify_preview\n"); ++ ++ do { ++ fbi = (struct fb_info *)registered_fb[i]; ++ if (fbi == NULL) { ++ pr_err("ERROR: verify_preview frame buffer NULL.\n"); ++ return -1; ++ } ++ ++ /* Which DI supports 2 layers? */ ++ if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) && ++ (cam->output < 3)) || ++ ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) && ++ (cam->output >= 3))) { ++ if (fbi->fbops->fb_ioctl) { ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN, ++ (unsigned long)&ipu_ch); ++ set_fs(old_fs); ++ } ++ if (ipu_ch == MEM_BG_SYNC) { ++ bg_fbi = fbi; ++ pr_debug("Found background frame buffer.\n"); ++ } ++ } ++ ++ /* Found the frame buffer to preview on. */ ++ if (strcmp(fbi->fix.id, ++ mxc_capture_outputs[cam->output].name) == 0) { ++ if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) && ++ (cam->output < 3)) || ++ ((strcmp(fbi->fix.id, "DISP4 FG") == 0) && ++ (cam->output >= 3))) ++ foregound_fb = true; ++ ++ cam->overlay_fb = fbi; ++ break; ++ } ++ } while (++i < FB_MAX); ++ ++ if (foregound_fb) { ++ width_bound = bg_fbi->var.xres; ++ height_bound = bg_fbi->var.yres; ++ ++ if (win->w.width + win->w.left > bg_fbi->var.xres || ++ win->w.height + win->w.top > bg_fbi->var.yres) { ++ pr_err("ERROR: FG window position exceeds.\n"); ++ return -1; ++ } ++ } else { ++ /* 4 bytes alignment for BG */ ++ width_bound = cam->overlay_fb->var.xres; ++ height_bound = cam->overlay_fb->var.yres; ++ ++ if (cam->overlay_fb->var.bits_per_pixel == 24) ++ win->w.left -= win->w.left % 4; ++ else if (cam->overlay_fb->var.bits_per_pixel == 16) ++ win->w.left -= win->w.left % 2; ++ ++ if (win->w.width + win->w.left > cam->overlay_fb->var.xres) ++ win->w.width = cam->overlay_fb->var.xres - win->w.left; ++ if (win->w.height + win->w.top > cam->overlay_fb->var.yres) ++ win->w.height = cam->overlay_fb->var.yres - win->w.top; ++ } ++ ++ /* stride line limitation */ ++ win->w.height -= win->w.height % 8; ++ win->w.width -= win->w.width % 8; ++ ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ height = &win->w.width; ++ width = &win->w.height; ++ } else { ++ width = &win->w.width; ++ height = &win->w.height; ++ } ++ ++ if (*width == 0 || *height == 0) { ++ pr_err("ERROR: v4l2 capture: width or height" ++ " too small.\n"); ++ return -EINVAL; ++ } ++ ++ if ((cam->crop_bounds.width / *width > 8) || ++ ((cam->crop_bounds.width / *width == 8) && ++ (cam->crop_bounds.width % *width))) { ++ *width = cam->crop_bounds.width / 8; ++ if (*width % 8) ++ *width += 8 - *width % 8; ++ if (*width + win->w.left > width_bound) { ++ pr_err("ERROR: v4l2 capture: width exceeds " ++ "resize limit.\n"); ++ return -1; ++ } ++ pr_err("ERROR: v4l2 capture: width exceeds limit. " ++ "Resize to %d.\n", ++ *width); ++ } ++ ++ if ((cam->crop_bounds.height / *height > 8) || ++ ((cam->crop_bounds.height / *height == 8) && ++ (cam->crop_bounds.height % *height))) { ++ *height = cam->crop_bounds.height / 8; ++ if (*height % 8) ++ *height += 8 - *height % 8; ++ if (*height + win->w.top > height_bound) { ++ pr_err("ERROR: v4l2 capture: height exceeds " ++ "resize limit.\n"); ++ return -1; ++ } ++ pr_err("ERROR: v4l2 capture: height exceeds limit " ++ "resize to %d.\n", ++ *height); ++ } ++ ++ return 0; ++} ++ ++/*! ++ * start the viewfinder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int start_preview(cam_data *cam) ++{ ++ int err = 0; ++ ++ pr_debug("MVC: start_preview\n"); ++ ++ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) ++ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++ err = prp_vf_sdc_select(cam); ++ #else ++ err = foreground_sdc_select(cam); ++ #endif ++ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) ++ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++ err = prp_vf_sdc_select_bg(cam); ++ #else ++ err = bg_overlay_sdc_select(cam); ++ #endif ++ if (err != 0) ++ return err; ++ ++ if (cam->vf_start_sdc) { ++ err = cam->vf_start_sdc(cam); ++ if (err != 0) ++ return err; ++ } ++ ++ if (cam->vf_enable_csi) ++ err = cam->vf_enable_csi(cam); ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, ++ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", ++ __func__, ++ cam->crop_bounds.width, cam->crop_bounds.height); ++ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", ++ __func__, ++ cam->crop_defrect.width, cam->crop_defrect.height); ++ pr_debug("End of %s: crop_current widthxheight %d x %d\n", ++ __func__, ++ cam->crop_current.width, cam->crop_current.height); ++ ++ return err; ++} ++ ++/*! ++ * shut down the viewfinder job ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int stop_preview(cam_data *cam) ++{ ++ int err = 0; ++ ++ if (cam->vf_disable_csi) { ++ err = cam->vf_disable_csi(cam); ++ if (err != 0) ++ return err; ++ } ++ ++ if (cam->vf_stop_sdc) { ++ err = cam->vf_stop_sdc(cam); ++ if (err != 0) ++ return err; ++ } ++ ++ if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) ++ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++ err = prp_vf_sdc_deselect(cam); ++ #else ++ err = foreground_sdc_deselect(cam); ++ #endif ++ else if (cam->v4l2_fb.flags == V4L2_FBUF_FLAG_PRIMARY) ++ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++ err = prp_vf_sdc_deselect_bg(cam); ++ #else ++ err = bg_overlay_sdc_deselect(cam); ++ #endif ++ ++ return err; ++} ++ ++/*************************************************************************** ++ * VIDIOC Functions. ++ **************************************************************************/ ++ ++/*! ++ * V4L2 - mxc_v4l2_g_fmt function ++ * ++ * @param cam structure cam_data * ++ * ++ * @param f structure v4l2_format * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_g_fmt(cam_data *cam, struct v4l2_format *f) ++{ ++ int retval = 0; ++ ++ pr_debug("In MVC: mxc_v4l2_g_fmt type=%d\n", f->type); ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ++ f->fmt.pix = cam->v2f.fmt.pix; ++ break; ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); ++ f->fmt.win = cam->win; ++ break; ++ default: ++ pr_debug(" type is invalid\n"); ++ retval = -EINVAL; ++ } ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, ++ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", ++ __func__, ++ cam->crop_bounds.width, cam->crop_bounds.height); ++ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", ++ __func__, ++ cam->crop_defrect.width, cam->crop_defrect.height); ++ pr_debug("End of %s: crop_current widthxheight %d x %d\n", ++ __func__, ++ cam->crop_current.width, cam->crop_current.height); ++ ++ return retval; ++} ++ ++/*! ++ * V4L2 - mxc_v4l2_s_fmt function ++ * ++ * @param cam structure cam_data * ++ * ++ * @param f structure v4l2_format * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_s_fmt(cam_data *cam, struct v4l2_format *f) ++{ ++ int retval = 0; ++ int size = 0; ++ int bytesperline = 0; ++ int *width, *height; ++ ++ pr_debug("In MVC: mxc_v4l2_s_fmt\n"); ++ ++ switch (f->type) { ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); ++ if (!valid_mode(f->fmt.pix.pixelformat)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l2_s_fmt: format " ++ "not supported\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Force the capture window resolution to be crop bounds ++ * for CSI MEM input mode. ++ */ ++ if (strcmp(mxc_capture_inputs[cam->current_input].name, ++ "CSI MEM") == 0) { ++ f->fmt.pix.width = cam->crop_current.width; ++ f->fmt.pix.height = cam->crop_current.height; ++ } ++ ++ if (cam->rotation >= IPU_ROTATE_90_RIGHT) { ++ height = &f->fmt.pix.width; ++ width = &f->fmt.pix.height; ++ } else { ++ width = &f->fmt.pix.width; ++ height = &f->fmt.pix.height; ++ } ++ ++ /* stride line limitation */ ++ *width -= *width % 8; ++ *height -= *height % 8; ++ ++ if (*width == 0 || *height == 0) { ++ pr_err("ERROR: v4l2 capture: width or height" ++ " too small.\n"); ++ return -EINVAL; ++ } ++ ++ if ((cam->crop_current.width / *width > 8) || ++ ((cam->crop_current.width / *width == 8) && ++ (cam->crop_current.width % *width))) { ++ *width = cam->crop_current.width / 8; ++ if (*width % 8) ++ *width += 8 - *width % 8; ++ pr_err("ERROR: v4l2 capture: width exceeds limit " ++ "resize to %d.\n", ++ *width); ++ } ++ ++ if ((cam->crop_current.height / *height > 8) || ++ ((cam->crop_current.height / *height == 8) && ++ (cam->crop_current.height % *height))) { ++ *height = cam->crop_current.height / 8; ++ if (*height % 8) ++ *height += 8 - *height % 8; ++ pr_err("ERROR: v4l2 capture: height exceeds limit " ++ "resize to %d.\n", ++ *height); ++ } ++ ++ switch (f->fmt.pix.pixelformat) { ++ case V4L2_PIX_FMT_RGB565: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ bytesperline = f->fmt.pix.width * 2; ++ break; ++ case V4L2_PIX_FMT_BGR24: ++ size = f->fmt.pix.width * f->fmt.pix.height * 3; ++ bytesperline = f->fmt.pix.width * 3; ++ break; ++ case V4L2_PIX_FMT_RGB24: ++ size = f->fmt.pix.width * f->fmt.pix.height * 3; ++ bytesperline = f->fmt.pix.width * 3; ++ break; ++ case V4L2_PIX_FMT_BGR32: ++ size = f->fmt.pix.width * f->fmt.pix.height * 4; ++ bytesperline = f->fmt.pix.width * 4; ++ break; ++ case V4L2_PIX_FMT_RGB32: ++ size = f->fmt.pix.width * f->fmt.pix.height * 4; ++ bytesperline = f->fmt.pix.width * 4; ++ break; ++ case V4L2_PIX_FMT_YUV422P: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ bytesperline = f->fmt.pix.width; ++ break; ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_YUYV: ++ size = f->fmt.pix.width * f->fmt.pix.height * 2; ++ bytesperline = f->fmt.pix.width * 2; ++ break; ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_YVU420: ++ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; ++ bytesperline = f->fmt.pix.width; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ size = f->fmt.pix.width * f->fmt.pix.height * 3 / 2; ++ bytesperline = f->fmt.pix.width; ++ break; ++ default: ++ break; ++ } ++ ++ if (f->fmt.pix.bytesperline < bytesperline) ++ f->fmt.pix.bytesperline = bytesperline; ++ else ++ bytesperline = f->fmt.pix.bytesperline; ++ ++ if (f->fmt.pix.sizeimage < size) ++ f->fmt.pix.sizeimage = size; ++ else ++ size = f->fmt.pix.sizeimage; ++ ++ cam->v2f.fmt.pix = f->fmt.pix; ++ ++ if (cam->v2f.fmt.pix.priv != 0) { ++ if (copy_from_user(&cam->offset, ++ (void *)cam->v2f.fmt.pix.priv, ++ sizeof(cam->offset))) { ++ retval = -EFAULT; ++ break; ++ } ++ } ++ break; ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ pr_debug(" type=V4L2_BUF_TYPE_VIDEO_OVERLAY\n"); ++ retval = verify_preview(cam, &f->fmt.win); ++ cam->win = f->fmt.win; ++ break; ++ default: ++ retval = -EINVAL; ++ } ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, ++ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", ++ __func__, ++ cam->crop_bounds.width, cam->crop_bounds.height); ++ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", ++ __func__, ++ cam->crop_defrect.width, cam->crop_defrect.height); ++ pr_debug("End of %s: crop_current widthxheight %d x %d\n", ++ __func__, ++ cam->crop_current.width, cam->crop_current.height); ++ ++ return retval; ++} ++ ++/*! ++ * get control param ++ * ++ * @param cam structure cam_data * ++ * ++ * @param c structure v4l2_control * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_g_ctrl(cam_data *cam, struct v4l2_control *c) ++{ ++ int status = 0; ++ ++ pr_debug("In MVC:mxc_v4l2_g_ctrl\n"); ++ ++ /* probably don't need to store the values that can be retrieved, ++ * locally, but they are for now. */ ++ switch (c->id) { ++ case V4L2_CID_HFLIP: ++ /* This is handled in the ipu. */ ++ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP) ++ c->value = 1; ++ break; ++ case V4L2_CID_VFLIP: ++ /* This is handled in the ipu. */ ++ if (cam->rotation == IPU_ROTATE_VERT_FLIP) ++ c->value = 1; ++ break; ++ case V4L2_CID_MXC_ROT: ++ /* This is handled in the ipu. */ ++ c->value = cam->rotation; ++ break; ++ case V4L2_CID_BRIGHTNESS: ++ if (cam->sensor) { ++ c->value = cam->bright; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->bright = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_HUE: ++ if (cam->sensor) { ++ c->value = cam->hue; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->hue = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_CONTRAST: ++ if (cam->sensor) { ++ c->value = cam->contrast; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->contrast = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_SATURATION: ++ if (cam->sensor) { ++ c->value = cam->saturation; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->saturation = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_RED_BALANCE: ++ if (cam->sensor) { ++ c->value = cam->red; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->red = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ if (cam->sensor) { ++ c->value = cam->blue; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->blue = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ case V4L2_CID_BLACK_LEVEL: ++ if (cam->sensor) { ++ c->value = cam->ae_mode; ++ status = vidioc_int_g_ctrl(cam->sensor, c); ++ cam->ae_mode = c->value; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ status = -ENODEV; ++ } ++ break; ++ default: ++ pr_err("ERROR: v4l2 capture: unsupported ioctrl!\n"); ++ } ++ ++ return status; ++} ++ ++/*! ++ * V4L2 - set_control function ++ * V4L2_CID_PRIVATE_BASE is the extention for IPU preprocessing. ++ * 0 for normal operation ++ * 1 for vertical flip ++ * 2 for horizontal flip ++ * 3 for horizontal and vertical flip ++ * 4 for 90 degree rotation ++ * @param cam structure cam_data * ++ * ++ * @param c structure v4l2_control * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_s_ctrl(cam_data *cam, struct v4l2_control *c) ++{ ++ int i, ret = 0; ++ int tmp_rotation = IPU_ROTATE_NONE; ++ struct sensor_data *sensor_data; ++ ++ pr_debug("In MVC:mxc_v4l2_s_ctrl\n"); ++ ++ switch (c->id) { ++ case V4L2_CID_HFLIP: ++ /* This is done by the IPU */ ++ if (c->value == 1) { ++ if ((cam->rotation != IPU_ROTATE_VERT_FLIP) && ++ (cam->rotation != IPU_ROTATE_180)) ++ cam->rotation = IPU_ROTATE_HORIZ_FLIP; ++ else ++ cam->rotation = IPU_ROTATE_180; ++ } else { ++ if (cam->rotation == IPU_ROTATE_HORIZ_FLIP) ++ cam->rotation = IPU_ROTATE_NONE; ++ if (cam->rotation == IPU_ROTATE_180) ++ cam->rotation = IPU_ROTATE_VERT_FLIP; ++ } ++ break; ++ case V4L2_CID_VFLIP: ++ /* This is done by the IPU */ ++ if (c->value == 1) { ++ if ((cam->rotation != IPU_ROTATE_HORIZ_FLIP) && ++ (cam->rotation != IPU_ROTATE_180)) ++ cam->rotation = IPU_ROTATE_VERT_FLIP; ++ else ++ cam->rotation = IPU_ROTATE_180; ++ } else { ++ if (cam->rotation == IPU_ROTATE_VERT_FLIP) ++ cam->rotation = IPU_ROTATE_NONE; ++ if (cam->rotation == IPU_ROTATE_180) ++ cam->rotation = IPU_ROTATE_HORIZ_FLIP; ++ } ++ break; ++ case V4L2_CID_MXC_ROT: ++ case V4L2_CID_MXC_VF_ROT: ++ /* This is done by the IPU */ ++ switch (c->value) { ++ case V4L2_MXC_ROTATE_NONE: ++ tmp_rotation = IPU_ROTATE_NONE; ++ break; ++ case V4L2_MXC_ROTATE_VERT_FLIP: ++ tmp_rotation = IPU_ROTATE_VERT_FLIP; ++ break; ++ case V4L2_MXC_ROTATE_HORIZ_FLIP: ++ tmp_rotation = IPU_ROTATE_HORIZ_FLIP; ++ break; ++ case V4L2_MXC_ROTATE_180: ++ tmp_rotation = IPU_ROTATE_180; ++ break; ++ case V4L2_MXC_ROTATE_90_RIGHT: ++ tmp_rotation = IPU_ROTATE_90_RIGHT; ++ break; ++ case V4L2_MXC_ROTATE_90_RIGHT_VFLIP: ++ tmp_rotation = IPU_ROTATE_90_RIGHT_VFLIP; ++ break; ++ case V4L2_MXC_ROTATE_90_RIGHT_HFLIP: ++ tmp_rotation = IPU_ROTATE_90_RIGHT_HFLIP; ++ break; ++ case V4L2_MXC_ROTATE_90_LEFT: ++ tmp_rotation = IPU_ROTATE_90_LEFT; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ #ifdef CONFIG_MXC_IPU_PRP_VF_SDC ++ if (c->id == V4L2_CID_MXC_VF_ROT) ++ cam->vf_rotation = tmp_rotation; ++ else ++ cam->rotation = tmp_rotation; ++ #else ++ cam->rotation = tmp_rotation; ++ #endif ++ ++ break; ++ case V4L2_CID_HUE: ++ if (cam->sensor) { ++ cam->hue = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_CONTRAST: ++ if (cam->sensor) { ++ cam->contrast = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_BRIGHTNESS: ++ if (cam->sensor) { ++ cam->bright = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_SATURATION: ++ if (cam->sensor) { ++ cam->saturation = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_RED_BALANCE: ++ if (cam->sensor) { ++ cam->red = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ if (cam->sensor) { ++ cam->blue = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_EXPOSURE: ++ if (cam->sensor) { ++ cam->ae_mode = c->value; ++ ret = vidioc_int_s_ctrl(cam->sensor, c); ++ } else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ ret = -ENODEV; ++ } ++ break; ++ case V4L2_CID_MXC_FLASH: ++#ifdef CONFIG_MXC_IPU_V1 ++ ipu_csi_flash_strobe(true); ++#endif ++ break; ++ case V4L2_CID_MXC_SWITCH_CAM: ++ if (cam->sensor == cam->all_sensors[c->value]) ++ break; ++ ++ /* power down other cameraes before enable new one */ ++ for (i = 0; i < cam->sensor_index; i++) { ++ if (i != c->value) { ++ vidioc_int_dev_exit(cam->all_sensors[i]); ++ vidioc_int_s_power(cam->all_sensors[i], 0); ++ if (cam->mclk_on[cam->mclk_source]) { ++ ipu_csi_enable_mclk_if(cam->ipu, ++ CSI_MCLK_I2C, ++ cam->mclk_source, ++ false, false); ++ cam->mclk_on[cam->mclk_source] = ++ false; ++ } ++ } ++ } ++ sensor_data = cam->all_sensors[c->value]->priv; ++ if (sensor_data->io_init) ++ sensor_data->io_init(); ++ cam->sensor = cam->all_sensors[c->value]; ++ cam->mclk_source = sensor_data->mclk_source; ++ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, ++ cam->mclk_source, true, true); ++ cam->mclk_on[cam->mclk_source] = true; ++ vidioc_int_s_power(cam->sensor, 1); ++ vidioc_int_dev_init(cam->sensor); ++ break; ++ default: ++ pr_debug(" default case\n"); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * V4L2 - mxc_v4l2_s_param function ++ * Allows setting of capturemode and frame rate. ++ * ++ * @param cam structure cam_data * ++ * @param parm structure v4l2_streamparm * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_s_param(cam_data *cam, struct v4l2_streamparm *parm) ++{ ++ struct v4l2_ifparm ifparm; ++ struct v4l2_format cam_fmt; ++ struct v4l2_streamparm currentparm; ++ ipu_csi_signal_cfg_t csi_param; ++ u32 current_fps, parm_fps; ++ int err = 0; ++ ++ pr_debug("In mxc_v4l2_s_param\n"); ++ ++ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ pr_err(KERN_ERR "mxc_v4l2_s_param invalid type\n"); ++ return -EINVAL; ++ } ++ ++ /* Stop the viewfinder */ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ currentparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ /* First check that this device can support the changes requested. */ ++ err = vidioc_int_g_parm(cam->sensor, ¤tparm); ++ if (err) { ++ pr_err("%s: vidioc_int_g_parm returned an error %d\n", ++ __func__, err); ++ goto exit; ++ } ++ ++ current_fps = currentparm.parm.capture.timeperframe.denominator ++ / currentparm.parm.capture.timeperframe.numerator; ++ parm_fps = parm->parm.capture.timeperframe.denominator ++ / parm->parm.capture.timeperframe.numerator; ++ ++ pr_debug(" Current capabilities are %x\n", ++ currentparm.parm.capture.capability); ++ pr_debug(" Current capturemode is %d change to %d\n", ++ currentparm.parm.capture.capturemode, ++ parm->parm.capture.capturemode); ++ pr_debug(" Current framerate is %d change to %d\n", ++ current_fps, parm_fps); ++ ++ /* This will change any camera settings needed. */ ++ err = vidioc_int_s_parm(cam->sensor, parm); ++ if (err) { ++ pr_err("%s: vidioc_int_s_parm returned an error %d\n", ++ __func__, err); ++ goto exit; ++ } ++ ++ /* If resolution changed, need to re-program the CSI */ ++ /* Get new values. */ ++ vidioc_int_g_ifparm(cam->sensor, &ifparm); ++ ++ csi_param.data_width = 0; ++ csi_param.clk_mode = 0; ++ csi_param.ext_vsync = 0; ++ csi_param.Vsync_pol = 0; ++ csi_param.Hsync_pol = 0; ++ csi_param.pixclk_pol = 0; ++ csi_param.data_pol = 0; ++ csi_param.sens_clksrc = 0; ++ csi_param.pack_tight = 0; ++ csi_param.force_eof = 0; ++ csi_param.data_en_pol = 0; ++ csi_param.data_fmt = 0; ++ csi_param.csi = cam->csi; ++ csi_param.mclk = 0; ++ ++ pr_debug(" clock_curr=mclk=%d\n", ifparm.u.bt656.clock_curr); ++ if (ifparm.u.bt656.clock_curr == 0) ++ csi_param.clk_mode = IPU_CSI_CLK_MODE_CCIR656_INTERLACED; ++ else ++ csi_param.clk_mode = IPU_CSI_CLK_MODE_GATED_CLK; ++ ++ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv; ++ ++ if (ifparm.u.bt656.mode == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) { ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; ++ } else if (ifparm.u.bt656.mode ++ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) { ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_10; ++ } else { ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; ++ } ++ ++ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv; ++ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv; ++ csi_param.ext_vsync = ifparm.u.bt656.bt_sync_correct; ++ ++ /* if the capturemode changed, the size bounds will have changed. */ ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); ++ pr_debug(" g_fmt_cap returns widthxheight of input as %d x %d\n", ++ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); ++ ++ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat; ++ ++ cam->crop_bounds.top = cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = cam_fmt.fmt.pix.width; ++ cam->crop_bounds.height = cam_fmt.fmt.pix.height; ++ ++ /* ++ * Set the default current cropped resolution to be the same with ++ * the cropping boundary(except for tvin module). ++ */ ++ if (cam->device_type != 1) { ++ cam->crop_current.width = cam->crop_bounds.width; ++ cam->crop_current.height = cam->crop_bounds.height; ++ } ++ ++ /* This essentially loses the data at the left and bottom of the image ++ * giving a digital zoom image, if crop_current is less than the full ++ * size of the image. */ ++ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, ++ cam->crop_current.height, cam->csi); ++ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, ++ cam->crop_current.top, ++ cam->csi); ++ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width, ++ cam->crop_bounds.height, ++ cam_fmt.fmt.pix.pixelformat, csi_param); ++ ++ ++exit: ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ ++ return err; ++} ++ ++/*! ++ * V4L2 - mxc_v4l2_s_std function ++ * ++ * Sets the TV standard to be used. ++ * ++ * @param cam structure cam_data * ++ * @param parm structure v4l2_streamparm * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_s_std(cam_data *cam, v4l2_std_id e) ++{ ++ pr_debug("In mxc_v4l2_s_std %Lx\n", e); ++ ++ if (e == V4L2_STD_PAL) { ++ pr_debug(" Setting standard to PAL %Lx\n", V4L2_STD_PAL); ++ cam->standard.id = V4L2_STD_PAL; ++ video_index = TV_PAL; ++ } else if (e == V4L2_STD_NTSC) { ++ pr_debug(" Setting standard to NTSC %Lx\n", ++ V4L2_STD_NTSC); ++ /* Get rid of the white dot line in NTSC signal input */ ++ cam->standard.id = V4L2_STD_NTSC; ++ video_index = TV_NTSC; ++ } else { ++ cam->standard.id = V4L2_STD_ALL; ++ video_index = TV_NOT_LOCKED; ++ pr_err("ERROR: unrecognized std! %Lx (PAL=%Lx, NTSC=%Lx\n", ++ e, V4L2_STD_PAL, V4L2_STD_NTSC); ++ } ++ ++ cam->standard.index = video_index; ++ strcpy(cam->standard.name, video_fmts[video_index].name); ++ cam->crop_bounds.width = video_fmts[video_index].raw_width; ++ cam->crop_bounds.height = video_fmts[video_index].raw_height; ++ cam->crop_current.width = video_fmts[video_index].active_width; ++ cam->crop_current.height = video_fmts[video_index].active_height; ++ cam->crop_current.top = video_fmts[video_index].active_top; ++ cam->crop_current.left = video_fmts[video_index].active_left; ++ ++ return 0; ++} ++ ++/*! ++ * V4L2 - mxc_v4l2_g_std function ++ * ++ * Gets the TV standard from the TV input device. ++ * ++ * @param cam structure cam_data * ++ * ++ * @param e structure v4l2_streamparm * ++ * ++ * @return status 0 success, EINVAL failed ++ */ ++static int mxc_v4l2_g_std(cam_data *cam, v4l2_std_id *e) ++{ ++ struct v4l2_format tv_fmt; ++ ++ pr_debug("In mxc_v4l2_g_std\n"); ++ ++ if (cam->device_type == 1) { ++ /* Use this function to get what the TV-In device detects the ++ * format to be. pixelformat is used to return the std value ++ * since the interface has no vidioc_g_std.*/ ++ tv_fmt.type = V4L2_BUF_TYPE_PRIVATE; ++ vidioc_int_g_fmt_cap(cam->sensor, &tv_fmt); ++ ++ /* If the TV-in automatically detects the standard, then if it ++ * changes, the settings need to change. */ ++ if (cam->standard_autodetect) { ++ if (cam->standard.id != tv_fmt.fmt.pix.pixelformat) { ++ pr_debug("MVC: mxc_v4l2_g_std: " ++ "Changing standard\n"); ++ mxc_v4l2_s_std(cam, tv_fmt.fmt.pix.pixelformat); ++ } ++ } ++ ++ *e = tv_fmt.fmt.pix.pixelformat; ++ } ++ ++ return 0; ++} ++ ++/*! ++ * Dequeue one V4L capture buffer ++ * ++ * @param cam structure cam_data * ++ * @param buf structure v4l2_buffer * ++ * ++ * @return status 0 success, EINVAL invalid frame number, ++ * ETIME timeout, ERESTARTSYS interrupted by user ++ */ ++static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) ++{ ++ int retval = 0; ++ struct mxc_v4l_frame *frame; ++ unsigned long lock_flags; ++ ++ pr_debug("In MVC:mxc_v4l_dqueue\n"); ++ ++ if (!wait_event_interruptible_timeout(cam->enc_queue, ++ cam->enc_counter != 0, 10 * HZ)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue timeout " ++ "enc_counter %x\n", ++ cam->enc_counter); ++ return -ETIME; ++ } else if (signal_pending(current)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l_dqueue() " ++ "interrupt received\n"); ++ return -ERESTARTSYS; ++ } ++ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EBUSY; ++ ++ spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); ++ cam->enc_counter--; ++ ++ frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); ++ list_del(cam->done_q.next); ++ if (frame->buffer.flags & V4L2_BUF_FLAG_DONE) { ++ frame->buffer.flags &= ~V4L2_BUF_FLAG_DONE; ++ } else if (frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " ++ "Buffer not filled.\n"); ++ frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; ++ retval = -EINVAL; ++ } else if ((frame->buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_DQBUF: " ++ "Buffer not queued.\n"); ++ retval = -EINVAL; ++ } ++ ++ cam->frame[frame->index].buffer.field = cam->device_type ? ++ V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE; ++ ++ buf->bytesused = cam->v2f.fmt.pix.sizeimage; ++ buf->index = frame->index; ++ buf->flags = frame->buffer.flags; ++ buf->m = cam->frame[frame->index].buffer.m; ++ buf->timestamp = cam->frame[frame->index].buffer.timestamp; ++ buf->field = cam->frame[frame->index].buffer.field; ++ spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); ++ ++ up(&cam->busy_lock); ++ return retval; ++} ++ ++/*! ++ * V4L interface - open function ++ * ++ * @param file structure file * ++ * ++ * @return status 0 success, ENODEV invalid device instance, ++ * ENODEV timeout, ERESTARTSYS interrupted by user ++ */ ++static int mxc_v4l_open(struct file *file) ++{ ++ struct v4l2_ifparm ifparm; ++ struct v4l2_format cam_fmt; ++ ipu_csi_signal_cfg_t csi_param; ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ int err = 0; ++ struct sensor_data *sensor; ++ ++ pr_debug("\nIn MVC: mxc_v4l_open\n"); ++ pr_debug(" device name is %s\n", dev->name); ++ ++ if (!cam) { ++ pr_err("ERROR: v4l2 capture: Internal error, " ++ "cam_data not found!\n"); ++ return -EBADF; ++ } ++ ++ if (cam->sensor == NULL || ++ cam->sensor->type != v4l2_int_type_slave) { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ return -EAGAIN; ++ } ++ ++ sensor = cam->sensor->priv; ++ if (!sensor) { ++ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ down(&cam->busy_lock); ++ err = 0; ++ if (signal_pending(current)) ++ goto oops; ++ ++ if (cam->open_count++ == 0) { ++ wait_event_interruptible(cam->power_queue, ++ cam->low_power == false); ++ ++ if (strcmp(mxc_capture_inputs[cam->current_input].name, ++ "CSI MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) ++ err = csi_enc_select(cam); ++#endif ++ } else if (strcmp(mxc_capture_inputs[cam->current_input].name, ++ "CSI IC MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) ++ err = prp_enc_select(cam); ++#endif ++ } ++ ++ cam->enc_counter = 0; ++ INIT_LIST_HEAD(&cam->ready_q); ++ INIT_LIST_HEAD(&cam->working_q); ++ INIT_LIST_HEAD(&cam->done_q); ++ ++ vidioc_int_g_ifparm(cam->sensor, &ifparm); ++ ++ csi_param.sens_clksrc = 0; ++ ++ csi_param.clk_mode = 0; ++ csi_param.data_pol = 0; ++ csi_param.ext_vsync = 0; ++ ++ csi_param.pack_tight = 0; ++ csi_param.force_eof = 0; ++ csi_param.data_en_pol = 0; ++ ++ csi_param.mclk = ifparm.u.bt656.clock_curr; ++ ++ csi_param.pixclk_pol = ifparm.u.bt656.latch_clk_inv; ++ ++ if (ifparm.u.bt656.mode ++ == V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT) ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; ++ else if (ifparm.u.bt656.mode ++ == V4L2_IF_TYPE_BT656_MODE_NOBT_10BIT) ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_10; ++ else ++ csi_param.data_width = IPU_CSI_DATA_WIDTH_8; ++ ++ ++ csi_param.Vsync_pol = ifparm.u.bt656.nobt_vs_inv; ++ csi_param.Hsync_pol = ifparm.u.bt656.nobt_hs_inv; ++ ++ csi_param.csi = cam->csi; ++ ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); ++ ++ /* Reset the sizes. Needed to prevent carryover of last ++ * operation.*/ ++ cam->crop_bounds.top = cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = cam_fmt.fmt.pix.width; ++ cam->crop_bounds.height = cam_fmt.fmt.pix.height; ++ ++ /* This also is the max crop size for this device. */ ++ cam->crop_defrect.top = cam->crop_defrect.left = 0; ++ cam->crop_defrect.width = cam_fmt.fmt.pix.width; ++ cam->crop_defrect.height = cam_fmt.fmt.pix.height; ++ ++ /* At this point, this is also the current image size. */ ++ cam->crop_current.top = cam->crop_current.left = 0; ++ cam->crop_current.width = cam_fmt.fmt.pix.width; ++ cam->crop_current.height = cam_fmt.fmt.pix.height; ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, ++ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", ++ __func__, ++ cam->crop_bounds.width, cam->crop_bounds.height); ++ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", ++ __func__, ++ cam->crop_defrect.width, cam->crop_defrect.height); ++ pr_debug("End of %s: crop_current widthxheight %d x %d\n", ++ __func__, ++ cam->crop_current.width, cam->crop_current.height); ++ ++ csi_param.data_fmt = cam_fmt.fmt.pix.pixelformat; ++ pr_debug("On Open: Input to ipu size is %d x %d\n", ++ cam_fmt.fmt.pix.width, cam_fmt.fmt.pix.height); ++ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, ++ cam->crop_current.height, ++ cam->csi); ++ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, ++ cam->crop_current.top, ++ cam->csi); ++ ipu_csi_init_interface(cam->ipu, cam->crop_bounds.width, ++ cam->crop_bounds.height, ++ cam_fmt.fmt.pix.pixelformat, ++ csi_param); ++ clk_prepare_enable(sensor->sensor_clk); ++ vidioc_int_s_power(cam->sensor, 1); ++ vidioc_int_init(cam->sensor); ++ vidioc_int_dev_init(cam->sensor); ++ } ++ ++ file->private_data = dev; ++ ++oops: ++ up(&cam->busy_lock); ++ return err; ++} ++ ++/*! ++ * V4L interface - close function ++ * ++ * @param file struct file * ++ * ++ * @return 0 success ++ */ ++static int mxc_v4l_close(struct file *file) ++{ ++ struct video_device *dev = video_devdata(file); ++ int err = 0; ++ cam_data *cam = video_get_drvdata(dev); ++ struct sensor_data *sensor; ++ pr_debug("In MVC:mxc_v4l_close\n"); ++ ++ if (!cam) { ++ pr_err("ERROR: v4l2 capture: Internal error, " ++ "cam_data not found!\n"); ++ return -EBADF; ++ } ++ ++ if (!cam->sensor) { ++ pr_err("%s: Internal error, camera is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ sensor = cam->sensor->priv; ++ if (!sensor) { ++ pr_err("%s: Internal error, sensor_data is not found!\n", __func__); ++ return -EBADF; ++ } ++ ++ down(&cam->busy_lock); ++ ++ /* for the case somebody hit the ctrl C */ ++ if (cam->overlay_pid == current->pid && cam->overlay_on) { ++ err = stop_preview(cam); ++ cam->overlay_on = false; ++ } ++ if (cam->capture_pid == current->pid) { ++ err |= mxc_streamoff(cam); ++ wake_up_interruptible(&cam->enc_queue); ++ } ++ ++ if (--cam->open_count == 0) { ++ vidioc_int_s_power(cam->sensor, 0); ++ clk_disable_unprepare(sensor->sensor_clk); ++ wait_event_interruptible(cam->power_queue, ++ cam->low_power == false); ++ pr_debug("mxc_v4l_close: release resource\n"); ++ ++ if (strcmp(mxc_capture_inputs[cam->current_input].name, ++ "CSI MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) ++ err |= csi_enc_deselect(cam); ++#endif ++ } else if (strcmp(mxc_capture_inputs[cam->current_input].name, ++ "CSI IC MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) ++ err |= prp_enc_deselect(cam); ++#endif ++ } ++ ++ mxc_free_frame_buf(cam); ++ file->private_data = NULL; ++ ++ /* capture off */ ++ wake_up_interruptible(&cam->enc_queue); ++ mxc_free_frames(cam); ++ cam->enc_counter++; ++ } ++ ++ up(&cam->busy_lock); ++ ++ return err; ++} ++ ++#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC) || \ ++ defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) || \ ++ defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) ++/* ++ * V4L interface - read function ++ * ++ * @param file struct file * ++ * @param read buf char * ++ * @param count size_t ++ * @param ppos structure loff_t * ++ * ++ * @return bytes read ++ */ ++static ssize_t mxc_v4l_read(struct file *file, char *buf, size_t count, ++ loff_t *ppos) ++{ ++ int err = 0; ++ u8 *v_address[2]; ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EINTR; ++ ++ /* Stop the viewfinder */ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ ++ v_address[0] = dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->still_buf[0], ++ GFP_DMA | GFP_KERNEL); ++ ++ v_address[1] = dma_alloc_coherent(0, ++ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage), ++ &cam->still_buf[1], ++ GFP_DMA | GFP_KERNEL); ++ ++ if (!v_address[0] || !v_address[1]) { ++ err = -ENOBUFS; ++ goto exit0; ++ } ++ ++ err = prp_still_select(cam); ++ if (err != 0) { ++ err = -EIO; ++ goto exit0; ++ } ++ ++ cam->still_counter = 0; ++ err = cam->csi_start(cam); ++ if (err != 0) { ++ err = -EIO; ++ goto exit1; ++ } ++ ++ if (!wait_event_interruptible_timeout(cam->still_queue, ++ cam->still_counter != 0, ++ 10 * HZ)) { ++ pr_err("ERROR: v4l2 capture: mxc_v4l_read timeout counter %x\n", ++ cam->still_counter); ++ err = -ETIME; ++ goto exit1; ++ } ++ err = copy_to_user(buf, v_address[1], cam->v2f.fmt.pix.sizeimage); ++ ++exit1: ++ prp_still_deselect(cam); ++ ++exit0: ++ if (v_address[0] != 0) ++ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[0], ++ cam->still_buf[0]); ++ if (v_address[1] != 0) ++ dma_free_coherent(0, cam->v2f.fmt.pix.sizeimage, v_address[1], ++ cam->still_buf[1]); ++ ++ cam->still_buf[0] = cam->still_buf[1] = 0; ++ ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ ++ up(&cam->busy_lock); ++ if (err < 0) ++ return err; ++ ++ return cam->v2f.fmt.pix.sizeimage - err; ++} ++#endif ++ ++/*! ++ * V4L interface - ioctl function ++ * ++ * @param file struct file* ++ * ++ * @param ioctlnr unsigned int ++ * ++ * @param arg void* ++ * ++ * @return 0 success, ENODEV for invalid device instance, ++ * -1 for other errors. ++ */ ++static long mxc_v4l_do_ioctl(struct file *file, ++ unsigned int ioctlnr, void *arg) ++{ ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ int retval = 0; ++ unsigned long lock_flags; ++ ++ pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr); ++ wait_event_interruptible(cam->power_queue, cam->low_power == false); ++ /* make this _really_ smp-safe */ ++ if (ioctlnr != VIDIOC_DQBUF) ++ if (down_interruptible(&cam->busy_lock)) ++ return -EBUSY; ++ ++ switch (ioctlnr) { ++ /*! ++ * V4l2 VIDIOC_QUERYCAP ioctl ++ */ ++ case VIDIOC_QUERYCAP: { ++ struct v4l2_capability *cap = arg; ++ pr_debug(" case VIDIOC_QUERYCAP\n"); ++ strcpy(cap->driver, "mxc_v4l2"); ++ cap->version = KERNEL_VERSION(0, 1, 11); ++ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | ++ V4L2_CAP_VIDEO_OVERLAY | ++ V4L2_CAP_STREAMING | ++ V4L2_CAP_READWRITE; ++ cap->card[0] = '\0'; ++ cap->bus_info[0] = '\0'; ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_G_FMT ioctl ++ */ ++ case VIDIOC_G_FMT: { ++ struct v4l2_format *gf = arg; ++ pr_debug(" case VIDIOC_G_FMT\n"); ++ retval = mxc_v4l2_g_fmt(cam, gf); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_FMT ioctl ++ */ ++ case VIDIOC_S_FMT: { ++ struct v4l2_format *sf = arg; ++ pr_debug(" case VIDIOC_S_FMT\n"); ++ retval = mxc_v4l2_s_fmt(cam, sf); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_REQBUFS ioctl ++ */ ++ case VIDIOC_REQBUFS: { ++ struct v4l2_requestbuffers *req = arg; ++ pr_debug(" case VIDIOC_REQBUFS\n"); ++ ++ if (req->count > FRAME_NUM) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " ++ "not enough buffers\n"); ++ req->count = FRAME_NUM; ++ } ++ ++ if ((req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_REQBUFS: " ++ "wrong buffer type\n"); ++ retval = -EINVAL; ++ break; ++ } ++ ++ mxc_streamoff(cam); ++ if (req->memory & V4L2_MEMORY_MMAP) { ++ mxc_free_frame_buf(cam); ++ retval = mxc_allocate_frame_buf(cam, req->count); ++ } ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_QUERYBUF ioctl ++ */ ++ case VIDIOC_QUERYBUF: { ++ struct v4l2_buffer *buf = arg; ++ int index = buf->index; ++ pr_debug(" case VIDIOC_QUERYBUF\n"); ++ ++ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ pr_err("ERROR: v4l2 capture: " ++ "VIDIOC_QUERYBUFS: " ++ "wrong buffer type\n"); ++ retval = -EINVAL; ++ break; ++ } ++ ++ if (buf->memory & V4L2_MEMORY_MMAP) { ++ memset(buf, 0, sizeof(buf)); ++ buf->index = index; ++ } ++ ++ down(&cam->param_lock); ++ if (buf->memory & V4L2_MEMORY_USERPTR) { ++ mxc_v4l2_release_bufs(cam); ++ retval = mxc_v4l2_prepare_bufs(cam, buf); ++ } ++ ++ if (buf->memory & V4L2_MEMORY_MMAP) ++ retval = mxc_v4l2_buffer_status(cam, buf); ++ up(&cam->param_lock); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_QBUF ioctl ++ */ ++ case VIDIOC_QBUF: { ++ struct v4l2_buffer *buf = arg; ++ int index = buf->index; ++ pr_debug(" case VIDIOC_QBUF\n"); ++ ++ spin_lock_irqsave(&cam->queue_int_lock, lock_flags); ++ if ((cam->frame[index].buffer.flags & 0x7) == ++ V4L2_BUF_FLAG_MAPPED) { ++ cam->frame[index].buffer.flags |= ++ V4L2_BUF_FLAG_QUEUED; ++ list_add_tail(&cam->frame[index].queue, ++ &cam->ready_q); ++ } else if (cam->frame[index].buffer. ++ flags & V4L2_BUF_FLAG_QUEUED) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " ++ "buffer already queued\n"); ++ retval = -EINVAL; ++ } else if (cam->frame[index].buffer. ++ flags & V4L2_BUF_FLAG_DONE) { ++ pr_err("ERROR: v4l2 capture: VIDIOC_QBUF: " ++ "overwrite done buffer.\n"); ++ cam->frame[index].buffer.flags &= ++ ~V4L2_BUF_FLAG_DONE; ++ cam->frame[index].buffer.flags |= ++ V4L2_BUF_FLAG_QUEUED; ++ retval = -EINVAL; ++ } ++ ++ buf->flags = cam->frame[index].buffer.flags; ++ spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_DQBUF ioctl ++ */ ++ case VIDIOC_DQBUF: { ++ struct v4l2_buffer *buf = arg; ++ pr_debug(" case VIDIOC_DQBUF\n"); ++ ++ if ((cam->enc_counter == 0) && ++ (file->f_flags & O_NONBLOCK)) { ++ retval = -EAGAIN; ++ break; ++ } ++ ++ retval = mxc_v4l_dqueue(cam, buf); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_STREAMON ioctl ++ */ ++ case VIDIOC_STREAMON: { ++ pr_debug(" case VIDIOC_STREAMON\n"); ++ retval = mxc_streamon(cam); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_STREAMOFF ioctl ++ */ ++ case VIDIOC_STREAMOFF: { ++ pr_debug(" case VIDIOC_STREAMOFF\n"); ++ retval = mxc_streamoff(cam); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_G_CTRL ioctl ++ */ ++ case VIDIOC_G_CTRL: { ++ pr_debug(" case VIDIOC_G_CTRL\n"); ++ retval = mxc_v4l2_g_ctrl(cam, arg); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_CTRL ioctl ++ */ ++ case VIDIOC_S_CTRL: { ++ pr_debug(" case VIDIOC_S_CTRL\n"); ++ retval = mxc_v4l2_s_ctrl(cam, arg); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_CROPCAP ioctl ++ */ ++ case VIDIOC_CROPCAP: { ++ struct v4l2_cropcap *cap = arg; ++ pr_debug(" case VIDIOC_CROPCAP\n"); ++ if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { ++ retval = -EINVAL; ++ break; ++ } ++ cap->bounds = cam->crop_bounds; ++ cap->defrect = cam->crop_defrect; ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_G_CROP ioctl ++ */ ++ case VIDIOC_G_CROP: { ++ struct v4l2_crop *crop = arg; ++ pr_debug(" case VIDIOC_G_CROP\n"); ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { ++ retval = -EINVAL; ++ break; ++ } ++ crop->c = cam->crop_current; ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_CROP ioctl ++ */ ++ case VIDIOC_S_CROP: { ++ struct v4l2_crop *crop = arg; ++ struct v4l2_rect *b = &cam->crop_bounds; ++ pr_debug(" case VIDIOC_S_CROP\n"); ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY) { ++ retval = -EINVAL; ++ break; ++ } ++ ++ crop->c.top = (crop->c.top < b->top) ? b->top ++ : crop->c.top; ++ if (crop->c.top > b->top + b->height) ++ crop->c.top = b->top + b->height - 1; ++ if (crop->c.height > b->top + b->height - crop->c.top) ++ crop->c.height = ++ b->top + b->height - crop->c.top; ++ ++ crop->c.left = (crop->c.left < b->left) ? b->left ++ : crop->c.left; ++ if (crop->c.left > b->left + b->width) ++ crop->c.left = b->left + b->width - 1; ++ if (crop->c.width > b->left - crop->c.left + b->width) ++ crop->c.width = ++ b->left - crop->c.left + b->width; ++ ++ crop->c.width -= crop->c.width % 8; ++ crop->c.left -= crop->c.left % 4; ++ cam->crop_current = crop->c; ++ ++ pr_debug(" Cropping Input to ipu size %d x %d\n", ++ cam->crop_current.width, ++ cam->crop_current.height); ++ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, ++ cam->crop_current.height, ++ cam->csi); ++ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, ++ cam->crop_current.top, ++ cam->csi); ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_OVERLAY ioctl ++ */ ++ case VIDIOC_OVERLAY: { ++ int *on = arg; ++ pr_debug(" VIDIOC_OVERLAY on=%d\n", *on); ++ if (*on) { ++ cam->overlay_on = true; ++ cam->overlay_pid = current->pid; ++ retval = start_preview(cam); ++ } ++ if (!*on) { ++ retval = stop_preview(cam); ++ cam->overlay_on = false; ++ } ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_G_FBUF ioctl ++ */ ++ case VIDIOC_G_FBUF: { ++ struct v4l2_framebuffer *fb = arg; ++ pr_debug(" case VIDIOC_G_FBUF\n"); ++ *fb = cam->v4l2_fb; ++ fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY; ++ break; ++ } ++ ++ /*! ++ * V4l2 VIDIOC_S_FBUF ioctl ++ */ ++ case VIDIOC_S_FBUF: { ++ struct v4l2_framebuffer *fb = arg; ++ pr_debug(" case VIDIOC_S_FBUF\n"); ++ cam->v4l2_fb = *fb; ++ break; ++ } ++ ++ case VIDIOC_G_PARM: { ++ struct v4l2_streamparm *parm = arg; ++ pr_debug(" case VIDIOC_G_PARM\n"); ++ if (cam->sensor) ++ retval = vidioc_int_g_parm(cam->sensor, parm); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ ++ case VIDIOC_S_PARM: { ++ struct v4l2_streamparm *parm = arg; ++ pr_debug(" case VIDIOC_S_PARM\n"); ++ if (cam->sensor) ++ retval = mxc_v4l2_s_param(cam, parm); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ ++ /* linux v4l2 bug, kernel c0485619 user c0405619 */ ++ case VIDIOC_ENUMSTD: { ++ struct v4l2_standard *e = arg; ++ pr_debug(" case VIDIOC_ENUMSTD\n"); ++ *e = cam->standard; ++ break; ++ } ++ ++ case VIDIOC_G_STD: { ++ v4l2_std_id *e = arg; ++ pr_debug(" case VIDIOC_G_STD\n"); ++ if (cam->sensor) ++ retval = mxc_v4l2_g_std(cam, e); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ ++ case VIDIOC_S_STD: { ++ v4l2_std_id *e = arg; ++ pr_debug(" case VIDIOC_S_STD\n"); ++ retval = mxc_v4l2_s_std(cam, *e); ++ ++ break; ++ } ++ ++ case VIDIOC_ENUMOUTPUT: { ++ struct v4l2_output *output = arg; ++ pr_debug(" case VIDIOC_ENUMOUTPUT\n"); ++ if (output->index >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) { ++ retval = -EINVAL; ++ break; ++ } ++ *output = mxc_capture_outputs[output->index]; ++ ++ break; ++ } ++ case VIDIOC_G_OUTPUT: { ++ int *p_output_num = arg; ++ pr_debug(" case VIDIOC_G_OUTPUT\n"); ++ *p_output_num = cam->output; ++ break; ++ } ++ ++ case VIDIOC_S_OUTPUT: { ++ int *p_output_num = arg; ++ pr_debug(" case VIDIOC_S_OUTPUT\n"); ++ if (*p_output_num >= MXC_V4L2_CAPTURE_NUM_OUTPUTS) { ++ retval = -EINVAL; ++ break; ++ } ++ cam->output = *p_output_num; ++ break; ++ } ++ ++ case VIDIOC_ENUMINPUT: { ++ struct v4l2_input *input = arg; ++ pr_debug(" case VIDIOC_ENUMINPUT\n"); ++ if (input->index >= MXC_V4L2_CAPTURE_NUM_INPUTS) { ++ retval = -EINVAL; ++ break; ++ } ++ *input = mxc_capture_inputs[input->index]; ++ break; ++ } ++ ++ case VIDIOC_G_INPUT: { ++ int *index = arg; ++ pr_debug(" case VIDIOC_G_INPUT\n"); ++ *index = cam->current_input; ++ break; ++ } ++ ++ case VIDIOC_S_INPUT: { ++ int *index = arg; ++ pr_debug(" case VIDIOC_S_INPUT\n"); ++ if (*index >= MXC_V4L2_CAPTURE_NUM_INPUTS) { ++ retval = -EINVAL; ++ break; ++ } ++ ++ if (*index == cam->current_input) ++ break; ++ ++ if ((mxc_capture_inputs[cam->current_input].status & ++ V4L2_IN_ST_NO_POWER) == 0) { ++ retval = mxc_streamoff(cam); ++ if (retval) ++ break; ++ mxc_capture_inputs[cam->current_input].status |= ++ V4L2_IN_ST_NO_POWER; ++ } ++ ++ if (strcmp(mxc_capture_inputs[*index].name, "CSI MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_CSI_ENC) || defined(CONFIG_MXC_IPU_CSI_ENC_MODULE) ++ retval = csi_enc_select(cam); ++ if (retval) ++ break; ++#endif ++ } else if (strcmp(mxc_capture_inputs[*index].name, ++ "CSI IC MEM") == 0) { ++#if defined(CONFIG_MXC_IPU_PRP_ENC) || defined(CONFIG_MXC_IPU_PRP_ENC_MODULE) ++ retval = prp_enc_select(cam); ++ if (retval) ++ break; ++#endif ++ } ++ ++ mxc_capture_inputs[*index].status &= ~V4L2_IN_ST_NO_POWER; ++ cam->current_input = *index; ++ break; ++ } ++ case VIDIOC_ENUM_FMT: { ++ struct v4l2_fmtdesc *f = arg; ++ if (cam->sensor) ++ retval = vidioc_int_enum_fmt_cap(cam->sensor, f); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_ENUM_FRAMESIZES: { ++ struct v4l2_frmsizeenum *fsize = arg; ++ if (cam->sensor) ++ retval = vidioc_int_enum_framesizes(cam->sensor, fsize); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_DBG_G_CHIP_IDENT: { ++ struct v4l2_dbg_chip_ident *p = arg; ++ p->ident = V4L2_IDENT_NONE; ++ p->revision = 0; ++ if (cam->sensor) ++ retval = vidioc_int_g_chip_ident(cam->sensor, (int *)p); ++ else { ++ pr_err("ERROR: v4l2 capture: slave not found!\n"); ++ retval = -ENODEV; ++ } ++ break; ++ } ++ case VIDIOC_TRY_FMT: ++ case VIDIOC_QUERYCTRL: ++ case VIDIOC_G_TUNER: ++ case VIDIOC_S_TUNER: ++ case VIDIOC_G_FREQUENCY: ++ case VIDIOC_S_FREQUENCY: ++ default: ++ pr_debug(" case default or not supported\n"); ++ retval = -EINVAL; ++ break; ++ } ++ ++ if (ioctlnr != VIDIOC_DQBUF) ++ up(&cam->busy_lock); ++ return retval; ++} ++ ++/* ++ * V4L interface - ioctl function ++ * ++ * @return None ++ */ ++static long mxc_v4l_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ pr_debug("In MVC:mxc_v4l_ioctl\n"); ++ return video_usercopy(file, cmd, arg, mxc_v4l_do_ioctl); ++} ++ ++/*! ++ * V4L interface - mmap function ++ * ++ * @param file structure file * ++ * ++ * @param vma structure vm_area_struct * ++ * ++ * @return status 0 Success, EINTR busy lock error, ENOBUFS remap_page error ++ */ ++static int mxc_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct video_device *dev = video_devdata(file); ++ unsigned long size; ++ int res = 0; ++ cam_data *cam = video_get_drvdata(dev); ++ ++ pr_debug("In MVC:mxc_mmap\n"); ++ pr_debug(" pgoff=0x%lx, start=0x%lx, end=0x%lx\n", ++ vma->vm_pgoff, vma->vm_start, vma->vm_end); ++ ++ /* make this _really_ smp-safe */ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EINTR; ++ ++ size = vma->vm_end - vma->vm_start; ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ ++ if (remap_pfn_range(vma, vma->vm_start, ++ vma->vm_pgoff, size, vma->vm_page_prot)) { ++ pr_err("ERROR: v4l2 capture: mxc_mmap: " ++ "remap_pfn_range failed\n"); ++ res = -ENOBUFS; ++ goto mxc_mmap_exit; ++ } ++ ++ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */ ++ ++mxc_mmap_exit: ++ up(&cam->busy_lock); ++ return res; ++} ++ ++/*! ++ * V4L interface - poll function ++ * ++ * @param file structure file * ++ * ++ * @param wait structure poll_table_struct * ++ * ++ * @return status POLLIN | POLLRDNORM ++ */ ++static unsigned int mxc_poll(struct file *file, struct poll_table_struct *wait) ++{ ++ struct video_device *dev = video_devdata(file); ++ cam_data *cam = video_get_drvdata(dev); ++ wait_queue_head_t *queue = NULL; ++ int res = POLLIN | POLLRDNORM; ++ ++ pr_debug("In MVC:mxc_poll\n"); ++ ++ if (down_interruptible(&cam->busy_lock)) ++ return -EINTR; ++ ++ queue = &cam->enc_queue; ++ poll_wait(file, queue, wait); ++ ++ up(&cam->busy_lock); ++ ++ return res; ++} ++ ++/*! ++ * This structure defines the functions to be called in this driver. ++ */ ++static struct v4l2_file_operations mxc_v4l_fops = { ++ .owner = THIS_MODULE, ++ .open = mxc_v4l_open, ++ .release = mxc_v4l_close, ++ .read = mxc_v4l_read, ++ .ioctl = mxc_v4l_ioctl, ++ .mmap = mxc_mmap, ++ .poll = mxc_poll, ++}; ++ ++static struct video_device mxc_v4l_template = { ++ .name = "Mxc Camera", ++ .fops = &mxc_v4l_fops, ++ .release = video_device_release, ++}; ++ ++/*! ++ * This function can be used to release any platform data on closing. ++ */ ++static void camera_platform_release(struct device *device) ++{ ++} ++ ++/*! ++ * Camera V4l2 callback function. ++ * ++ * @param mask u32 ++ * ++ * @param dev void device structure ++ * ++ * @return status ++ */ ++static void camera_callback(u32 mask, void *dev) ++{ ++ struct mxc_v4l_frame *done_frame; ++ struct mxc_v4l_frame *ready_frame; ++ struct timeval cur_time; ++ ++ cam_data *cam = (cam_data *) dev; ++ if (cam == NULL) ++ return; ++ ++ pr_debug("In MVC:camera_callback\n"); ++ ++ spin_lock(&cam->queue_int_lock); ++ spin_lock(&cam->dqueue_int_lock); ++ if (!list_empty(&cam->working_q)) { ++ do_gettimeofday(&cur_time); ++ ++ done_frame = list_entry(cam->working_q.next, ++ struct mxc_v4l_frame, ++ queue); ++ ++ if (done_frame->ipu_buf_num != cam->local_buf_num) ++ goto next; ++ ++ /* ++ * Set the current time to done frame buffer's ++ * timestamp. Users can use this information to judge ++ * the frame's usage. ++ */ ++ done_frame->buffer.timestamp = cur_time; ++ ++ if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) { ++ done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE; ++ done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED; ++ ++ /* Added to the done queue */ ++ list_del(cam->working_q.next); ++ list_add_tail(&done_frame->queue, &cam->done_q); ++ ++ /* Wake up the queue */ ++ cam->enc_counter++; ++ wake_up_interruptible(&cam->enc_queue); ++ } else ++ pr_err("ERROR: v4l2 capture: camera_callback: " ++ "buffer not queued\n"); ++ } ++ ++next: ++ if (!list_empty(&cam->ready_q)) { ++ ready_frame = list_entry(cam->ready_q.next, ++ struct mxc_v4l_frame, ++ queue); ++ if (cam->enc_update_eba) ++ if (cam->enc_update_eba(cam->ipu, ++ ready_frame->buffer.m.offset, ++ &cam->ping_pong_csi) == 0) { ++ list_del(cam->ready_q.next); ++ list_add_tail(&ready_frame->queue, ++ &cam->working_q); ++ ready_frame->ipu_buf_num = cam->local_buf_num; ++ } ++ } else { ++ if (cam->enc_update_eba) ++ cam->enc_update_eba( ++ cam->ipu, cam->dummy_frame.buffer.m.offset, ++ &cam->ping_pong_csi); ++ } ++ ++ cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0; ++ spin_unlock(&cam->dqueue_int_lock); ++ spin_unlock(&cam->queue_int_lock); ++ ++ return; ++} ++ ++/*! ++ * initialize cam_data structure ++ * ++ * @param cam structure cam_data * ++ * ++ * @return status 0 Success ++ */ ++static int init_camera_struct(cam_data *cam, struct platform_device *pdev) ++{ ++ const struct of_device_id *of_id = ++ of_match_device(mxc_v4l2_dt_ids, &pdev->dev); ++ struct device_node *np = pdev->dev.of_node; ++ int ipu_id, csi_id, mclk_source; ++ int ret = 0; ++ ++ pr_debug("In MVC: init_camera_struct\n"); ++ ++ ret = of_property_read_u32(np, "ipu_id", &ipu_id); ++ if (ret) { ++ dev_err(&pdev->dev, "ipu_id missing or invalid\n"); ++ return ret; ++ } ++ ++ ret = of_property_read_u32(np, "csi_id", &csi_id); ++ if (ret) { ++ dev_err(&pdev->dev, "csi_id missing or invalid\n"); ++ return ret; ++ } ++ ++ ret = of_property_read_u32(np, "mclk_source", &mclk_source); ++ if (ret) { ++ dev_err(&pdev->dev, "sensor mclk missing or invalid\n"); ++ return ret; ++ } ++ ++ /* Default everything to 0 */ ++ memset(cam, 0, sizeof(cam_data)); ++ ++ /* get devtype to distinguish if the cpu is imx5 or imx6 ++ * IMX5_V4L2 specify the cpu is imx5 ++ * IMX6_V4L2 specify the cpu is imx6q or imx6sdl ++ */ ++ if (of_id) ++ pdev->id_entry = of_id->data; ++ cam->devtype = pdev->id_entry->driver_data; ++ ++ cam->ipu = ipu_get_soc(ipu_id); ++ if (cam->ipu == NULL) { ++ pr_err("ERROR: v4l2 capture: failed to get ipu\n"); ++ return -EINVAL; ++ } else if (cam->ipu == ERR_PTR(-ENODEV)) { ++ pr_err("ERROR: v4l2 capture: get invalid ipu\n"); ++ return -ENODEV; ++ } ++ ++ init_MUTEX(&cam->param_lock); ++ init_MUTEX(&cam->busy_lock); ++ ++ cam->video_dev = video_device_alloc(); ++ if (cam->video_dev == NULL) ++ return -ENODEV; ++ ++ *(cam->video_dev) = mxc_v4l_template; ++ ++ video_set_drvdata(cam->video_dev, cam); ++ dev_set_drvdata(&pdev->dev, (void *)cam); ++ cam->video_dev->minor = -1; ++ ++ init_waitqueue_head(&cam->enc_queue); ++ init_waitqueue_head(&cam->still_queue); ++ ++ /* setup cropping */ ++ cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = 640; ++ cam->crop_bounds.top = 0; ++ cam->crop_bounds.height = 480; ++ cam->crop_current = cam->crop_defrect = cam->crop_bounds; ++ ipu_csi_set_window_size(cam->ipu, cam->crop_current.width, ++ cam->crop_current.height, cam->csi); ++ ipu_csi_set_window_pos(cam->ipu, cam->crop_current.left, ++ cam->crop_current.top, cam->csi); ++ cam->streamparm.parm.capture.capturemode = 0; ++ ++ cam->standard.index = 0; ++ cam->standard.id = V4L2_STD_UNKNOWN; ++ cam->standard.frameperiod.denominator = 30; ++ cam->standard.frameperiod.numerator = 1; ++ cam->standard.framelines = 480; ++ cam->standard_autodetect = true; ++ cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod; ++ cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME; ++ cam->overlay_on = false; ++ cam->capture_on = false; ++ cam->v4l2_fb.flags = V4L2_FBUF_FLAG_OVERLAY; ++ ++ cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2; ++ cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2; ++ cam->v2f.fmt.pix.width = 288; ++ cam->v2f.fmt.pix.height = 352; ++ cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; ++ cam->win.w.width = 160; ++ cam->win.w.height = 160; ++ cam->win.w.left = 0; ++ cam->win.w.top = 0; ++ ++ cam->ipu_id = ipu_id; ++ cam->csi = csi_id; ++ cam->mclk_source = mclk_source; ++ cam->mclk_on[cam->mclk_source] = false; ++ ++ cam->enc_callback = camera_callback; ++ init_waitqueue_head(&cam->power_queue); ++ spin_lock_init(&cam->queue_int_lock); ++ spin_lock_init(&cam->dqueue_int_lock); ++ ++ cam->self = kmalloc(sizeof(struct v4l2_int_device), GFP_KERNEL); ++ cam->self->module = THIS_MODULE; ++ sprintf(cam->self->name, "mxc_v4l2_cap%d", cam->csi); ++ cam->self->type = v4l2_int_type_master; ++ cam->self->u.master = &mxc_v4l2_master; ++ ++ return 0; ++} ++ ++static ssize_t show_streaming(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct video_device *video_dev = container_of(dev, ++ struct video_device, dev); ++ cam_data *cam = video_get_drvdata(video_dev); ++ ++ if (cam->capture_on) ++ return sprintf(buf, "stream on\n"); ++ else ++ return sprintf(buf, "stream off\n"); ++} ++static DEVICE_ATTR(fsl_v4l2_capture_property, S_IRUGO, show_streaming, NULL); ++ ++static ssize_t show_overlay(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct video_device *video_dev = container_of(dev, ++ struct video_device, dev); ++ cam_data *cam = video_get_drvdata(video_dev); ++ ++ if (cam->overlay_on) ++ return sprintf(buf, "overlay on\n"); ++ else ++ return sprintf(buf, "overlay off\n"); ++} ++static DEVICE_ATTR(fsl_v4l2_overlay_property, S_IRUGO, show_overlay, NULL); ++ ++static ssize_t show_csi(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct video_device *video_dev = container_of(dev, ++ struct video_device, dev); ++ cam_data *cam = video_get_drvdata(video_dev); ++ ++ return sprintf(buf, "ipu%d_csi%d\n", cam->ipu_id, cam->csi); ++} ++static DEVICE_ATTR(fsl_csi_property, S_IRUGO, show_csi, NULL); ++ ++/*! ++ * This function is called to probe the devices if registered. ++ * ++ * @param pdev the device structure used to give information on which device ++ * to probe ++ * ++ * @return The function returns 0 on success and -1 on failure. ++ */ ++static int mxc_v4l2_probe(struct platform_device *pdev) ++{ ++ /* Create cam and initialize it. */ ++ cam_data *cam = kmalloc(sizeof(cam_data), GFP_KERNEL); ++ if (cam == NULL) { ++ pr_err("ERROR: v4l2 capture: failed to register camera\n"); ++ return -1; ++ } ++ ++ init_camera_struct(cam, pdev); ++ pdev->dev.release = camera_platform_release; ++ ++ /* Set up the v4l2 device and register it*/ ++ cam->self->priv = cam; ++ v4l2_int_device_register(cam->self); ++ ++ /* register v4l video device */ ++ if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr) ++ == -1) { ++ kfree(cam); ++ cam = NULL; ++ pr_err("ERROR: v4l2 capture: video_register_device failed\n"); ++ return -1; ++ } ++ pr_debug(" Video device registered: %s #%d\n", ++ cam->video_dev->name, cam->video_dev->minor); ++ ++ if (device_create_file(&cam->video_dev->dev, ++ &dev_attr_fsl_v4l2_capture_property)) ++ dev_err(&pdev->dev, "Error on creating sysfs file" ++ " for capture\n"); ++ ++ if (device_create_file(&cam->video_dev->dev, ++ &dev_attr_fsl_v4l2_overlay_property)) ++ dev_err(&pdev->dev, "Error on creating sysfs file" ++ " for overlay\n"); ++ ++ if (device_create_file(&cam->video_dev->dev, ++ &dev_attr_fsl_csi_property)) ++ dev_err(&pdev->dev, "Error on creating sysfs file" ++ " for csi number\n"); ++ ++ return 0; ++} ++ ++/*! ++ * This function is called to remove the devices when device unregistered. ++ * ++ * @param pdev the device structure used to give information on which device ++ * to remove ++ * ++ * @return The function returns 0 on success and -1 on failure. ++ */ ++static int mxc_v4l2_remove(struct platform_device *pdev) ++{ ++ cam_data *cam = (cam_data *)platform_get_drvdata(pdev); ++ if (cam->open_count) { ++ pr_err("ERROR: v4l2 capture:camera open " ++ "-- setting ops to NULL\n"); ++ return -EBUSY; ++ } else { ++ device_remove_file(&cam->video_dev->dev, ++ &dev_attr_fsl_v4l2_capture_property); ++ device_remove_file(&cam->video_dev->dev, ++ &dev_attr_fsl_v4l2_overlay_property); ++ device_remove_file(&cam->video_dev->dev, ++ &dev_attr_fsl_csi_property); ++ ++ pr_info("V4L2 freeing image input device\n"); ++ v4l2_int_device_unregister(cam->self); ++ video_unregister_device(cam->video_dev); ++ ++ mxc_free_frame_buf(cam); ++ kfree(cam); ++ } ++ ++ pr_info("V4L2 unregistering video\n"); ++ return 0; ++} ++ ++/*! ++ * This function is called to put the sensor in a low power state. ++ * Refer to the document driver-model/driver.txt in the kernel source tree ++ * for more information. ++ * ++ * @param pdev the device structure used to give information on which I2C ++ * to suspend ++ * @param state the power state the device is entering ++ * ++ * @return The function returns 0 on success and -1 on failure. ++ */ ++static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ cam_data *cam = platform_get_drvdata(pdev); ++ ++ pr_debug("In MVC:mxc_v4l2_suspend\n"); ++ ++ if (cam == NULL) ++ return -1; ++ ++ down(&cam->busy_lock); ++ ++ cam->low_power = true; ++ ++ if (cam->overlay_on == true) ++ stop_preview(cam); ++ if ((cam->capture_on == true) && cam->enc_disable) ++ cam->enc_disable(cam); ++ ++ if (cam->sensor && cam->open_count) { ++ if (cam->mclk_on[cam->mclk_source]) { ++ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, ++ cam->mclk_source, ++ false, false); ++ cam->mclk_on[cam->mclk_source] = false; ++ } ++ vidioc_int_s_power(cam->sensor, 0); ++ } ++ ++ up(&cam->busy_lock); ++ ++ return 0; ++} ++ ++/*! ++ * This function is called to bring the sensor back from a low power state. ++ * Refer to the document driver-model/driver.txt in the kernel source tree ++ * for more information. ++ * ++ * @param pdev the device structure ++ * ++ * @return The function returns 0 on success and -1 on failure ++ */ ++static int mxc_v4l2_resume(struct platform_device *pdev) ++{ ++ cam_data *cam = platform_get_drvdata(pdev); ++ ++ pr_debug("In MVC:mxc_v4l2_resume\n"); ++ ++ if (cam == NULL) ++ return -1; ++ ++ down(&cam->busy_lock); ++ ++ cam->low_power = false; ++ wake_up_interruptible(&cam->power_queue); ++ ++ if (cam->sensor && cam->open_count) { ++ vidioc_int_s_power(cam->sensor, 1); ++ ++ if (!cam->mclk_on[cam->mclk_source]) { ++ ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, ++ cam->mclk_source, ++ true, true); ++ cam->mclk_on[cam->mclk_source] = true; ++ } ++ } ++ ++ if (cam->overlay_on == true) ++ start_preview(cam); ++ if (cam->capture_on == true) ++ mxc_streamon(cam); ++ ++ up(&cam->busy_lock); ++ ++ return 0; ++} ++ ++/*! ++ * This structure contains pointers to the power management callback functions. ++ */ ++static struct platform_driver mxc_v4l2_driver = { ++ .driver = { ++ .name = "mxc_v4l2_capture", ++ .owner = THIS_MODULE, ++ .of_match_table = mxc_v4l2_dt_ids, ++ }, ++ .id_table = imx_v4l2_devtype, ++ .probe = mxc_v4l2_probe, ++ .remove = mxc_v4l2_remove, ++ .suspend = mxc_v4l2_suspend, ++ .resume = mxc_v4l2_resume, ++ .shutdown = NULL, ++}; ++ ++/*! ++ * Initializes the camera driver. ++ */ ++static int mxc_v4l2_master_attach(struct v4l2_int_device *slave) ++{ ++ cam_data *cam = slave->u.slave->master->priv; ++ struct v4l2_format cam_fmt; ++ int i; ++ struct sensor_data *sdata = slave->priv; ++ ++ pr_debug("In MVC: mxc_v4l2_master_attach\n"); ++ pr_debug(" slave.name = %s\n", slave->name); ++ pr_debug(" master.name = %s\n", slave->u.slave->master->name); ++ ++ if (slave == NULL) { ++ pr_err("ERROR: v4l2 capture: slave parameter not valid.\n"); ++ return -1; ++ } ++ ++ if (sdata->csi != cam->csi) { ++ pr_debug("%s: csi doesn't match\n", __func__); ++ return -1; ++ } ++ ++ cam->sensor = slave; ++ ++ if (cam->sensor_index < MXC_SENSOR_NUM) { ++ cam->all_sensors[cam->sensor_index] = slave; ++ cam->sensor_index++; ++ } else { ++ pr_err("ERROR: v4l2 capture: slave number exceeds the maximum.\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < cam->sensor_index; i++) { ++ vidioc_int_dev_exit(cam->all_sensors[i]); ++ vidioc_int_s_power(cam->all_sensors[i], 0); ++ } ++ ++ cam_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vidioc_int_g_fmt_cap(cam->sensor, &cam_fmt); ++ ++ /* Used to detect TV in (type 1) vs. camera (type 0)*/ ++ cam->device_type = cam_fmt.fmt.pix.priv; ++ ++ /* Set the input size to the ipu for this device */ ++ cam->crop_bounds.top = cam->crop_bounds.left = 0; ++ cam->crop_bounds.width = cam_fmt.fmt.pix.width; ++ cam->crop_bounds.height = cam_fmt.fmt.pix.height; ++ ++ /* This also is the max crop size for this device. */ ++ cam->crop_defrect.top = cam->crop_defrect.left = 0; ++ cam->crop_defrect.width = cam_fmt.fmt.pix.width; ++ cam->crop_defrect.height = cam_fmt.fmt.pix.height; ++ ++ /* At this point, this is also the current image size. */ ++ cam->crop_current.top = cam->crop_current.left = 0; ++ cam->crop_current.width = cam_fmt.fmt.pix.width; ++ cam->crop_current.height = cam_fmt.fmt.pix.height; ++ ++ pr_debug("End of %s: v2f pix widthxheight %d x %d\n", ++ __func__, ++ cam->v2f.fmt.pix.width, cam->v2f.fmt.pix.height); ++ pr_debug("End of %s: crop_bounds widthxheight %d x %d\n", ++ __func__, ++ cam->crop_bounds.width, cam->crop_bounds.height); ++ pr_debug("End of %s: crop_defrect widthxheight %d x %d\n", ++ __func__, ++ cam->crop_defrect.width, cam->crop_defrect.height); ++ pr_debug("End of %s: crop_current widthxheight %d x %d\n", ++ __func__, ++ cam->crop_current.width, cam->crop_current.height); ++ ++ return 0; ++} ++ ++/*! ++ * Disconnects the camera driver. ++ */ ++static void mxc_v4l2_master_detach(struct v4l2_int_device *slave) ++{ ++ unsigned int i; ++ cam_data *cam = slave->u.slave->master->priv; ++ ++ pr_debug("In MVC:mxc_v4l2_master_detach\n"); ++ ++ if (cam->sensor_index > 1) { ++ for (i = 0; i < cam->sensor_index; i++) { ++ if (cam->all_sensors[i] != slave) ++ continue; ++ /* Move all the sensors behind this ++ * sensor one step forward ++ */ ++ for (; i <= MXC_SENSOR_NUM - 2; i++) ++ cam->all_sensors[i] = cam->all_sensors[i+1]; ++ break; ++ } ++ /* Point current sensor to the last one */ ++ cam->sensor = cam->all_sensors[cam->sensor_index - 2]; ++ } else ++ cam->sensor = NULL; ++ ++ cam->sensor_index--; ++ vidioc_int_dev_exit(slave); ++} ++ ++/*! ++ * Entry point for the V4L2 ++ * ++ * @return Error code indicating success or failure ++ */ ++static __init int camera_init(void) ++{ ++ u8 err = 0; ++ ++ pr_debug("In MVC:camera_init\n"); ++ ++ /* Register the device driver structure. */ ++ err = platform_driver_register(&mxc_v4l2_driver); ++ if (err != 0) { ++ pr_err("ERROR: v4l2 capture:camera_init: " ++ "platform_driver_register failed.\n"); ++ return err; ++ } ++ ++ return err; ++} ++ ++/*! ++ * Exit and cleanup for the V4L2 ++ */ ++static void __exit camera_exit(void) ++{ ++ pr_debug("In MVC: camera_exit\n"); ++ ++ platform_driver_unregister(&mxc_v4l2_driver); ++} ++ ++module_init(camera_init); ++module_exit(camera_exit); ++ ++module_param(video_nr, int, 0444); ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras"); ++MODULE_LICENSE("GPL"); ++MODULE_SUPPORTED_DEVICE("video"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h linux-imx6-3.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h +--- linux-3.14.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/mxc_v4l2_capture.h 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,260 @@ ++/* ++ * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/*! ++ * @defgroup MXC_V4L2_CAPTURE MXC V4L2 Video Capture Driver ++ */ ++/*! ++ * @file mxc_v4l2_capture.h ++ * ++ * @brief mxc V4L2 capture device API Header file ++ * ++ * It include all the defines for frame operations, also three structure defines ++ * use case ops structure, common v4l2 driver structure and frame structure. ++ * ++ * @ingroup MXC_V4L2_CAPTURE ++ */ ++#ifndef __MXC_V4L2_CAPTURE_H__ ++#define __MXC_V4L2_CAPTURE_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++ ++#define FRAME_NUM 10 ++#define MXC_SENSOR_NUM 2 ++ ++enum imx_v4l2_devtype { ++ IMX5_V4L2, ++ IMX6_V4L2, ++}; ++ ++/*! ++ * v4l2 frame structure. ++ */ ++struct mxc_v4l_frame { ++ u32 paddress; ++ void *vaddress; ++ int count; ++ int width; ++ int height; ++ ++ struct v4l2_buffer buffer; ++ struct list_head queue; ++ int index; ++ union { ++ int ipu_buf_num; ++ int csi_buf_num; ++ }; ++}; ++ ++/* Only for old version. Will go away soon. */ ++typedef struct { ++ u8 clk_mode; ++ u8 ext_vsync; ++ u8 Vsync_pol; ++ u8 Hsync_pol; ++ u8 pixclk_pol; ++ u8 data_pol; ++ u8 data_width; ++ u8 pack_tight; ++ u8 force_eof; ++ u8 data_en_pol; ++ u16 width; ++ u16 height; ++ u32 pixel_fmt; ++ u32 mclk; ++ u16 active_width; ++ u16 active_height; ++} sensor_interface; ++ ++/* Sensor control function */ ++/* Only for old version. Will go away soon. */ ++struct camera_sensor { ++ void (*set_color) (int bright, int saturation, int red, int green, ++ int blue); ++ void (*get_color) (int *bright, int *saturation, int *red, int *green, ++ int *blue); ++ void (*set_ae_mode) (int ae_mode); ++ void (*get_ae_mode) (int *ae_mode); ++ sensor_interface *(*config) (int *frame_rate, int high_quality); ++ sensor_interface *(*reset) (void); ++ void (*get_std) (v4l2_std_id *std); ++ void (*set_std) (v4l2_std_id std); ++ unsigned int csi; ++}; ++ ++/*! ++ * common v4l2 driver structure. ++ */ ++typedef struct _cam_data { ++ struct video_device *video_dev; ++ int device_type; ++ ++ /* semaphore guard against SMP multithreading */ ++ struct semaphore busy_lock; ++ ++ int open_count; ++ ++ /* params lock for this camera */ ++ struct semaphore param_lock; ++ ++ /* Encoder */ ++ struct list_head ready_q; ++ struct list_head done_q; ++ struct list_head working_q; ++ int ping_pong_csi; ++ spinlock_t queue_int_lock; ++ spinlock_t dqueue_int_lock; ++ struct mxc_v4l_frame frame[FRAME_NUM]; ++ struct mxc_v4l_frame dummy_frame; ++ wait_queue_head_t enc_queue; ++ int enc_counter; ++ dma_addr_t rot_enc_bufs[2]; ++ void *rot_enc_bufs_vaddr[2]; ++ int rot_enc_buf_size[2]; ++ enum v4l2_buf_type type; ++ ++ /* still image capture */ ++ wait_queue_head_t still_queue; ++ int still_counter; ++ dma_addr_t still_buf[2]; ++ void *still_buf_vaddr; ++ ++ /* overlay */ ++ struct v4l2_window win; ++ struct v4l2_framebuffer v4l2_fb; ++ dma_addr_t vf_bufs[2]; ++ void *vf_bufs_vaddr[2]; ++ int vf_bufs_size[2]; ++ dma_addr_t rot_vf_bufs[2]; ++ void *rot_vf_bufs_vaddr[2]; ++ int rot_vf_buf_size[2]; ++ bool overlay_active; ++ int output; ++ struct fb_info *overlay_fb; ++ int fb_origin_std; ++ struct work_struct csi_work_struct; ++ ++ /* v4l2 format */ ++ struct v4l2_format v2f; ++ int rotation; /* for IPUv1 and IPUv3, this means encoder rotation */ ++ int vf_rotation; /* viewfinder rotation only for IPUv1 and IPUv3 */ ++ struct v4l2_mxc_offset offset; ++ ++ /* V4l2 control bit */ ++ int bright; ++ int hue; ++ int contrast; ++ int saturation; ++ int red; ++ int green; ++ int blue; ++ int ae_mode; ++ ++ /* standard */ ++ struct v4l2_streamparm streamparm; ++ struct v4l2_standard standard; ++ bool standard_autodetect; ++ ++ /* crop */ ++ struct v4l2_rect crop_bounds; ++ struct v4l2_rect crop_defrect; ++ struct v4l2_rect crop_current; ++ ++ int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, ++ int *bufferNum); ++ int (*enc_enable) (void *private); ++ int (*enc_disable) (void *private); ++ int (*enc_enable_csi) (void *private); ++ int (*enc_disable_csi) (void *private); ++ void (*enc_callback) (u32 mask, void *dev); ++ int (*vf_start_adc) (void *private); ++ int (*vf_stop_adc) (void *private); ++ int (*vf_start_sdc) (void *private); ++ int (*vf_stop_sdc) (void *private); ++ int (*vf_enable_csi) (void *private); ++ int (*vf_disable_csi) (void *private); ++ int (*csi_start) (void *private); ++ int (*csi_stop) (void *private); ++ ++ /* misc status flag */ ++ bool overlay_on; ++ bool capture_on; ++ int overlay_pid; ++ int capture_pid; ++ bool low_power; ++ wait_queue_head_t power_queue; ++ unsigned int ipu_id; ++ unsigned int csi; ++ u8 mclk_source; ++ bool mclk_on[2]; /* two mclk sources at most now */ ++ int current_input; ++ ++ int local_buf_num; ++ ++ /* camera sensor interface */ ++ struct camera_sensor *cam_sensor; /* old version */ ++ struct v4l2_int_device *all_sensors[MXC_SENSOR_NUM]; ++ struct v4l2_int_device *sensor; ++ struct v4l2_int_device *self; ++ int sensor_index; ++ void *ipu; ++ enum imx_v4l2_devtype devtype; ++ ++ /* v4l2 buf elements related to PxP DMA */ ++ struct completion pxp_tx_cmpl; ++ struct pxp_channel *pxp_chan; ++ struct pxp_config_data pxp_conf; ++ struct dma_async_tx_descriptor *txd; ++ dma_cookie_t cookie; ++ struct scatterlist sg[2]; ++} cam_data; ++ ++struct sensor_data { ++ const struct ov5642_platform_data *platform_data; ++ struct v4l2_int_device *v4l2_int_device; ++ struct i2c_client *i2c_client; ++ struct v4l2_pix_format pix; ++ struct v4l2_captureparm streamcap; ++ bool on; ++ ++ /* control settings */ ++ int brightness; ++ int hue; ++ int contrast; ++ int saturation; ++ int red; ++ int green; ++ int blue; ++ int ae_mode; ++ ++ u32 mclk; ++ u8 mclk_source; ++ struct clk *sensor_clk; ++ int csi; ++ ++ void (*io_init)(void); ++}; ++ ++void set_mclk_rate(uint32_t *p_mclk_freq, uint32_t csi); ++#endif /* __MXC_V4L2_CAPTURE_H__ */ +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ov5640.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5640.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ov5640.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5640.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,1951 @@ ++/* ++ * Copyright (C) 2012-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. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.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 ++ ++#define OV5640_XCLK_MIN 6000000 ++#define OV5640_XCLK_MAX 24000000 ++ ++#define OV5640_CHIP_ID_HIGH_BYTE 0x300A ++#define OV5640_CHIP_ID_LOW_BYTE 0x300B ++ ++enum ov5640_mode { ++ ov5640_mode_MIN = 0, ++ ov5640_mode_VGA_640_480 = 0, ++ ov5640_mode_QVGA_320_240 = 1, ++ ov5640_mode_NTSC_720_480 = 2, ++ ov5640_mode_PAL_720_576 = 3, ++ ov5640_mode_720P_1280_720 = 4, ++ ov5640_mode_1080P_1920_1080 = 5, ++ ov5640_mode_QSXGA_2592_1944 = 6, ++ ov5640_mode_QCIF_176_144 = 7, ++ ov5640_mode_XGA_1024_768 = 8, ++ ov5640_mode_MAX = 8 ++}; ++ ++enum ov5640_frame_rate { ++ ov5640_15_fps, ++ ov5640_30_fps ++}; ++ ++static int ov5640_framerates[] = { ++ [ov5640_15_fps] = 15, ++ [ov5640_30_fps] = 30, ++}; ++ ++struct reg_value { ++ u16 u16RegAddr; ++ u8 u8Val; ++ u8 u8Mask; ++ u32 u32Delay_ms; ++}; ++ ++struct ov5640_mode_info { ++ enum ov5640_mode mode; ++ u32 width; ++ u32 height; ++ struct reg_value *init_data_ptr; ++ u32 init_data_size; ++}; ++ ++/*! ++ * Maintains the information on the current state of the sesor. ++ */ ++static struct sensor_data ov5640_data; ++static int pwn_gpio, rst_gpio; ++static int prev_sysclk; ++static int AE_Target = 52, night_mode; ++static int prev_HTS; ++static int AE_high, AE_low; ++ ++static struct reg_value ov5640_global_init_setting[] = { ++ {0x3008, 0x42, 0, 0}, ++ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0}, ++ {0x3034, 0x1a, 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, 0x7c, 0, 0}, ++ {0x3635, 0x13, 0, 0}, {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, ++ {0x3622, 0x01, 0, 0}, {0x3c01, 0x34, 0, 0}, {0x3c04, 0x28, 0, 0}, ++ {0x3c05, 0x98, 0, 0}, {0x3c06, 0x00, 0, 0}, {0x3c07, 0x07, 0, 0}, ++ {0x3c08, 0x00, 0, 0}, {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, ++ {0x3c0b, 0x40, 0, 0}, {0x3810, 0x00, 0, 0}, {0x3811, 0x10, 0, 0}, ++ {0x3812, 0x00, 0, 0}, {0x3708, 0x64, 0, 0}, {0x4001, 0x02, 0, 0}, ++ {0x4005, 0x1a, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, ++ {0x300e, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, ++ {0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x5000, 0xa7, 0, 0}, ++ {0x3008, 0x02, 0, 0}, ++}; ++ ++static struct reg_value ov5640_init_setting_30fps_VGA[] = { ++ {0x3008, 0x42, 0, 0}, ++ {0x3103, 0x03, 0, 0}, {0x3017, 0xff, 0, 0}, {0x3018, 0xff, 0, 0}, ++ {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, {0x3036, 0x46, 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, 0x34, 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, 0x58, 0, 0}, {0x302e, 0x00, 0, 0}, {0x4300, 0x30, 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, 0x22, 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}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_VGA_640_480[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_VGA_640_480[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, {0x3503, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_QVGA_320_240[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_QVGA_320_240[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_NTSC_720_480[] = { ++ {0x3c07, 0x08, 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, 0x06, 0, 0}, ++ {0x3807, 0xd4, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_NTSC_720_480[] = { ++ {0x3c07, 0x08, 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, 0x06, 0, 0}, ++ {0x3807, 0xd4, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_PAL_720_576[] = { ++ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, ++ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, ++ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, ++ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_PAL_720_576[] = { ++ {0x3c07, 0x08, 0, 0}, {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, ++ {0x3814, 0x31, 0, 0}, {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, ++ {0x3801, 0x60, 0, 0}, {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, ++ {0x3804, 0x09, 0, 0}, {0x3805, 0x7e, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_720P_1280_720[] = { ++ {0x3035, 0x21, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 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}, {0x3813, 0x04, 0, 0}, ++ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0}, ++ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0}, ++ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0}, ++ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, ++ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, ++ {0x3503, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_720P_1280_720[] = { ++ {0x3035, 0x41, 0, 0}, {0x3036, 0x69, 0, 0}, {0x3c07, 0x07, 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}, {0x3813, 0x04, 0, 0}, ++ {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3709, 0x52, 0, 0}, ++ {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0}, {0x3a03, 0xe0, 0, 0}, ++ {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe0, 0, 0}, {0x4004, 0x02, 0, 0}, ++ {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, {0x4713, 0x03, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, ++ {0x4837, 0x16, 0, 0}, {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0}, ++ {0x3503, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_QCIF_176_144[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x11, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_QCIF_176_144[] = { ++ {0x3c07, 0x08, 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}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x02, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = { ++ {0x3c07, 0x08, 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, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, ++ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0}, ++ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_XGA_1024_768[] = { ++ {0x3c07, 0x08, 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, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, ++ {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0}, {0x380c, 0x07, 0, 0}, ++ {0x380d, 0x68, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, ++ {0x3813, 0x06, 0, 0}, {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, ++ {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x0b, 0, 0}, ++ {0x3a03, 0x88, 0, 0}, {0x3a14, 0x0b, 0, 0}, {0x3a15, 0x88, 0, 0}, ++ {0x4004, 0x02, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x4837, 0x22, 0, 0}, {0x3824, 0x01, 0, 0}, ++ {0x5001, 0xa3, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x46, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++ ++static struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = { ++ {0x3c07, 0x07, 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, 0xee, 0, 0}, ++ {0x3804, 0x0a, 0, 0}, {0x3805, 0x3f, 0, 0}, {0x3806, 0x05, 0, 0}, ++ {0x3807, 0xc3, 0, 0}, {0x3808, 0x07, 0, 0}, {0x3809, 0x80, 0, 0}, ++ {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, {0x380c, 0x0b, 0, 0}, ++ {0x380d, 0x1c, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, ++ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0}, ++ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0}, ++ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0}, ++ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0}, ++ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = { ++ {0x3c07, 0x07, 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}, ++ {0x3813, 0x04, 0, 0}, {0x3618, 0x04, 0, 0}, {0x3612, 0x2b, 0, 0}, ++ {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x07, 0, 0}, ++ {0x3a03, 0xae, 0, 0}, {0x3a14, 0x07, 0, 0}, {0x3a15, 0xae, 0, 0}, ++ {0x4004, 0x06, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3006, 0xc3, 0, 0}, ++ {0x4713, 0x02, 0, 0}, {0x4407, 0x0c, 0, 0}, {0x460b, 0x37, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x4837, 0x2c, 0, 0}, {0x3824, 0x01, 0, 0}, ++ {0x5001, 0x83, 0, 0}, {0x3034, 0x1a, 0, 0}, {0x3035, 0x21, 0, 0}, ++ {0x3036, 0x69, 0, 0}, {0x3037, 0x13, 0, 0}, ++}; ++ ++static struct ov5640_mode_info ov5640_mode_info_data[2][ov5640_mode_MAX + 1] = { ++ { ++ {ov5640_mode_VGA_640_480, 640, 480, ++ ov5640_setting_15fps_VGA_640_480, ++ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)}, ++ {ov5640_mode_QVGA_320_240, 320, 240, ++ ov5640_setting_15fps_QVGA_320_240, ++ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)}, ++ {ov5640_mode_NTSC_720_480, 720, 480, ++ ov5640_setting_15fps_NTSC_720_480, ++ ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)}, ++ {ov5640_mode_PAL_720_576, 720, 576, ++ ov5640_setting_15fps_PAL_720_576, ++ ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)}, ++ {ov5640_mode_720P_1280_720, 1280, 720, ++ ov5640_setting_15fps_720P_1280_720, ++ ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)}, ++ {ov5640_mode_1080P_1920_1080, 1920, 1080, ++ ov5640_setting_15fps_1080P_1920_1080, ++ ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)}, ++ {ov5640_mode_QSXGA_2592_1944, 2592, 1944, ++ ov5640_setting_15fps_QSXGA_2592_1944, ++ ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)}, ++ {ov5640_mode_QCIF_176_144, 176, 144, ++ ov5640_setting_15fps_QCIF_176_144, ++ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)}, ++ {ov5640_mode_XGA_1024_768, 1024, 768, ++ ov5640_setting_15fps_XGA_1024_768, ++ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)}, ++ }, ++ { ++ {ov5640_mode_VGA_640_480, 640, 480, ++ ov5640_setting_30fps_VGA_640_480, ++ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)}, ++ {ov5640_mode_QVGA_320_240, 320, 240, ++ ov5640_setting_30fps_QVGA_320_240, ++ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)}, ++ {ov5640_mode_NTSC_720_480, 720, 480, ++ ov5640_setting_30fps_NTSC_720_480, ++ ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)}, ++ {ov5640_mode_PAL_720_576, 720, 576, ++ ov5640_setting_30fps_PAL_720_576, ++ ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)}, ++ {ov5640_mode_720P_1280_720, 1280, 720, ++ ov5640_setting_30fps_720P_1280_720, ++ ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)}, ++ {ov5640_mode_1080P_1920_1080, 0, 0, NULL, 0}, ++ {ov5640_mode_QSXGA_2592_1944, 0, 0, NULL, 0}, ++ {ov5640_mode_QCIF_176_144, 176, 144, ++ ov5640_setting_30fps_QCIF_176_144, ++ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)}, ++ {ov5640_mode_XGA_1024_768, 1024, 768, ++ ov5640_setting_30fps_XGA_1024_768, ++ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)}, ++ }, ++}; ++ ++static struct regulator *io_regulator; ++static struct regulator *core_regulator; ++static struct regulator *analog_regulator; ++ ++static int ov5640_probe(struct i2c_client *adapter, ++ const struct i2c_device_id *device_id); ++static int ov5640_remove(struct i2c_client *client); ++ ++static s32 ov5640_read_reg(u16 reg, u8 *val); ++static s32 ov5640_write_reg(u16 reg, u8 val); ++ ++static const struct i2c_device_id ov5640_id[] = { ++ {"ov5640", 0}, ++ {"ov564x", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, ov5640_id); ++ ++static struct i2c_driver ov5640_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ov5640", ++ }, ++ .probe = ov5640_probe, ++ .remove = ov5640_remove, ++ .id_table = ov5640_id, ++}; ++ ++static inline void ov5640_power_down(int enable) ++{ ++ gpio_set_value(pwn_gpio, enable); ++ ++ msleep(2); ++} ++ ++static inline void ov5640_reset(void) ++{ ++ /* camera reset */ ++ gpio_set_value(rst_gpio, 1); ++ ++ /* camera power down */ ++ gpio_set_value(pwn_gpio, 1); ++ msleep(5); ++ gpio_set_value(pwn_gpio, 0); ++ msleep(5); ++ gpio_set_value(rst_gpio, 0); ++ msleep(1); ++ gpio_set_value(rst_gpio, 1); ++ msleep(5); ++ gpio_set_value(pwn_gpio, 1); ++} ++ ++static int ov5640_regulator_enable(struct device *dev) ++{ ++ int ret = 0; ++ ++ io_regulator = devm_regulator_get(dev, "DOVDD"); ++ if (!IS_ERR(io_regulator)) { ++ regulator_set_voltage(io_regulator, ++ OV5640_VOLTAGE_DIGITAL_IO, ++ OV5640_VOLTAGE_DIGITAL_IO); ++ ret = regulator_enable(io_regulator); ++ if (ret) { ++ dev_err(dev, "set io voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set io voltage ok\n"); ++ } ++ } else { ++ io_regulator = NULL; ++ dev_warn(dev, "cannot get io voltage\n"); ++ } ++ ++ core_regulator = devm_regulator_get(dev, "DVDD"); ++ if (!IS_ERR(core_regulator)) { ++ regulator_set_voltage(core_regulator, ++ OV5640_VOLTAGE_DIGITAL_CORE, ++ OV5640_VOLTAGE_DIGITAL_CORE); ++ ret = regulator_enable(core_regulator); ++ if (ret) { ++ dev_err(dev, "set core voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set core voltage ok\n"); ++ } ++ } else { ++ core_regulator = NULL; ++ dev_warn(dev, "cannot get core voltage\n"); ++ } ++ ++ analog_regulator = devm_regulator_get(dev, "AVDD"); ++ if (!IS_ERR(analog_regulator)) { ++ regulator_set_voltage(analog_regulator, ++ OV5640_VOLTAGE_ANALOG, ++ OV5640_VOLTAGE_ANALOG); ++ ret = regulator_enable(analog_regulator); ++ if (ret) { ++ dev_err(dev, "set analog voltage failed\n"); ++ return ret; ++ } else { ++ dev_dbg(dev, "set analog voltage ok\n"); ++ } ++ } else { ++ analog_regulator = NULL; ++ dev_warn(dev, "cannot get analog voltage\n"); ++ } ++ ++ return ret; ++} ++ ++static s32 ov5640_write_reg(u16 reg, u8 val) ++{ ++ u8 au8Buf[3] = {0}; ++ ++ au8Buf[0] = reg >> 8; ++ au8Buf[1] = reg & 0xff; ++ au8Buf[2] = val; ++ ++ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) { ++ pr_err("%s:write reg error:reg=%x,val=%x\n", ++ __func__, reg, val); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static s32 ov5640_read_reg(u16 reg, u8 *val) ++{ ++ u8 au8RegBuf[2] = {0}; ++ u8 u8RdVal = 0; ++ ++ au8RegBuf[0] = reg >> 8; ++ au8RegBuf[1] = reg & 0xff; ++ ++ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) { ++ pr_err("%s:write reg error:reg=%x\n", ++ __func__, reg); ++ return -1; ++ } ++ ++ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) { ++ pr_err("%s:read reg error:reg=%x,val=%x\n", ++ __func__, reg, u8RdVal); ++ return -1; ++ } ++ ++ *val = u8RdVal; ++ ++ return u8RdVal; ++} ++ ++static void ov5640_soft_reset(void) ++{ ++ /* sysclk from pad */ ++ ov5640_write_reg(0x3103, 0x11); ++ ++ /* software reset */ ++ ov5640_write_reg(0x3008, 0x82); ++ ++ /* delay at least 5ms */ ++ msleep(10); ++} ++ ++/* set sensor driver capability ++ * 0x302c[7:6] - strength ++ 00 - 1x ++ 01 - 2x ++ 10 - 3x ++ 11 - 4x ++ */ ++static int ov5640_driver_capability(int strength) ++{ ++ u8 temp = 0; ++ ++ if (strength > 4 || strength < 1) { ++ pr_err("The valid driver capability of ov5640 is 1x~4x\n"); ++ return -EINVAL; ++ } ++ ++ ov5640_read_reg(0x302c, &temp); ++ ++ temp &= ~0xc0; /* clear [7:6] */ ++ temp |= ((strength - 1) << 6); /* set [7:6] */ ++ ++ ov5640_write_reg(0x302c, temp); ++ ++ return 0; ++} ++ ++/* calculate sysclk */ ++static int ov5640_get_sysclk(void) ++{ ++ int xvclk = ov5640_data.mclk / 10000; ++ int sysclk; ++ int temp1, temp2; ++ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv, Bit_div2x, sclk_rdiv; ++ int sclk_rdiv_map[] = {1, 2, 4, 8}; ++ u8 regval = 0; ++ ++ temp1 = ov5640_read_reg(0x3034, ®val); ++ temp2 = temp1 & 0x0f; ++ if (temp2 == 8 || temp2 == 10) { ++ Bit_div2x = temp2 / 2; ++ } else { ++ pr_err("ov5640: unsupported bit mode %d\n", temp2); ++ return -1; ++ } ++ ++ temp1 = ov5640_read_reg(0x3035, ®val); ++ SysDiv = temp1 >> 4; ++ if (SysDiv == 0) ++ SysDiv = 16; ++ ++ temp1 = ov5640_read_reg(0x3036, ®val); ++ Multiplier = temp1; ++ temp1 = ov5640_read_reg(0x3037, ®val); ++ PreDiv = temp1 & 0x0f; ++ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1; ++ ++ temp1 = ov5640_read_reg(0x3108, ®val); ++ 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; ++} ++ ++/* read HTS from register settings */ ++static int ov5640_get_HTS(void) ++{ ++ int HTS; ++ u8 temp = 0; ++ ++ HTS = ov5640_read_reg(0x380c, &temp); ++ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp); ++ return HTS; ++} ++ ++/* read VTS from register settings */ ++static int ov5640_get_VTS(void) ++{ ++ int VTS; ++ u8 temp = 0; ++ ++ VTS = ov5640_read_reg(0x380e, &temp); ++ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp); ++ ++ return VTS; ++} ++ ++/* write VTS to registers */ ++static int ov5640_set_VTS(int VTS) ++{ ++ int temp; ++ ++ temp = VTS & 0xff; ++ ov5640_write_reg(0x380f, temp); ++ ++ temp = VTS>>8; ++ ov5640_write_reg(0x380e, temp); ++ return 0; ++} ++ ++/* read shutter, in number of line period */ ++static int ov5640_get_shutter(void) ++{ ++ int shutter; ++ u8 regval; ++ ++ shutter = (ov5640_read_reg(0x03500, ®val) & 0x0f); ++ ++ shutter = (shutter<<8) + ov5640_read_reg(0x3501, ®val); ++ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, ®val)>>4); ++ ++ return shutter; ++} ++ ++/* write shutter, in number of line period */ ++static int ov5640_set_shutter(int shutter) ++{ ++ int temp; ++ ++ shutter = shutter & 0xffff; ++ temp = shutter & 0x0f; ++ temp = temp<<4; ++ ov5640_write_reg(0x3502, temp); ++ ++ temp = shutter & 0xfff; ++ temp = temp>>4; ++ ov5640_write_reg(0x3501, temp); ++ ++ temp = shutter>>12; ++ ov5640_write_reg(0x3500, temp); ++ ++ return 0; ++} ++ ++/* read gain, 16 = 1x */ ++static int ov5640_get_gain16(void) ++{ ++ int gain16; ++ u8 regval; ++ ++ gain16 = ov5640_read_reg(0x350a, ®val) & 0x03; ++ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, ®val); ++ ++ return gain16; ++} ++ ++/* write gain, 16 = 1x */ ++static int ov5640_set_gain16(int gain16) ++{ ++ int temp; ++ ++ gain16 = gain16 & 0x3ff; ++ temp = gain16 & 0xff; ++ ++ ov5640_write_reg(0x350b, temp); ++ temp = gain16>>8; ++ ++ ov5640_write_reg(0x350a, temp); ++ return 0; ++} ++ ++/* get banding filter value */ ++static int ov5640_get_light_freq(void) ++{ ++ int temp, temp1, light_frequency; ++ u8 regval; ++ ++ temp = ov5640_read_reg(0x3c01, ®val); ++ if (temp & 0x80) { ++ /* manual */ ++ temp1 = ov5640_read_reg(0x3c00, ®val); ++ if (temp1 & 0x04) { ++ /* 50Hz */ ++ light_frequency = 50; ++ } else { ++ /* 60Hz */ ++ light_frequency = 60; ++ } ++ } else { ++ /* auto */ ++ temp1 = ov5640_read_reg(0x3c0c, ®val); ++ if (temp1 & 0x01) { ++ /* 50Hz */ ++ light_frequency = 50; ++ } else { ++ /* 60Hz */ ++ light_frequency = 60; ++ } ++ } ++ ++ return light_frequency; ++} ++ ++static void ov5640_set_bandingfilter(void) ++{ ++ int prev_VTS; ++ int band_step60, max_band60, band_step50, max_band50; ++ ++ /* read preview PCLK */ ++ prev_sysclk = ov5640_get_sysclk(); ++ ++ /* read preview HTS */ ++ prev_HTS = ov5640_get_HTS(); ++ ++ /* read preview VTS */ ++ prev_VTS = ov5640_get_VTS(); ++ ++ /* calculate banding filter */ ++ /* 60Hz */ ++ band_step60 = prev_sysclk * 100/prev_HTS * 100/120; ++ ov5640_write_reg(0x3a0a, (band_step60 >> 8)); ++ ov5640_write_reg(0x3a0b, (band_step60 & 0xff)); ++ ++ max_band60 = (int)((prev_VTS-4)/band_step60); ++ ov5640_write_reg(0x3a0d, max_band60); ++ ++ /* 50Hz */ ++ band_step50 = prev_sysclk * 100/prev_HTS; ++ ov5640_write_reg(0x3a08, (band_step50 >> 8)); ++ ov5640_write_reg(0x3a09, (band_step50 & 0xff)); ++ ++ max_band50 = (int)((prev_VTS-4)/band_step50); ++ ov5640_write_reg(0x3a0e, max_band50); ++} ++ ++/* stable in high */ ++static int ov5640_set_AE_target(int target) ++{ ++ int fast_high, fast_low; ++ ++ AE_low = target * 23 / 25; /* 0.92 */ ++ AE_high = target * 27 / 25; /* 1.08 */ ++ fast_high = AE_high << 1; ++ ++ if (fast_high > 255) ++ fast_high = 255; ++ fast_low = AE_low >> 1; ++ ++ ov5640_write_reg(0x3a0f, AE_high); ++ ov5640_write_reg(0x3a10, AE_low); ++ ov5640_write_reg(0x3a1b, AE_high); ++ ov5640_write_reg(0x3a1e, AE_low); ++ ov5640_write_reg(0x3a11, fast_high); ++ ov5640_write_reg(0x3a1f, fast_low); ++ ++ return 0; ++} ++ ++/* enable = 0 to turn off night mode ++ enable = 1 to turn on night mode */ ++static int ov5640_set_night_mode(int enable) ++{ ++ u8 mode; ++ ++ ov5640_read_reg(0x3a00, &mode); ++ ++ if (enable) { ++ /* night mode on */ ++ mode |= 0x04; ++ ov5640_write_reg(0x3a00, mode); ++ } else { ++ /* night mode off */ ++ mode &= 0xfb; ++ ov5640_write_reg(0x3a00, mode); ++ } ++ ++ return 0; ++} ++ ++/* enable = 0 to turn off AEC/AGC ++ enable = 1 to turn on AEC/AGC */ ++void ov5640_turn_on_AE_AG(int enable) ++{ ++ u8 ae_ag_ctrl; ++ ++ ov5640_read_reg(0x3503, &ae_ag_ctrl); ++ if (enable) { ++ /* turn on auto AE/AG */ ++ ae_ag_ctrl = ae_ag_ctrl & ~(0x03); ++ } else { ++ /* turn off AE/AG */ ++ ae_ag_ctrl = ae_ag_ctrl | 0x03; ++ } ++ ov5640_write_reg(0x3503, ae_ag_ctrl); ++} ++ ++/* download ov5640 settings to sensor through i2c */ ++static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize) ++{ ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int i, retval = 0; ++ ++ for (i = 0; i < ArySize; ++i, ++pModeSetting) { ++ Delay_ms = pModeSetting->u32Delay_ms; ++ RegAddr = pModeSetting->u16RegAddr; ++ Val = pModeSetting->u8Val; ++ Mask = pModeSetting->u8Mask; ++ ++ if (Mask) { ++ retval = ov5640_read_reg(RegAddr, &RegVal); ++ if (retval < 0) ++ goto err; ++ ++ RegVal &= ~(u8)Mask; ++ Val &= Mask; ++ Val |= RegVal; ++ } ++ ++ retval = ov5640_write_reg(RegAddr, Val); ++ if (retval < 0) ++ goto err; ++ ++ if (Delay_ms) ++ msleep(Delay_ms); ++ } ++err: ++ return retval; ++} ++ ++static int ov5640_init_mode(void) ++{ ++ struct reg_value *pModeSetting = NULL; ++ int ArySize = 0, retval = 0; ++ ++ ov5640_soft_reset(); ++ ++ pModeSetting = ov5640_global_init_setting; ++ ArySize = ARRAY_SIZE(ov5640_global_init_setting); ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ pModeSetting = ov5640_init_setting_30fps_VGA; ++ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA); ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ /* change driver capability to 2x according to validation board. ++ * if the image is not stable, please increase the driver strength. ++ */ ++ ov5640_driver_capability(2); ++ ov5640_set_bandingfilter(); ++ ov5640_set_AE_target(AE_Target); ++ ov5640_set_night_mode(night_mode); ++ ++ /* skip 9 vysnc: start capture at 10th vsync */ ++ msleep(300); ++ ++ /* turn off night mode */ ++ night_mode = 0; ++ ov5640_data.pix.width = 640; ++ ov5640_data.pix.height = 480; ++err: ++ return retval; ++} ++ ++/* change to or back to subsampling mode set the mode directly ++ * image size below 1280 * 960 is subsampling mode */ ++static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 ArySize = 0; ++ int retval = 0; ++ ++ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) { ++ pr_err("Wrong ov5640 mode detected!\n"); ++ return -1; ++ } ++ ++ pModeSetting = ov5640_mode_info_data[frame_rate][mode].init_data_ptr; ++ ArySize = ++ ov5640_mode_info_data[frame_rate][mode].init_data_size; ++ ++ ov5640_data.pix.width = ov5640_mode_info_data[frame_rate][mode].width; ++ ov5640_data.pix.height = ov5640_mode_info_data[frame_rate][mode].height; ++ ++ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || ++ pModeSetting == NULL || ArySize == 0) ++ return -EINVAL; ++ ++ /* set ov5640 to subsampling mode */ ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ ++ /* turn on AE AG for subsampling mode, in case the firmware didn't */ ++ ov5640_turn_on_AE_AG(1); ++ ++ /* calculate banding filter */ ++ ov5640_set_bandingfilter(); ++ ++ /* set AE target */ ++ ov5640_set_AE_target(AE_Target); ++ ++ /* update night mode setting */ ++ ov5640_set_night_mode(night_mode); ++ ++ /* skip 9 vysnc: start capture at 10th vsync */ ++ if (mode == ov5640_mode_XGA_1024_768 && frame_rate == ov5640_30_fps) { ++ pr_warning("ov5640: actual frame rate of XGA is 22.5fps\n"); ++ /* 1/22.5 * 9*/ ++ msleep(400); ++ return retval; ++ } ++ ++ if (frame_rate == ov5640_15_fps) { ++ /* 1/15 * 9*/ ++ msleep(600); ++ } else if (frame_rate == ov5640_30_fps) { ++ /* 1/30 * 9*/ ++ msleep(300); ++ } ++ ++ return retval; ++} ++ ++/* change to scaling mode go through exposure calucation ++ * image size above 1280 * 960 is scaling mode */ ++static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode) ++{ ++ int prev_shutter, prev_gain16, average; ++ int cap_shutter, cap_gain16; ++ int cap_sysclk, cap_HTS, cap_VTS; ++ int light_freq, cap_bandfilt, cap_maxband; ++ long cap_gain16_shutter; ++ u8 temp; ++ struct reg_value *pModeSetting = NULL; ++ s32 ArySize = 0; ++ int retval = 0; ++ ++ /* check if the input mode and frame rate is valid */ ++ pModeSetting = ++ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; ++ ArySize = ++ ov5640_mode_info_data[frame_rate][mode].init_data_size; ++ ++ ov5640_data.pix.width = ++ ov5640_mode_info_data[frame_rate][mode].width; ++ ov5640_data.pix.height = ++ ov5640_mode_info_data[frame_rate][mode].height; ++ ++ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || ++ pModeSetting == NULL || ArySize == 0) ++ return -EINVAL; ++ ++ /* read preview shutter */ ++ prev_shutter = ov5640_get_shutter(); ++ ++ /* read preview gain */ ++ prev_gain16 = ov5640_get_gain16(); ++ ++ /* get average */ ++ average = ov5640_read_reg(0x56a1, &temp); ++ ++ /* turn off night mode for capture */ ++ ov5640_set_night_mode(0); ++ ++ /* turn off overlay */ ++ ov5640_write_reg(0x3022, 0x06); ++ ++ /* Write capture setting */ ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ /* turn off AE AG when capture image. */ ++ ov5640_turn_on_AE_AG(0); ++ ++ /* read capture VTS */ ++ cap_VTS = ov5640_get_VTS(); ++ cap_HTS = ov5640_get_HTS(); ++ cap_sysclk = ov5640_get_sysclk(); ++ ++ /* calculate capture banding filter */ ++ light_freq = ov5640_get_light_freq(); ++ 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 > AE_low && average < AE_high) { ++ /* in stable range */ ++ cap_gain16_shutter = ++ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk * ++ prev_HTS/cap_HTS * AE_Target / average; ++ } else { ++ cap_gain16_shutter = ++ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk * ++ 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 =< max, cap_shutter = n/100 */ ++ cap_shutter = ++ ((int)(cap_gain16_shutter/16/cap_bandfilt)) ++ * cap_bandfilt; ++ cap_gain16 = cap_gain16_shutter / cap_shutter; ++ } ++ } ++ ++ /* write capture gain */ ++ ov5640_set_gain16(cap_gain16); ++ ++ /* write capture shutter */ ++ if (cap_shutter > (cap_VTS - 4)) { ++ cap_VTS = cap_shutter + 4; ++ ov5640_set_VTS(cap_VTS); ++ } ++ ++ ov5640_set_shutter(cap_shutter); ++ ++ /* skip 2 vysnc: start capture at 3rd vsync ++ * frame rate of QSXGA and 1080P is 7.5fps: 1/7.5 * 2 ++ */ ++ pr_warning("ov5640: the actual frame rate of %s is 7.5fps\n", ++ mode == ov5640_mode_1080P_1920_1080 ? "1080P" : "QSXGA"); ++ msleep(267); ++err: ++ return retval; ++} ++ ++static int ov5640_change_mode(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode) ++{ ++ int retval = 0; ++ ++ if (mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) { ++ pr_err("Wrong ov5640 mode detected!\n"); ++ return -1; ++ } ++ ++ if (mode == ov5640_mode_1080P_1920_1080 || ++ mode == ov5640_mode_QSXGA_2592_1944) { ++ /* change to scaling mode go through exposure calucation ++ * image size above 1280 * 960 is scaling mode */ ++ retval = ov5640_change_mode_exposure_calc(frame_rate, mode); ++ } else { ++ /* change back to subsampling modem download firmware directly ++ * image size below 1280 * 960 is subsampling mode */ ++ retval = ov5640_change_mode_direct(frame_rate, mode); ++ } ++ ++ return retval; ++} ++ ++/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ ++ ++static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) ++{ ++ if (s == NULL) { ++ pr_err(" ERROR!! no slave device set!\n"); ++ return -1; ++ } ++ ++ memset(p, 0, sizeof(*p)); ++ p->u.bt656.clock_curr = ov5640_data.mclk; ++ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk); ++ p->if_type = V4L2_IF_TYPE_BT656; ++ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; ++ p->u.bt656.clock_min = OV5640_XCLK_MIN; ++ p->u.bt656.clock_max = OV5640_XCLK_MAX; ++ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @on: indicates power mode (on or off) ++ * ++ * Turns the power on or off, depending on the value of on and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_power(struct v4l2_int_device *s, int on) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ if (on && !sensor->on) { ++ if (io_regulator) ++ if (regulator_enable(io_regulator) != 0) ++ return -EIO; ++ if (core_regulator) ++ if (regulator_enable(core_regulator) != 0) ++ return -EIO; ++ if (analog_regulator) ++ if (regulator_enable(analog_regulator) != 0) ++ return -EIO; ++ /* Make sure power on */ ++ ov5640_power_down(0); ++ } else if (!on && sensor->on) { ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ ++ ov5640_power_down(1); ++} ++ ++ sensor->on = on; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure ++ * ++ * Returns the sensor's video CAPTURE parameters. ++ */ ++static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_captureparm *cparm = &a->parm.capture; ++ int ret = 0; ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ 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; ++ ret = 0; ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure ++ * ++ * Configures the sensor to use the input parameters, if possible. If ++ * not possible, reverts to the old parameters and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; ++ u32 tgt_fps; /* target frames per secound */ ++ enum ov5640_frame_rate frame_rate; ++ int ret = 0; ++ ++ /* Make sure power on */ ++ ov5640_power_down(0); ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ /* 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 { ++ pr_err(" The camera frame rate is not supported!\n"); ++ return -EINVAL; ++ } ++ ++ ret = ov5640_change_mode(frame_rate, ++ a->parm.capture.capturemode); ++ if (ret < 0) ++ return ret; ++ ++ sensor->streamcap.timeperframe = *timeperframe; ++ sensor->streamcap.capturemode = a->parm.capture.capturemode; ++ ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ pr_debug(" type is not " \ ++ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", ++ a->type); ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap ++ * @s: pointer to standard V4L2 device structure ++ * @f: pointer to standard V4L2 v4l2_format structure ++ * ++ * Returns the sensor's current pixel format in the v4l2_format ++ * parameter. ++ */ ++static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ f->fmt.pix = sensor->pix; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure ++ * ++ * If the requested control is supported, returns the control's current ++ * value from the video_control[] array. Otherwise, returns -EINVAL ++ * if the control is not supported. ++ */ ++static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int ret = 0; ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ vc->value = ov5640_data.brightness; ++ break; ++ case V4L2_CID_HUE: ++ vc->value = ov5640_data.hue; ++ break; ++ case V4L2_CID_CONTRAST: ++ vc->value = ov5640_data.contrast; ++ break; ++ case V4L2_CID_SATURATION: ++ vc->value = ov5640_data.saturation; ++ break; ++ case V4L2_CID_RED_BALANCE: ++ vc->value = ov5640_data.red; ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ vc->value = ov5640_data.blue; ++ break; ++ case V4L2_CID_EXPOSURE: ++ vc->value = ov5640_data.ae_mode; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure ++ * ++ * If the requested control is supported, sets the control's current ++ * value in HW (and updates the video_control[] array). Otherwise, ++ * returns -EINVAL if the control is not supported. ++ */ ++static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int retval = 0; ++ ++ pr_debug("In ov5640:ioctl_s_ctrl %d\n", ++ vc->id); ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_DO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_RED_BALANCE: ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ break; ++ case V4L2_CID_HFLIP: ++ break; ++ case V4L2_CID_VFLIP: ++ break; ++ default: ++ retval = -EPERM; ++ break; ++ } ++ ++ return retval; ++} ++ ++/*! ++ * ioctl_enum_framesizes - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMESIZES ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_framesizes(struct v4l2_int_device *s, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ if (fsize->index > ov5640_mode_MAX) ++ return -EINVAL; ++ ++ fsize->pixel_format = ov5640_data.pix.pixelformat; ++ fsize->discrete.width = ++ max(ov5640_mode_info_data[0][fsize->index].width, ++ ov5640_mode_info_data[1][fsize->index].width); ++ fsize->discrete.height = ++ max(ov5640_mode_info_data[0][fsize->index].height, ++ ov5640_mode_info_data[1][fsize->index].height); ++ return 0; ++} ++ ++/*! ++ * ioctl_enum_frameintervals - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMEINTERVALS ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_frameintervals(struct v4l2_int_device *s, ++ struct v4l2_frmivalenum *fival) ++{ ++ int i, j, count; ++ ++ if (fival->index < 0 || fival->index > ov5640_mode_MAX) ++ return -EINVAL; ++ ++ if (fival->width == 0 || fival->height == 0 || ++ fival->pixel_format == 0) { ++ pr_warning("Please assign pixelformat, width and height.\n"); ++ return -EINVAL; ++ } ++ ++ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ fival->discrete.numerator = 1; ++ ++ count = 0; ++ for (i = 0; i < ARRAY_SIZE(ov5640_mode_info_data); i++) { ++ for (j = 0; j < (ov5640_mode_MAX + 1); j++) { ++ if (fival->pixel_format == ov5640_data.pix.pixelformat ++ && fival->width == ov5640_mode_info_data[i][j].width ++ && fival->height == ov5640_mode_info_data[i][j].height ++ && ov5640_mode_info_data[i][j].init_data_ptr != NULL) { ++ count++; ++ } ++ if (fival->index == (count - 1)) { ++ fival->discrete.denominator = ++ ov5640_framerates[i]; ++ return 0; ++ } ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++/*! ++ * ioctl_g_chip_ident - V4L2 sensor interface handler for ++ * VIDIOC_DBG_G_CHIP_IDENT ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @id: pointer to int ++ * ++ * Return 0. ++ */ ++static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) ++{ ++ ((struct v4l2_dbg_chip_ident *)id)->match.type = ++ V4L2_CHIP_MATCH_I2C_DRIVER; ++ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5640_camera"); ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT ++ * @s: pointer to standard V4L2 device structure ++ */ ++static int ioctl_init(struct v4l2_int_device *s) ++{ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT ++ * @s: pointer to standard V4L2 device structure ++ * @fmt: pointer to standard V4L2 fmt description structure ++ * ++ * Return 0. ++ */ ++static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, ++ struct v4l2_fmtdesc *fmt) ++{ ++ if (fmt->index > ov5640_mode_MAX) ++ return -EINVAL; ++ ++ fmt->pixelformat = ov5640_data.pix.pixelformat; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Initialise the device when slave attaches to the master. ++ */ ++static int ioctl_dev_init(struct v4l2_int_device *s) ++{ ++ struct sensor_data *sensor = s->priv; ++ u32 tgt_xclk; /* target xclk */ ++ u32 tgt_fps; /* target frames per secound */ ++ enum ov5640_frame_rate frame_rate; ++ int ret; ++ ++ ov5640_data.on = true; ++ ++ /* mclk */ ++ tgt_xclk = ov5640_data.mclk; ++ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX); ++ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN); ++ ov5640_data.mclk = tgt_xclk; ++ ++ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); ++ clk_set_rate(ov5640_data.sensor_clk, ov5640_data.mclk); ++ ++ /* Default camera frame rate is set in probe */ ++ tgt_fps = sensor->streamcap.timeperframe.denominator / ++ sensor->streamcap.timeperframe.numerator; ++ ++ if (tgt_fps == 15) ++ frame_rate = ov5640_15_fps; ++ else if (tgt_fps == 30) ++ frame_rate = ov5640_30_fps; ++ else ++ return -EINVAL; /* Only support 15fps or 30fps now. */ ++ ++ ret = ov5640_init_mode(); ++ return ret; ++} ++ ++/*! ++ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Delinitialise the device when slave detaches to the master. ++ */ ++static int ioctl_dev_exit(struct v4l2_int_device *s) ++{ ++ return 0; ++} ++ ++/*! ++ * This structure defines all the ioctls for this module and links them to the ++ * enumeration. ++ */ ++static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = { ++ { vidioc_int_dev_init_num, ++ (v4l2_int_ioctl_func *)ioctl_dev_init }, ++ { vidioc_int_dev_exit_num, ++ ioctl_dev_exit}, ++ { vidioc_int_s_power_num, ++ (v4l2_int_ioctl_func *)ioctl_s_power }, ++ { vidioc_int_g_ifparm_num, ++ (v4l2_int_ioctl_func *)ioctl_g_ifparm }, ++ { vidioc_int_init_num, ++ (v4l2_int_ioctl_func *)ioctl_init }, ++ { vidioc_int_enum_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, ++ { vidioc_int_g_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, ++ { vidioc_int_g_parm_num, ++ (v4l2_int_ioctl_func *)ioctl_g_parm }, ++ { vidioc_int_s_parm_num, ++ (v4l2_int_ioctl_func *)ioctl_s_parm }, ++ { vidioc_int_g_ctrl_num, ++ (v4l2_int_ioctl_func *)ioctl_g_ctrl }, ++ { vidioc_int_s_ctrl_num, ++ (v4l2_int_ioctl_func *)ioctl_s_ctrl }, ++ { vidioc_int_enum_framesizes_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_framesizes }, ++ { vidioc_int_enum_frameintervals_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals }, ++ { vidioc_int_g_chip_ident_num, ++ (v4l2_int_ioctl_func *)ioctl_g_chip_ident }, ++}; ++ ++static struct v4l2_int_slave ov5640_slave = { ++ .ioctls = ov5640_ioctl_desc, ++ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc), ++}; ++ ++static struct v4l2_int_device ov5640_int_device = { ++ .module = THIS_MODULE, ++ .name = "ov5640", ++ .type = v4l2_int_type_slave, ++ .u = { ++ .slave = &ov5640_slave, ++ }, ++}; ++ ++/*! ++ * ov5640 I2C probe function ++ * ++ * @param adapter struct i2c_adapter * ++ * @return Error code indicating success or failure ++ */ ++static int ov5640_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pinctrl *pinctrl; ++ struct device *dev = &client->dev; ++ int retval; ++ u8 chip_id_high, chip_id_low; ++ ++ /* ov5640 pinctrl */ ++ pinctrl = devm_pinctrl_get_select_default(dev); ++ if (IS_ERR(pinctrl)) { ++ dev_err(dev, "setup pinctrl failed\n"); ++ return PTR_ERR(pinctrl); ++ } ++ ++ /* request power down pin */ ++ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); ++ if (!gpio_is_valid(pwn_gpio)) { ++ dev_err(dev, "no sensor pwdn pin available\n"); ++ return -ENODEV; ++ } ++ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5640_pwdn"); ++ if (retval < 0) ++ return retval; ++ ++ /* request reset pin */ ++ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); ++ if (!gpio_is_valid(rst_gpio)) { ++ dev_err(dev, "no sensor reset pin available\n"); ++ return -EINVAL; ++ } ++ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5640_reset"); ++ if (retval < 0) ++ return retval; ++ ++ /* Set initial values for the sensor struct. */ ++ memset(&ov5640_data, 0, sizeof(ov5640_data)); ++ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); ++ if (IS_ERR(ov5640_data.sensor_clk)) { ++ dev_err(dev, "get mclk failed\n"); ++ return PTR_ERR(ov5640_data.sensor_clk); ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk", ++ &ov5640_data.mclk); ++ if (retval) { ++ dev_err(dev, "mclk frequency is invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk_source", ++ (u32 *) &(ov5640_data.mclk_source)); ++ if (retval) { ++ dev_err(dev, "mclk_source invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "csi_id", ++ &(ov5640_data.csi)); ++ if (retval) { ++ dev_err(dev, "csi_id invalid\n"); ++ return retval; ++ } ++ ++ clk_prepare_enable(ov5640_data.sensor_clk); ++ ++ ov5640_data.io_init = ov5640_reset; ++ ov5640_data.i2c_client = client; ++ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; ++ ov5640_data.pix.width = 640; ++ ov5640_data.pix.height = 480; ++ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | ++ V4L2_CAP_TIMEPERFRAME; ++ ov5640_data.streamcap.capturemode = 0; ++ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS; ++ ov5640_data.streamcap.timeperframe.numerator = 1; ++ ++ ov5640_regulator_enable(&client->dev); ++ ++ ov5640_reset(); ++ ++ ov5640_power_down(0); ++ ++ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high); ++ if (retval < 0 || chip_id_high != 0x56) { ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ pr_warning("camera ov5640 is not found\n"); ++ return -ENODEV; ++ } ++ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low); ++ if (retval < 0 || chip_id_low != 0x40) { ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ pr_warning("camera ov5640 is not found\n"); ++ return -ENODEV; ++ } ++ ++ ov5640_power_down(1); ++ ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ ++ ov5640_int_device.priv = &ov5640_data; ++ retval = v4l2_int_device_register(&ov5640_int_device); ++ ++ pr_info("camera ov5640 is found\n"); ++ return retval; ++} ++ ++/*! ++ * ov5640 I2C detach function ++ * ++ * @param client struct i2c_client * ++ * @return Error code indicating success or failure ++ */ ++static int ov5640_remove(struct i2c_client *client) ++{ ++ v4l2_int_device_unregister(&ov5640_int_device); ++ ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ ++ return 0; ++} ++ ++module_i2c_driver(ov5640_i2c_driver); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("OV5640 Camera Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++MODULE_ALIAS("CSI"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ov5640_mipi.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5640_mipi.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ov5640_mipi.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5640_mipi.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,2104 @@ ++/* ++ * 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. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.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 ++ ++#define OV5640_XCLK_MIN 6000000 ++#define OV5640_XCLK_MAX 24000000 ++ ++#define OV5640_CHIP_ID_HIGH_BYTE 0x300A ++#define OV5640_CHIP_ID_LOW_BYTE 0x300B ++ ++enum ov5640_mode { ++ ov5640_mode_MIN = 0, ++ ov5640_mode_VGA_640_480 = 0, ++ ov5640_mode_QVGA_320_240 = 1, ++ ov5640_mode_NTSC_720_480 = 2, ++ ov5640_mode_PAL_720_576 = 3, ++ ov5640_mode_720P_1280_720 = 4, ++ ov5640_mode_1080P_1920_1080 = 5, ++ ov5640_mode_QSXGA_2592_1944 = 6, ++ ov5640_mode_QCIF_176_144 = 7, ++ ov5640_mode_XGA_1024_768 = 8, ++ ov5640_mode_MAX = 8, ++ ov5640_mode_INIT = 0xff, /*only for sensor init*/ ++}; ++ ++enum ov5640_frame_rate { ++ ov5640_15_fps, ++ ov5640_30_fps ++}; ++ ++/* image size under 1280 * 960 are SUBSAMPLING ++ * image size upper 1280 * 960 are SCALING ++ */ ++enum ov5640_downsize_mode { ++ SUBSAMPLING, ++ SCALING, ++}; ++ ++struct reg_value { ++ u16 u16RegAddr; ++ u8 u8Val; ++ u8 u8Mask; ++ u32 u32Delay_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; ++}; ++ ++/*! ++ * Maintains the information on the current state of the sesor. ++ */ ++static struct sensor_data ov5640_data; ++static int pwn_gpio, rst_gpio; ++ ++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[2][ov5640_mode_MAX + 1] = { ++ { ++ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480, ++ ov5640_setting_15fps_VGA_640_480, ++ ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)}, ++ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240, ++ ov5640_setting_15fps_QVGA_320_240, ++ ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)}, ++ {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_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_15fps_QCIF_176_144, ++ ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)}, ++ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768, ++ ov5640_setting_15fps_XGA_1024_768, ++ ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)}, ++ }, ++ { ++ {ov5640_mode_VGA_640_480, SUBSAMPLING, 640, 480, ++ ov5640_setting_30fps_VGA_640_480, ++ ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)}, ++ {ov5640_mode_QVGA_320_240, SUBSAMPLING, 320, 240, ++ ov5640_setting_30fps_QVGA_320_240, ++ ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)}, ++ {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_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}, ++ {ov5640_mode_QCIF_176_144, SUBSAMPLING, 176, 144, ++ ov5640_setting_30fps_QCIF_176_144, ++ ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)}, ++ {ov5640_mode_XGA_1024_768, SUBSAMPLING, 1024, 768, ++ ov5640_setting_30fps_XGA_1024_768, ++ ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)}, ++ }, ++}; ++ ++static struct regulator *io_regulator; ++static struct regulator *core_regulator; ++static struct regulator *analog_regulator; ++static struct regulator *gpo_regulator; ++ ++static int ov5640_probe(struct i2c_client *adapter, ++ const struct i2c_device_id *device_id); ++static int ov5640_remove(struct i2c_client *client); ++ ++static s32 ov5640_read_reg(u16 reg, u8 *val); ++static s32 ov5640_write_reg(u16 reg, u8 val); ++ ++static const struct i2c_device_id ov5640_id[] = { ++ {"ov5640_mipi", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, ov5640_id); ++ ++static struct i2c_driver ov5640_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ov5640_mipi", ++ }, ++ .probe = ov5640_probe, ++ .remove = ov5640_remove, ++ .id_table = ov5640_id, ++}; ++ ++static void ov5640_standby(s32 enable) ++{ ++ if (enable) ++ gpio_set_value(pwn_gpio, 1); ++ else ++ gpio_set_value(pwn_gpio, 0); ++ ++ msleep(2); ++} ++ ++static void ov5640_reset(void) ++{ ++ /* camera reset */ ++ gpio_set_value(rst_gpio, 1); ++ ++ /* camera power dowmn */ ++ gpio_set_value(pwn_gpio, 1); ++ msleep(5); ++ ++ gpio_set_value(pwn_gpio, 0); ++ msleep(5); ++ ++ gpio_set_value(rst_gpio, 0); ++ msleep(1); ++ ++ gpio_set_value(rst_gpio, 1); ++ msleep(5); ++ ++ gpio_set_value(pwn_gpio, 1); ++} ++ ++static int ov5640_power_on(struct device *dev) ++{ ++ int ret = 0; ++ ++ io_regulator = devm_regulator_get(dev, "DOVDD"); ++ if (!IS_ERR(io_regulator)) { ++ regulator_set_voltage(io_regulator, ++ OV5640_VOLTAGE_DIGITAL_IO, ++ OV5640_VOLTAGE_DIGITAL_IO); ++ ret = regulator_enable(io_regulator); ++ if (ret) { ++ pr_err("%s:io set voltage error\n", __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:io set voltage ok\n", __func__); ++ } ++ } else { ++ pr_err("%s: cannot get io voltage error\n", __func__); ++ io_regulator = NULL; ++ } ++ ++ core_regulator = devm_regulator_get(dev, "DVDD"); ++ if (!IS_ERR(core_regulator)) { ++ regulator_set_voltage(core_regulator, ++ OV5640_VOLTAGE_DIGITAL_CORE, ++ OV5640_VOLTAGE_DIGITAL_CORE); ++ ret = regulator_enable(core_regulator); ++ if (ret) { ++ pr_err("%s:core set voltage error\n", __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:core set voltage ok\n", __func__); ++ } ++ } else { ++ core_regulator = NULL; ++ pr_err("%s: cannot get core voltage error\n", __func__); ++ } ++ ++ analog_regulator = devm_regulator_get(dev, "AVDD"); ++ if (!IS_ERR(analog_regulator)) { ++ regulator_set_voltage(analog_regulator, ++ OV5640_VOLTAGE_ANALOG, ++ OV5640_VOLTAGE_ANALOG); ++ ret = regulator_enable(analog_regulator); ++ if (ret) { ++ pr_err("%s:analog set voltage error\n", ++ __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:analog set voltage ok\n", __func__); ++ } ++ } else { ++ analog_regulator = NULL; ++ pr_err("%s: cannot get analog voltage error\n", __func__); ++ } ++ ++ return ret; ++} ++ ++static s32 ov5640_write_reg(u16 reg, u8 val) ++{ ++ u8 au8Buf[3] = {0}; ++ ++ au8Buf[0] = reg >> 8; ++ au8Buf[1] = reg & 0xff; ++ au8Buf[2] = val; ++ ++ if (i2c_master_send(ov5640_data.i2c_client, au8Buf, 3) < 0) { ++ pr_err("%s:write reg error:reg=%x,val=%x\n", ++ __func__, reg, val); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static s32 ov5640_read_reg(u16 reg, u8 *val) ++{ ++ u8 au8RegBuf[2] = {0}; ++ u8 u8RdVal = 0; ++ ++ au8RegBuf[0] = reg >> 8; ++ au8RegBuf[1] = reg & 0xff; ++ ++ if (2 != i2c_master_send(ov5640_data.i2c_client, au8RegBuf, 2)) { ++ pr_err("%s:write reg error:reg=%x\n", ++ __func__, reg); ++ return -1; ++ } ++ ++ if (1 != i2c_master_recv(ov5640_data.i2c_client, &u8RdVal, 1)) { ++ pr_err("%s:read reg error:reg=%x,val=%x\n", ++ __func__, reg, u8RdVal); ++ return -1; ++ } ++ ++ *val = u8RdVal; ++ ++ return u8RdVal; ++} ++ ++static int prev_sysclk, prev_HTS; ++static int AE_low, AE_high, AE_Target = 52; ++ ++void OV5640_stream_on(void) ++{ ++ ov5640_write_reg(0x4202, 0x00); ++} ++ ++void OV5640_stream_off(void) ++{ ++ ov5640_write_reg(0x4202, 0x0f); ++} ++ ++ ++int OV5640_get_sysclk(void) ++{ ++ /* calculate sysclk */ ++ int xvclk = ov5640_data.mclk / 10000; ++ int temp1, temp2; ++ int Multiplier, PreDiv, VCO, SysDiv, Pll_rdiv; ++ int Bit_div2x = 1, sclk_rdiv, sysclk; ++ u8 temp; ++ ++ int sclk_rdiv_map[] = {1, 2, 4, 8}; ++ ++ temp1 = ov5640_read_reg(0x3034, &temp); ++ temp2 = temp1 & 0x0f; ++ if (temp2 == 8 || temp2 == 10) ++ Bit_div2x = temp2 / 2; ++ ++ temp1 = ov5640_read_reg(0x3035, &temp); ++ SysDiv = temp1>>4; ++ if (SysDiv == 0) ++ SysDiv = 16; ++ ++ temp1 = ov5640_read_reg(0x3036, &temp); ++ Multiplier = temp1; ++ ++ temp1 = ov5640_read_reg(0x3037, &temp); ++ PreDiv = temp1 & 0x0f; ++ Pll_rdiv = ((temp1 >> 4) & 0x01) + 1; ++ ++ temp1 = ov5640_read_reg(0x3108, &temp); ++ 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; ++} ++ ++void OV5640_set_night_mode(void) ++{ ++ /* read HTS from register settings */ ++ u8 mode; ++ ++ ov5640_read_reg(0x3a00, &mode); ++ mode &= 0xfb; ++ ov5640_write_reg(0x3a00, mode); ++} ++ ++int OV5640_get_HTS(void) ++{ ++ /* read HTS from register settings */ ++ int HTS; ++ u8 temp; ++ ++ HTS = ov5640_read_reg(0x380c, &temp); ++ HTS = (HTS<<8) + ov5640_read_reg(0x380d, &temp); ++ ++ return HTS; ++} ++ ++int OV5640_get_VTS(void) ++{ ++ /* read VTS from register settings */ ++ int VTS; ++ u8 temp; ++ ++ /* total vertical size[15:8] high byte */ ++ VTS = ov5640_read_reg(0x380e, &temp); ++ ++ VTS = (VTS<<8) + ov5640_read_reg(0x380f, &temp); ++ ++ return VTS; ++} ++ ++int OV5640_set_VTS(int VTS) ++{ ++ /* write VTS to registers */ ++ int temp; ++ ++ temp = VTS & 0xff; ++ ov5640_write_reg(0x380f, temp); ++ ++ temp = VTS>>8; ++ ov5640_write_reg(0x380e, temp); ++ ++ return 0; ++} ++ ++int OV5640_get_shutter(void) ++{ ++ /* read shutter, in number of line period */ ++ int shutter; ++ u8 temp; ++ ++ shutter = (ov5640_read_reg(0x03500, &temp) & 0x0f); ++ shutter = (shutter<<8) + ov5640_read_reg(0x3501, &temp); ++ shutter = (shutter<<4) + (ov5640_read_reg(0x3502, &temp)>>4); ++ ++ return shutter; ++} ++ ++int OV5640_set_shutter(int shutter) ++{ ++ /* write shutter, in number of line period */ ++ int temp; ++ ++ shutter = shutter & 0xffff; ++ ++ temp = shutter & 0x0f; ++ temp = temp<<4; ++ ov5640_write_reg(0x3502, temp); ++ ++ temp = shutter & 0xfff; ++ temp = temp>>4; ++ ov5640_write_reg(0x3501, temp); ++ ++ temp = shutter>>12; ++ ov5640_write_reg(0x3500, temp); ++ ++ return 0; ++} ++ ++int OV5640_get_gain16(void) ++{ ++ /* read gain, 16 = 1x */ ++ int gain16; ++ u8 temp; ++ ++ gain16 = ov5640_read_reg(0x350a, &temp) & 0x03; ++ gain16 = (gain16<<8) + ov5640_read_reg(0x350b, &temp); ++ ++ return gain16; ++} ++ ++int OV5640_set_gain16(int gain16) ++{ ++ /* write gain, 16 = 1x */ ++ u8 temp; ++ gain16 = gain16 & 0x3ff; ++ ++ temp = gain16 & 0xff; ++ ov5640_write_reg(0x350b, temp); ++ ++ temp = gain16>>8; ++ ov5640_write_reg(0x350a, temp); ++ ++ return 0; ++} ++ ++int OV5640_get_light_freq(void) ++{ ++ /* get banding filter value */ ++ int temp, temp1, light_freq = 0; ++ u8 tmp; ++ ++ temp = ov5640_read_reg(0x3c01, &tmp); ++ ++ if (temp & 0x80) { ++ /* manual */ ++ temp1 = ov5640_read_reg(0x3c00, &tmp); ++ if (temp1 & 0x04) { ++ /* 50Hz */ ++ light_freq = 50; ++ } else { ++ /* 60Hz */ ++ light_freq = 60; ++ } ++ } else { ++ /* auto */ ++ temp1 = ov5640_read_reg(0x3c0c, &tmp); ++ if (temp1 & 0x01) { ++ /* 50Hz */ ++ light_freq = 50; ++ } else { ++ /* 60Hz */ ++ } ++ } ++ return light_freq; ++} ++ ++void OV5640_set_bandingfilter(void) ++{ ++ int prev_VTS; ++ int band_step60, max_band60, band_step50, max_band50; ++ ++ /* read preview PCLK */ ++ prev_sysclk = OV5640_get_sysclk(); ++ /* read preview HTS */ ++ prev_HTS = OV5640_get_HTS(); ++ ++ /* read preview VTS */ ++ prev_VTS = OV5640_get_VTS(); ++ ++ /* calculate banding filter */ ++ /* 60Hz */ ++ band_step60 = prev_sysclk * 100/prev_HTS * 100/120; ++ ov5640_write_reg(0x3a0a, (band_step60 >> 8)); ++ ov5640_write_reg(0x3a0b, (band_step60 & 0xff)); ++ ++ max_band60 = (int)((prev_VTS-4)/band_step60); ++ ov5640_write_reg(0x3a0d, max_band60); ++ ++ /* 50Hz */ ++ band_step50 = prev_sysclk * 100/prev_HTS; ++ ov5640_write_reg(0x3a08, (band_step50 >> 8)); ++ ov5640_write_reg(0x3a09, (band_step50 & 0xff)); ++ ++ max_band50 = (int)((prev_VTS-4)/band_step50); ++ ov5640_write_reg(0x3a0e, max_band50); ++} ++ ++int OV5640_set_AE_target(int target) ++{ ++ /* stable in high */ ++ int fast_high, fast_low; ++ AE_low = target * 23 / 25; /* 0.92 */ ++ AE_high = target * 27 / 25; /* 1.08 */ ++ ++ fast_high = AE_high<<1; ++ if (fast_high > 255) ++ fast_high = 255; ++ ++ fast_low = AE_low >> 1; ++ ++ ov5640_write_reg(0x3a0f, AE_high); ++ ov5640_write_reg(0x3a10, AE_low); ++ ov5640_write_reg(0x3a1b, AE_high); ++ ov5640_write_reg(0x3a1e, AE_low); ++ ov5640_write_reg(0x3a11, fast_high); ++ ov5640_write_reg(0x3a1f, fast_low); ++ ++ return 0; ++} ++ ++void OV5640_turn_on_AE_AG(int enable) ++{ ++ u8 ae_ag_ctrl; ++ ++ ov5640_read_reg(0x3503, &ae_ag_ctrl); ++ if (enable) { ++ /* turn on auto AE/AG */ ++ ae_ag_ctrl = ae_ag_ctrl & ~(0x03); ++ } else { ++ /* turn off AE/AG */ ++ ae_ag_ctrl = ae_ag_ctrl | 0x03; ++ } ++ ov5640_write_reg(0x3503, ae_ag_ctrl); ++} ++ ++bool binning_on(void) ++{ ++ u8 temp; ++ ov5640_read_reg(0x3821, &temp); ++ temp &= 0xfe; ++ if (temp) ++ return true; ++ else ++ return false; ++} ++ ++static void ov5640_set_virtual_channel(int channel) ++{ ++ u8 channel_id; ++ ++ ov5640_read_reg(0x4814, &channel_id); ++ channel_id &= ~(3 << 6); ++ ov5640_write_reg(0x4814, channel_id | (channel << 6)); ++} ++ ++/* download ov5640 settings to sensor through i2c */ ++static int ov5640_download_firmware(struct reg_value *pModeSetting, s32 ArySize) ++{ ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int i, retval = 0; ++ ++ for (i = 0; i < ArySize; ++i, ++pModeSetting) { ++ Delay_ms = pModeSetting->u32Delay_ms; ++ RegAddr = pModeSetting->u16RegAddr; ++ Val = pModeSetting->u8Val; ++ Mask = pModeSetting->u8Mask; ++ ++ if (Mask) { ++ retval = ov5640_read_reg(RegAddr, &RegVal); ++ if (retval < 0) ++ goto err; ++ ++ RegVal &= ~(u8)Mask; ++ Val &= Mask; ++ Val |= RegVal; ++ } ++ ++ retval = ov5640_write_reg(RegAddr, Val); ++ if (retval < 0) ++ goto err; ++ ++ if (Delay_ms) ++ msleep(Delay_ms); ++ } ++err: ++ return retval; ++} ++ ++/* sensor changes between scaling and subsampling ++ * go through exposure calcualtion ++ */ ++static int ov5640_change_mode_exposure_calc(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 ArySize = 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 retval = 0; ++ ++ /* check if the input mode and frame rate is valid */ ++ pModeSetting = ++ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; ++ ArySize = ++ ov5640_mode_info_data[frame_rate][mode].init_data_size; ++ ++ ov5640_data.pix.width = ++ ov5640_mode_info_data[frame_rate][mode].width; ++ ov5640_data.pix.height = ++ ov5640_mode_info_data[frame_rate][mode].height; ++ ++ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || ++ pModeSetting == NULL || ArySize == 0) ++ return -EINVAL; ++ ++ /* auto focus */ ++ /* OV5640_auto_focus();//if no af function, just skip it */ ++ ++ /* turn off AE/AG */ ++ OV5640_turn_on_AE_AG(0); ++ ++ /* read preview shutter */ ++ prev_shutter = OV5640_get_shutter(); ++ if ((binning_on()) && (mode != ov5640_mode_720P_1280_720) ++ && (mode != ov5640_mode_1080P_1920_1080)) ++ prev_shutter *= 2; ++ ++ /* read preview gain */ ++ prev_gain16 = OV5640_get_gain16(); ++ ++ /* get average */ ++ ov5640_read_reg(0x56a1, &average); ++ ++ /* turn off night mode for capture */ ++ OV5640_set_night_mode(); ++ ++ /* turn off overlay */ ++ /* ov5640_write_reg(0x3022, 0x06);//if no af function, just skip it */ ++ ++ OV5640_stream_off(); ++ ++ /* Write capture setting */ ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ /* read capture VTS */ ++ cap_VTS = OV5640_get_VTS(); ++ cap_HTS = OV5640_get_HTS(); ++ cap_sysclk = OV5640_get_sysclk(); ++ ++ /* calculate capture banding filter */ ++ light_freq = OV5640_get_light_freq(); ++ 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 > AE_low && average < AE_high) { ++ /* in stable range */ ++ cap_gain16_shutter = ++ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk ++ * prev_HTS/cap_HTS * AE_Target / average; ++ } else { ++ cap_gain16_shutter = ++ prev_gain16 * prev_shutter * cap_sysclk/prev_sysclk ++ * 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 */ ++ OV5640_set_gain16(cap_gain16); ++ ++ /* write capture shutter */ ++ if (cap_shutter > (cap_VTS - 4)) { ++ cap_VTS = cap_shutter + 4; ++ OV5640_set_VTS(cap_VTS); ++ } ++ OV5640_set_shutter(cap_shutter); ++ ++ OV5640_stream_on(); ++ ++err: ++ return retval; ++} ++ ++/* if sensor changes inside scaling or subsampling ++ * change mode directly ++ * */ ++static int ov5640_change_mode_direct(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 ArySize = 0; ++ int retval = 0; ++ ++ /* check if the input mode and frame rate is valid */ ++ pModeSetting = ++ ov5640_mode_info_data[frame_rate][mode].init_data_ptr; ++ ArySize = ++ ov5640_mode_info_data[frame_rate][mode].init_data_size; ++ ++ ov5640_data.pix.width = ++ ov5640_mode_info_data[frame_rate][mode].width; ++ ov5640_data.pix.height = ++ ov5640_mode_info_data[frame_rate][mode].height; ++ ++ if (ov5640_data.pix.width == 0 || ov5640_data.pix.height == 0 || ++ pModeSetting == NULL || ArySize == 0) ++ return -EINVAL; ++ ++ /* turn off AE/AG */ ++ OV5640_turn_on_AE_AG(0); ++ ++ OV5640_stream_off(); ++ ++ /* Write capture setting */ ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ OV5640_stream_on(); ++ ++ OV5640_turn_on_AE_AG(1); ++ ++err: ++ return retval; ++} ++ ++static int ov5640_init_mode(enum ov5640_frame_rate frame_rate, ++ enum ov5640_mode mode, enum ov5640_mode orig_mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 ArySize = 0; ++ int retval = 0; ++ void *mipi_csi2_info; ++ u32 mipi_reg, msec_wait4stable = 0; ++ enum ov5640_downsize_mode dn_mode, orig_dn_mode; ++ ++ if ((mode > ov5640_mode_MAX || mode < ov5640_mode_MIN) ++ && (mode != ov5640_mode_INIT)) { ++ pr_err("Wrong ov5640 mode detected!\n"); ++ return -1; ++ } ++ ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ /* initial mipi dphy */ ++ if (!mipi_csi2_info) { ++ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n", ++ __func__, __FILE__); ++ return -1; ++ } ++ ++ if (!mipi_csi2_get_status(mipi_csi2_info)) ++ mipi_csi2_enable(mipi_csi2_info); ++ ++ if (!mipi_csi2_get_status(mipi_csi2_info)) { ++ pr_err("Can not enable mipi csi2 driver!\n"); ++ return -1; ++ } ++ ++ mipi_csi2_set_lanes(mipi_csi2_info); ++ ++ /*Only reset MIPI CSI2 HW at sensor initialize*/ ++ if (mode == ov5640_mode_INIT) ++ mipi_csi2_reset(mipi_csi2_info); ++ ++ if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_UYVY) ++ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_YUV422); ++ else if (ov5640_data.pix.pixelformat == V4L2_PIX_FMT_RGB565) ++ mipi_csi2_set_datatype(mipi_csi2_info, MIPI_DT_RGB565); ++ else ++ pr_err("currently this sensor format can not be supported!\n"); ++ ++ 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) { ++ pModeSetting = ov5640_init_setting_30fps_VGA; ++ ArySize = ARRAY_SIZE(ov5640_init_setting_30fps_VGA); ++ ++ ov5640_data.pix.width = 640; ++ ov5640_data.pix.height = 480; ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ if (retval < 0) ++ goto err; ++ ++ pModeSetting = ov5640_setting_30fps_VGA_640_480; ++ ArySize = ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480); ++ retval = ov5640_download_firmware(pModeSetting, ArySize); ++ } 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 */ ++ retval = ov5640_change_mode_exposure_calc(frame_rate, mode); ++ } else { ++ /* change inside subsampling or scaling ++ * download firmware directly */ ++ retval = ov5640_change_mode_direct(frame_rate, mode); ++ } ++ ++ if (retval < 0) ++ goto err; ++ ++ OV5640_set_AE_target(AE_Target); ++ OV5640_get_light_freq(); ++ OV5640_set_bandingfilter(); ++ ov5640_set_virtual_channel(ov5640_data.csi); ++ ++ /* add delay to wait for sensor stable */ ++ if (mode == ov5640_mode_QSXGA_2592_1944) { ++ /* dump the first two frames: 1/7.5*2 ++ * the frame rate of QSXGA is 7.5fps */ ++ msec_wait4stable = 267; ++ } else if (frame_rate == ov5640_15_fps) { ++ /* dump the first nine frames: 1/15*9 */ ++ msec_wait4stable = 600; ++ } else if (frame_rate == ov5640_30_fps) { ++ /* dump the first nine frames: 1/30*9 */ ++ msec_wait4stable = 300; ++ } ++ msleep(msec_wait4stable); ++ ++ if (mipi_csi2_info) { ++ unsigned int i; ++ ++ i = 0; ++ ++ /* wait for mipi sensor ready */ ++ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); ++ while ((mipi_reg == 0x200) && (i < 10)) { ++ mipi_reg = mipi_csi2_dphy_status(mipi_csi2_info); ++ i++; ++ msleep(10); ++ } ++ ++ if (i >= 10) { ++ pr_err("mipi csi2 can not receive sensor clk!\n"); ++ return -1; ++ } ++ ++ i = 0; ++ ++ /* wait for mipi stable */ ++ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); ++ while ((mipi_reg != 0x0) && (i < 10)) { ++ mipi_reg = mipi_csi2_get_error1(mipi_csi2_info); ++ i++; ++ msleep(10); ++ } ++ ++ if (i >= 10) { ++ pr_err("mipi csi2 can not reveive data correctly!\n"); ++ return -1; ++ } ++ } ++err: ++ return retval; ++} ++ ++/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ ++ ++static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) ++{ ++ if (s == NULL) { ++ pr_err(" ERROR!! no slave device set!\n"); ++ return -1; ++ } ++ ++ memset(p, 0, sizeof(*p)); ++ p->u.bt656.clock_curr = ov5640_data.mclk; ++ pr_debug(" clock_curr=mclk=%d\n", ov5640_data.mclk); ++ p->if_type = V4L2_IF_TYPE_BT656; ++ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; ++ p->u.bt656.clock_min = OV5640_XCLK_MIN; ++ p->u.bt656.clock_max = OV5640_XCLK_MAX; ++ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @on: indicates power mode (on or off) ++ * ++ * Turns the power on or off, depending on the value of on and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_power(struct v4l2_int_device *s, int on) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ if (on && !sensor->on) { ++ if (io_regulator) ++ if (regulator_enable(io_regulator) != 0) ++ return -EIO; ++ if (core_regulator) ++ if (regulator_enable(core_regulator) != 0) ++ return -EIO; ++ if (gpo_regulator) ++ if (regulator_enable(gpo_regulator) != 0) ++ return -EIO; ++ if (analog_regulator) ++ if (regulator_enable(analog_regulator) != 0) ++ return -EIO; ++ /* Make sure power on */ ++ ov5640_standby(0); ++ } else if (!on && sensor->on) { ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ if (gpo_regulator) ++ regulator_disable(gpo_regulator); ++ ++ ov5640_standby(1); ++ } ++ ++ sensor->on = on; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure ++ * ++ * Returns the sensor's video CAPTURE parameters. ++ */ ++static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_captureparm *cparm = &a->parm.capture; ++ int ret = 0; ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ 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; ++ ret = 0; ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure ++ * ++ * Configures the sensor to use the input parameters, if possible. If ++ * not possible, reverts to the old parameters and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; ++ u32 tgt_fps; /* target frames per secound */ ++ enum ov5640_frame_rate frame_rate; ++ enum ov5640_mode orig_mode; ++ int ret = 0; ++ ++ /* Make sure power on */ ++ ov5640_standby(0); ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ /* 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 { ++ pr_err(" The camera frame rate is not supported!\n"); ++ return -EINVAL; ++ } ++ ++ orig_mode = sensor->streamcap.capturemode; ++ ret = ov5640_init_mode(frame_rate, ++ (u32)a->parm.capture.capturemode, orig_mode); ++ if (ret < 0) ++ return ret; ++ ++ sensor->streamcap.timeperframe = *timeperframe; ++ sensor->streamcap.capturemode = ++ (u32)a->parm.capture.capturemode; ++ ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ pr_debug(" type is not " \ ++ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", ++ a->type); ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap ++ * @s: pointer to standard V4L2 device structure ++ * @f: pointer to standard V4L2 v4l2_format structure ++ * ++ * Returns the sensor's current pixel format in the v4l2_format ++ * parameter. ++ */ ++static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ f->fmt.pix = sensor->pix; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure ++ * ++ * If the requested control is supported, returns the control's current ++ * value from the video_control[] array. Otherwise, returns -EINVAL ++ * if the control is not supported. ++ */ ++static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int ret = 0; ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ vc->value = ov5640_data.brightness; ++ break; ++ case V4L2_CID_HUE: ++ vc->value = ov5640_data.hue; ++ break; ++ case V4L2_CID_CONTRAST: ++ vc->value = ov5640_data.contrast; ++ break; ++ case V4L2_CID_SATURATION: ++ vc->value = ov5640_data.saturation; ++ break; ++ case V4L2_CID_RED_BALANCE: ++ vc->value = ov5640_data.red; ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ vc->value = ov5640_data.blue; ++ break; ++ case V4L2_CID_EXPOSURE: ++ vc->value = ov5640_data.ae_mode; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure ++ * ++ * If the requested control is supported, sets the control's current ++ * value in HW (and updates the video_control[] array). Otherwise, ++ * returns -EINVAL if the control is not supported. ++ */ ++static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int retval = 0; ++ ++ pr_debug("In ov5640:ioctl_s_ctrl %d\n", ++ vc->id); ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_DO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_RED_BALANCE: ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ break; ++ case V4L2_CID_HFLIP: ++ break; ++ case V4L2_CID_VFLIP: ++ break; ++ default: ++ retval = -EPERM; ++ break; ++ } ++ ++ return retval; ++} ++ ++/*! ++ * ioctl_enum_framesizes - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMESIZES ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_framesizes(struct v4l2_int_device *s, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ if (fsize->index > ov5640_mode_MAX) ++ return -EINVAL; ++ ++ fsize->pixel_format = ov5640_data.pix.pixelformat; ++ fsize->discrete.width = ++ max(ov5640_mode_info_data[0][fsize->index].width, ++ ov5640_mode_info_data[1][fsize->index].width); ++ fsize->discrete.height = ++ max(ov5640_mode_info_data[0][fsize->index].height, ++ ov5640_mode_info_data[1][fsize->index].height); ++ return 0; ++} ++ ++/*! ++ * ioctl_g_chip_ident - V4L2 sensor interface handler for ++ * VIDIOC_DBG_G_CHIP_IDENT ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @id: pointer to int ++ * ++ * Return 0. ++ */ ++static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) ++{ ++ ((struct v4l2_dbg_chip_ident *)id)->match.type = ++ V4L2_CHIP_MATCH_I2C_DRIVER; ++ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, ++ "ov5640_mipi_camera"); ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT ++ * @s: pointer to standard V4L2 device structure ++ */ ++static int ioctl_init(struct v4l2_int_device *s) ++{ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT ++ * @s: pointer to standard V4L2 device structure ++ * @fmt: pointer to standard V4L2 fmt description structure ++ * ++ * Return 0. ++ */ ++static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, ++ struct v4l2_fmtdesc *fmt) ++{ ++ if (fmt->index > ov5640_mode_MAX) ++ return -EINVAL; ++ ++ fmt->pixelformat = ov5640_data.pix.pixelformat; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Initialise the device when slave attaches to the master. ++ */ ++static int ioctl_dev_init(struct v4l2_int_device *s) ++{ ++ struct sensor_data *sensor = s->priv; ++ u32 tgt_xclk; /* target xclk */ ++ u32 tgt_fps; /* target frames per secound */ ++ int ret; ++ enum ov5640_frame_rate frame_rate; ++ void *mipi_csi2_info; ++ ++ ov5640_data.on = true; ++ ++ /* mclk */ ++ tgt_xclk = ov5640_data.mclk; ++ tgt_xclk = min(tgt_xclk, (u32)OV5640_XCLK_MAX); ++ tgt_xclk = max(tgt_xclk, (u32)OV5640_XCLK_MIN); ++ ov5640_data.mclk = tgt_xclk; ++ ++ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); ++ ++ /* Default camera frame rate is set in probe */ ++ tgt_fps = sensor->streamcap.timeperframe.denominator / ++ sensor->streamcap.timeperframe.numerator; ++ ++ if (tgt_fps == 15) ++ frame_rate = ov5640_15_fps; ++ else if (tgt_fps == 30) ++ frame_rate = ov5640_30_fps; ++ else ++ return -EINVAL; /* Only support 15fps or 30fps now. */ ++ ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ /* enable mipi csi2 */ ++ if (mipi_csi2_info) ++ mipi_csi2_enable(mipi_csi2_info); ++ else { ++ printk(KERN_ERR "%s() in %s: Fail to get mipi_csi2_info!\n", ++ __func__, __FILE__); ++ return -EPERM; ++ } ++ ++ ret = ov5640_init_mode(frame_rate, ov5640_mode_INIT, ov5640_mode_INIT); ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Delinitialise the device when slave detaches to the master. ++ */ ++static int ioctl_dev_exit(struct v4l2_int_device *s) ++{ ++ void *mipi_csi2_info; ++ ++ mipi_csi2_info = mipi_csi2_get_info(); ++ ++ /* disable mipi csi2 */ ++ if (mipi_csi2_info) ++ if (mipi_csi2_get_status(mipi_csi2_info)) ++ mipi_csi2_disable(mipi_csi2_info); ++ ++ return 0; ++} ++ ++/*! ++ * This structure defines all the ioctls for this module and links them to the ++ * enumeration. ++ */ ++static struct v4l2_int_ioctl_desc ov5640_ioctl_desc[] = { ++ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *) ioctl_dev_init}, ++ {vidioc_int_dev_exit_num, ioctl_dev_exit}, ++ {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power}, ++ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm}, ++/* {vidioc_int_g_needs_reset_num, ++ (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */ ++/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */ ++ {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init}, ++ {vidioc_int_enum_fmt_cap_num, ++ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, ++/* {vidioc_int_try_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */ ++ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap}, ++/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_s_fmt_cap}, */ ++ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm}, ++ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm}, ++/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */ ++ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl}, ++ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl}, ++ {vidioc_int_enum_framesizes_num, ++ (v4l2_int_ioctl_func *) ioctl_enum_framesizes}, ++ {vidioc_int_g_chip_ident_num, ++ (v4l2_int_ioctl_func *) ioctl_g_chip_ident}, ++}; ++ ++static struct v4l2_int_slave ov5640_slave = { ++ .ioctls = ov5640_ioctl_desc, ++ .num_ioctls = ARRAY_SIZE(ov5640_ioctl_desc), ++}; ++ ++static struct v4l2_int_device ov5640_int_device = { ++ .module = THIS_MODULE, ++ .name = "ov5640", ++ .type = v4l2_int_type_slave, ++ .u = { ++ .slave = &ov5640_slave, ++ }, ++}; ++ ++/*! ++ * ov5640 I2C probe function ++ * ++ * @param adapter struct i2c_adapter * ++ * @return Error code indicating success or failure ++ */ ++static int ov5640_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct device *dev = &client->dev; ++ int retval; ++ u8 chip_id_high, chip_id_low; ++ ++ /* request power down pin */ ++ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); ++ if (!gpio_is_valid(pwn_gpio)) { ++ dev_warn(dev, "no sensor pwdn pin available"); ++ return -EINVAL; ++ } ++ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5640_mipi_pwdn"); ++ if (retval < 0) ++ return retval; ++ ++ /* request reset pin */ ++ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); ++ if (!gpio_is_valid(rst_gpio)) { ++ dev_warn(dev, "no sensor reset pin available"); ++ return -EINVAL; ++ } ++ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5640_mipi_reset"); ++ if (retval < 0) ++ return retval; ++ ++ /* Set initial values for the sensor struct. */ ++ memset(&ov5640_data, 0, sizeof(ov5640_data)); ++ ov5640_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); ++ if (IS_ERR(ov5640_data.sensor_clk)) { ++ /* assuming clock enabled by default */ ++ ov5640_data.sensor_clk = NULL; ++ dev_err(dev, "clock-frequency missing or invalid\n"); ++ return PTR_ERR(ov5640_data.sensor_clk); ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk", ++ &(ov5640_data.mclk)); ++ if (retval) { ++ dev_err(dev, "mclk missing or invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk_source", ++ (u32 *) &(ov5640_data.mclk_source)); ++ if (retval) { ++ dev_err(dev, "mclk_source missing or invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "csi_id", ++ &(ov5640_data.csi)); ++ if (retval) { ++ dev_err(dev, "csi id missing or invalid\n"); ++ return retval; ++ } ++ ++ clk_prepare_enable(ov5640_data.sensor_clk); ++ ++ ov5640_data.io_init = ov5640_reset; ++ ov5640_data.i2c_client = client; ++ ov5640_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; ++ ov5640_data.pix.width = 640; ++ ov5640_data.pix.height = 480; ++ ov5640_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | ++ V4L2_CAP_TIMEPERFRAME; ++ ov5640_data.streamcap.capturemode = 0; ++ ov5640_data.streamcap.timeperframe.denominator = DEFAULT_FPS; ++ ov5640_data.streamcap.timeperframe.numerator = 1; ++ ++ ov5640_power_on(dev); ++ ++ ov5640_reset(); ++ ++ ov5640_standby(0); ++ ++ retval = ov5640_read_reg(OV5640_CHIP_ID_HIGH_BYTE, &chip_id_high); ++ if (retval < 0 || chip_id_high != 0x56) { ++ pr_warning("camera ov5640_mipi is not found\n"); ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ return -ENODEV; ++ } ++ retval = ov5640_read_reg(OV5640_CHIP_ID_LOW_BYTE, &chip_id_low); ++ if (retval < 0 || chip_id_low != 0x40) { ++ pr_warning("camera ov5640_mipi is not found\n"); ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ return -ENODEV; ++ } ++ ++ ov5640_standby(1); ++ ++ ov5640_int_device.priv = &ov5640_data; ++ retval = v4l2_int_device_register(&ov5640_int_device); ++ ++ clk_disable_unprepare(ov5640_data.sensor_clk); ++ ++ pr_info("camera ov5640_mipi is found\n"); ++ return retval; ++} ++ ++/*! ++ * ov5640 I2C detach function ++ * ++ * @param client struct i2c_client * ++ * @return Error code indicating success or failure ++ */ ++static int ov5640_remove(struct i2c_client *client) ++{ ++ v4l2_int_device_unregister(&ov5640_int_device); ++ ++ if (gpo_regulator) ++ regulator_disable(gpo_regulator); ++ ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ ++ return 0; ++} ++ ++/*! ++ * ov5640 init function ++ * Called by insmod ov5640_camera.ko. ++ * ++ * @return Error code indicating success or failure ++ */ ++static __init int ov5640_init(void) ++{ ++ u8 err; ++ ++ err = i2c_add_driver(&ov5640_i2c_driver); ++ if (err != 0) ++ pr_err("%s:driver registration failed, error=%d\n", ++ __func__, err); ++ ++ return err; ++} ++ ++/*! ++ * OV5640 cleanup function ++ * Called on rmmod ov5640_camera.ko ++ * ++ * @return Error code indicating success or failure ++ */ ++static void __exit ov5640_clean(void) ++{ ++ i2c_del_driver(&ov5640_i2c_driver); ++} ++ ++module_init(ov5640_init); ++module_exit(ov5640_clean); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("OV5640 MIPI Camera Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++MODULE_ALIAS("CSI"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/capture/ov5642.c linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5642.c +--- linux-3.14.14/drivers/media/platform/mxc/capture/ov5642.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/capture/ov5642.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,4252 @@ ++/* ++ * Copyright (C) 2012-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. ++ ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mxc_v4l2_capture.h" ++ ++#define OV5642_VOLTAGE_ANALOG 2800000 ++#define OV5642_VOLTAGE_DIGITAL_CORE 1500000 ++#define OV5642_VOLTAGE_DIGITAL_IO 1800000 ++ ++#define MIN_FPS 15 ++#define MAX_FPS 30 ++#define DEFAULT_FPS 30 ++ ++#define OV5642_XCLK_MIN 6000000 ++#define OV5642_XCLK_MAX 24000000 ++ ++#define OV5642_CHIP_ID_HIGH_BYTE 0x300A ++#define OV5642_CHIP_ID_LOW_BYTE 0x300B ++ ++enum ov5642_mode { ++ ov5642_mode_MIN = 0, ++ ov5642_mode_VGA_640_480 = 0, ++ ov5642_mode_QVGA_320_240 = 1, ++ ov5642_mode_NTSC_720_480 = 2, ++ ov5642_mode_PAL_720_576 = 3, ++ ov5642_mode_720P_1280_720 = 4, ++ ov5642_mode_1080P_1920_1080 = 5, ++ ov5642_mode_QSXGA_2592_1944 = 6, ++ ov5642_mode_QCIF_176_144 = 7, ++ ov5642_mode_XGA_1024_768 = 8, ++ ov5642_mode_MAX = 8 ++}; ++ ++enum ov5642_frame_rate { ++ ov5642_15_fps, ++ ov5642_30_fps ++}; ++ ++static int ov5642_framerates[] = { ++ [ov5642_15_fps] = 15, ++ [ov5642_30_fps] = 30, ++}; ++ ++struct reg_value { ++ u16 u16RegAddr; ++ u8 u8Val; ++ u8 u8Mask; ++ u32 u32Delay_ms; ++}; ++ ++struct ov5642_mode_info { ++ enum ov5642_mode mode; ++ u32 width; ++ u32 height; ++ struct reg_value *init_data_ptr; ++ u32 init_data_size; ++}; ++ ++/*! ++ * Maintains the information on the current state of the sesor. ++ */ ++static struct sensor_data ov5642_data; ++static int pwn_gpio, rst_gpio; ++ ++static struct reg_value ov5642_rot_none_VGA[] = { ++ {0x3818, 0xc1, 0x00, 0x00}, {0x3621, 0x87, 0x00, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_vert_flip_VGA[] = { ++ {0x3818, 0x20, 0xbf, 0x00}, {0x3621, 0x20, 0xff, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_horiz_flip_VGA[] = { ++ {0x3818, 0x81, 0x00, 0x01}, {0x3621, 0xa7, 0x00, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_180_VGA[] = { ++ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00}, ++}; ++ ++ ++static struct reg_value ov5642_rot_none_FULL[] = { ++ {0x3818, 0xc0, 0x00, 0x00}, {0x3621, 0x09, 0x00, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_vert_flip_FULL[] = { ++ {0x3818, 0x20, 0xbf, 0x01}, {0x3621, 0x20, 0xff, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_horiz_flip_FULL[] = { ++ {0x3818, 0x80, 0x00, 0x01}, {0x3621, 0x29, 0x00, 0x00}, ++}; ++ ++static struct reg_value ov5642_rot_180_FULL[] = { ++ {0x3818, 0x60, 0xff, 0x00}, {0x3621, 0x00, 0xdf, 0x00}, ++}; ++ ++ ++static struct reg_value ov5642_initial_setting[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c00, 0x04, 0, 0}, {0x3c01, 0x80, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, ++ {0x5182, 0x00, 0, 0}, {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, ++ {0x5001, 0xff, 0, 0}, {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, ++ {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, ++ {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, ++ {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, ++ {0x380b, 0xe0, 0, 0}, {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, ++ {0x501f, 0x00, 0, 0}, {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, ++ {0x350b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x0b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 300}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_QCIF_176_144[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, ++ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, ++ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, ++ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, ++ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, ++ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, ++ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, ++ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, ++ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, ++ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, ++ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, ++ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, ++ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, ++ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, ++ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, ++ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, ++ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, ++ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, ++ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, ++ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, ++ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, ++ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, ++ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, ++ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, ++ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, ++ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, ++ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, ++ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, ++ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, ++ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, ++ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, ++ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, ++ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, ++ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, ++ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, ++ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, ++ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, ++ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, ++ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, ++ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, ++ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, ++ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, ++ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, ++ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, ++ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, ++ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, ++ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, ++ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, ++ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, ++ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, ++ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, ++ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, ++ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, ++ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, ++ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, ++ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, ++ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, ++ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, ++ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, ++ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, ++ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, ++ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, ++ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, ++ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, ++ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, ++ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, ++ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, ++ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, ++ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, ++ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, ++ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, ++ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, ++ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, ++ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, ++ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, ++ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, ++ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, ++ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, ++ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, ++ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, ++ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, ++ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, ++ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, ++ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, ++ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, ++ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, ++ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, ++ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, ++ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, ++ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, ++ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, ++ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, ++ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, ++ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, ++ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, ++ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, ++ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, ++ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, ++ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, ++ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, ++ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, ++ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, ++ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, ++ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, ++ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, ++ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, ++ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, ++ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, ++ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, ++ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, ++ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, ++ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, ++ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, ++ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, ++ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, ++ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, ++ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, ++ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, ++ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, ++ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, ++ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, ++ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0}, ++ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_QCIF_176_144[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x10, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, ++ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, ++ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, ++ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, ++ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, ++ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, ++ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, ++ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, ++ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, ++ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, ++ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, ++ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, ++ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, ++ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, ++ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, ++ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, ++ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, ++ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, ++ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, ++ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, ++ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, ++ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, ++ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, ++ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, ++ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, ++ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, ++ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, ++ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, ++ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, ++ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, ++ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, ++ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, ++ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, ++ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, ++ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, ++ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, ++ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, ++ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, ++ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, ++ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, ++ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, ++ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, ++ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, ++ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, ++ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, ++ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, ++ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, ++ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, ++ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, ++ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, ++ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, ++ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, ++ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, ++ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, ++ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, ++ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, ++ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, ++ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, ++ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, ++ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, ++ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, ++ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, ++ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, ++ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, ++ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, ++ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, ++ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, ++ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, ++ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, ++ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, ++ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, ++ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, ++ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, ++ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, ++ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, ++ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, ++ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, ++ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, ++ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, ++ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, ++ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, ++ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, ++ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, ++ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, ++ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, ++ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, ++ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, ++ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, ++ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, ++ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, ++ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, ++ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, ++ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, ++ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, ++ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, ++ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, ++ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, ++ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, ++ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, ++ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, ++ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, ++ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, ++ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, ++ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, ++ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, ++ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, ++ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, ++ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, ++ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, ++ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, ++ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, ++ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, ++ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, ++ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, ++ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, ++ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, ++ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, ++ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, ++ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, ++ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, ++ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, ++ {0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0}, ++ {0x380b, 0x90, 0, 0}, {0x3a00, 0x78, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_QSXGA_2592_1944[] = { ++ {0x3503, 0x07, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, ++ {0x3002, 0x00, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, ++ {0x3005, 0xff, 0, 0}, {0x3006, 0xff, 0, 0}, {0x3007, 0x3f, 0, 0}, ++ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3818, 0xc0, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3602, 0xe4, 0, 0}, {0x3612, 0xac, 0, 0}, {0x3613, 0x44, 0, 0}, ++ {0x3622, 0x60, 0, 0}, {0x3623, 0x22, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3705, 0xda, 0, 0}, {0x370a, 0x80, 0, 0}, {0x3801, 0x95, 0, 0}, ++ {0x3803, 0x0e, 0, 0}, {0x3804, 0x0a, 0, 0}, {0x3805, 0x20, 0, 0}, ++ {0x3806, 0x07, 0, 0}, {0x3807, 0x98, 0, 0}, {0x3808, 0x0a, 0, 0}, ++ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, ++ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3815, 0x44, 0, 0}, ++ {0x3824, 0x11, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, ++ {0x3a00, 0x78, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, ++ {0x5682, 0x0a, 0, 0}, {0x5683, 0x20, 0, 0}, {0x5686, 0x07, 0, 0}, ++ {0x5687, 0x98, 0, 0}, {0x5001, 0xff, 0, 0}, {0x589b, 0x00, 0, 0}, ++ {0x589a, 0xc0, 0, 0}, {0x4407, 0x04, 0, 0}, {0x3008, 0x02, 0, 0}, ++ {0x460b, 0x37, 0, 0}, {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, ++ {0x4713, 0x03, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x3815, 0x01, 0, 0}, ++ {0x501f, 0x00, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0}, ++ {0x5002, 0xe0, 0, 0}, {0x530a, 0x01, 0, 0}, {0x530d, 0x10, 0, 0}, ++ {0x530c, 0x04, 0, 0}, {0x5312, 0x20, 0, 0}, {0x5282, 0x01, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x3012, 0x00, 0, 0}, ++}; ++ ++ ++static struct reg_value ov5642_setting_VGA_2_QVGA[] = { ++ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, ++ {0x380b, 0xf0, 0, 0}, {0x3815, 0x04, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_QSXGA_2_VGA[] = { ++ {0x3503, 0x00, 0, 0}, {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, ++ {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, ++ {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x3818, 0xc1, 0, 0}, {0x3621, 0x87, 0, 0}, ++ {0x350c, 0x03, 0, 0}, {0x350d, 0xe8, 0, 0}, {0x3602, 0xfc, 0, 0}, ++ {0x3612, 0xff, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3622, 0x60, 0, 0}, ++ {0x3623, 0x01, 0, 0}, {0x3604, 0x48, 0, 0}, {0x3705, 0xdb, 0, 0}, ++ {0x370a, 0x81, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, ++ {0x3807, 0xc0, 0, 0}, {0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, ++ {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3810, 0x40, 0, 0}, {0x3815, 0x04, 0, 0}, {0x3824, 0x11, 0, 0}, ++ {0x3825, 0xb4, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, ++ {0x5001, 0xff, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x4407, 0x0c, 0, 0}, {0x3008, 0x02, 0, 0}, {0x460b, 0x37, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x471d, 0x05, 0, 0}, {0x4713, 0x02, 0, 0}, ++ {0x471c, 0xd0, 0, 0}, {0x3815, 0x04, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x3002, 0x5c, 0, 0}, {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, ++ {0x530a, 0x01, 0, 0}, {0x530d, 0x0c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x5312, 0x40, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x3012, 0x02, 0, 0}, {0x3010, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_VGA_640_480[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_VGA_640_480[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++}; ++ ++ ++static struct reg_value ov5642_setting_30fps_XGA_1024_768[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, ++ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_XGA_1024_768[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, ++ {0x380b, 0x00, 0, 0}, {0x3815, 0x02, 0, 0}, {0x302c, 0x60, 0x60, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_QVGA_320_240[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x08, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3808, 0x01, 0, 0}, ++ {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, {0x380b, 0xf0, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_NTSC_720_480[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xb0, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, ++ {0x5683, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x302c, 0x60, 0x60, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_PAL_720_576[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3615, 0xf0, 0, 0}, {0x3000, 0x00, 0, 0}, ++ {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, {0x3003, 0x00, 0, 0}, ++ {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, {0x3006, 0x43, 0, 0}, ++ {0x3007, 0x37, 0, 0}, {0x3011, 0x09, 0, 0}, {0x3012, 0x02, 0, 0}, ++ {0x3010, 0x00, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0}, {0x380b, 0x40, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3825, 0xd8, 0, 0}, ++ {0x3501, 0x1e, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, ++ {0x380c, 0x07, 0, 0}, {0x380d, 0x2a, 0, 0}, {0x380e, 0x03, 0, 0}, ++ {0x380f, 0xe8, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x3818, 0xc1, 0, 0}, {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, ++ {0x3801, 0x80, 0, 0}, {0x3621, 0xc7, 0, 0}, {0x3801, 0x50, 0, 0}, ++ {0x3803, 0x08, 0, 0}, {0x3827, 0x3c, 0, 0}, {0x3810, 0x80, 0, 0}, ++ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x5682, 0x04, 0, 0}, ++ {0x5683, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, {0x3807, 0x58, 0, 0}, ++ {0x5686, 0x03, 0, 0}, {0x5687, 0x58, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a1a, 0x05, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, ++ {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, ++ {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, ++ {0x350d, 0xd0, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, ++ {0x528c, 0x08, 0, 0}, {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, ++ {0x528f, 0x10, 0, 0}, {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, ++ {0x5293, 0x02, 0, 0}, {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, ++ {0x5296, 0x00, 0, 0}, {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, ++ {0x5299, 0x02, 0, 0}, {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, ++ {0x529c, 0x00, 0, 0}, {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, ++ {0x529f, 0x02, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, ++ {0x3a1f, 0x10, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, ++ {0x5193, 0x70, 0, 0}, {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, ++ {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3621, 0x87, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x302c, 0x60, 0x60, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_720P_1280_720[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, ++ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, ++ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, ++ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, ++ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, ++ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, ++ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, ++ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, ++ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, ++ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, ++ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, ++ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, ++ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, ++ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, ++ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, ++ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, ++ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, ++ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, ++ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, ++ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, ++ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, ++ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, ++ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0}, ++ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0}, ++ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0}, ++ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0}, ++ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0}, ++ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0}, ++ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0}, ++ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0}, ++ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0}, ++ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0}, ++ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0}, ++ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, ++ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, ++ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, {0x3010, 0x30, 0, 0}, ++ {0x3a08, 0x06, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x05, 0, 0}, ++ {0x3a0b, 0x50, 0, 0}, {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x07, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_30fps_720P_1280_720[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, ++ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, ++ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, ++ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, ++ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, ++ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, ++ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, ++ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, ++ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, ++ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, ++ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, ++ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, ++ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, ++ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, ++ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, ++ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, ++ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, ++ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, ++ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, ++ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, ++ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, ++ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, ++ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x350c, 0x02, 0, 0}, {0x350d, 0xe4, 0, 0}, {0x3621, 0xc9, 0, 0}, ++ {0x370a, 0x81, 0, 0}, {0x3803, 0x08, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x3806, 0x02, 0, 0}, {0x3807, 0xd0, 0, 0}, ++ {0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0}, ++ {0x380b, 0xd0, 0, 0}, {0x380c, 0x08, 0, 0}, {0x380d, 0x72, 0, 0}, ++ {0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0xc0, 0, 0}, ++ {0x3818, 0xc9, 0, 0}, {0x381c, 0x10, 0, 0}, {0x381d, 0xa0, 0, 0}, ++ {0x381e, 0x05, 0, 0}, {0x381f, 0xb0, 0, 0}, {0x3820, 0x00, 0, 0}, ++ {0x3821, 0x00, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3a08, 0x1b, 0, 0}, ++ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x17, 0, 0}, {0x3a0b, 0x20, 0, 0}, ++ {0x3a0d, 0x02, 0, 0}, {0x3a0e, 0x01, 0, 0}, {0x401c, 0x04, 0, 0}, ++ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, {0x5686, 0x02, 0, 0}, ++ {0x5687, 0xcc, 0, 0}, {0x5001, 0x7f, 0, 0}, {0x589b, 0x06, 0, 0}, ++ {0x589a, 0xc5, 0, 0}, {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, ++ {0x460c, 0x20, 0, 0}, {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, ++ {0x501f, 0x00, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, ++ {0x3819, 0x80, 0, 0}, {0x5002, 0xe0, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_1080P_1920_1080[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x00, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3030, 0x2b, 0, 0}, ++ {0x3011, 0x08, 0, 0}, {0x3010, 0x10, 0, 0}, {0x3604, 0x60, 0, 0}, ++ {0x3622, 0x60, 0, 0}, {0x3621, 0x09, 0, 0}, {0x3709, 0x00, 0, 0}, ++ {0x4000, 0x21, 0, 0}, {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, ++ {0x3605, 0x04, 0, 0}, {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, ++ {0x300d, 0x22, 0, 0}, {0x3623, 0x22, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5500, 0x0a, 0, 0}, ++ {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, {0x5080, 0x08, 0, 0}, ++ {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, {0x471d, 0x05, 0, 0}, ++ {0x4708, 0x06, 0, 0}, {0x370c, 0xa0, 0, 0}, {0x3808, 0x0a, 0, 0}, ++ {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0}, {0x380b, 0x98, 0, 0}, ++ {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, {0x380e, 0x07, 0, 0}, ++ {0x380f, 0xd0, 0, 0}, {0x5687, 0x94, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x5001, 0xcf, 0, 0}, {0x4300, 0x30, 0, 0}, ++ {0x4300, 0x30, 0, 0}, {0x460b, 0x35, 0, 0}, {0x471d, 0x00, 0, 0}, ++ {0x3002, 0x0c, 0, 0}, {0x3002, 0x00, 0, 0}, {0x4713, 0x03, 0, 0}, ++ {0x471c, 0x50, 0, 0}, {0x4721, 0x02, 0, 0}, {0x4402, 0x90, 0, 0}, ++ {0x460c, 0x22, 0, 0}, {0x3815, 0x44, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3818, 0xc8, 0, 0}, {0x3801, 0x88, 0, 0}, {0x3824, 0x11, 0, 0}, ++ {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x04, 0, 0}, {0x3a13, 0x30, 0, 0}, ++ {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, {0x3a08, 0x12, 0, 0}, ++ {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, {0x3a0b, 0xa0, 0, 0}, ++ {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, {0x3a0d, 0x08, 0, 0}, ++ {0x3a0e, 0x06, 0, 0}, {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, ++ {0x3502, 0x00, 0, 0}, {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x32, 0, 0}, ++ {0x3a1b, 0x3c, 0, 0}, {0x3a1e, 0x32, 0, 0}, {0x3a11, 0x80, 0, 0}, ++ {0x3a1f, 0x20, 0, 0}, {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, ++ {0x3a03, 0x7d, 0, 0}, {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, ++ {0x3a15, 0x7d, 0, 0}, {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, ++ {0x3a08, 0x09, 0, 0}, {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, ++ {0x3a0b, 0xd0, 0, 0}, {0x3a0d, 0x10, 0, 0}, {0x3a0e, 0x0d, 0, 0}, ++ {0x4407, 0x04, 0, 0}, {0x5193, 0x70, 0, 0}, {0x589b, 0x00, 0, 0}, ++ {0x589a, 0xc0, 0, 0}, {0x401e, 0x20, 0, 0}, {0x4001, 0x42, 0, 0}, ++ {0x401c, 0x06, 0, 0}, {0x3825, 0xac, 0, 0}, {0x3827, 0x0c, 0, 0}, ++ {0x528a, 0x01, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x10, 0, 0}, {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, ++ {0x5290, 0x30, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x08, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x28, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, ++ {0x5282, 0x00, 0, 0}, {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, ++ {0x5302, 0x00, 0, 0}, {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, ++ {0x530d, 0x0c, 0, 0}, {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, ++ {0x5310, 0x20, 0, 0}, {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, ++ {0x5309, 0x40, 0, 0}, {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, ++ {0x5306, 0x00, 0, 0}, {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, ++ {0x5315, 0x20, 0, 0}, {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, ++ {0x5317, 0x00, 0, 0}, {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, ++ {0x5381, 0x00, 0, 0}, {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, ++ {0x5384, 0x00, 0, 0}, {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, ++ {0x5387, 0x00, 0, 0}, {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, ++ {0x538a, 0x00, 0, 0}, {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, ++ {0x538d, 0x00, 0, 0}, {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, ++ {0x5390, 0x00, 0, 0}, {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, ++ {0x5393, 0xa2, 0, 0}, {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, ++ {0x5481, 0x21, 0, 0}, {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, ++ {0x5484, 0x65, 0, 0}, {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, ++ {0x5487, 0x87, 0, 0}, {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, ++ {0x548a, 0xaa, 0, 0}, {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, ++ {0x548d, 0xdd, 0, 0}, {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, ++ {0x5490, 0x05, 0, 0}, {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, ++ {0x5493, 0x20, 0, 0}, {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, ++ {0x5496, 0x02, 0, 0}, {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, ++ {0x5499, 0x86, 0, 0}, {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, ++ {0x549c, 0x02, 0, 0}, {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, ++ {0x549f, 0x1c, 0, 0}, {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, ++ {0x54a2, 0x01, 0, 0}, {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, ++ {0x54a5, 0xc5, 0, 0}, {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, ++ {0x54a8, 0x01, 0, 0}, {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, ++ {0x54ab, 0x41, 0, 0}, {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, ++ {0x54ae, 0x00, 0, 0}, {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, ++ {0x54b1, 0x20, 0, 0}, {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, ++ {0x54b4, 0x00, 0, 0}, {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, ++ {0x54b7, 0xdf, 0, 0}, {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, ++ {0x3406, 0x00, 0, 0}, {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, ++ {0x5182, 0x11, 0, 0}, {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, ++ {0x5185, 0x24, 0, 0}, {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, ++ {0x5188, 0x08, 0, 0}, {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, ++ {0x518b, 0xb2, 0, 0}, {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, ++ {0x518e, 0x3d, 0, 0}, {0x518f, 0x58, 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, 0x12, 0, 0}, ++ {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, ++ {0x519d, 0x82, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, ++ {0x3a0f, 0x38, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, ++ {0x3a1e, 0x2e, 0, 0}, {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x5688, 0xa6, 0, 0}, {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, ++ {0x568b, 0xae, 0, 0}, {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, ++ {0x568e, 0x62, 0, 0}, {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, ++ {0x5584, 0x40, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, ++ {0x5800, 0x27, 0, 0}, {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, ++ {0x5803, 0x0f, 0, 0}, {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, ++ {0x5806, 0x1e, 0, 0}, {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, ++ {0x5809, 0x0d, 0, 0}, {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, ++ {0x580c, 0x0a, 0, 0}, {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, ++ {0x580f, 0x19, 0, 0}, {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, ++ {0x5812, 0x04, 0, 0}, {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, ++ {0x5815, 0x06, 0, 0}, {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, ++ {0x5818, 0x0a, 0, 0}, {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, ++ {0x581b, 0x00, 0, 0}, {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, ++ {0x581e, 0x08, 0, 0}, {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, ++ {0x5821, 0x05, 0, 0}, {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, ++ {0x5824, 0x00, 0, 0}, {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, ++ {0x5827, 0x0c, 0, 0}, {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, ++ {0x582a, 0x06, 0, 0}, {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, ++ {0x582d, 0x07, 0, 0}, {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, ++ {0x5830, 0x18, 0, 0}, {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, ++ {0x5833, 0x0a, 0, 0}, {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, ++ {0x5836, 0x15, 0, 0}, {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, ++ {0x5839, 0x1f, 0, 0}, {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, ++ {0x583c, 0x17, 0, 0}, {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, ++ {0x583f, 0x53, 0, 0}, {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, ++ {0x5842, 0x0d, 0, 0}, {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, ++ {0x5845, 0x09, 0, 0}, {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, ++ {0x5848, 0x10, 0, 0}, {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, ++ {0x584b, 0x0e, 0, 0}, {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, ++ {0x584e, 0x11, 0, 0}, {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, ++ {0x5851, 0x0c, 0, 0}, {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, ++ {0x5854, 0x10, 0, 0}, {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, ++ {0x5857, 0x0b, 0, 0}, {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, ++ {0x585a, 0x0d, 0, 0}, {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, ++ {0x585d, 0x0c, 0, 0}, {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, ++ {0x5860, 0x0c, 0, 0}, {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, ++ {0x5863, 0x08, 0, 0}, {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, ++ {0x5866, 0x18, 0, 0}, {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, ++ {0x5869, 0x19, 0, 0}, {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, ++ {0x586c, 0x13, 0, 0}, {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, ++ {0x586f, 0x16, 0, 0}, {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, ++ {0x5872, 0x10, 0, 0}, {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, ++ {0x5875, 0x16, 0, 0}, {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, ++ {0x5878, 0x10, 0, 0}, {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, ++ {0x587b, 0x14, 0, 0}, {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, ++ {0x587e, 0x11, 0, 0}, {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, ++ {0x5881, 0x15, 0, 0}, {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, ++ {0x5884, 0x15, 0, 0}, {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, ++ {0x5887, 0x17, 0, 0}, {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, ++ {0x3702, 0x10, 0, 0}, {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, ++ {0x370b, 0x40, 0, 0}, {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, ++ {0x3632, 0x52, 0, 0}, {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, ++ {0x5785, 0x07, 0, 0}, {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, ++ {0x3604, 0x48, 0, 0}, {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, ++ {0x370f, 0xc0, 0, 0}, {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, ++ {0x5007, 0x00, 0, 0}, {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, ++ {0x5013, 0x00, 0, 0}, {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, ++ {0x5087, 0x00, 0, 0}, {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, ++ {0x302b, 0x00, 0, 0}, {0x3503, 0x07, 0, 0}, {0x3011, 0x07, 0, 0}, ++ {0x350c, 0x04, 0, 0}, {0x350d, 0x58, 0, 0}, {0x3801, 0x8a, 0, 0}, ++ {0x3803, 0x0a, 0, 0}, {0x3804, 0x07, 0, 0}, {0x3805, 0x80, 0, 0}, ++ {0x3806, 0x04, 0, 0}, {0x3807, 0x39, 0, 0}, {0x3808, 0x07, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0}, ++ {0x380c, 0x09, 0, 0}, {0x380d, 0xd6, 0, 0}, {0x380e, 0x04, 0, 0}, ++ {0x380f, 0x58, 0, 0}, {0x381c, 0x11, 0, 0}, {0x381d, 0xba, 0, 0}, ++ {0x381e, 0x04, 0, 0}, {0x381f, 0x48, 0, 0}, {0x3820, 0x04, 0, 0}, ++ {0x3821, 0x18, 0, 0}, {0x3a08, 0x14, 0, 0}, {0x3a09, 0xe0, 0, 0}, ++ {0x3a0a, 0x11, 0, 0}, {0x3a0b, 0x60, 0, 0}, {0x3a0d, 0x04, 0, 0}, ++ {0x3a0e, 0x03, 0, 0}, {0x5682, 0x07, 0, 0}, {0x5683, 0x60, 0, 0}, ++ {0x5686, 0x04, 0, 0}, {0x5687, 0x1c, 0, 0}, {0x5001, 0x7f, 0, 0}, ++ {0x3503, 0x00, 0, 0}, {0x3010, 0x10, 0, 0}, {0x460c, 0x20, 0, 0}, ++ {0x460b, 0x37, 0, 0}, {0x471c, 0xd0, 0, 0}, {0x471d, 0x05, 0, 0}, ++ {0x3815, 0x01, 0, 0}, {0x3818, 0x00, 0x08, 0}, {0x501f, 0x00, 0, 0}, ++ {0x4300, 0x30, 0, 0}, {0x3002, 0x1c, 0, 0}, {0x3819, 0x80, 0, 0}, ++ {0x5002, 0xe0, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_QVGA_320_240[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, ++ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, ++ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, ++ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, ++ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, ++ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, ++ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, ++ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, ++ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, ++ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, ++ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, ++ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, ++ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, ++ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, ++ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, ++ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, ++ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, ++ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, ++ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, ++ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, ++ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, ++ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, ++ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, ++ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, ++ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, ++ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, ++ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, ++ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, ++ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, ++ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, ++ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, ++ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, ++ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, ++ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, ++ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, ++ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, ++ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, ++ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, ++ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, ++ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, ++ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, ++ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, ++ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, ++ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, ++ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, ++ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, ++ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, ++ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, ++ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, ++ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, ++ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, ++ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, ++ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, ++ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, ++ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, ++ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, ++ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, ++ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, ++ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, ++ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, ++ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, ++ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, ++ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, ++ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, ++ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, ++ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, ++ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, ++ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, ++ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, ++ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, ++ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, ++ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, ++ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, ++ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, ++ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, ++ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, ++ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, ++ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, ++ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, ++ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, ++ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, ++ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, ++ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, ++ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, ++ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, ++ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, ++ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, ++ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, ++ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, ++ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, ++ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, ++ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, ++ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, ++ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, ++ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, ++ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, ++ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, ++ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, ++ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, ++ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, ++ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, ++ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, ++ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, ++ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, ++ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, ++ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, ++ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, ++ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, ++ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, ++ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, ++ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, ++ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, ++ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, ++ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, ++ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, ++ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, ++ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, ++ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, ++ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, ++ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, ++ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, ++ {0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0}, ++ {0x380b, 0xf0, 0, 0}, {0x3a00, 0x78, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_NTSC_720_480[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, ++ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, ++ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, ++ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, ++ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, ++ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, ++ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, ++ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, ++ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, ++ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, ++ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, ++ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, ++ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, ++ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, ++ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, ++ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, ++ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, ++ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, ++ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, ++ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, ++ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, ++ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, ++ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, ++ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, ++ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, ++ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, ++ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, ++ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, ++ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, ++ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, ++ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, ++ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, ++ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, ++ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, ++ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, ++ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, ++ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, ++ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, ++ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, ++ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, ++ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, ++ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, ++ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, ++ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, ++ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, ++ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, ++ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, ++ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, ++ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, ++ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, ++ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, ++ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, ++ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, ++ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, ++ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, ++ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, ++ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, ++ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, ++ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, ++ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, ++ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, ++ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, ++ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, ++ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, ++ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, ++ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, ++ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, ++ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, ++ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, ++ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, ++ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, ++ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, ++ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, ++ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, ++ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, ++ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, ++ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, ++ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, ++ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, ++ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, ++ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, ++ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, ++ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, ++ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, ++ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, ++ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, ++ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, ++ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, ++ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, ++ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, ++ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, ++ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, ++ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, ++ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, ++ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, ++ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, ++ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, ++ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, ++ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, ++ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, ++ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, ++ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, ++ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, ++ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, ++ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, ++ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, ++ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, ++ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, ++ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, ++ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, ++ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, ++ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, ++ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, ++ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, ++ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, ++ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, ++ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, ++ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, ++ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, ++ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, ++ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, ++ {0x3824, 0x11, 0, 0}, {0x3825, 0xb4, 0, 0}, {0x3826, 0x00, 0, 0}, ++ {0x3827, 0x3d, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, ++ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0xd0, 0, 0}, {0x380A, 0x01, 0, 0}, {0x380B, 0xe0, 0, 0}, ++ {0x3804, 0x05, 0, 0}, {0x3805, 0x00, 0, 0}, {0x3806, 0x03, 0, 0}, ++ {0x3807, 0x55, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0x55, 0, 0}, ++ {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++}; ++ ++static struct reg_value ov5642_setting_15fps_PAL_720_576[] = { ++ {0x3103, 0x93, 0, 0}, {0x3008, 0x82, 0, 0}, {0x3017, 0x7f, 0, 0}, ++ {0x3018, 0xfc, 0, 0}, {0x3810, 0xc2, 0, 0}, {0x3615, 0xf0, 0, 0}, ++ {0x3000, 0x00, 0, 0}, {0x3001, 0x00, 0, 0}, {0x3002, 0x5c, 0, 0}, ++ {0x3003, 0x00, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3005, 0xff, 0, 0}, ++ {0x3006, 0x43, 0, 0}, {0x3007, 0x37, 0, 0}, {0x3011, 0x08, 0, 0}, ++ {0x3010, 0x10, 0, 0}, {0x460c, 0x22, 0, 0}, {0x3815, 0x04, 0, 0}, ++ {0x370c, 0xa0, 0, 0}, {0x3602, 0xfc, 0, 0}, {0x3612, 0xff, 0, 0}, ++ {0x3634, 0xc0, 0, 0}, {0x3613, 0x00, 0, 0}, {0x3605, 0x7c, 0, 0}, ++ {0x3621, 0x09, 0, 0}, {0x3622, 0x60, 0, 0}, {0x3604, 0x40, 0, 0}, ++ {0x3603, 0xa7, 0, 0}, {0x3603, 0x27, 0, 0}, {0x4000, 0x21, 0, 0}, ++ {0x401d, 0x22, 0, 0}, {0x3600, 0x54, 0, 0}, {0x3605, 0x04, 0, 0}, ++ {0x3606, 0x3f, 0, 0}, {0x3c01, 0x80, 0, 0}, {0x5000, 0x4f, 0, 0}, ++ {0x5020, 0x04, 0, 0}, {0x5181, 0x79, 0, 0}, {0x5182, 0x00, 0, 0}, ++ {0x5185, 0x22, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5001, 0xff, 0, 0}, ++ {0x5500, 0x0a, 0, 0}, {0x5504, 0x00, 0, 0}, {0x5505, 0x7f, 0, 0}, ++ {0x5080, 0x08, 0, 0}, {0x300e, 0x18, 0, 0}, {0x4610, 0x00, 0, 0}, ++ {0x471d, 0x05, 0, 0}, {0x4708, 0x06, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0}, {0x380b, 0xe0, 0, 0}, ++ {0x380e, 0x07, 0, 0}, {0x380f, 0xd0, 0, 0}, {0x501f, 0x00, 0, 0}, ++ {0x5000, 0x4f, 0, 0}, {0x4300, 0x30, 0, 0}, {0x3503, 0x07, 0, 0}, ++ {0x3501, 0x73, 0, 0}, {0x3502, 0x80, 0, 0}, {0x350b, 0x00, 0, 0}, ++ {0x3503, 0x07, 0, 0}, {0x3824, 0x11, 0, 0}, {0x3501, 0x1e, 0, 0}, ++ {0x3502, 0x80, 0, 0}, {0x350b, 0x7f, 0, 0}, {0x380c, 0x0c, 0, 0}, ++ {0x380d, 0x80, 0, 0}, {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, ++ {0x3a0d, 0x04, 0, 0}, {0x3a0e, 0x03, 0, 0}, {0x3818, 0xc1, 0, 0}, ++ {0x3705, 0xdb, 0, 0}, {0x370a, 0x81, 0, 0}, {0x3801, 0x80, 0, 0}, ++ {0x3621, 0x87, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3803, 0x08, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x3810, 0x40, 0, 0}, {0x3804, 0x05, 0, 0}, ++ {0x3805, 0x00, 0, 0}, {0x5682, 0x05, 0, 0}, {0x5683, 0x00, 0, 0}, ++ {0x3806, 0x03, 0, 0}, {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, ++ {0x5687, 0xbc, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a1a, 0x05, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3a18, 0x00, 0, 0}, {0x3a19, 0x7c, 0, 0}, ++ {0x3a08, 0x12, 0, 0}, {0x3a09, 0xc0, 0, 0}, {0x3a0a, 0x0f, 0, 0}, ++ {0x3a0b, 0xa0, 0, 0}, {0x350c, 0x07, 0, 0}, {0x350d, 0xd0, 0, 0}, ++ {0x3500, 0x00, 0, 0}, {0x3501, 0x00, 0, 0}, {0x3502, 0x00, 0, 0}, ++ {0x350a, 0x00, 0, 0}, {0x350b, 0x00, 0, 0}, {0x3503, 0x00, 0, 0}, ++ {0x528a, 0x02, 0, 0}, {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, ++ {0x528d, 0x08, 0, 0}, {0x528e, 0x08, 0, 0}, {0x528f, 0x10, 0, 0}, ++ {0x5290, 0x10, 0, 0}, {0x5292, 0x00, 0, 0}, {0x5293, 0x02, 0, 0}, ++ {0x5294, 0x00, 0, 0}, {0x5295, 0x02, 0, 0}, {0x5296, 0x00, 0, 0}, ++ {0x5297, 0x02, 0, 0}, {0x5298, 0x00, 0, 0}, {0x5299, 0x02, 0, 0}, ++ {0x529a, 0x00, 0, 0}, {0x529b, 0x02, 0, 0}, {0x529c, 0x00, 0, 0}, ++ {0x529d, 0x02, 0, 0}, {0x529e, 0x00, 0, 0}, {0x529f, 0x02, 0, 0}, ++ {0x3a0f, 0x3c, 0, 0}, {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3c, 0, 0}, ++ {0x3a1e, 0x30, 0, 0}, {0x3a11, 0x70, 0, 0}, {0x3a1f, 0x10, 0, 0}, ++ {0x3030, 0x2b, 0, 0}, {0x3a02, 0x00, 0, 0}, {0x3a03, 0x7d, 0, 0}, ++ {0x3a04, 0x00, 0, 0}, {0x3a14, 0x00, 0, 0}, {0x3a15, 0x7d, 0, 0}, ++ {0x3a16, 0x00, 0, 0}, {0x3a00, 0x78, 0, 0}, {0x3a08, 0x09, 0, 0}, ++ {0x3a09, 0x60, 0, 0}, {0x3a0a, 0x07, 0, 0}, {0x3a0b, 0xd0, 0, 0}, ++ {0x3a0d, 0x08, 0, 0}, {0x3a0e, 0x06, 0, 0}, {0x5193, 0x70, 0, 0}, ++ {0x589b, 0x04, 0, 0}, {0x589a, 0xc5, 0, 0}, {0x401e, 0x20, 0, 0}, ++ {0x4001, 0x42, 0, 0}, {0x401c, 0x04, 0, 0}, {0x528a, 0x01, 0, 0}, ++ {0x528b, 0x04, 0, 0}, {0x528c, 0x08, 0, 0}, {0x528d, 0x10, 0, 0}, ++ {0x528e, 0x20, 0, 0}, {0x528f, 0x28, 0, 0}, {0x5290, 0x30, 0, 0}, ++ {0x5292, 0x00, 0, 0}, {0x5293, 0x01, 0, 0}, {0x5294, 0x00, 0, 0}, ++ {0x5295, 0x04, 0, 0}, {0x5296, 0x00, 0, 0}, {0x5297, 0x08, 0, 0}, ++ {0x5298, 0x00, 0, 0}, {0x5299, 0x10, 0, 0}, {0x529a, 0x00, 0, 0}, ++ {0x529b, 0x20, 0, 0}, {0x529c, 0x00, 0, 0}, {0x529d, 0x28, 0, 0}, ++ {0x529e, 0x00, 0, 0}, {0x529f, 0x30, 0, 0}, {0x5282, 0x00, 0, 0}, ++ {0x5300, 0x00, 0, 0}, {0x5301, 0x20, 0, 0}, {0x5302, 0x00, 0, 0}, ++ {0x5303, 0x7c, 0, 0}, {0x530c, 0x00, 0, 0}, {0x530d, 0x0c, 0, 0}, ++ {0x530e, 0x20, 0, 0}, {0x530f, 0x80, 0, 0}, {0x5310, 0x20, 0, 0}, ++ {0x5311, 0x80, 0, 0}, {0x5308, 0x20, 0, 0}, {0x5309, 0x40, 0, 0}, ++ {0x5304, 0x00, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x00, 0, 0}, ++ {0x5307, 0x80, 0, 0}, {0x5314, 0x08, 0, 0}, {0x5315, 0x20, 0, 0}, ++ {0x5319, 0x30, 0, 0}, {0x5316, 0x10, 0, 0}, {0x5317, 0x00, 0, 0}, ++ {0x5318, 0x02, 0, 0}, {0x5380, 0x01, 0, 0}, {0x5381, 0x00, 0, 0}, ++ {0x5382, 0x00, 0, 0}, {0x5383, 0x4e, 0, 0}, {0x5384, 0x00, 0, 0}, ++ {0x5385, 0x0f, 0, 0}, {0x5386, 0x00, 0, 0}, {0x5387, 0x00, 0, 0}, ++ {0x5388, 0x01, 0, 0}, {0x5389, 0x15, 0, 0}, {0x538a, 0x00, 0, 0}, ++ {0x538b, 0x31, 0, 0}, {0x538c, 0x00, 0, 0}, {0x538d, 0x00, 0, 0}, ++ {0x538e, 0x00, 0, 0}, {0x538f, 0x0f, 0, 0}, {0x5390, 0x00, 0, 0}, ++ {0x5391, 0xab, 0, 0}, {0x5392, 0x00, 0, 0}, {0x5393, 0xa2, 0, 0}, ++ {0x5394, 0x08, 0, 0}, {0x5480, 0x14, 0, 0}, {0x5481, 0x21, 0, 0}, ++ {0x5482, 0x36, 0, 0}, {0x5483, 0x57, 0, 0}, {0x5484, 0x65, 0, 0}, ++ {0x5485, 0x71, 0, 0}, {0x5486, 0x7d, 0, 0}, {0x5487, 0x87, 0, 0}, ++ {0x5488, 0x91, 0, 0}, {0x5489, 0x9a, 0, 0}, {0x548a, 0xaa, 0, 0}, ++ {0x548b, 0xb8, 0, 0}, {0x548c, 0xcd, 0, 0}, {0x548d, 0xdd, 0, 0}, ++ {0x548e, 0xea, 0, 0}, {0x548f, 0x1d, 0, 0}, {0x5490, 0x05, 0, 0}, ++ {0x5491, 0x00, 0, 0}, {0x5492, 0x04, 0, 0}, {0x5493, 0x20, 0, 0}, ++ {0x5494, 0x03, 0, 0}, {0x5495, 0x60, 0, 0}, {0x5496, 0x02, 0, 0}, ++ {0x5497, 0xb8, 0, 0}, {0x5498, 0x02, 0, 0}, {0x5499, 0x86, 0, 0}, ++ {0x549a, 0x02, 0, 0}, {0x549b, 0x5b, 0, 0}, {0x549c, 0x02, 0, 0}, ++ {0x549d, 0x3b, 0, 0}, {0x549e, 0x02, 0, 0}, {0x549f, 0x1c, 0, 0}, ++ {0x54a0, 0x02, 0, 0}, {0x54a1, 0x04, 0, 0}, {0x54a2, 0x01, 0, 0}, ++ {0x54a3, 0xed, 0, 0}, {0x54a4, 0x01, 0, 0}, {0x54a5, 0xc5, 0, 0}, ++ {0x54a6, 0x01, 0, 0}, {0x54a7, 0xa5, 0, 0}, {0x54a8, 0x01, 0, 0}, ++ {0x54a9, 0x6c, 0, 0}, {0x54aa, 0x01, 0, 0}, {0x54ab, 0x41, 0, 0}, ++ {0x54ac, 0x01, 0, 0}, {0x54ad, 0x20, 0, 0}, {0x54ae, 0x00, 0, 0}, ++ {0x54af, 0x16, 0, 0}, {0x54b0, 0x01, 0, 0}, {0x54b1, 0x20, 0, 0}, ++ {0x54b2, 0x00, 0, 0}, {0x54b3, 0x10, 0, 0}, {0x54b4, 0x00, 0, 0}, ++ {0x54b5, 0xf0, 0, 0}, {0x54b6, 0x00, 0, 0}, {0x54b7, 0xdf, 0, 0}, ++ {0x5402, 0x3f, 0, 0}, {0x5403, 0x00, 0, 0}, {0x3406, 0x00, 0, 0}, ++ {0x5180, 0xff, 0, 0}, {0x5181, 0x52, 0, 0}, {0x5182, 0x11, 0, 0}, ++ {0x5183, 0x14, 0, 0}, {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, ++ {0x5186, 0x06, 0, 0}, {0x5187, 0x08, 0, 0}, {0x5188, 0x08, 0, 0}, ++ {0x5189, 0x7c, 0, 0}, {0x518a, 0x60, 0, 0}, {0x518b, 0xb2, 0, 0}, ++ {0x518c, 0xb2, 0, 0}, {0x518d, 0x44, 0, 0}, {0x518e, 0x3d, 0, 0}, ++ {0x518f, 0x58, 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, 0x12, 0, 0}, {0x519a, 0x04, 0, 0}, ++ {0x519b, 0x00, 0, 0}, {0x519c, 0x06, 0, 0}, {0x519d, 0x82, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5025, 0x80, 0, 0}, {0x3a0f, 0x38, 0, 0}, ++ {0x3a10, 0x30, 0, 0}, {0x3a1b, 0x3a, 0, 0}, {0x3a1e, 0x2e, 0, 0}, ++ {0x3a11, 0x60, 0, 0}, {0x3a1f, 0x10, 0, 0}, {0x5688, 0xa6, 0, 0}, ++ {0x5689, 0x6a, 0, 0}, {0x568a, 0xea, 0, 0}, {0x568b, 0xae, 0, 0}, ++ {0x568c, 0xa6, 0, 0}, {0x568d, 0x6a, 0, 0}, {0x568e, 0x62, 0, 0}, ++ {0x568f, 0x26, 0, 0}, {0x5583, 0x40, 0, 0}, {0x5584, 0x40, 0, 0}, ++ {0x5580, 0x02, 0, 0}, {0x5000, 0xcf, 0, 0}, {0x5800, 0x27, 0, 0}, ++ {0x5801, 0x19, 0, 0}, {0x5802, 0x12, 0, 0}, {0x5803, 0x0f, 0, 0}, ++ {0x5804, 0x10, 0, 0}, {0x5805, 0x15, 0, 0}, {0x5806, 0x1e, 0, 0}, ++ {0x5807, 0x2f, 0, 0}, {0x5808, 0x15, 0, 0}, {0x5809, 0x0d, 0, 0}, ++ {0x580a, 0x0a, 0, 0}, {0x580b, 0x09, 0, 0}, {0x580c, 0x0a, 0, 0}, ++ {0x580d, 0x0c, 0, 0}, {0x580e, 0x12, 0, 0}, {0x580f, 0x19, 0, 0}, ++ {0x5810, 0x0b, 0, 0}, {0x5811, 0x07, 0, 0}, {0x5812, 0x04, 0, 0}, ++ {0x5813, 0x03, 0, 0}, {0x5814, 0x03, 0, 0}, {0x5815, 0x06, 0, 0}, ++ {0x5816, 0x0a, 0, 0}, {0x5817, 0x0f, 0, 0}, {0x5818, 0x0a, 0, 0}, ++ {0x5819, 0x05, 0, 0}, {0x581a, 0x01, 0, 0}, {0x581b, 0x00, 0, 0}, ++ {0x581c, 0x00, 0, 0}, {0x581d, 0x03, 0, 0}, {0x581e, 0x08, 0, 0}, ++ {0x581f, 0x0c, 0, 0}, {0x5820, 0x0a, 0, 0}, {0x5821, 0x05, 0, 0}, ++ {0x5822, 0x01, 0, 0}, {0x5823, 0x00, 0, 0}, {0x5824, 0x00, 0, 0}, ++ {0x5825, 0x03, 0, 0}, {0x5826, 0x08, 0, 0}, {0x5827, 0x0c, 0, 0}, ++ {0x5828, 0x0e, 0, 0}, {0x5829, 0x08, 0, 0}, {0x582a, 0x06, 0, 0}, ++ {0x582b, 0x04, 0, 0}, {0x582c, 0x05, 0, 0}, {0x582d, 0x07, 0, 0}, ++ {0x582e, 0x0b, 0, 0}, {0x582f, 0x12, 0, 0}, {0x5830, 0x18, 0, 0}, ++ {0x5831, 0x10, 0, 0}, {0x5832, 0x0c, 0, 0}, {0x5833, 0x0a, 0, 0}, ++ {0x5834, 0x0b, 0, 0}, {0x5835, 0x0e, 0, 0}, {0x5836, 0x15, 0, 0}, ++ {0x5837, 0x19, 0, 0}, {0x5838, 0x32, 0, 0}, {0x5839, 0x1f, 0, 0}, ++ {0x583a, 0x18, 0, 0}, {0x583b, 0x16, 0, 0}, {0x583c, 0x17, 0, 0}, ++ {0x583d, 0x1e, 0, 0}, {0x583e, 0x26, 0, 0}, {0x583f, 0x53, 0, 0}, ++ {0x5840, 0x10, 0, 0}, {0x5841, 0x0f, 0, 0}, {0x5842, 0x0d, 0, 0}, ++ {0x5843, 0x0c, 0, 0}, {0x5844, 0x0e, 0, 0}, {0x5845, 0x09, 0, 0}, ++ {0x5846, 0x11, 0, 0}, {0x5847, 0x10, 0, 0}, {0x5848, 0x10, 0, 0}, ++ {0x5849, 0x10, 0, 0}, {0x584a, 0x10, 0, 0}, {0x584b, 0x0e, 0, 0}, ++ {0x584c, 0x10, 0, 0}, {0x584d, 0x10, 0, 0}, {0x584e, 0x11, 0, 0}, ++ {0x584f, 0x10, 0, 0}, {0x5850, 0x0f, 0, 0}, {0x5851, 0x0c, 0, 0}, ++ {0x5852, 0x0f, 0, 0}, {0x5853, 0x10, 0, 0}, {0x5854, 0x10, 0, 0}, ++ {0x5855, 0x0f, 0, 0}, {0x5856, 0x0e, 0, 0}, {0x5857, 0x0b, 0, 0}, ++ {0x5858, 0x10, 0, 0}, {0x5859, 0x0d, 0, 0}, {0x585a, 0x0d, 0, 0}, ++ {0x585b, 0x0c, 0, 0}, {0x585c, 0x0c, 0, 0}, {0x585d, 0x0c, 0, 0}, ++ {0x585e, 0x0b, 0, 0}, {0x585f, 0x0c, 0, 0}, {0x5860, 0x0c, 0, 0}, ++ {0x5861, 0x0c, 0, 0}, {0x5862, 0x0d, 0, 0}, {0x5863, 0x08, 0, 0}, ++ {0x5864, 0x11, 0, 0}, {0x5865, 0x18, 0, 0}, {0x5866, 0x18, 0, 0}, ++ {0x5867, 0x19, 0, 0}, {0x5868, 0x17, 0, 0}, {0x5869, 0x19, 0, 0}, ++ {0x586a, 0x16, 0, 0}, {0x586b, 0x13, 0, 0}, {0x586c, 0x13, 0, 0}, ++ {0x586d, 0x12, 0, 0}, {0x586e, 0x13, 0, 0}, {0x586f, 0x16, 0, 0}, ++ {0x5870, 0x14, 0, 0}, {0x5871, 0x12, 0, 0}, {0x5872, 0x10, 0, 0}, ++ {0x5873, 0x11, 0, 0}, {0x5874, 0x11, 0, 0}, {0x5875, 0x16, 0, 0}, ++ {0x5876, 0x14, 0, 0}, {0x5877, 0x11, 0, 0}, {0x5878, 0x10, 0, 0}, ++ {0x5879, 0x0f, 0, 0}, {0x587a, 0x10, 0, 0}, {0x587b, 0x14, 0, 0}, ++ {0x587c, 0x13, 0, 0}, {0x587d, 0x12, 0, 0}, {0x587e, 0x11, 0, 0}, ++ {0x587f, 0x11, 0, 0}, {0x5880, 0x12, 0, 0}, {0x5881, 0x15, 0, 0}, ++ {0x5882, 0x14, 0, 0}, {0x5883, 0x15, 0, 0}, {0x5884, 0x15, 0, 0}, ++ {0x5885, 0x15, 0, 0}, {0x5886, 0x13, 0, 0}, {0x5887, 0x17, 0, 0}, ++ {0x3710, 0x10, 0, 0}, {0x3632, 0x51, 0, 0}, {0x3702, 0x10, 0, 0}, ++ {0x3703, 0xb2, 0, 0}, {0x3704, 0x18, 0, 0}, {0x370b, 0x40, 0, 0}, ++ {0x370d, 0x03, 0, 0}, {0x3631, 0x01, 0, 0}, {0x3632, 0x52, 0, 0}, ++ {0x3606, 0x24, 0, 0}, {0x3620, 0x96, 0, 0}, {0x5785, 0x07, 0, 0}, ++ {0x3a13, 0x30, 0, 0}, {0x3600, 0x52, 0, 0}, {0x3604, 0x48, 0, 0}, ++ {0x3606, 0x1b, 0, 0}, {0x370d, 0x0b, 0, 0}, {0x370f, 0xc0, 0, 0}, ++ {0x3709, 0x01, 0, 0}, {0x3823, 0x00, 0, 0}, {0x5007, 0x00, 0, 0}, ++ {0x5009, 0x00, 0, 0}, {0x5011, 0x00, 0, 0}, {0x5013, 0x00, 0, 0}, ++ {0x519e, 0x00, 0, 0}, {0x5086, 0x00, 0, 0}, {0x5087, 0x00, 0, 0}, ++ {0x5088, 0x00, 0, 0}, {0x5089, 0x00, 0, 0}, {0x302b, 0x00, 0, 0}, ++ {0x3824, 0x11, 0, 0}, {0x3825, 0xdc, 0, 0}, {0x3826, 0x00, 0, 0}, ++ {0x3827, 0x08, 0, 0}, {0x380c, 0x0c, 0, 0}, {0x380d, 0x80, 0, 0}, ++ {0x380e, 0x03, 0, 0}, {0x380f, 0xe8, 0, 0}, {0x3808, 0x02, 0, 0}, ++ {0x3809, 0xd0, 0, 0}, {0x380A, 0x02, 0, 0}, {0x380B, 0x40, 0, 0}, ++ {0x3804, 0x04, 0, 0}, {0x3805, 0xb0, 0, 0}, {0x3806, 0x03, 0, 0}, ++ {0x3807, 0xc0, 0, 0}, {0x5686, 0x03, 0, 0}, {0x5687, 0xc0, 0, 0}, ++ {0x5682, 0x04, 0, 0}, {0x5683, 0xb0, 0, 0}, ++}; ++ ++static struct ov5642_mode_info ov5642_mode_info_data[2][ov5642_mode_MAX + 1] = { ++ { ++ {ov5642_mode_VGA_640_480, 640, 480, ++ ov5642_setting_15fps_VGA_640_480, ++ ARRAY_SIZE(ov5642_setting_15fps_VGA_640_480)}, ++ {ov5642_mode_QVGA_320_240, 320, 240, ++ ov5642_setting_15fps_QVGA_320_240, ++ ARRAY_SIZE(ov5642_setting_15fps_QVGA_320_240)}, ++ {ov5642_mode_NTSC_720_480, 720, 480, ++ ov5642_setting_15fps_NTSC_720_480, ++ ARRAY_SIZE(ov5642_setting_15fps_NTSC_720_480)}, ++ {ov5642_mode_PAL_720_576, 720, 576, ++ ov5642_setting_15fps_PAL_720_576, ++ ARRAY_SIZE(ov5642_setting_15fps_PAL_720_576)}, ++ {ov5642_mode_720P_1280_720, 1280, 720, ++ ov5642_setting_15fps_720P_1280_720, ++ ARRAY_SIZE(ov5642_setting_15fps_720P_1280_720)}, ++ {ov5642_mode_1080P_1920_1080, 1920, 1080, ++ ov5642_setting_15fps_1080P_1920_1080, ++ ARRAY_SIZE(ov5642_setting_15fps_1080P_1920_1080)}, ++ {ov5642_mode_QSXGA_2592_1944, 2592, 1944, ++ ov5642_setting_15fps_QSXGA_2592_1944, ++ ARRAY_SIZE(ov5642_setting_15fps_QSXGA_2592_1944)}, ++ {ov5642_mode_QCIF_176_144, 176, 144, ++ ov5642_setting_15fps_QCIF_176_144, ++ ARRAY_SIZE(ov5642_setting_15fps_QCIF_176_144)}, ++ {ov5642_mode_XGA_1024_768, 1024, 768, ++ ov5642_setting_15fps_XGA_1024_768, ++ ARRAY_SIZE(ov5642_setting_15fps_XGA_1024_768)}, ++ }, ++ { ++ {ov5642_mode_VGA_640_480, 640, 480, ++ ov5642_setting_30fps_VGA_640_480, ++ ARRAY_SIZE(ov5642_setting_30fps_VGA_640_480)}, ++ {ov5642_mode_QVGA_320_240, 320, 240, ++ ov5642_setting_30fps_QVGA_320_240, ++ ARRAY_SIZE(ov5642_setting_30fps_QVGA_320_240)}, ++ {ov5642_mode_NTSC_720_480, 720, 480, ++ ov5642_setting_30fps_NTSC_720_480, ++ ARRAY_SIZE(ov5642_setting_30fps_NTSC_720_480)}, ++ {ov5642_mode_PAL_720_576, 720, 576, ++ ov5642_setting_30fps_PAL_720_576, ++ ARRAY_SIZE(ov5642_setting_30fps_PAL_720_576)}, ++ {ov5642_mode_720P_1280_720, 1280, 720, ++ ov5642_setting_30fps_720P_1280_720, ++ ARRAY_SIZE(ov5642_setting_30fps_720P_1280_720)}, ++ {ov5642_mode_1080P_1920_1080, 0, 0, NULL, 0}, ++ {ov5642_mode_QSXGA_2592_1944, 0, 0, NULL, 0}, ++ {ov5642_mode_QCIF_176_144, 176, 144, ++ ov5642_setting_30fps_QCIF_176_144, ++ ARRAY_SIZE(ov5642_setting_30fps_QCIF_176_144)}, ++ {ov5642_mode_XGA_1024_768, 1024, 768, ++ ov5642_setting_30fps_XGA_1024_768, ++ ARRAY_SIZE(ov5642_setting_30fps_XGA_1024_768)}, ++ }, ++}; ++ ++static struct regulator *io_regulator; ++static struct regulator *core_regulator; ++static struct regulator *analog_regulator; ++static struct regulator *gpo_regulator; ++ ++static int ov5642_probe(struct i2c_client *adapter, ++ const struct i2c_device_id *device_id); ++static int ov5642_remove(struct i2c_client *client); ++ ++static s32 ov5642_read_reg(u16 reg, u8 *val); ++static s32 ov5642_write_reg(u16 reg, u8 val); ++ ++static const struct i2c_device_id ov5642_id[] = { ++ {"ov5642", 0}, ++ {"ov564x", 0}, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(i2c, ov5642_id); ++ ++static struct i2c_driver ov5642_i2c_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "ov5642", ++ }, ++ .probe = ov5642_probe, ++ .remove = ov5642_remove, ++ .id_table = ov5642_id, ++}; ++ ++static void ov5642_standby(s32 enable) ++{ ++ if (enable) ++ gpio_set_value(pwn_gpio, 1); ++ else ++ gpio_set_value(pwn_gpio, 0); ++ ++ msleep(2); ++} ++ ++static void ov5642_reset(void) ++{ ++ /* camera reset */ ++ gpio_set_value(rst_gpio, 1); ++ ++ /* camera power down */ ++ gpio_set_value(pwn_gpio, 1); ++ msleep(5); ++ ++ gpio_set_value(pwn_gpio, 0); ++ msleep(5); ++ ++ gpio_set_value(rst_gpio, 0); ++ msleep(1); ++ ++ gpio_set_value(rst_gpio, 1); ++ msleep(5); ++ ++ gpio_set_value(pwn_gpio, 1); ++} ++ ++static int ov5642_power_on(struct device *dev) ++{ ++ int ret = 0; ++ ++ io_regulator = devm_regulator_get(dev, "DOVDD"); ++ if (!IS_ERR(io_regulator)) { ++ regulator_set_voltage(io_regulator, ++ OV5642_VOLTAGE_DIGITAL_IO, ++ OV5642_VOLTAGE_DIGITAL_IO); ++ ret = regulator_enable(io_regulator); ++ if (ret) { ++ pr_err("%s:io set voltage error\n", __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:io set voltage ok\n", __func__); ++ } ++ } else { ++ pr_err("%s: cannot get io voltage error\n", __func__); ++ io_regulator = NULL; ++ } ++ ++ core_regulator = devm_regulator_get(dev, "DVDD"); ++ if (!IS_ERR(core_regulator)) { ++ regulator_set_voltage(core_regulator, ++ OV5642_VOLTAGE_DIGITAL_CORE, ++ OV5642_VOLTAGE_DIGITAL_CORE); ++ ret = regulator_enable(core_regulator); ++ if (ret) { ++ pr_err("%s:core set voltage error\n", __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:core set voltage ok\n", __func__); ++ } ++ } else { ++ core_regulator = NULL; ++ pr_err("%s: cannot get core voltage error\n", __func__); ++ } ++ ++ analog_regulator = devm_regulator_get(dev, "AVDD"); ++ if (!IS_ERR(analog_regulator)) { ++ regulator_set_voltage(analog_regulator, ++ OV5642_VOLTAGE_ANALOG, ++ OV5642_VOLTAGE_ANALOG); ++ ret = regulator_enable(analog_regulator); ++ if (ret) { ++ pr_err("%s:analog set voltage error\n", ++ __func__); ++ return ret; ++ } else { ++ dev_dbg(dev, ++ "%s:analog set voltage ok\n", __func__); ++ } ++ } else { ++ analog_regulator = NULL; ++ pr_err("%s: cannot get analog voltage error\n", __func__); ++ } ++ ++ return ret; ++} ++ ++static s32 ov5642_write_reg(u16 reg, u8 val) ++{ ++ u8 au8Buf[3] = {0}; ++ ++ au8Buf[0] = reg >> 8; ++ au8Buf[1] = reg & 0xff; ++ au8Buf[2] = val; ++ ++ if (i2c_master_send(ov5642_data.i2c_client, au8Buf, 3) < 0) { ++ pr_err("%s:write reg error:reg=%x,val=%x\n", ++ __func__, reg, val); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static s32 ov5642_read_reg(u16 reg, u8 *val) ++{ ++ u8 au8RegBuf[2] = {0}; ++ u8 u8RdVal = 0; ++ ++ au8RegBuf[0] = reg >> 8; ++ au8RegBuf[1] = reg & 0xff; ++ ++ if (2 != i2c_master_send(ov5642_data.i2c_client, au8RegBuf, 2)) { ++ pr_err("%s:write reg error:reg=%x\n", ++ __func__, reg); ++ return -1; ++ } ++ ++ if (1 != i2c_master_recv(ov5642_data.i2c_client, &u8RdVal, 1)) { ++ pr_err("%s:read reg error:reg=%x,val=%x\n", ++ __func__, reg, u8RdVal); ++ return -1; ++ } ++ ++ *val = u8RdVal; ++ ++ return u8RdVal; ++} ++ ++static int ov5642_set_rot_mode(struct reg_value *rot_mode) ++{ ++ s32 i = 0; ++ s32 iModeSettingArySize = 2; ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int retval = 0; ++ for (i = 0; i < iModeSettingArySize; ++i, ++rot_mode) { ++ Delay_ms = rot_mode->u32Delay_ms; ++ RegAddr = rot_mode->u16RegAddr; ++ Val = rot_mode->u8Val; ++ Mask = rot_mode->u8Mask; ++ ++ if (Mask) { ++ retval = ov5642_read_reg(RegAddr, &RegVal); ++ if (retval < 0) { ++ pr_err("%s, read reg 0x%x failed\n", ++ __func__, RegAddr); ++ goto err; ++ } ++ ++ Val |= RegVal; ++ Val &= Mask; ++ } ++ ++ retval = ov5642_write_reg(RegAddr, Val); ++ if (retval < 0) { ++ pr_err("%s, write reg 0x%x failed\n", ++ __func__, RegAddr); ++ goto err; ++ } ++ ++ if (Delay_ms) ++ mdelay(Delay_ms); ++ } ++err: ++ return retval; ++} ++static int ov5642_init_mode(enum ov5642_frame_rate frame_rate, ++ enum ov5642_mode mode); ++static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate, ++ enum ov5642_mode mode); ++static int ov5642_change_mode(enum ov5642_frame_rate new_frame_rate, ++ enum ov5642_frame_rate old_frame_rate, ++ enum ov5642_mode new_mode, ++ enum ov5642_mode orig_mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 i = 0; ++ s32 iModeSettingArySize = 0; ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int retval = 0; ++ ++ if (new_mode > ov5642_mode_MAX || new_mode < ov5642_mode_MIN) { ++ pr_err("Wrong ov5642 mode detected!\n"); ++ return -1; ++ } ++ ++ if ((new_frame_rate == old_frame_rate) && ++ (new_mode == ov5642_mode_VGA_640_480) && ++ (orig_mode == ov5642_mode_QSXGA_2592_1944)) { ++ pModeSetting = ov5642_setting_QSXGA_2_VGA; ++ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_QSXGA_2_VGA); ++ ov5642_data.pix.width = 640; ++ ov5642_data.pix.height = 480; ++ } else if ((new_frame_rate == old_frame_rate) && ++ (new_mode == ov5642_mode_QVGA_320_240) && ++ (orig_mode == ov5642_mode_VGA_640_480)) { ++ pModeSetting = ov5642_setting_VGA_2_QVGA; ++ iModeSettingArySize = ARRAY_SIZE(ov5642_setting_VGA_2_QVGA); ++ ov5642_data.pix.width = 320; ++ ov5642_data.pix.height = 240; ++ } else { ++ retval = ov5642_write_snapshot_para(new_frame_rate, new_mode); ++ goto err; ++ } ++ ++ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 || ++ pModeSetting == NULL || iModeSettingArySize == 0) ++ return -EINVAL; ++ ++ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { ++ Delay_ms = pModeSetting->u32Delay_ms; ++ RegAddr = pModeSetting->u16RegAddr; ++ Val = pModeSetting->u8Val; ++ Mask = pModeSetting->u8Mask; ++ ++ if (Mask) { ++ retval = ov5642_read_reg(RegAddr, &RegVal); ++ if (retval < 0) { ++ pr_err("read reg error addr=0x%x", RegAddr); ++ goto err; ++ } ++ ++ RegVal &= ~(u8)Mask; ++ Val &= Mask; ++ Val |= RegVal; ++ } ++ ++ retval = ov5642_write_reg(RegAddr, Val); ++ if (retval < 0) { ++ pr_err("write reg error addr=0x%x", RegAddr); ++ goto err; ++ } ++ ++ if (Delay_ms) ++ msleep(Delay_ms); ++ } ++err: ++ return retval; ++} ++static int ov5642_init_mode(enum ov5642_frame_rate frame_rate, ++ enum ov5642_mode mode) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 i = 0; ++ s32 iModeSettingArySize = 0; ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int retval = 0; ++ ++ if (mode > ov5642_mode_MAX || mode < ov5642_mode_MIN) { ++ pr_err("Wrong ov5642 mode detected!\n"); ++ return -1; ++ } ++ ++ pModeSetting = ov5642_mode_info_data[frame_rate][mode].init_data_ptr; ++ iModeSettingArySize = ++ ov5642_mode_info_data[frame_rate][mode].init_data_size; ++ ++ ov5642_data.pix.width = ov5642_mode_info_data[frame_rate][mode].width; ++ ov5642_data.pix.height = ov5642_mode_info_data[frame_rate][mode].height; ++ ++ if (ov5642_data.pix.width == 0 || ov5642_data.pix.height == 0 || ++ pModeSetting == NULL || iModeSettingArySize == 0) ++ return -EINVAL; ++ ++ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { ++ Delay_ms = pModeSetting->u32Delay_ms; ++ RegAddr = pModeSetting->u16RegAddr; ++ Val = pModeSetting->u8Val; ++ Mask = pModeSetting->u8Mask; ++ ++ if (Mask) { ++ retval = ov5642_read_reg(RegAddr, &RegVal); ++ if (retval < 0) { ++ pr_err("read reg error addr=0x%x", RegAddr); ++ goto err; ++ } ++ ++ RegVal &= ~(u8)Mask; ++ Val &= Mask; ++ Val |= RegVal; ++ } ++ ++ retval = ov5642_write_reg(RegAddr, Val); ++ if (retval < 0) { ++ pr_err("write reg error addr=0x%x", RegAddr); ++ goto err; ++ } ++ ++ if (Delay_ms) ++ msleep(Delay_ms); ++ } ++err: ++ return retval; ++} ++ ++static int ov5642_write_snapshot_para(enum ov5642_frame_rate frame_rate, ++ enum ov5642_mode mode) ++{ ++ int ret = 0; ++ bool m_60Hz = false; ++ u16 cap_frame_rate = 50; ++ u16 g_prev_frame_rate = 225; ++ ++ u8 ev_low, ev_mid, ev_high; ++ u8 ret_l, ret_m, ret_h, gain, lines_10ms; ++ u16 ulcap_ev, icap_gain, prev_maxlines; ++ u32 ulcap_ev_gain, cap_maxlines, g_prev_ev; ++ ++ ov5642_write_reg(0x3503, 0x07); ++ ++ ret_h = ret_m = ret_l = 0; ++ g_prev_ev = 0; ++ ov5642_read_reg(0x3500, &ret_h); ++ ov5642_read_reg(0x3501, &ret_m); ++ ov5642_read_reg(0x3502, &ret_l); ++ g_prev_ev = (ret_h << 12) + (ret_m << 4) + (ret_l >> 4); ++ ++ ret_h = ret_m = ret_l = 0; ++ prev_maxlines = 0; ++ ov5642_read_reg(0x380e, &ret_h); ++ ov5642_read_reg(0x380f, &ret_l); ++ prev_maxlines = (ret_h << 8) + ret_l; ++ /*Read back AGC Gain for preview*/ ++ gain = 0; ++ ov5642_read_reg(0x350b, &gain); ++ ++ ret = ov5642_init_mode(frame_rate, mode); ++ if (ret < 0) ++ return ret; ++ ++ ret_h = ret_m = ret_l = 0; ++ ov5642_read_reg(0x380e, &ret_h); ++ ov5642_read_reg(0x380f, &ret_l); ++ cap_maxlines = (ret_h << 8) + ret_l; ++ if (m_60Hz == true) ++ lines_10ms = cap_frame_rate * cap_maxlines/12000; ++ else ++ lines_10ms = cap_frame_rate * cap_maxlines/10000; ++ ++ if (prev_maxlines == 0) ++ prev_maxlines = 1; ++ ++ ulcap_ev = (g_prev_ev*(cap_frame_rate)*(cap_maxlines))/ ++ (((prev_maxlines)*(g_prev_frame_rate))); ++ icap_gain = (gain & 0x0f) + 16; ++ if (gain & 0x10) ++ icap_gain = icap_gain << 1; ++ ++ if (gain & 0x20) ++ icap_gain = icap_gain << 1; ++ ++ if (gain & 0x40) ++ icap_gain = icap_gain << 1; ++ ++ if (gain & 0x80) ++ icap_gain = icap_gain << 1; ++ ++ ulcap_ev_gain = 2 * ulcap_ev * icap_gain; ++ ++ if (ulcap_ev_gain < cap_maxlines*16) { ++ ulcap_ev = ulcap_ev_gain/16; ++ if (ulcap_ev > lines_10ms) { ++ ulcap_ev /= lines_10ms; ++ ulcap_ev *= lines_10ms; ++ } ++ } else ++ ulcap_ev = cap_maxlines; ++ ++ if (ulcap_ev == 0) ++ ulcap_ev = 1; ++ ++ icap_gain = (ulcap_ev_gain*2/ulcap_ev + 1)/2; ++ ev_low = ((unsigned char)ulcap_ev)<<4; ++ ev_mid = (unsigned char)(ulcap_ev >> 4) & 0xff; ++ ev_high = (unsigned char)(ulcap_ev >> 12); ++ ++ gain = 0; ++ if (icap_gain > 31) { ++ gain |= 0x10; ++ icap_gain = icap_gain >> 1; ++ } ++ if (icap_gain > 31) { ++ gain |= 0x20; ++ icap_gain = icap_gain >> 1; ++ } ++ if (icap_gain > 31) { ++ gain |= 0x40; ++ icap_gain = icap_gain >> 1; ++ } ++ if (icap_gain > 31) { ++ gain |= 0x80; ++ icap_gain = icap_gain >> 1; ++ } ++ if (icap_gain > 16) ++ gain |= ((icap_gain - 16) & 0x0f); ++ ++ if (gain == 0x10) ++ gain = 0x11; ++ ++ ov5642_write_reg(0x350b, gain); ++ ov5642_write_reg(0x3502, ev_low); ++ ov5642_write_reg(0x3501, ev_mid); ++ ov5642_write_reg(0x3500, ev_high); ++ msleep(500); ++ ++ return ret ; ++} ++ ++ ++/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */ ++ ++static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p) ++{ ++ if (s == NULL) { ++ pr_err(" ERROR!! no slave device set!\n"); ++ return -1; ++ } ++ ++ memset(p, 0, sizeof(*p)); ++ p->u.bt656.clock_curr = ov5642_data.mclk; ++ pr_debug(" clock_curr=mclk=%d\n", ov5642_data.mclk); ++ p->if_type = V4L2_IF_TYPE_BT656; ++ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT; ++ p->u.bt656.clock_min = OV5642_XCLK_MIN; ++ p->u.bt656.clock_max = OV5642_XCLK_MAX; ++ p->u.bt656.bt_sync_correct = 1; /* Indicate external vsync */ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_s_power - V4L2 sensor interface handler for VIDIOC_S_POWER ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @on: indicates power mode (on or off) ++ * ++ * Turns the power on or off, depending on the value of on and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_power(struct v4l2_int_device *s, int on) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ if (on && !sensor->on) { ++ if (io_regulator) ++ if (regulator_enable(io_regulator) != 0) ++ return -EIO; ++ if (core_regulator) ++ if (regulator_enable(core_regulator) != 0) ++ return -EIO; ++ if (gpo_regulator) ++ if (regulator_enable(gpo_regulator) != 0) ++ return -EIO; ++ if (analog_regulator) ++ if (regulator_enable(analog_regulator) != 0) ++ return -EIO; ++ /* Make sure power on */ ++ ov5642_standby(0); ++ } else if (!on && sensor->on) { ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ if (gpo_regulator) ++ regulator_disable(gpo_regulator); ++ ++ ov5642_standby(1); ++ } ++ ++ sensor->on = on; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure ++ * ++ * Returns the sensor's video CAPTURE parameters. ++ */ ++static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_captureparm *cparm = &a->parm.capture; ++ int ret = 0; ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ 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; ++ ret = 0; ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure ++ * ++ * Configures the sensor to use the input parameters, if possible. If ++ * not possible, reverts to the old parameters and returns the ++ * appropriate error code. ++ */ ++static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a) ++{ ++ struct sensor_data *sensor = s->priv; ++ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe; ++ u32 tgt_fps, old_fps; /* target frames per secound */ ++ enum ov5642_frame_rate new_frame_rate, old_frame_rate; ++ int ret = 0; ++ ++ /* Make sure power on */ ++ ov5642_standby(0); ++ ++ switch (a->type) { ++ /* This is the only case currently handled. */ ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ /* 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) ++ new_frame_rate = ov5642_15_fps; ++ else if (tgt_fps == 30) ++ new_frame_rate = ov5642_30_fps; ++ else { ++ pr_err(" The camera frame rate is not supported!\n"); ++ return -EINVAL; ++ } ++ ++ if (sensor->streamcap.timeperframe.numerator != 0) ++ old_fps = sensor->streamcap.timeperframe.denominator / ++ sensor->streamcap.timeperframe.numerator; ++ else ++ old_fps = 30; ++ ++ if (old_fps == 15) ++ old_frame_rate = ov5642_15_fps; ++ else if (old_fps == 30) ++ old_frame_rate = ov5642_30_fps; ++ else { ++ pr_warning(" No valid frame rate set!\n"); ++ old_frame_rate = ov5642_30_fps; ++ } ++ ++ ret = ov5642_change_mode(new_frame_rate, old_frame_rate, ++ a->parm.capture.capturemode, ++ sensor->streamcap.capturemode); ++ if (ret < 0) ++ return ret; ++ ++ sensor->streamcap.timeperframe = *timeperframe; ++ sensor->streamcap.capturemode = ++ (u32)a->parm.capture.capturemode; ++ break; ++ ++ /* These are all the possible cases. */ ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ case V4L2_BUF_TYPE_VIDEO_OVERLAY: ++ case V4L2_BUF_TYPE_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_VBI_OUTPUT: ++ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: ++ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: ++ pr_debug(" type is not " \ ++ "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n", ++ a->type); ++ ret = -EINVAL; ++ break; ++ ++ default: ++ pr_debug(" type is unknown - %d\n", a->type); ++ ret = -EINVAL; ++ break; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap ++ * @s: pointer to standard V4L2 device structure ++ * @f: pointer to standard V4L2 v4l2_format structure ++ * ++ * Returns the sensor's current pixel format in the v4l2_format ++ * parameter. ++ */ ++static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f) ++{ ++ struct sensor_data *sensor = s->priv; ++ ++ f->fmt.pix = sensor->pix; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure ++ * ++ * If the requested control is supported, returns the control's current ++ * value from the video_control[] array. Otherwise, returns -EINVAL ++ * if the control is not supported. ++ */ ++static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int ret = 0; ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ vc->value = ov5642_data.brightness; ++ break; ++ case V4L2_CID_HUE: ++ vc->value = ov5642_data.hue; ++ break; ++ case V4L2_CID_CONTRAST: ++ vc->value = ov5642_data.contrast; ++ break; ++ case V4L2_CID_SATURATION: ++ vc->value = ov5642_data.saturation; ++ break; ++ case V4L2_CID_RED_BALANCE: ++ vc->value = ov5642_data.red; ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ vc->value = ov5642_data.blue; ++ break; ++ case V4L2_CID_EXPOSURE: ++ vc->value = ov5642_data.ae_mode; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++/*! ++ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure ++ * ++ * If the requested control is supported, sets the control's current ++ * value in HW (and updates the video_control[] array). Otherwise, ++ * returns -EINVAL if the control is not supported. ++ */ ++static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc) ++{ ++ int retval = 0; ++ struct sensor_data *sensor = s->priv; ++ __u32 captureMode = sensor->streamcap.capturemode; ++ struct reg_value *rot_mode = NULL; ++ ++ pr_debug("In ov5642:ioctl_s_ctrl %d\n", ++ vc->id); ++ ++ switch (vc->id) { ++ case V4L2_CID_BRIGHTNESS: ++ break; ++ case V4L2_CID_CONTRAST: ++ break; ++ case V4L2_CID_SATURATION: ++ break; ++ case V4L2_CID_HUE: ++ break; ++ case V4L2_CID_AUTO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_DO_WHITE_BALANCE: ++ break; ++ case V4L2_CID_RED_BALANCE: ++ break; ++ case V4L2_CID_BLUE_BALANCE: ++ break; ++ case V4L2_CID_GAMMA: ++ break; ++ case V4L2_CID_EXPOSURE: ++ break; ++ case V4L2_CID_AUTOGAIN: ++ break; ++ case V4L2_CID_GAIN: ++ break; ++ case V4L2_CID_HFLIP: ++ break; ++ case V4L2_CID_VFLIP: ++ break; ++ case V4L2_CID_MXC_ROT: ++ case V4L2_CID_MXC_VF_ROT: ++ switch (vc->value) { ++ case V4L2_MXC_ROTATE_NONE: ++ if (captureMode == ov5642_mode_QSXGA_2592_1944) ++ rot_mode = ov5642_rot_none_FULL; ++ else ++ rot_mode = ov5642_rot_none_VGA; ++ ++ if (ov5642_set_rot_mode(rot_mode)) ++ retval = -EPERM; ++ break; ++ case V4L2_MXC_ROTATE_VERT_FLIP: ++ if (captureMode == ov5642_mode_QSXGA_2592_1944) ++ rot_mode = ov5642_rot_vert_flip_FULL; ++ else ++ rot_mode = ov5642_rot_vert_flip_VGA ; ++ ++ if (ov5642_set_rot_mode(rot_mode)) ++ retval = -EPERM; ++ break; ++ case V4L2_MXC_ROTATE_HORIZ_FLIP: ++ if (captureMode == ov5642_mode_QSXGA_2592_1944) ++ rot_mode = ov5642_rot_horiz_flip_FULL; ++ else ++ rot_mode = ov5642_rot_horiz_flip_VGA; ++ ++ if (ov5642_set_rot_mode(rot_mode)) ++ retval = -EPERM; ++ break; ++ case V4L2_MXC_ROTATE_180: ++ if (captureMode == ov5642_mode_QSXGA_2592_1944) ++ rot_mode = ov5642_rot_180_FULL; ++ else ++ rot_mode = ov5642_rot_180_VGA; ++ ++ if (ov5642_set_rot_mode(rot_mode)) ++ retval = -EPERM; ++ break; ++ default: ++ retval = -EPERM; ++ break; ++ } ++ break; ++ default: ++ retval = -EPERM; ++ break; ++ } ++ ++ return retval; ++} ++ ++/*! ++ * ioctl_enum_framesizes - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMESIZES ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fsize: standard V4L2 VIDIOC_ENUM_FRAMESIZES ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_framesizes(struct v4l2_int_device *s, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ if (fsize->index > ov5642_mode_MAX) ++ return -EINVAL; ++ ++ fsize->pixel_format = ov5642_data.pix.pixelformat; ++ fsize->discrete.width = ++ max(ov5642_mode_info_data[0][fsize->index].width, ++ ov5642_mode_info_data[1][fsize->index].width); ++ fsize->discrete.height = ++ max(ov5642_mode_info_data[0][fsize->index].height, ++ ov5642_mode_info_data[1][fsize->index].height); ++ return 0; ++} ++ ++/*! ++ * ioctl_enum_frameintervals - V4L2 sensor interface handler for ++ * VIDIOC_ENUM_FRAMEINTERVALS ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @fival: standard V4L2 VIDIOC_ENUM_FRAMEINTERVALS ioctl structure ++ * ++ * Return 0 if successful, otherwise -EINVAL. ++ */ ++static int ioctl_enum_frameintervals(struct v4l2_int_device *s, ++ struct v4l2_frmivalenum *fival) ++{ ++ int i, j, count; ++ ++ if (fival->index < 0 || fival->index > ov5642_mode_MAX) ++ return -EINVAL; ++ ++ if (fival->pixel_format == 0 || fival->width == 0 || ++ fival->height == 0) { ++ pr_warning("Please assign pixelformat, width and height.\n"); ++ return -EINVAL; ++ } ++ ++ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; ++ fival->discrete.numerator = 1; ++ ++ count = 0; ++ for (i = 0; i < ARRAY_SIZE(ov5642_mode_info_data); i++) { ++ for (j = 0; j < (ov5642_mode_MAX + 1); j++) { ++ if (fival->pixel_format == ov5642_data.pix.pixelformat ++ && fival->width == ov5642_mode_info_data[i][j].width ++ && fival->height == ov5642_mode_info_data[i][j].height ++ && ov5642_mode_info_data[i][j].init_data_ptr != NULL) { ++ count++; ++ } ++ if (fival->index == (count - 1)) { ++ fival->discrete.denominator = ++ ov5642_framerates[i]; ++ return 0; ++ } ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++/*! ++ * ioctl_g_chip_ident - V4L2 sensor interface handler for ++ * VIDIOC_DBG_G_CHIP_IDENT ioctl ++ * @s: pointer to standard V4L2 device structure ++ * @id: pointer to int ++ * ++ * Return 0. ++ */ ++static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id) ++{ ++ ((struct v4l2_dbg_chip_ident *)id)->match.type = ++ V4L2_CHIP_MATCH_I2C_DRIVER; ++ strcpy(((struct v4l2_dbg_chip_ident *)id)->match.name, "ov5642_camera"); ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT ++ * @s: pointer to standard V4L2 device structure ++ */ ++static int ioctl_init(struct v4l2_int_device *s) ++{ ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_enum_fmt_cap - V4L2 sensor interface handler for VIDIOC_ENUM_FMT ++ * @s: pointer to standard V4L2 device structure ++ * @fmt: pointer to standard V4L2 fmt description structure ++ * ++ * Return 0. ++ */ ++static int ioctl_enum_fmt_cap(struct v4l2_int_device *s, ++ struct v4l2_fmtdesc *fmt) ++{ ++ if (fmt->index > 0) /* only 1 pixelformat support so far */ ++ return -EINVAL; ++ ++ fmt->pixelformat = ov5642_data.pix.pixelformat; ++ ++ return 0; ++} ++ ++/*! ++ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Initialise the device when slave attaches to the master. ++ */ ++static int ioctl_dev_init(struct v4l2_int_device *s) ++{ ++ struct reg_value *pModeSetting = NULL; ++ s32 i = 0; ++ s32 iModeSettingArySize = 0; ++ register u32 Delay_ms = 0; ++ register u16 RegAddr = 0; ++ register u8 Mask = 0; ++ register u8 Val = 0; ++ u8 RegVal = 0; ++ int retval = 0; ++ ++ struct sensor_data *sensor = s->priv; ++ u32 tgt_xclk; /* target xclk */ ++ u32 tgt_fps; /* target frames per secound */ ++ enum ov5642_frame_rate frame_rate; ++ ++ ov5642_data.on = true; ++ ++ /* mclk */ ++ tgt_xclk = ov5642_data.mclk; ++ tgt_xclk = min(tgt_xclk, (u32)OV5642_XCLK_MAX); ++ tgt_xclk = max(tgt_xclk, (u32)OV5642_XCLK_MIN); ++ ov5642_data.mclk = tgt_xclk; ++ ++ pr_debug(" Setting mclk to %d MHz\n", tgt_xclk / 1000000); ++ ++ /* Default camera frame rate is set in probe */ ++ tgt_fps = sensor->streamcap.timeperframe.denominator / ++ sensor->streamcap.timeperframe.numerator; ++ ++ if (tgt_fps == 15) ++ frame_rate = ov5642_15_fps; ++ else if (tgt_fps == 30) ++ frame_rate = ov5642_30_fps; ++ else ++ return -EINVAL; /* Only support 15fps or 30fps now. */ ++ ++ pModeSetting = ov5642_initial_setting; ++ iModeSettingArySize = ARRAY_SIZE(ov5642_initial_setting); ++ ++ for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) { ++ Delay_ms = pModeSetting->u32Delay_ms; ++ RegAddr = pModeSetting->u16RegAddr; ++ Val = pModeSetting->u8Val; ++ Mask = pModeSetting->u8Mask; ++ if (Mask) { ++ retval = ov5642_read_reg(RegAddr, &RegVal); ++ if (retval < 0) ++ goto err; ++ ++ RegVal &= ~(u8)Mask; ++ Val &= Mask; ++ Val |= RegVal; ++ } ++ ++ retval = ov5642_write_reg(RegAddr, Val); ++ if (retval < 0) ++ goto err; ++ ++ if (Delay_ms) ++ msleep(Delay_ms); ++ } ++err: ++ return retval; ++} ++ ++/*! ++ * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num ++ * @s: pointer to standard V4L2 device structure ++ * ++ * Delinitialise the device when slave detaches to the master. ++ */ ++static int ioctl_dev_exit(struct v4l2_int_device *s) ++{ ++ return 0; ++} ++ ++/*! ++ * This structure defines all the ioctls for this module and links them to the ++ * enumeration. ++ */ ++static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = { ++ { vidioc_int_dev_init_num, ++ (v4l2_int_ioctl_func *)ioctl_dev_init }, ++ { vidioc_int_dev_exit_num, ioctl_dev_exit}, ++ { vidioc_int_s_power_num, ++ (v4l2_int_ioctl_func *)ioctl_s_power }, ++ { vidioc_int_g_ifparm_num, ++ (v4l2_int_ioctl_func *)ioctl_g_ifparm }, ++/* { vidioc_int_g_needs_reset_num, ++ (v4l2_int_ioctl_func *)ioctl_g_needs_reset }, */ ++/* { vidioc_int_reset_num, ++ (v4l2_int_ioctl_func *)ioctl_reset }, */ ++ { vidioc_int_init_num, ++ (v4l2_int_ioctl_func *)ioctl_init }, ++ { vidioc_int_enum_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap }, ++/* { vidioc_int_try_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_try_fmt_cap }, */ ++ { vidioc_int_g_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_g_fmt_cap }, ++/* { vidioc_int_s_fmt_cap_num, ++ (v4l2_int_ioctl_func *)ioctl_s_fmt_cap }, */ ++ { vidioc_int_g_parm_num, ++ (v4l2_int_ioctl_func *)ioctl_g_parm }, ++ { vidioc_int_s_parm_num, ++ (v4l2_int_ioctl_func *)ioctl_s_parm }, ++/* { vidioc_int_queryctrl_num, ++ (v4l2_int_ioctl_func *)ioctl_queryctrl }, */ ++ { vidioc_int_g_ctrl_num, ++ (v4l2_int_ioctl_func *)ioctl_g_ctrl }, ++ { vidioc_int_s_ctrl_num, ++ (v4l2_int_ioctl_func *)ioctl_s_ctrl }, ++ { vidioc_int_enum_framesizes_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_framesizes }, ++ { vidioc_int_enum_frameintervals_num, ++ (v4l2_int_ioctl_func *)ioctl_enum_frameintervals }, ++ { vidioc_int_g_chip_ident_num, ++ (v4l2_int_ioctl_func *)ioctl_g_chip_ident }, ++}; ++ ++static struct v4l2_int_slave ov5642_slave = { ++ .ioctls = ov5642_ioctl_desc, ++ .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc), ++}; ++ ++static struct v4l2_int_device ov5642_int_device = { ++ .module = THIS_MODULE, ++ .name = "ov5642", ++ .type = v4l2_int_type_slave, ++ .u = { ++ .slave = &ov5642_slave, ++ }, ++}; ++ ++/*! ++ * ov5642 I2C probe function ++ * ++ * @param adapter struct i2c_adapter * ++ * @return Error code indicating success or failure ++ */ ++static int ov5642_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pinctrl *pinctrl; ++ struct device *dev = &client->dev; ++ int retval; ++ u8 chip_id_high, chip_id_low; ++ ++ /* ov5642 pinctrl */ ++ pinctrl = devm_pinctrl_get_select_default(dev); ++ if (IS_ERR(pinctrl)) { ++ dev_err(dev, "ov5642 setup pinctrl failed!"); ++ return PTR_ERR(pinctrl); ++ } ++ ++ /* request power down pin */ ++ pwn_gpio = of_get_named_gpio(dev->of_node, "pwn-gpios", 0); ++ if (!gpio_is_valid(pwn_gpio)) { ++ dev_warn(dev, "no sensor pwdn pin available"); ++ return -EINVAL; ++ } ++ retval = devm_gpio_request_one(dev, pwn_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5642_pwdn"); ++ if (retval < 0) ++ return retval; ++ ++ /* request reset pin */ ++ rst_gpio = of_get_named_gpio(dev->of_node, "rst-gpios", 0); ++ if (!gpio_is_valid(rst_gpio)) { ++ dev_warn(dev, "no sensor reset pin available"); ++ return -EINVAL; ++ } ++ retval = devm_gpio_request_one(dev, rst_gpio, GPIOF_OUT_INIT_HIGH, ++ "ov5642_reset"); ++ if (retval < 0) ++ return retval; ++ ++ /* Set initial values for the sensor struct. */ ++ memset(&ov5642_data, 0, sizeof(ov5642_data)); ++ ov5642_data.sensor_clk = devm_clk_get(dev, "csi_mclk"); ++ if (IS_ERR(ov5642_data.sensor_clk)) { ++ /* assuming clock enabled by default */ ++ ov5642_data.sensor_clk = NULL; ++ dev_err(dev, "clock-frequency missing or invalid\n"); ++ return PTR_ERR(ov5642_data.sensor_clk); ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk", ++ (u32 *) &(ov5642_data.mclk)); ++ if (retval) { ++ dev_err(dev, "mclk missing or invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "mclk_source", ++ (u32 *) &(ov5642_data.mclk_source)); ++ if (retval) { ++ dev_err(dev, "mclk_source missing or invalid\n"); ++ return retval; ++ } ++ ++ retval = of_property_read_u32(dev->of_node, "csi_id", ++ &(ov5642_data.csi)); ++ if (retval) { ++ dev_err(dev, "csi_id missing or invalid\n"); ++ return retval; ++ } ++ ++ clk_prepare_enable(ov5642_data.sensor_clk); ++ ++ ov5642_data.io_init = ov5642_reset; ++ ov5642_data.i2c_client = client; ++ ov5642_data.pix.pixelformat = V4L2_PIX_FMT_YUYV; ++ ov5642_data.pix.width = 640; ++ ov5642_data.pix.height = 480; ++ ov5642_data.streamcap.capability = V4L2_MODE_HIGHQUALITY | ++ V4L2_CAP_TIMEPERFRAME; ++ ov5642_data.streamcap.capturemode = 0; ++ ov5642_data.streamcap.timeperframe.denominator = DEFAULT_FPS; ++ ov5642_data.streamcap.timeperframe.numerator = 1; ++ ++ ov5642_power_on(&client->dev); ++ ++ ov5642_reset(); ++ ++ ov5642_standby(0); ++ ++ retval = ov5642_read_reg(OV5642_CHIP_ID_HIGH_BYTE, &chip_id_high); ++ if (retval < 0 || chip_id_high != 0x56) { ++ pr_warning("camera ov5642 is not found\n"); ++ clk_disable_unprepare(ov5642_data.sensor_clk); ++ return -ENODEV; ++ } ++ retval = ov5642_read_reg(OV5642_CHIP_ID_LOW_BYTE, &chip_id_low); ++ if (retval < 0 || chip_id_low != 0x42) { ++ pr_warning("camera ov5642 is not found\n"); ++ clk_disable_unprepare(ov5642_data.sensor_clk); ++ return -ENODEV; ++ } ++ ++ ov5642_standby(1); ++ ++ ov5642_int_device.priv = &ov5642_data; ++ retval = v4l2_int_device_register(&ov5642_int_device); ++ ++ clk_disable_unprepare(ov5642_data.sensor_clk); ++ ++ pr_info("camera ov5642 is found\n"); ++ return retval; ++} ++ ++/*! ++ * ov5642 I2C detach function ++ * ++ * @param client struct i2c_client * ++ * @return Error code indicating success or failure ++ */ ++static int ov5642_remove(struct i2c_client *client) ++{ ++ v4l2_int_device_unregister(&ov5642_int_device); ++ ++ if (gpo_regulator) ++ regulator_disable(gpo_regulator); ++ ++ if (analog_regulator) ++ regulator_disable(analog_regulator); ++ ++ if (core_regulator) ++ regulator_disable(core_regulator); ++ ++ if (io_regulator) ++ regulator_disable(io_regulator); ++ ++ return 0; ++} ++ ++/*! ++ * ov5642 init function ++ * Called by insmod ov5642_camera.ko. ++ * ++ * @return Error code indicating success or failure ++ */ ++static __init int ov5642_init(void) ++{ ++ u8 err; ++ ++ err = i2c_add_driver(&ov5642_i2c_driver); ++ if (err != 0) ++ pr_err("%s:driver registration failed, error=%d\n", ++ __func__, err); ++ ++ return err; ++} ++ ++/*! ++ * OV5642 cleanup function ++ * Called on rmmod ov5642_camera.ko ++ * ++ * @return Error code indicating success or failure ++ */ ++static void __exit ov5642_clean(void) ++{ ++ i2c_del_driver(&ov5642_i2c_driver); ++} ++ ++module_init(ov5642_init); ++module_exit(ov5642_clean); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("OV5642 Camera Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); ++MODULE_ALIAS("CSI"); +diff -Nur linux-3.14.14/drivers/media/platform/mxc/output/Kconfig linux-imx6-3.14/drivers/media/platform/mxc/output/Kconfig +--- linux-3.14.14/drivers/media/platform/mxc/output/Kconfig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/output/Kconfig 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,5 @@ ++config VIDEO_MXC_IPU_OUTPUT ++ tristate "IPU v4l2 output support" ++ depends on VIDEO_MXC_OUTPUT && MXC_IPU ++ ---help--- ++ This is the video4linux2 driver for IPU post processing video output. +diff -Nur linux-3.14.14/drivers/media/platform/mxc/output/Makefile linux-imx6-3.14/drivers/media/platform/mxc/output/Makefile +--- linux-3.14.14/drivers/media/platform/mxc/output/Makefile 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/output/Makefile 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1 @@ ++obj-$(CONFIG_VIDEO_MXC_IPU_OUTPUT) += mxc_vout.o +diff -Nur linux-3.14.14/drivers/media/platform/mxc/output/mxc_vout.c linux-imx6-3.14/drivers/media/platform/mxc/output/mxc_vout.c +--- linux-3.14.14/drivers/media/platform/mxc/output/mxc_vout.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/media/platform/mxc/output/mxc_vout.c 2014-12-08 00:31:53.256418001 -0600 +@@ -0,0 +1,2265 @@ ++/* ++ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. ++ */ ++ ++/* ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define UYVY_BLACK (0x00800080) ++#define RGB_BLACK (0x0) ++#define UV_BLACK (0x80) ++#define Y_BLACK (0x0) ++ ++#define MAX_FB_NUM 6 ++#define FB_BUFS 3 ++#define VDOA_FB_BUFS (FB_BUFS - 1) ++#define VALID_HEIGHT_1080P (1080) ++#define FRAME_HEIGHT_1080P (1088) ++#define FRAME_WIDTH_1080P (1920) ++#define CHECK_TILED_1080P_DISPLAY(vout) \ ++ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \ ++ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\ ++ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \ ++ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \ ++ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \ ++ (((vout)->task.input.crop.h == FRAME_HEIGHT_1080P) || \ ++ ((vout)->task.input.crop.h == VALID_HEIGHT_1080P)) && \ ++ ((vout)->task.output.width == FRAME_WIDTH_1080P) && \ ++ ((vout)->task.output.height == VALID_HEIGHT_1080P) && \ ++ ((vout)->task.output.crop.w == FRAME_WIDTH_1080P) && \ ++ ((vout)->task.output.crop.h == VALID_HEIGHT_1080P)) ++#define CHECK_TILED_1080P_STREAM(vout) \ ++ ((((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12) || \ ++ ((vout)->task.input.format == IPU_PIX_FMT_TILED_NV12F)) &&\ ++ ((vout)->task.input.width == FRAME_WIDTH_1080P) && \ ++ ((vout)->task.input.crop.w == FRAME_WIDTH_1080P) && \ ++ ((vout)->task.input.height == FRAME_HEIGHT_1080P) && \ ++ ((vout)->task.input.crop.h == FRAME_HEIGHT_1080P)) ++#define IS_PLANAR_PIXEL_FORMAT(format) \ ++ (format == IPU_PIX_FMT_NV12 || \ ++ format == IPU_PIX_FMT_YUV420P2 || \ ++ format == IPU_PIX_FMT_YUV420P || \ ++ format == IPU_PIX_FMT_YVU420P || \ ++ format == IPU_PIX_FMT_YUV422P || \ ++ format == IPU_PIX_FMT_YVU422P || \ ++ format == IPU_PIX_FMT_YUV444P) ++ ++#define NSEC_PER_FRAME_30FPS (33333333) ++ ++struct mxc_vout_fb { ++ char *name; ++ int ipu_id; ++ struct v4l2_rect crop_bounds; ++ unsigned int disp_fmt; ++ bool disp_support_csc; ++ bool disp_support_windows; ++}; ++ ++struct dma_mem { ++ void *vaddr; ++ dma_addr_t paddr; ++ size_t size; ++}; ++ ++struct mxc_vout_output { ++ int open_cnt; ++ struct fb_info *fbi; ++ unsigned long fb_smem_start; ++ unsigned long fb_smem_len; ++ struct video_device *vfd; ++ struct mutex mutex; ++ struct mutex task_lock; ++ enum v4l2_buf_type type; ++ ++ struct videobuf_queue vbq; ++ spinlock_t vbq_lock; ++ ++ struct list_head queue_list; ++ struct list_head active_list; ++ ++ struct v4l2_rect crop_bounds; ++ unsigned int disp_fmt; ++ struct mxcfb_pos win_pos; ++ bool disp_support_windows; ++ bool disp_support_csc; ++ ++ bool fmt_init; ++ bool release; ++ bool linear_bypass_pp; ++ bool vdoa_1080p; ++ bool tiled_bypass_pp; ++ struct v4l2_rect in_rect; ++ struct ipu_task task; ++ struct ipu_task vdoa_task; ++ struct dma_mem vdoa_work; ++ struct dma_mem vdoa_output[VDOA_FB_BUFS]; ++ ++ bool timer_stop; ++ struct hrtimer timer; ++ struct workqueue_struct *v4l_wq; ++ struct work_struct disp_work; ++ unsigned long frame_count; ++ unsigned long vdi_frame_cnt; ++ ktime_t start_ktime; ++ ++ int ctrl_rotate; ++ int ctrl_vflip; ++ int ctrl_hflip; ++ ++ dma_addr_t disp_bufs[FB_BUFS]; ++ ++ struct videobuf_buffer *pre1_vb; ++ struct videobuf_buffer *pre2_vb; ++}; ++ ++struct mxc_vout_dev { ++ struct device *dev; ++ struct v4l2_device v4l2_dev; ++ struct mxc_vout_output *out[MAX_FB_NUM]; ++ int out_num; ++}; ++ ++/* Driver Configuration macros */ ++#define VOUT_NAME "mxc_vout" ++ ++/* Variables configurable through module params*/ ++static int debug; ++static int vdi_rate_double; ++static int video_nr = 16; ++ ++/* Module parameters */ ++module_param(video_nr, int, S_IRUGO); ++MODULE_PARM_DESC(video_nr, "video device numbers"); ++module_param(debug, int, 0600); ++MODULE_PARM_DESC(debug, "Debug level (0-1)"); ++module_param(vdi_rate_double, int, 0600); ++MODULE_PARM_DESC(vdi_rate_double, "vdi frame rate double on/off"); ++ ++static const struct v4l2_fmtdesc mxc_formats[] = { ++ { ++ .description = "RGB565", ++ .pixelformat = V4L2_PIX_FMT_RGB565, ++ }, ++ { ++ .description = "BGR24", ++ .pixelformat = V4L2_PIX_FMT_BGR24, ++ }, ++ { ++ .description = "RGB24", ++ .pixelformat = V4L2_PIX_FMT_RGB24, ++ }, ++ { ++ .description = "RGB32", ++ .pixelformat = V4L2_PIX_FMT_RGB32, ++ }, ++ { ++ .description = "BGR32", ++ .pixelformat = V4L2_PIX_FMT_BGR32, ++ }, ++ { ++ .description = "NV12", ++ .pixelformat = V4L2_PIX_FMT_NV12, ++ }, ++ { ++ .description = "UYVY", ++ .pixelformat = V4L2_PIX_FMT_UYVY, ++ }, ++ { ++ .description = "YUYV", ++ .pixelformat = V4L2_PIX_FMT_YUYV, ++ }, ++ { ++ .description = "YUV422 planar", ++ .pixelformat = V4L2_PIX_FMT_YUV422P, ++ }, ++ { ++ .description = "YUV444", ++ .pixelformat = V4L2_PIX_FMT_YUV444, ++ }, ++ { ++ .description = "YUV420", ++ .pixelformat = V4L2_PIX_FMT_YUV420, ++ }, ++ { ++ .description = "YVU420", ++ .pixelformat = V4L2_PIX_FMT_YVU420, ++ }, ++ { ++ .description = "TILED NV12P", ++ .pixelformat = IPU_PIX_FMT_TILED_NV12, ++ }, ++ { ++ .description = "TILED NV12F", ++ .pixelformat = IPU_PIX_FMT_TILED_NV12F, ++ }, ++ { ++ .description = "YUV444 planar", ++ .pixelformat = IPU_PIX_FMT_YUV444P, ++ }, ++}; ++ ++#define NUM_MXC_VOUT_FORMATS (ARRAY_SIZE(mxc_formats)) ++ ++#define DEF_INPUT_WIDTH 320 ++#define DEF_INPUT_HEIGHT 240 ++ ++static int mxc_vidioc_streamoff(struct file *file, void *fh, ++ enum v4l2_buf_type i); ++ ++static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM]; ++static int config_disp_output(struct mxc_vout_output *vout); ++static void release_disp_output(struct mxc_vout_output *vout); ++ ++static unsigned int get_frame_size(struct mxc_vout_output *vout) ++{ ++ unsigned int size; ++ ++ if (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ++ size = TILED_NV12_FRAME_SIZE(vout->task.input.width, ++ vout->task.input.height); ++ else if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) { ++ size = TILED_NV12_FRAME_SIZE(vout->task.input.width, ++ vout->task.input.height/2); ++ size *= 2; ++ } else ++ size = vout->task.input.width * vout->task.input.height * ++ fmt_to_bpp(vout->task.input.format)/8; ++ ++ return size; ++} ++ ++static void free_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf) ++{ ++ dma_free_coherent(vout->vbq.dev, buf->size, buf->vaddr, buf->paddr); ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "free dma size:0x%x, paddr:0x%x\n", ++ buf->size, buf->paddr); ++ memset(buf, 0, sizeof(*buf)); ++} ++ ++static int alloc_dma_buf(struct mxc_vout_output *vout, struct dma_mem *buf) ++{ ++ ++ buf->vaddr = dma_alloc_coherent(vout->vbq.dev, buf->size, &buf->paddr, ++ GFP_DMA | GFP_KERNEL); ++ if (!buf->vaddr) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "cannot get dma buf size:0x%x\n", buf->size); ++ return -ENOMEM; ++ } ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "alloc dma buf size:0x%x, paddr:0x%x\n", buf->size, buf->paddr); ++ return 0; ++} ++ ++static ipu_channel_t get_ipu_channel(struct fb_info *fbi) ++{ ++ ipu_channel_t ipu_ch = CHAN_NONE; ++ mm_segment_t old_fs; ++ ++ if (fbi->fbops->fb_ioctl) { ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_FB_IPU_CHAN, ++ (unsigned long)&ipu_ch); ++ set_fs(old_fs); ++ } ++ ++ return ipu_ch; ++} ++ ++static unsigned int get_ipu_fmt(struct fb_info *fbi) ++{ ++ mm_segment_t old_fs; ++ unsigned int fb_fmt; ++ ++ if (fbi->fbops->fb_ioctl) { ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ fbi->fbops->fb_ioctl(fbi, MXCFB_GET_DIFMT, ++ (unsigned long)&fb_fmt); ++ set_fs(old_fs); ++ } ++ ++ return fb_fmt; ++} ++ ++static void update_display_setting(void) ++{ ++ int i; ++ struct fb_info *fbi; ++ struct v4l2_rect bg_crop_bounds[2]; ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ fbi = registered_fb[i]; ++ ++ memset(&g_fb_setting[i], 0, sizeof(struct mxc_vout_fb)); ++ ++ if (!strncmp(fbi->fix.id, "DISP3", 5)) ++ g_fb_setting[i].ipu_id = 0; ++ else ++ g_fb_setting[i].ipu_id = 1; ++ ++ g_fb_setting[i].name = fbi->fix.id; ++ g_fb_setting[i].crop_bounds.left = 0; ++ g_fb_setting[i].crop_bounds.top = 0; ++ g_fb_setting[i].crop_bounds.width = fbi->var.xres; ++ g_fb_setting[i].crop_bounds.height = fbi->var.yres; ++ g_fb_setting[i].disp_fmt = get_ipu_fmt(fbi); ++ ++ if (get_ipu_channel(fbi) == MEM_BG_SYNC) { ++ bg_crop_bounds[g_fb_setting[i].ipu_id] = ++ g_fb_setting[i].crop_bounds; ++ g_fb_setting[i].disp_support_csc = true; ++ } else if (get_ipu_channel(fbi) == MEM_FG_SYNC) { ++ g_fb_setting[i].disp_support_csc = true; ++ g_fb_setting[i].disp_support_windows = true; ++ } ++ } ++ ++ for (i = 0; i < num_registered_fb; i++) { ++ fbi = registered_fb[i]; ++ ++ if (get_ipu_channel(fbi) == MEM_FG_SYNC) ++ g_fb_setting[i].crop_bounds = ++ bg_crop_bounds[g_fb_setting[i].ipu_id]; ++ } ++} ++ ++/* called after g_fb_setting filled by update_display_setting */ ++static int update_setting_from_fbi(struct mxc_vout_output *vout, ++ struct fb_info *fbi) ++{ ++ int i; ++ bool found = false; ++ ++ for (i = 0; i < MAX_FB_NUM; i++) { ++ if (g_fb_setting[i].name) { ++ if (!strcmp(fbi->fix.id, g_fb_setting[i].name)) { ++ vout->crop_bounds = g_fb_setting[i].crop_bounds; ++ vout->disp_fmt = g_fb_setting[i].disp_fmt; ++ vout->disp_support_csc = ++ g_fb_setting[i].disp_support_csc; ++ vout->disp_support_windows = ++ g_fb_setting[i].disp_support_windows; ++ found = true; ++ break; ++ } ++ } ++ } ++ ++ if (!found) { ++ v4l2_err(vout->vfd->v4l2_dev, "can not find output\n"); ++ return -EINVAL; ++ } ++ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name)); ++ ++ memset(&vout->task, 0, sizeof(struct ipu_task)); ++ ++ vout->task.input.width = DEF_INPUT_WIDTH; ++ vout->task.input.height = DEF_INPUT_HEIGHT; ++ vout->task.input.crop.pos.x = 0; ++ vout->task.input.crop.pos.y = 0; ++ vout->task.input.crop.w = DEF_INPUT_WIDTH; ++ vout->task.input.crop.h = DEF_INPUT_HEIGHT; ++ ++ vout->task.output.width = vout->crop_bounds.width; ++ vout->task.output.height = vout->crop_bounds.height; ++ vout->task.output.crop.pos.x = 0; ++ vout->task.output.crop.pos.y = 0; ++ vout->task.output.crop.w = vout->crop_bounds.width; ++ vout->task.output.crop.h = vout->crop_bounds.height; ++ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS) ++ vout->task.output.format = IPU_PIX_FMT_UYVY; ++ else ++ vout->task.output.format = IPU_PIX_FMT_RGB565; ++ ++ return 0; ++} ++ ++static inline unsigned long get_jiffies(struct timeval *t) ++{ ++ struct timeval cur; ++ ++ if (t->tv_usec >= 1000000) { ++ t->tv_sec += t->tv_usec / 1000000; ++ t->tv_usec = t->tv_usec % 1000000; ++ } ++ ++ do_gettimeofday(&cur); ++ if ((t->tv_sec < cur.tv_sec) ++ || ((t->tv_sec == cur.tv_sec) && (t->tv_usec < cur.tv_usec))) ++ return jiffies; ++ ++ if (t->tv_usec < cur.tv_usec) { ++ cur.tv_sec = t->tv_sec - cur.tv_sec - 1; ++ cur.tv_usec = t->tv_usec + 1000000 - cur.tv_usec; ++ } else { ++ cur.tv_sec = t->tv_sec - cur.tv_sec; ++ cur.tv_usec = t->tv_usec - cur.tv_usec; ++ } ++ ++ return jiffies + timeval_to_jiffies(&cur); ++} ++ ++static bool deinterlace_3_field(struct mxc_vout_output *vout) ++{ ++ return (vout->task.input.deinterlace.enable && ++ (vout->task.input.deinterlace.motion != HIGH_MOTION)); ++} ++ ++static int set_field_fmt(struct mxc_vout_output *vout, enum v4l2_field field) ++{ ++ struct ipu_deinterlace *deinterlace = &vout->task.input.deinterlace; ++ ++ switch (field) { ++ /* Images are in progressive format, not interlaced */ ++ case V4L2_FIELD_NONE: ++ case V4L2_FIELD_ANY: ++ deinterlace->enable = false; ++ deinterlace->field_fmt = 0; ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "Progressive frame.\n"); ++ break; ++ case V4L2_FIELD_INTERLACED_TB: ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "Enable deinterlace TB.\n"); ++ deinterlace->enable = true; ++ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_TOP; ++ break; ++ case V4L2_FIELD_INTERLACED_BT: ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "Enable deinterlace BT.\n"); ++ deinterlace->enable = true; ++ deinterlace->field_fmt = IPU_DEINTERLACE_FIELD_BOTTOM; ++ break; ++ default: ++ v4l2_err(vout->vfd->v4l2_dev, ++ "field format:%d not supported yet!\n", field); ++ return -EINVAL; ++ } ++ ++ if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) { ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "tiled fmt enable deinterlace.\n"); ++ deinterlace->enable = true; ++ } ++ ++ if (deinterlace->enable && vdi_rate_double) ++ deinterlace->field_fmt |= IPU_DEINTERLACE_RATE_EN; ++ ++ return 0; ++} ++ ++static bool is_pp_bypass(struct mxc_vout_output *vout) ++{ ++ if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) || ++ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format)) ++ return false; ++ if ((vout->task.input.width == vout->task.output.width) && ++ (vout->task.input.height == vout->task.output.height) && ++ (vout->task.input.crop.w == vout->task.output.crop.w) && ++ (vout->task.input.crop.h == vout->task.output.crop.h) && ++ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && ++ !vout->task.input.deinterlace.enable) { ++ if (vout->disp_support_csc) ++ return true; ++ else if (!need_csc(vout->task.input.format, vout->disp_fmt)) ++ return true; ++ /* ++ * input crop show to full output which can show based on ++ * xres_virtual/yres_virtual ++ */ ++ } else if ((vout->task.input.crop.w == vout->task.output.crop.w) && ++ (vout->task.output.crop.w == vout->task.output.width) && ++ (vout->task.input.crop.h == vout->task.output.crop.h) && ++ (vout->task.output.crop.h == ++ vout->task.output.height) && ++ (vout->task.output.rotate < IPU_ROTATE_HORIZ_FLIP) && ++ !vout->task.input.deinterlace.enable) { ++ if (vout->disp_support_csc) ++ return true; ++ else if (!need_csc(vout->task.input.format, vout->disp_fmt)) ++ return true; ++ } ++ return false; ++} ++ ++static void setup_buf_timer(struct mxc_vout_output *vout, ++ struct videobuf_buffer *vb) ++{ ++ ktime_t expiry_time, now; ++ ++ /* if timestamp is 0, then default to 30fps */ ++ if ((vb->ts.tv_sec == 0) && (vb->ts.tv_usec == 0)) ++ expiry_time = ktime_add_ns(vout->start_ktime, ++ NSEC_PER_FRAME_30FPS * vout->frame_count); ++ else ++ expiry_time = timeval_to_ktime(vb->ts); ++ ++ now = hrtimer_cb_get_time(&vout->timer); ++ if ((now.tv64 > expiry_time.tv64)) { ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "warning: timer timeout already expired.\n"); ++ expiry_time = now; ++ } ++ ++ hrtimer_start(&vout->timer, expiry_time, HRTIMER_MODE_ABS); ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "timer handler next " ++ "schedule: %lldnsecs\n", expiry_time.tv64); ++} ++ ++static int show_buf(struct mxc_vout_output *vout, int idx, ++ struct ipu_pos *ipos) ++{ ++ struct fb_info *fbi = vout->fbi; ++ struct fb_var_screeninfo var; ++ int ret; ++ u32 fb_base = 0; ++ ++ memcpy(&var, &fbi->var, sizeof(var)); ++ ++ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) { ++ /* ++ * crack fb base ++ * NOTE: should not do other fb operation during v4l2 ++ */ ++ console_lock(); ++ fb_base = fbi->fix.smem_start; ++ fbi->fix.smem_start = vout->task.output.paddr; ++ fbi->var.yoffset = ipos->y + 1; ++ var.xoffset = ipos->x; ++ var.yoffset = ipos->y; ++ var.vmode |= FB_VMODE_YWRAP; ++ ret = fb_pan_display(fbi, &var); ++ fbi->fix.smem_start = fb_base; ++ console_unlock(); ++ } else { ++ console_lock(); ++ var.yoffset = idx * fbi->var.yres; ++ var.vmode &= ~FB_VMODE_YWRAP; ++ ret = fb_pan_display(fbi, &var); ++ console_unlock(); ++ } ++ ++ return ret; ++} ++ ++static void disp_work_func(struct work_struct *work) ++{ ++ struct mxc_vout_output *vout = ++ container_of(work, struct mxc_vout_output, disp_work); ++ struct videobuf_queue *q = &vout->vbq; ++ struct videobuf_buffer *vb, *vb_next = NULL; ++ unsigned long flags = 0; ++ struct ipu_pos ipos; ++ int ret = 0; ++ u32 in_fmt = 0; ++ u32 vdi_cnt = 0; ++ u32 vdi_frame; ++ u32 index = 0; ++ u32 ocrop_h = 0; ++ u32 o_height = 0; ++ u32 tiled_interlaced = 0; ++ bool tiled_fmt = false; ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n"); ++ ++ spin_lock_irqsave(q->irqlock, flags); ++ ++ if (list_empty(&vout->active_list)) { ++ v4l2_warn(vout->vfd->v4l2_dev, ++ "no entry in active_list, should not be here\n"); ++ spin_unlock_irqrestore(q->irqlock, flags); ++ return; ++ } ++ ++ vb = list_first_entry(&vout->active_list, ++ struct videobuf_buffer, queue); ++ ret = set_field_fmt(vout, vb->field); ++ if (ret < 0) { ++ spin_unlock_irqrestore(q->irqlock, flags); ++ return; ++ } ++ if (deinterlace_3_field(vout)) { ++ if (list_is_singular(&vout->active_list)) { ++ if (list_empty(&vout->queue_list)) { ++ vout->timer_stop = true; ++ spin_unlock_irqrestore(q->irqlock, flags); ++ v4l2_warn(vout->vfd->v4l2_dev, ++ "no enough entry for 3 fields " ++ "deinterlacer\n"); ++ return; ++ } ++ ++ /* ++ * We need to use the next vb even if it is ++ * not on the active list. ++ */ ++ vb_next = list_first_entry(&vout->queue_list, ++ struct videobuf_buffer, queue); ++ } else ++ vb_next = list_first_entry(vout->active_list.next, ++ struct videobuf_buffer, queue); ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "cur field_fmt:%d, next field_fmt:%d.\n", ++ vb->field, vb_next->field); ++ /* repeat the last field during field format changing */ ++ if ((vb->field != vb_next->field) && ++ (vb_next->field != V4L2_FIELD_NONE)) ++ vb_next = vb; ++ } ++ ++ spin_unlock_irqrestore(q->irqlock, flags); ++ ++vdi_frame_rate_double: ++ mutex_lock(&vout->task_lock); ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "v4l2 frame_cnt:%ld, vb_field:%d, fmt:%d\n", ++ vout->frame_count, vb->field, ++ vout->task.input.deinterlace.field_fmt); ++ if (vb->memory == V4L2_MEMORY_USERPTR) ++ vout->task.input.paddr = vb->baddr; ++ else ++ vout->task.input.paddr = videobuf_to_dma_contig(vb); ++ ++ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) ++ index = vout->vdi_frame_cnt % FB_BUFS; ++ else ++ index = vout->frame_count % FB_BUFS; ++ if (vout->linear_bypass_pp) { ++ vout->task.output.paddr = vout->task.input.paddr; ++ ipos.x = vout->task.input.crop.pos.x; ++ ipos.y = vout->task.input.crop.pos.y; ++ } else { ++ if (deinterlace_3_field(vout)) { ++ if (vb->memory == V4L2_MEMORY_USERPTR) ++ vout->task.input.paddr_n = vb_next->baddr; ++ else ++ vout->task.input.paddr_n = ++ videobuf_to_dma_contig(vb_next); ++ } ++ vout->task.output.paddr = vout->disp_bufs[index]; ++ if (vout->vdoa_1080p) { ++ o_height = vout->task.output.height; ++ ocrop_h = vout->task.output.crop.h; ++ vout->task.output.height = FRAME_HEIGHT_1080P; ++ vout->task.output.crop.h = FRAME_HEIGHT_1080P; ++ } ++ tiled_fmt = ++ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) || ++ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format); ++ if (vout->tiled_bypass_pp) { ++ ipos.x = vout->task.input.crop.pos.x; ++ ipos.y = vout->task.input.crop.pos.y; ++ } else if (tiled_fmt) { ++ vout->vdoa_task.input.paddr = vout->task.input.paddr; ++ if (deinterlace_3_field(vout)) ++ vout->vdoa_task.input.paddr_n = ++ vout->task.input.paddr_n; ++ vout->vdoa_task.output.paddr = vout->vdoa_work.paddr; ++ ret = ipu_queue_task(&vout->vdoa_task); ++ if (ret < 0) { ++ mutex_unlock(&vout->task_lock); ++ goto err; ++ } ++ vout->task.input.paddr = vout->vdoa_task.output.paddr; ++ in_fmt = vout->task.input.format; ++ vout->task.input.format = vout->vdoa_task.output.format; ++ if (vout->task.input.deinterlace.enable) { ++ tiled_interlaced = 1; ++ vout->task.input.deinterlace.enable = 0; ++ } ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "tiled queue task\n"); ++ } ++ ret = ipu_queue_task(&vout->task); ++ if ((!vout->tiled_bypass_pp) && tiled_fmt) ++ vout->task.input.format = in_fmt; ++ if (tiled_interlaced) ++ vout->task.input.deinterlace.enable = 1; ++ if (ret < 0) { ++ mutex_unlock(&vout->task_lock); ++ goto err; ++ } ++ if (vout->vdoa_1080p) { ++ vout->task.output.crop.h = ocrop_h; ++ vout->task.output.height = o_height; ++ } ++ } ++ ++ mutex_unlock(&vout->task_lock); ++ ++ ret = show_buf(vout, index, &ipos); ++ if (ret < 0) ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "show buf with ret %d\n", ret); ++ ++ if (vout->task.input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) { ++ vdi_frame = vout->task.input.deinterlace.field_fmt ++ & IPU_DEINTERLACE_RATE_FRAME1; ++ if (vdi_frame) ++ vout->task.input.deinterlace.field_fmt &= ++ ~IPU_DEINTERLACE_RATE_FRAME1; ++ else ++ vout->task.input.deinterlace.field_fmt |= ++ IPU_DEINTERLACE_RATE_FRAME1; ++ vout->vdi_frame_cnt++; ++ vdi_cnt++; ++ if (vdi_cnt < IPU_DEINTERLACE_MAX_FRAME) ++ goto vdi_frame_rate_double; ++ } ++ spin_lock_irqsave(q->irqlock, flags); ++ ++ list_del(&vb->queue); ++ ++ /* ++ * The videobuf before the last one has been shown. Set ++ * VIDEOBUF_DONE state here to avoid tearing issue in ic bypass ++ * case, which makes sure a buffer being shown will not be ++ * dequeued to be overwritten. It also brings side-effect that ++ * the last 2 buffers can not be dequeued correctly, apps need ++ * to take care of it. ++ */ ++ if (vout->pre2_vb) { ++ vout->pre2_vb->state = VIDEOBUF_DONE; ++ wake_up_interruptible(&vout->pre2_vb->done); ++ vout->pre2_vb = NULL; ++ } ++ ++ if (vout->linear_bypass_pp) { ++ vout->pre2_vb = vout->pre1_vb; ++ vout->pre1_vb = vb; ++ } else { ++ if (vout->pre1_vb) { ++ vout->pre1_vb->state = VIDEOBUF_DONE; ++ wake_up_interruptible(&vout->pre1_vb->done); ++ vout->pre1_vb = NULL; ++ } ++ vb->state = VIDEOBUF_DONE; ++ wake_up_interruptible(&vb->done); ++ } ++ ++ vout->frame_count++; ++ ++ /* pick next queue buf to setup timer */ ++ if (list_empty(&vout->queue_list)) ++ vout->timer_stop = true; ++ else { ++ vb = list_first_entry(&vout->queue_list, ++ struct videobuf_buffer, queue); ++ setup_buf_timer(vout, vb); ++ } ++ ++ spin_unlock_irqrestore(q->irqlock, flags); ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work finish one frame\n"); ++ ++ return; ++err: ++ v4l2_err(vout->vfd->v4l2_dev, "display work fail ret = %d\n", ret); ++ vout->timer_stop = true; ++ vb->state = VIDEOBUF_ERROR; ++ return; ++} ++ ++static enum hrtimer_restart mxc_vout_timer_handler(struct hrtimer *timer) ++{ ++ struct mxc_vout_output *vout = container_of(timer, ++ struct mxc_vout_output, ++ timer); ++ struct videobuf_queue *q = &vout->vbq; ++ struct videobuf_buffer *vb; ++ unsigned long flags = 0; ++ ++ spin_lock_irqsave(q->irqlock, flags); ++ ++ /* ++ * put first queued entry into active, if previous entry did not ++ * finish, setup current entry's timer again. ++ */ ++ if (list_empty(&vout->queue_list)) { ++ spin_unlock_irqrestore(q->irqlock, flags); ++ return HRTIMER_NORESTART; ++ } ++ ++ /* move videobuf from queued list to active list */ ++ vb = list_first_entry(&vout->queue_list, ++ struct videobuf_buffer, queue); ++ list_del(&vb->queue); ++ list_add_tail(&vb->queue, &vout->active_list); ++ ++ if (queue_work(vout->v4l_wq, &vout->disp_work) == 0) { ++ v4l2_warn(vout->vfd->v4l2_dev, ++ "disp work was in queue already, queue buf again next time\n"); ++ list_del(&vb->queue); ++ list_add(&vb->queue, &vout->queue_list); ++ spin_unlock_irqrestore(q->irqlock, flags); ++ return HRTIMER_NORESTART; ++ } ++ ++ vb->state = VIDEOBUF_ACTIVE; ++ ++ spin_unlock_irqrestore(q->irqlock, flags); ++ ++ return HRTIMER_NORESTART; ++} ++ ++/* Video buffer call backs */ ++ ++/* ++ * Buffer setup function is called by videobuf layer when REQBUF ioctl is ++ * called. This is used to setup buffers and return size and count of ++ * buffers allocated. After the call to this buffer, videobuf layer will ++ * setup buffer queue depending on the size and count of buffers ++ */ ++static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, ++ unsigned int *size) ++{ ++ struct mxc_vout_output *vout = q->priv_data; ++ unsigned int frame_size; ++ ++ if (!vout) ++ return -EINVAL; ++ ++ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) ++ return -EINVAL; ++ ++ frame_size = get_frame_size(vout); ++ *size = PAGE_ALIGN(frame_size); ++ ++ return 0; ++} ++ ++/* ++ * This function will be called when VIDIOC_QBUF ioctl is called. ++ * It prepare buffers before give out for the display. This function ++ * converts user space virtual address into physical address if userptr memory ++ * exchange mechanism is used. ++ */ ++static int mxc_vout_buffer_prepare(struct videobuf_queue *q, ++ struct videobuf_buffer *vb, ++ enum v4l2_field field) ++{ ++ vb->state = VIDEOBUF_PREPARED; ++ return 0; ++} ++ ++/* ++ * Buffer queue funtion will be called from the videobuf layer when _QBUF ++ * ioctl is called. It is used to enqueue buffer, which is ready to be ++ * displayed. ++ * This function is protected by q->irqlock. ++ */ ++static void mxc_vout_buffer_queue(struct videobuf_queue *q, ++ struct videobuf_buffer *vb) ++{ ++ struct mxc_vout_output *vout = q->priv_data; ++ struct videobuf_buffer *active_vb; ++ ++ list_add_tail(&vb->queue, &vout->queue_list); ++ vb->state = VIDEOBUF_QUEUED; ++ ++ if (vout->timer_stop) { ++ if (deinterlace_3_field(vout) && ++ !list_empty(&vout->active_list)) { ++ active_vb = list_first_entry(&vout->active_list, ++ struct videobuf_buffer, queue); ++ setup_buf_timer(vout, active_vb); ++ } else { ++ setup_buf_timer(vout, vb); ++ } ++ vout->timer_stop = false; ++ } ++} ++ ++/* ++ * Buffer release function is called from videobuf layer to release buffer ++ * which are already allocated ++ */ ++static void mxc_vout_buffer_release(struct videobuf_queue *q, ++ struct videobuf_buffer *vb) ++{ ++ vb->state = VIDEOBUF_NEEDS_INIT; ++} ++ ++static int mxc_vout_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ int ret; ++ struct mxc_vout_output *vout = file->private_data; ++ ++ if (!vout) ++ return -ENODEV; ++ ++ ret = videobuf_mmap_mapper(&vout->vbq, vma); ++ if (ret < 0) ++ v4l2_err(vout->vfd->v4l2_dev, ++ "offset invalid [offset=0x%lx]\n", ++ (vma->vm_pgoff << PAGE_SHIFT)); ++ ++ return ret; ++} ++ ++static int mxc_vout_release(struct file *file) ++{ ++ unsigned int ret = 0; ++ struct videobuf_queue *q; ++ struct mxc_vout_output *vout = file->private_data; ++ ++ if (!vout) ++ return 0; ++ ++ if (--vout->open_cnt == 0) { ++ q = &vout->vbq; ++ if (q->streaming) ++ mxc_vidioc_streamoff(file, vout, vout->type); ++ else { ++ release_disp_output(vout); ++ videobuf_queue_cancel(q); ++ } ++ destroy_workqueue(vout->v4l_wq); ++ ret = videobuf_mmap_free(q); ++ } ++ ++ return ret; ++} ++ ++static int mxc_vout_open(struct file *file) ++{ ++ struct mxc_vout_output *vout = NULL; ++ int ret = 0; ++ ++ vout = video_drvdata(file); ++ ++ if (vout == NULL) ++ return -ENODEV; ++ ++ if (vout->open_cnt++ == 0) { ++ vout->ctrl_rotate = 0; ++ vout->ctrl_vflip = 0; ++ vout->ctrl_hflip = 0; ++ update_display_setting(); ++ ret = update_setting_from_fbi(vout, vout->fbi); ++ if (ret < 0) ++ goto err; ++ ++ vout->v4l_wq = create_singlethread_workqueue("v4l2q"); ++ if (!vout->v4l_wq) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "Could not create work queue\n"); ++ ret = -ENOMEM; ++ goto err; ++ } ++ ++ INIT_WORK(&vout->disp_work, disp_work_func); ++ ++ INIT_LIST_HEAD(&vout->queue_list); ++ INIT_LIST_HEAD(&vout->active_list); ++ ++ vout->fmt_init = false; ++ vout->frame_count = 0; ++ vout->vdi_frame_cnt = 0; ++ ++ vout->win_pos.x = 0; ++ vout->win_pos.y = 0; ++ vout->release = true; ++ } ++ ++ file->private_data = vout; ++ ++err: ++ return ret; ++} ++ ++/* ++ * V4L2 ioctls ++ */ ++static int mxc_vidioc_querycap(struct file *file, void *fh, ++ struct v4l2_capability *cap) ++{ ++ struct mxc_vout_output *vout = fh; ++ ++ strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver)); ++ strlcpy(cap->card, vout->vfd->name, sizeof(cap->card)); ++ cap->bus_info[0] = '\0'; ++ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT; ++ ++ return 0; ++} ++ ++static int mxc_vidioc_enum_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_fmtdesc *fmt) ++{ ++ if (fmt->index >= NUM_MXC_VOUT_FORMATS) ++ return -EINVAL; ++ ++ strlcpy(fmt->description, mxc_formats[fmt->index].description, ++ sizeof(fmt->description)); ++ fmt->pixelformat = mxc_formats[fmt->index].pixelformat; ++ ++ return 0; ++} ++ ++static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct mxc_vout_output *vout = fh; ++ struct v4l2_rect rect; ++ ++ f->fmt.pix.width = vout->task.input.width; ++ f->fmt.pix.height = vout->task.input.height; ++ f->fmt.pix.pixelformat = vout->task.input.format; ++ f->fmt.pix.sizeimage = get_frame_size(vout); ++ ++ if (f->fmt.pix.priv) { ++ rect.left = vout->task.input.crop.pos.x; ++ rect.top = vout->task.input.crop.pos.y; ++ rect.width = vout->task.input.crop.w; ++ rect.height = vout->task.input.crop.h; ++ if (copy_to_user((void __user *)f->fmt.pix.priv, ++ &rect, sizeof(rect))) ++ return -EFAULT; ++ } ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "frame_size:0x%x, pix_fmt:0x%x\n", ++ f->fmt.pix.sizeimage, ++ vout->task.input.format); ++ ++ return 0; ++} ++ ++static inline int ipu_try_task(struct mxc_vout_output *vout) ++{ ++ int ret; ++ struct ipu_task *task = &vout->task; ++ ++again: ++ ret = ipu_check_task(task); ++ if (ret != IPU_CHECK_OK) { ++ if (ret > IPU_CHECK_ERR_MIN) { ++ if (ret == IPU_CHECK_ERR_SPLIT_INPUTW_OVER || ++ ret == IPU_CHECK_ERR_W_DOWNSIZE_OVER) { ++ task->input.crop.w -= 8; ++ goto again; ++ } ++ if (ret == IPU_CHECK_ERR_SPLIT_INPUTH_OVER || ++ ret == IPU_CHECK_ERR_H_DOWNSIZE_OVER) { ++ task->input.crop.h -= 8; ++ goto again; ++ } ++ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTW_OVER) { ++ if (vout->disp_support_windows) { ++ task->output.width -= 8; ++ task->output.crop.w = ++ task->output.width; ++ } else ++ task->output.crop.w -= 8; ++ goto again; ++ } ++ if (ret == IPU_CHECK_ERR_SPLIT_OUTPUTH_OVER) { ++ if (vout->disp_support_windows) { ++ task->output.height -= 8; ++ task->output.crop.h = ++ task->output.height; ++ } else ++ task->output.crop.h -= 8; ++ goto again; ++ } ++ ret = -EINVAL; ++ } ++ } else ++ ret = 0; ++ ++ return ret; ++} ++ ++static inline int vdoaipu_try_task(struct mxc_vout_output *vout) ++{ ++ int ret; ++ int is_1080p_stream; ++ size_t size; ++ struct ipu_task *ipu_task = &vout->task; ++ struct ipu_crop *icrop = &ipu_task->input.crop; ++ struct ipu_task *vdoa_task = &vout->vdoa_task; ++ u32 deinterlace = 0; ++ u32 in_fmt; ++ ++ if (vout->task.input.deinterlace.enable) ++ deinterlace = 1; ++ ++ memset(vdoa_task, 0, sizeof(*vdoa_task)); ++ vdoa_task->output.format = IPU_PIX_FMT_NV12; ++ memcpy(&vdoa_task->input, &ipu_task->input, ++ sizeof(ipu_task->input)); ++ if ((icrop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) || ++ (icrop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) { ++ vdoa_task->input.crop.w = ++ ALIGN(icrop->w, IPU_PIX_FMT_TILED_NV12_MBALIGN); ++ vdoa_task->input.crop.h = ++ ALIGN(icrop->h, IPU_PIX_FMT_TILED_NV12_MBALIGN); ++ } ++ vdoa_task->output.width = vdoa_task->input.crop.w; ++ vdoa_task->output.height = vdoa_task->input.crop.h; ++ vdoa_task->output.crop.w = vdoa_task->input.crop.w; ++ vdoa_task->output.crop.h = vdoa_task->input.crop.h; ++ ++ size = PAGE_ALIGN(vdoa_task->input.crop.w * ++ vdoa_task->input.crop.h * ++ fmt_to_bpp(vdoa_task->output.format)/8); ++ if (size > vout->vdoa_work.size) { ++ if (vout->vdoa_work.vaddr) ++ free_dma_buf(vout, &vout->vdoa_work); ++ vout->vdoa_work.size = size; ++ ret = alloc_dma_buf(vout, &vout->vdoa_work); ++ if (ret < 0) ++ return ret; ++ } ++ ret = ipu_check_task(vdoa_task); ++ if (ret != IPU_CHECK_OK) ++ return -EINVAL; ++ ++ is_1080p_stream = CHECK_TILED_1080P_STREAM(vout); ++ if (is_1080p_stream) ++ ipu_task->input.crop.h = VALID_HEIGHT_1080P; ++ in_fmt = ipu_task->input.format; ++ ipu_task->input.format = vdoa_task->output.format; ++ ipu_task->input.height = vdoa_task->output.height; ++ ipu_task->input.width = vdoa_task->output.width; ++ if (deinterlace) ++ ipu_task->input.deinterlace.enable = 0; ++ ret = ipu_try_task(vout); ++ if (deinterlace) ++ ipu_task->input.deinterlace.enable = 1; ++ ipu_task->input.format = in_fmt; ++ ++ return ret; ++} ++ ++static int mxc_vout_try_task(struct mxc_vout_output *vout) ++{ ++ int ret = 0; ++ struct ipu_output *output = &vout->task.output; ++ struct ipu_input *input = &vout->task.input; ++ struct ipu_crop *crop = &input->crop; ++ u32 o_height = 0; ++ u32 ocrop_h = 0; ++ bool tiled_fmt = false; ++ bool tiled_need_pp = false; ++ ++ vout->vdoa_1080p = CHECK_TILED_1080P_DISPLAY(vout); ++ if (vout->vdoa_1080p) { ++ input->crop.h = FRAME_HEIGHT_1080P; ++ o_height = output->height; ++ ocrop_h = output->crop.h; ++ output->height = FRAME_HEIGHT_1080P; ++ output->crop.h = FRAME_HEIGHT_1080P; ++ } ++ ++ if ((IPU_PIX_FMT_TILED_NV12 == input->format) || ++ (IPU_PIX_FMT_TILED_NV12F == input->format)) { ++ if ((input->width % IPU_PIX_FMT_TILED_NV12_MBALIGN) || ++ (input->height % IPU_PIX_FMT_TILED_NV12_MBALIGN) || ++ (crop->pos.x % IPU_PIX_FMT_TILED_NV12_MBALIGN) || ++ (crop->pos.y % IPU_PIX_FMT_TILED_NV12_MBALIGN)) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "ERR: tiled fmt needs 16 pixel align.\n"); ++ return -EINVAL; ++ } ++ if ((crop->w % IPU_PIX_FMT_TILED_NV12_MBALIGN) || ++ (crop->h % IPU_PIX_FMT_TILED_NV12_MBALIGN)) ++ tiled_need_pp = true; ++ } else { ++ crop->w -= crop->w % 8; ++ crop->h -= crop->h % 8; ++ } ++ /* assume task.output already set by S_CROP */ ++ vout->linear_bypass_pp = is_pp_bypass(vout); ++ if (vout->linear_bypass_pp) { ++ v4l2_info(vout->vfd->v4l2_dev, "Bypass IC.\n"); ++ output->format = input->format; ++ } else { ++ /* if need CSC, choose IPU-DP or IPU_IC do it */ ++ if (vout->disp_support_csc) { ++ if (colorspaceofpixel(input->format) == YUV_CS) ++ output->format = IPU_PIX_FMT_UYVY; ++ else ++ output->format = IPU_PIX_FMT_RGB565; ++ } else { ++ if (colorspaceofpixel(vout->disp_fmt) == YUV_CS) ++ output->format = IPU_PIX_FMT_UYVY; ++ else ++ output->format = IPU_PIX_FMT_RGB565; ++ } ++ ++ vout->tiled_bypass_pp = false; ++ if ((IPU_PIX_FMT_TILED_NV12 == input->format) || ++ (IPU_PIX_FMT_TILED_NV12F == input->format)) { ++ /* check resize/rotate/flip, or csc task */ ++ if (!(tiled_need_pp || ++ (IPU_ROTATE_NONE != output->rotate) || ++ (input->crop.w != output->crop.w) || ++ (input->crop.h != output->crop.h) || ++ (!vout->disp_support_csc && ++ (colorspaceofpixel(vout->disp_fmt) == RGB_CS))) ++ ) { ++ /* IC bypass */ ++ output->format = IPU_PIX_FMT_NV12; ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "tiled bypass pp\n"); ++ vout->tiled_bypass_pp = true; ++ } ++ tiled_fmt = true; ++ } ++ ++ if ((!vout->tiled_bypass_pp) && tiled_fmt) ++ ret = vdoaipu_try_task(vout); ++ else ++ ret = ipu_try_task(vout); ++ } ++ ++ if (vout->vdoa_1080p) { ++ output->height = o_height; ++ output->crop.h = ocrop_h; ++ } ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "icrop.w:%u, icrop.h:%u, iw:%u, ih:%u," ++ "ocrop.w:%u, ocrop.h:%u, ow:%u, oh:%u\n", ++ input->crop.w, input->crop.h, ++ input->width, input->height, ++ output->crop.w, output->crop.h, ++ output->width, output->height); ++ return ret; ++} ++ ++static int mxc_vout_try_format(struct mxc_vout_output *vout, ++ struct v4l2_format *f) ++{ ++ int ret = 0; ++ struct v4l2_rect rect; ++ ++ if ((f->fmt.pix.field != V4L2_FIELD_NONE) && ++ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "progressive tiled fmt should used V4L2_FIELD_NONE!\n"); ++ return -EINVAL; ++ } ++ ++ if (f->fmt.pix.priv && copy_from_user(&rect, ++ (void __user *)f->fmt.pix.priv, sizeof(rect))) ++ return -EFAULT; ++ ++ vout->task.input.width = f->fmt.pix.width; ++ vout->task.input.height = f->fmt.pix.height; ++ vout->task.input.format = f->fmt.pix.pixelformat; ++ ++ ret = set_field_fmt(vout, f->fmt.pix.field); ++ if (ret < 0) ++ return ret; ++ ++ if (f->fmt.pix.priv) { ++ vout->task.input.crop.pos.x = rect.left; ++ vout->task.input.crop.pos.y = rect.top; ++ vout->task.input.crop.w = rect.width; ++ vout->task.input.crop.h = rect.height; ++ } else { ++ vout->task.input.crop.pos.x = 0; ++ vout->task.input.crop.pos.y = 0; ++ vout->task.input.crop.w = f->fmt.pix.width; ++ vout->task.input.crop.h = f->fmt.pix.height; ++ } ++ memcpy(&vout->in_rect, &vout->task.input.crop, sizeof(vout->in_rect)); ++ ++ ret = mxc_vout_try_task(vout); ++ if (!ret) { ++ if (f->fmt.pix.priv) { ++ rect.width = vout->task.input.crop.w; ++ rect.height = vout->task.input.crop.h; ++ if (copy_to_user((void __user *)f->fmt.pix.priv, ++ &rect, sizeof(rect))) ++ ret = -EFAULT; ++ } else { ++ f->fmt.pix.width = vout->task.input.crop.w; ++ f->fmt.pix.height = vout->task.input.crop.h; ++ } ++ } ++ ++ return ret; ++} ++ ++static bool mxc_vout_need_fb_reconfig(struct mxc_vout_output *vout, ++ struct mxc_vout_output *pre_vout) ++{ ++ if (!vout->vbq.streaming) ++ return false; ++ ++ if (vout->tiled_bypass_pp) ++ return true; ++ ++ if (vout->linear_bypass_pp != pre_vout->linear_bypass_pp) ++ return true; ++ ++ /* cropped output resolution or format are changed */ ++ if (vout->task.output.format != pre_vout->task.output.format || ++ vout->task.output.crop.w != pre_vout->task.output.crop.w || ++ vout->task.output.crop.h != pre_vout->task.output.crop.h) ++ return true; ++ ++ /* overlay: window position or resolution are changed */ ++ if (vout->disp_support_windows && ++ (vout->win_pos.x != pre_vout->win_pos.x || ++ vout->win_pos.y != pre_vout->win_pos.y || ++ vout->task.output.width != pre_vout->task.output.width || ++ vout->task.output.height != pre_vout->task.output.height)) ++ return true; ++ ++ /* background: cropped position is changed */ ++ if (!vout->disp_support_windows && ++ (vout->task.output.crop.pos.x != ++ pre_vout->task.output.crop.pos.x || ++ vout->task.output.crop.pos.y != ++ pre_vout->task.output.crop.pos.y)) ++ return true; ++ ++ return false; ++} ++ ++static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh, ++ struct v4l2_format *f) ++{ ++ struct mxc_vout_output *vout = fh; ++ int ret = 0; ++ ++ if (vout->vbq.streaming) ++ return -EBUSY; ++ ++ mutex_lock(&vout->task_lock); ++ ret = mxc_vout_try_format(vout, f); ++ if (ret >= 0) ++ vout->fmt_init = true; ++ mutex_unlock(&vout->task_lock); ++ ++ return ret; ++} ++ ++static int mxc_vidioc_cropcap(struct file *file, void *fh, ++ struct v4l2_cropcap *cropcap) ++{ ++ struct mxc_vout_output *vout = fh; ++ ++ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ cropcap->bounds = vout->crop_bounds; ++ cropcap->defrect = vout->crop_bounds; ++ ++ return 0; ++} ++ ++static int mxc_vidioc_g_crop(struct file *file, void *fh, ++ struct v4l2_crop *crop) ++{ ++ struct mxc_vout_output *vout = fh; ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ if (vout->disp_support_windows) { ++ crop->c.left = vout->win_pos.x; ++ crop->c.top = vout->win_pos.y; ++ crop->c.width = vout->task.output.width; ++ crop->c.height = vout->task.output.height; ++ } else { ++ if (vout->task.output.crop.w && vout->task.output.crop.h) { ++ crop->c.left = vout->task.output.crop.pos.x; ++ crop->c.top = vout->task.output.crop.pos.y; ++ crop->c.width = vout->task.output.crop.w; ++ crop->c.height = vout->task.output.crop.h; ++ } else { ++ crop->c.left = 0; ++ crop->c.top = 0; ++ crop->c.width = vout->task.output.width; ++ crop->c.height = vout->task.output.height; ++ } ++ } ++ ++ return 0; ++} ++ ++static int mxc_vidioc_s_crop(struct file *file, void *fh, ++ const struct v4l2_crop *crop) ++{ ++ struct mxc_vout_output *vout = fh, *pre_vout; ++ struct v4l2_rect *b = &vout->crop_bounds; ++ struct v4l2_crop fix_up_crop; ++ int ret = 0; ++ ++ memcpy(&fix_up_crop, crop, sizeof(*crop)); ++ ++ if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ if (crop->c.width < 0 || crop->c.height < 0) ++ return -EINVAL; ++ ++ if (crop->c.width == 0) ++ fix_up_crop.c.width = b->width - b->left; ++ if (crop->c.height == 0) ++ fix_up_crop.c.height = b->height - b->top; ++ ++ if (crop->c.top < b->top) ++ fix_up_crop.c.top = b->top; ++ if (crop->c.top >= b->top + b->height) ++ fix_up_crop.c.top = b->top + b->height - 1; ++ if (crop->c.height > b->top - crop->c.top + b->height) ++ fix_up_crop.c.height = ++ b->top - fix_up_crop.c.top + b->height; ++ ++ if (crop->c.left < b->left) ++ fix_up_crop.c.left = b->left; ++ if (crop->c.left >= b->left + b->width) ++ fix_up_crop.c.left = b->left + b->width - 1; ++ if (crop->c.width > b->left - crop->c.left + b->width) ++ fix_up_crop.c.width = ++ b->left - fix_up_crop.c.left + b->width; ++ ++ /* stride line limitation */ ++ fix_up_crop.c.height -= fix_up_crop.c.height % 8; ++ fix_up_crop.c.width -= fix_up_crop.c.width % 8; ++ if ((fix_up_crop.c.width <= 0) || (fix_up_crop.c.height <= 0) || ++ ((fix_up_crop.c.left + fix_up_crop.c.width) > ++ (b->left + b->width)) || ++ ((fix_up_crop.c.top + fix_up_crop.c.height) > ++ (b->top + b->height))) { ++ v4l2_err(vout->vfd->v4l2_dev, "s_crop err: %d, %d, %d, %d", ++ fix_up_crop.c.left, fix_up_crop.c.top, ++ fix_up_crop.c.width, fix_up_crop.c.height); ++ return -EINVAL; ++ } ++ ++ /* the same setting, return */ ++ if (vout->disp_support_windows) { ++ if ((vout->win_pos.x == fix_up_crop.c.left) && ++ (vout->win_pos.y == fix_up_crop.c.top) && ++ (vout->task.output.crop.w == fix_up_crop.c.width) && ++ (vout->task.output.crop.h == fix_up_crop.c.height)) ++ return 0; ++ } else { ++ if ((vout->task.output.crop.pos.x == fix_up_crop.c.left) && ++ (vout->task.output.crop.pos.y == fix_up_crop.c.top) && ++ (vout->task.output.crop.w == fix_up_crop.c.width) && ++ (vout->task.output.crop.h == fix_up_crop.c.height)) ++ return 0; ++ } ++ ++ pre_vout = vmalloc(sizeof(*pre_vout)); ++ if (!pre_vout) ++ return -ENOMEM; ++ ++ /* wait current work finish */ ++ if (vout->vbq.streaming) ++ flush_workqueue(vout->v4l_wq); ++ ++ mutex_lock(&vout->task_lock); ++ ++ memcpy(pre_vout, vout, sizeof(*vout)); ++ ++ if (vout->disp_support_windows) { ++ vout->task.output.crop.pos.x = 0; ++ vout->task.output.crop.pos.y = 0; ++ vout->win_pos.x = fix_up_crop.c.left; ++ vout->win_pos.y = fix_up_crop.c.top; ++ vout->task.output.width = fix_up_crop.c.width; ++ vout->task.output.height = fix_up_crop.c.height; ++ } else { ++ vout->task.output.crop.pos.x = fix_up_crop.c.left; ++ vout->task.output.crop.pos.y = fix_up_crop.c.top; ++ } ++ ++ vout->task.output.crop.w = fix_up_crop.c.width; ++ vout->task.output.crop.h = fix_up_crop.c.height; ++ ++ /* ++ * must S_CROP before S_FMT, for fist time S_CROP, will not check ++ * ipu task, it will check in S_FMT, after S_FMT, S_CROP should ++ * check ipu task too. ++ */ ++ if (vout->fmt_init) { ++ memcpy(&vout->task.input.crop, &vout->in_rect, ++ sizeof(vout->in_rect)); ++ ret = mxc_vout_try_task(vout); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "vout check task failed\n"); ++ memcpy(vout, pre_vout, sizeof(*vout)); ++ goto done; ++ } ++ ++ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) { ++ ret = config_disp_output(vout); ++ if (ret < 0) ++ v4l2_err(vout->vfd->v4l2_dev, ++ "Config display output failed\n"); ++ } ++ } ++ ++done: ++ vfree(pre_vout); ++ mutex_unlock(&vout->task_lock); ++ ++ return ret; ++} ++ ++static int mxc_vidioc_queryctrl(struct file *file, void *fh, ++ struct v4l2_queryctrl *ctrl) ++{ ++ int ret = 0; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_ROTATE: ++ ret = v4l2_ctrl_query_fill(ctrl, 0, 270, 90, 0); ++ break; ++ case V4L2_CID_VFLIP: ++ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); ++ break; ++ case V4L2_CID_HFLIP: ++ ret = v4l2_ctrl_query_fill(ctrl, 0, 1, 1, 0); ++ break; ++ case V4L2_CID_MXC_MOTION: ++ ret = v4l2_ctrl_query_fill(ctrl, 0, 2, 1, 0); ++ break; ++ default: ++ ctrl->name[0] = '\0'; ++ ret = -EINVAL; ++ } ++ return ret; ++} ++ ++static int mxc_vidioc_g_ctrl(struct file *file, void *fh, ++ struct v4l2_control *ctrl) ++{ ++ int ret = 0; ++ struct mxc_vout_output *vout = fh; ++ ++ switch (ctrl->id) { ++ case V4L2_CID_ROTATE: ++ ctrl->value = vout->ctrl_rotate; ++ break; ++ case V4L2_CID_VFLIP: ++ ctrl->value = vout->ctrl_vflip; ++ break; ++ case V4L2_CID_HFLIP: ++ ctrl->value = vout->ctrl_hflip; ++ break; ++ case V4L2_CID_MXC_MOTION: ++ if (vout->task.input.deinterlace.enable) ++ ctrl->value = vout->task.input.deinterlace.motion; ++ else ++ ctrl->value = 0; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ return ret; ++} ++ ++static void setup_task_rotation(struct mxc_vout_output *vout) ++{ ++ if (vout->ctrl_rotate == 0) { ++ if (vout->ctrl_vflip && vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_180; ++ else if (vout->ctrl_vflip) ++ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP; ++ else if (vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP; ++ else ++ vout->task.output.rotate = IPU_ROTATE_NONE; ++ } else if (vout->ctrl_rotate == 90) { ++ if (vout->ctrl_vflip && vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_90_LEFT; ++ else if (vout->ctrl_vflip) ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP; ++ else if (vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP; ++ else ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT; ++ } else if (vout->ctrl_rotate == 180) { ++ if (vout->ctrl_vflip && vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_NONE; ++ else if (vout->ctrl_vflip) ++ vout->task.output.rotate = IPU_ROTATE_HORIZ_FLIP; ++ else if (vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_VERT_FLIP; ++ else ++ vout->task.output.rotate = IPU_ROTATE_180; ++ } else if (vout->ctrl_rotate == 270) { ++ if (vout->ctrl_vflip && vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT; ++ else if (vout->ctrl_vflip) ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_HFLIP; ++ else if (vout->ctrl_hflip) ++ vout->task.output.rotate = IPU_ROTATE_90_RIGHT_VFLIP; ++ else ++ vout->task.output.rotate = IPU_ROTATE_90_LEFT; ++ } ++} ++ ++static int mxc_vidioc_s_ctrl(struct file *file, void *fh, ++ struct v4l2_control *ctrl) ++{ ++ int ret = 0; ++ struct mxc_vout_output *vout = fh, *pre_vout; ++ ++ pre_vout = vmalloc(sizeof(*pre_vout)); ++ if (!pre_vout) ++ return -ENOMEM; ++ ++ /* wait current work finish */ ++ if (vout->vbq.streaming) ++ flush_workqueue(vout->v4l_wq); ++ ++ mutex_lock(&vout->task_lock); ++ ++ memcpy(pre_vout, vout, sizeof(*vout)); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_ROTATE: ++ { ++ vout->ctrl_rotate = (ctrl->value/90) * 90; ++ if (vout->ctrl_rotate > 270) ++ vout->ctrl_rotate = 270; ++ setup_task_rotation(vout); ++ break; ++ } ++ case V4L2_CID_VFLIP: ++ { ++ vout->ctrl_vflip = ctrl->value; ++ setup_task_rotation(vout); ++ break; ++ } ++ case V4L2_CID_HFLIP: ++ { ++ vout->ctrl_hflip = ctrl->value; ++ setup_task_rotation(vout); ++ break; ++ } ++ case V4L2_CID_MXC_MOTION: ++ { ++ vout->task.input.deinterlace.motion = ctrl->value; ++ break; ++ } ++ default: ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ if (vout->fmt_init) { ++ memcpy(&vout->task.input.crop, &vout->in_rect, ++ sizeof(vout->in_rect)); ++ ret = mxc_vout_try_task(vout); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "vout check task failed\n"); ++ memcpy(vout, pre_vout, sizeof(*vout)); ++ goto done; ++ } ++ ++ if (mxc_vout_need_fb_reconfig(vout, pre_vout)) { ++ ret = config_disp_output(vout); ++ if (ret < 0) ++ v4l2_err(vout->vfd->v4l2_dev, ++ "Config display output failed\n"); ++ } ++ } ++ ++done: ++ vfree(pre_vout); ++ mutex_unlock(&vout->task_lock); ++ ++ return ret; ++} ++ ++static int mxc_vidioc_reqbufs(struct file *file, void *fh, ++ struct v4l2_requestbuffers *req) ++{ ++ int ret = 0; ++ struct mxc_vout_output *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ ++ if (req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ /* should not be here after streaming, videobuf_reqbufs will control */ ++ mutex_lock(&vout->task_lock); ++ ++ ret = videobuf_reqbufs(q, req); ++ ++ mutex_unlock(&vout->task_lock); ++ return ret; ++} ++ ++static int mxc_vidioc_querybuf(struct file *file, void *fh, ++ struct v4l2_buffer *b) ++{ ++ int ret; ++ struct mxc_vout_output *vout = fh; ++ ++ ret = videobuf_querybuf(&vout->vbq, b); ++ if (!ret) { ++ /* return physical address */ ++ struct videobuf_buffer *vb = vout->vbq.bufs[b->index]; ++ if (b->flags & V4L2_BUF_FLAG_MAPPED) ++ b->m.offset = videobuf_to_dma_contig(vb); ++ } ++ ++ return ret; ++} ++ ++static int mxc_vidioc_qbuf(struct file *file, void *fh, ++ struct v4l2_buffer *buffer) ++{ ++ struct mxc_vout_output *vout = fh; ++ ++ return videobuf_qbuf(&vout->vbq, buffer); ++} ++ ++static int mxc_vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b) ++{ ++ struct mxc_vout_output *vout = fh; ++ ++ if (!vout->vbq.streaming) ++ return -EINVAL; ++ ++ if (file->f_flags & O_NONBLOCK) ++ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 1); ++ else ++ return videobuf_dqbuf(&vout->vbq, (struct v4l2_buffer *)b, 0); ++} ++ ++static int set_window_position(struct mxc_vout_output *vout, ++ struct mxcfb_pos *pos) ++{ ++ struct fb_info *fbi = vout->fbi; ++ mm_segment_t old_fs; ++ int ret = 0; ++ ++ if (vout->disp_support_windows) { ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ ret = fbi->fbops->fb_ioctl(fbi, MXCFB_SET_OVERLAY_POS, ++ (unsigned long)pos); ++ set_fs(old_fs); ++ } ++ ++ return ret; ++} ++ ++static int config_disp_output(struct mxc_vout_output *vout) ++{ ++ struct dma_mem *buf = NULL; ++ struct fb_info *fbi = vout->fbi; ++ struct fb_var_screeninfo var; ++ struct mxcfb_pos pos; ++ int i, fb_num, ret; ++ u32 fb_base; ++ u32 size; ++ u32 display_buf_size; ++ u32 *pixel = NULL; ++ u32 color; ++ int j; ++ ++ memcpy(&var, &fbi->var, sizeof(var)); ++ fb_base = fbi->fix.smem_start; ++ ++ var.xres = vout->task.output.width; ++ var.yres = vout->task.output.height; ++ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) { ++ fb_num = 1; ++ /* input crop */ ++ if (vout->task.input.width > vout->task.output.width) ++ var.xres_virtual = vout->task.input.width; ++ else ++ var.xres_virtual = var.xres; ++ if (vout->task.input.height > vout->task.output.height) ++ var.yres_virtual = vout->task.input.height; ++ else ++ var.yres_virtual = var.yres; ++ var.rotate = vout->task.output.rotate; ++ var.vmode |= FB_VMODE_YWRAP; ++ } else { ++ fb_num = FB_BUFS; ++ var.xres_virtual = var.xres; ++ var.yres_virtual = fb_num * var.yres; ++ var.vmode &= ~FB_VMODE_YWRAP; ++ } ++ var.bits_per_pixel = fmt_to_bpp(vout->task.output.format); ++ var.nonstd = vout->task.output.format; ++ ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "set display fb to %d %d\n", ++ var.xres, var.yres); ++ ++ /* ++ * To setup the overlay fb from scratch without ++ * the last time overlay fb position or resolution's ++ * impact, we take the following steps: ++ * - blank fb ++ * - set fb position to the starting point ++ * - reconfigure fb ++ * - set fb position to a specific point ++ * - unblank fb ++ * This procedure applies to non-overlay fbs as well. ++ */ ++ console_lock(); ++ fbi->flags |= FBINFO_MISC_USEREVENT; ++ fb_blank(fbi, FB_BLANK_POWERDOWN); ++ fbi->flags &= ~FBINFO_MISC_USEREVENT; ++ console_unlock(); ++ ++ pos.x = 0; ++ pos.y = 0; ++ ret = set_window_position(vout, &pos); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position " ++ "to starting point\n"); ++ return ret; ++ } ++ ++ /* Init display channel through fb API */ ++ var.yoffset = 0; ++ var.activate |= FB_ACTIVATE_FORCE; ++ console_lock(); ++ fbi->flags |= FBINFO_MISC_USEREVENT; ++ ret = fb_set_var(fbi, &var); ++ fbi->flags &= ~FBINFO_MISC_USEREVENT; ++ console_unlock(); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "ERR:%s fb_set_var ret:%d\n", __func__, ret); ++ return ret; ++ } ++ ++ ret = set_window_position(vout, &vout->win_pos); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, "failed to set fb position\n"); ++ return ret; ++ } ++ ++ if (vout->linear_bypass_pp || vout->tiled_bypass_pp) ++ display_buf_size = fbi->fix.line_length * fbi->var.yres_virtual; ++ else ++ display_buf_size = fbi->fix.line_length * fbi->var.yres; ++ for (i = 0; i < fb_num; i++) ++ vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size; ++ if (vout->tiled_bypass_pp) { ++ size = PAGE_ALIGN(vout->task.input.crop.w * ++ vout->task.input.crop.h * ++ fmt_to_bpp(vout->task.output.format)/8); ++ if (size > vout->vdoa_output[0].size) { ++ for (i = 0; i < VDOA_FB_BUFS; i++) { ++ buf = &vout->vdoa_output[i]; ++ if (buf->vaddr) ++ free_dma_buf(vout, buf); ++ buf->size = size; ++ ret = alloc_dma_buf(vout, buf); ++ if (ret < 0) ++ goto err; ++ } ++ } ++ for (i = fb_num; i < (fb_num + VDOA_FB_BUFS); i++) ++ vout->disp_bufs[i] = ++ vout->vdoa_output[i - fb_num].paddr; ++ } ++ vout->fb_smem_len = fbi->fix.smem_len; ++ vout->fb_smem_start = fbi->fix.smem_start; ++ if (fb_base != fbi->fix.smem_start) { ++ v4l2_dbg(1, debug, vout->vfd->v4l2_dev, ++ "realloc fb mem size:0x%x@0x%lx,old paddr @0x%x\n", ++ fbi->fix.smem_len, fbi->fix.smem_start, fb_base); ++ } ++ ++ /* fill black when video config changed */ ++ color = colorspaceofpixel(vout->task.output.format) == YUV_CS ? ++ UYVY_BLACK : RGB_BLACK; ++ if (IS_PLANAR_PIXEL_FORMAT(vout->task.output.format)) { ++ size = display_buf_size * 8 / ++ fmt_to_bpp(vout->task.output.format); ++ memset(fbi->screen_base, Y_BLACK, size); ++ memset(fbi->screen_base + size, UV_BLACK, ++ display_buf_size - size); ++ } else { ++ pixel = (u32 *)fbi->screen_base; ++ for (i = 0; i < (display_buf_size >> 2); i++) ++ *pixel++ = color; ++ } ++ console_lock(); ++ fbi->flags |= FBINFO_MISC_USEREVENT; ++ ret = fb_blank(fbi, FB_BLANK_UNBLANK); ++ fbi->flags &= ~FBINFO_MISC_USEREVENT; ++ console_unlock(); ++ vout->release = false; ++ ++ return ret; ++err: ++ for (j = i - 1; j >= 0; j--) { ++ buf = &vout->vdoa_output[j]; ++ if (buf->vaddr) ++ free_dma_buf(vout, buf); ++ } ++ return ret; ++} ++ ++static inline void wait_for_vsync(struct mxc_vout_output *vout) ++{ ++ struct fb_info *fbi = vout->fbi; ++ mm_segment_t old_fs; ++ ++ if (fbi->fbops->fb_ioctl) { ++ old_fs = get_fs(); ++ set_fs(KERNEL_DS); ++ fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC, ++ (unsigned long)NULL); ++ set_fs(old_fs); ++ } ++ ++ return; ++} ++ ++static void release_disp_output(struct mxc_vout_output *vout) ++{ ++ struct fb_info *fbi = vout->fbi; ++ struct mxcfb_pos pos; ++ ++ if (vout->release) ++ return; ++ console_lock(); ++ fbi->flags |= FBINFO_MISC_USEREVENT; ++ fb_blank(fbi, FB_BLANK_POWERDOWN); ++ fbi->flags &= ~FBINFO_MISC_USEREVENT; ++ console_unlock(); ++ ++ /* restore pos to 0,0 avoid fb pan display hang? */ ++ pos.x = 0; ++ pos.y = 0; ++ set_window_position(vout, &pos); ++ ++ if (get_ipu_channel(fbi) == MEM_BG_SYNC) { ++ console_lock(); ++ fbi->fix.smem_start = vout->disp_bufs[0]; ++ fbi->flags |= FBINFO_MISC_USEREVENT; ++ fb_blank(fbi, FB_BLANK_UNBLANK); ++ fbi->flags &= ~FBINFO_MISC_USEREVENT; ++ console_unlock(); ++ ++ } ++ ++ vout->release = true; ++} ++ ++static int mxc_vidioc_streamon(struct file *file, void *fh, ++ enum v4l2_buf_type i) ++{ ++ struct mxc_vout_output *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ int ret; ++ ++ if (q->streaming) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "video output already run\n"); ++ ret = -EBUSY; ++ goto done; ++ } ++ ++ if (deinterlace_3_field(vout) && list_is_singular(&q->stream)) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "deinterlacing: need queue 2 frame before streamon\n"); ++ ret = -EINVAL; ++ goto done; ++ } ++ ++ ret = config_disp_output(vout); ++ if (ret < 0) { ++ v4l2_err(vout->vfd->v4l2_dev, ++ "Config display output failed\n"); ++ goto done; ++ } ++ ++ hrtimer_init(&vout->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); ++ vout->timer.function = mxc_vout_timer_handler; ++ vout->timer_stop = true; ++ ++ vout->start_ktime = hrtimer_cb_get_time(&vout->timer); ++ ++ vout->pre1_vb = NULL; ++ vout->pre2_vb = NULL; ++ ++ ret = videobuf_streamon(q); ++done: ++ return ret; ++} ++ ++static int mxc_vidioc_streamoff(struct file *file, void *fh, ++ enum v4l2_buf_type i) ++{ ++ struct mxc_vout_output *vout = fh; ++ struct videobuf_queue *q = &vout->vbq; ++ int ret = 0; ++ ++ if (q->streaming) { ++ flush_workqueue(vout->v4l_wq); ++ ++ hrtimer_cancel(&vout->timer); ++ ++ /* ++ * Wait for 2 vsyncs to make sure ++ * frames are drained on triple ++ * buffer. ++ */ ++ wait_for_vsync(vout); ++ wait_for_vsync(vout); ++ ++ release_disp_output(vout); ++ ++ ret = videobuf_streamoff(&vout->vbq); ++ } ++ INIT_LIST_HEAD(&vout->queue_list); ++ INIT_LIST_HEAD(&vout->active_list); ++ ++ return ret; ++} ++ ++static const struct v4l2_ioctl_ops mxc_vout_ioctl_ops = { ++ .vidioc_querycap = mxc_vidioc_querycap, ++ .vidioc_enum_fmt_vid_out = mxc_vidioc_enum_fmt_vid_out, ++ .vidioc_g_fmt_vid_out = mxc_vidioc_g_fmt_vid_out, ++ .vidioc_s_fmt_vid_out = mxc_vidioc_s_fmt_vid_out, ++ .vidioc_cropcap = mxc_vidioc_cropcap, ++ .vidioc_g_crop = mxc_vidioc_g_crop, ++ .vidioc_s_crop = mxc_vidioc_s_crop, ++ .vidioc_queryctrl = mxc_vidioc_queryctrl, ++ .vidioc_g_ctrl = mxc_vidioc_g_ctrl, ++ .vidioc_s_ctrl = mxc_vidioc_s_ctrl, ++ .vidioc_reqbufs = mxc_vidioc_reqbufs, ++ .vidioc_querybuf = mxc_vidioc_querybuf, ++ .vidioc_qbuf = mxc_vidioc_qbuf, ++ .vidioc_dqbuf = mxc_vidioc_dqbuf, ++ .vidioc_streamon = mxc_vidioc_streamon, ++ .vidioc_streamoff = mxc_vidioc_streamoff, ++}; ++ ++static const struct v4l2_file_operations mxc_vout_fops = { ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = mxc_vout_mmap, ++ .open = mxc_vout_open, ++ .release = mxc_vout_release, ++}; ++ ++static struct video_device mxc_vout_template = { ++ .name = "MXC Video Output", ++ .fops = &mxc_vout_fops, ++ .ioctl_ops = &mxc_vout_ioctl_ops, ++ .release = video_device_release, ++}; ++ ++static struct videobuf_queue_ops mxc_vout_vbq_ops = { ++ .buf_setup = mxc_vout_buffer_setup, ++ .buf_prepare = mxc_vout_buffer_prepare, ++ .buf_release = mxc_vout_buffer_release, ++ .buf_queue = mxc_vout_buffer_queue, ++}; ++ ++static void mxc_vout_free_output(struct mxc_vout_dev *dev) ++{ ++ int i; ++ int j; ++ struct mxc_vout_output *vout; ++ struct video_device *vfd; ++ ++ for (i = 0; i < dev->out_num; i++) { ++ vout = dev->out[i]; ++ vfd = vout->vfd; ++ if (vout->vdoa_work.vaddr) ++ free_dma_buf(vout, &vout->vdoa_work); ++ for (j = 0; j < VDOA_FB_BUFS; j++) { ++ if (vout->vdoa_output[j].vaddr) ++ free_dma_buf(vout, &vout->vdoa_output[j]); ++ } ++ if (vfd) { ++ if (!video_is_registered(vfd)) ++ video_device_release(vfd); ++ else ++ video_unregister_device(vfd); ++ } ++ kfree(vout); ++ } ++} ++ ++static int mxc_vout_setup_output(struct mxc_vout_dev *dev) ++{ ++ struct videobuf_queue *q; ++ struct fb_info *fbi; ++ struct mxc_vout_output *vout; ++ int i, ret = 0; ++ ++ update_display_setting(); ++ ++ /* all output/overlay based on fb */ ++ for (i = 0; i < num_registered_fb; i++) { ++ fbi = registered_fb[i]; ++ ++ vout = kzalloc(sizeof(struct mxc_vout_output), GFP_KERNEL); ++ if (!vout) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ dev->out[dev->out_num] = vout; ++ dev->out_num++; ++ ++ vout->fbi = fbi; ++ vout->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ vout->vfd = video_device_alloc(); ++ if (!vout->vfd) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ *vout->vfd = mxc_vout_template; ++ vout->vfd->debug = debug; ++ vout->vfd->v4l2_dev = &dev->v4l2_dev; ++ vout->vfd->lock = &vout->mutex; ++ vout->vfd->vfl_dir = VFL_DIR_TX; ++ ++ mutex_init(&vout->mutex); ++ mutex_init(&vout->task_lock); ++ ++ strlcpy(vout->vfd->name, fbi->fix.id, sizeof(vout->vfd->name)); ++ ++ video_set_drvdata(vout->vfd, vout); ++ ++ if (video_register_device(vout->vfd, ++ VFL_TYPE_GRABBER, video_nr + i) < 0) { ++ ret = -ENODEV; ++ break; ++ } ++ ++ q = &vout->vbq; ++ q->dev = dev->dev; ++ spin_lock_init(&vout->vbq_lock); ++ videobuf_queue_dma_contig_init(q, &mxc_vout_vbq_ops, q->dev, ++ &vout->vbq_lock, vout->type, V4L2_FIELD_NONE, ++ sizeof(struct videobuf_buffer), vout, NULL); ++ ++ v4l2_info(vout->vfd->v4l2_dev, "V4L2 device registered as %s\n", ++ video_device_node_name(vout->vfd)); ++ ++ } ++ ++ return ret; ++} ++ ++static int mxc_vout_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct mxc_vout_dev *dev; ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->dev = &pdev->dev; ++ dev->dev->dma_mask = kmalloc(sizeof(*dev->dev->dma_mask), GFP_KERNEL); ++ *dev->dev->dma_mask = DMA_BIT_MASK(32); ++ dev->dev->coherent_dma_mask = DMA_BIT_MASK(32); ++ ++ ret = v4l2_device_register(dev->dev, &dev->v4l2_dev); ++ if (ret) { ++ dev_err(dev->dev, "v4l2_device_register failed\n"); ++ goto free_dev; ++ } ++ ++ ret = mxc_vout_setup_output(dev); ++ if (ret < 0) ++ goto rel_vdev; ++ ++ return 0; ++ ++rel_vdev: ++ mxc_vout_free_output(dev); ++ v4l2_device_unregister(&dev->v4l2_dev); ++free_dev: ++ kfree(dev); ++ return ret; ++} ++ ++static int mxc_vout_remove(struct platform_device *pdev) ++{ ++ struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); ++ struct mxc_vout_dev *dev = container_of(v4l2_dev, struct ++ mxc_vout_dev, v4l2_dev); ++ ++ mxc_vout_free_output(dev); ++ v4l2_device_unregister(v4l2_dev); ++ kfree(dev); ++ return 0; ++} ++ ++static const struct of_device_id mxc_v4l2_dt_ids[] = { ++ { .compatible = "fsl,mxc_v4l2_output", }, ++ { /* sentinel */ } ++}; ++ ++static struct platform_driver mxc_vout_driver = { ++ .driver = { ++ .name = "mxc_v4l2_output", ++ .of_match_table = mxc_v4l2_dt_ids, ++ }, ++ .probe = mxc_vout_probe, ++ .remove = mxc_vout_remove, ++}; ++ ++static int __init mxc_vout_init(void) ++{ ++ if (platform_driver_register(&mxc_vout_driver) != 0) { ++ printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static void mxc_vout_cleanup(void) ++{ ++ platform_driver_unregister(&mxc_vout_driver); ++} ++ ++module_init(mxc_vout_init); ++module_exit(mxc_vout_cleanup); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("V4L2-driver for MXC video output"); ++MODULE_LICENSE("GPL"); +diff -Nur linux-3.14.14/drivers/media/v4l2-core/videobuf2-dma-contig.c linux-imx6-3.14/drivers/media/v4l2-core/videobuf2-dma-contig.c +--- linux-3.14.14/drivers/media/v4l2-core/videobuf2-dma-contig.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/media/v4l2-core/videobuf2-dma-contig.c 2014-12-08 00:31:53.360418001 -0600 +@@ -719,7 +719,7 @@ + + /* get the associated scatterlist for this buffer */ + sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir); +- if (IS_ERR_OR_NULL(sgt)) { ++ if (IS_ERR(sgt)) { + pr_err("Error getting dmabuf scatterlist\n"); + return -EINVAL; + } +diff -Nur linux-3.14.14/drivers/media/v4l2-core/videobuf-dma-contig.c linux-imx6-3.14/drivers/media/v4l2-core/videobuf-dma-contig.c +--- linux-3.14.14/drivers/media/v4l2-core/videobuf-dma-contig.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/media/v4l2-core/videobuf-dma-contig.c 2014-12-08 00:31:53.360418001 -0600 +@@ -304,7 +304,7 @@ + + /* Try to remap memory */ + size = vma->vm_end - vma->vm_start; +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + retval = vm_iomap_memory(vma, vma->vm_start, size); + if (retval) { + dev_err(q->dev, "mmap: remap failed with error %d. ", +diff -Nur linux-3.14.14/drivers/mfd/ab8500-core.c linux-imx6-3.14/drivers/mfd/ab8500-core.c +--- linux-3.14.14/drivers/mfd/ab8500-core.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mfd/ab8500-core.c 2014-12-08 00:31:53.376418001 -0600 +@@ -592,7 +592,7 @@ + + /* If ->irq_base is zero this will give a linear mapping */ + ab8500->domain = irq_domain_add_simple(NULL, +- num_irqs, ab8500->irq_base, ++ num_irqs, 0, + &ab8500_irq_ops, ab8500); + + if (!ab8500->domain) { +@@ -1583,14 +1583,13 @@ + if (!ab8500) + return -ENOMEM; + +- if (plat) +- ab8500->irq_base = plat->irq_base; +- + ab8500->dev = &pdev->dev; + + resource = platform_get_resource(pdev, IORESOURCE_IRQ, 0); +- if (!resource) ++ if (!resource) { ++ dev_err(&pdev->dev, "no IRQ resource\n"); + return -ENODEV; ++ } + + ab8500->irq = resource->start; + +@@ -1612,8 +1611,10 @@ + else { + ret = get_register_interruptible(ab8500, AB8500_MISC, + AB8500_IC_NAME_REG, &value); +- if (ret < 0) ++ if (ret < 0) { ++ dev_err(&pdev->dev, "could not probe HW\n"); + return ret; ++ } + + ab8500->version = value; + } +@@ -1759,30 +1760,30 @@ + if (is_ab9540(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, + ARRAY_SIZE(ab9540_devs), NULL, +- ab8500->irq_base, ab8500->domain); ++ 0, ab8500->domain); + else if (is_ab8540(ab8500)) { + ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, + ARRAY_SIZE(ab8540_devs), NULL, +- ab8500->irq_base, NULL); ++ 0, ab8500->domain); + if (ret) + return ret; + + if (is_ab8540_1p2_or_earlier(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut1_devs, + ARRAY_SIZE(ab8540_cut1_devs), NULL, +- ab8500->irq_base, NULL); ++ 0, ab8500->domain); + else /* ab8540 >= cut2 */ + ret = mfd_add_devices(ab8500->dev, 0, ab8540_cut2_devs, + ARRAY_SIZE(ab8540_cut2_devs), NULL, +- ab8500->irq_base, NULL); ++ 0, ab8500->domain); + } else if (is_ab8505(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, + ARRAY_SIZE(ab8505_devs), NULL, +- ab8500->irq_base, ab8500->domain); ++ 0, ab8500->domain); + else + ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, + ARRAY_SIZE(ab8500_devs), NULL, +- ab8500->irq_base, ab8500->domain); ++ 0, ab8500->domain); + if (ret) + return ret; + +@@ -1790,7 +1791,7 @@ + /* Add battery management devices */ + ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, + ARRAY_SIZE(ab8500_bm_devs), NULL, +- ab8500->irq_base, ab8500->domain); ++ 0, ab8500->domain); + if (ret) + dev_err(ab8500->dev, "error adding bm devices\n"); + } +diff -Nur linux-3.14.14/drivers/mfd/db8500-prcmu.c linux-imx6-3.14/drivers/mfd/db8500-prcmu.c +--- linux-3.14.14/drivers/mfd/db8500-prcmu.c 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mfd/db8500-prcmu.c 2014-12-08 00:31:53.380418001 -0600 +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -2678,16 +2679,12 @@ + .xlate = irq_domain_xlate_twocell, + }; + +-static int db8500_irq_init(struct device_node *np, int irq_base) ++static int db8500_irq_init(struct device_node *np) + { + int i; + +- /* In the device tree case, just take some IRQs */ +- if (np) +- irq_base = 0; +- + db8500_irq_domain = irq_domain_add_simple( +- np, NUM_PRCMU_WAKEUPS, irq_base, ++ np, NUM_PRCMU_WAKEUPS, 0, + &db8500_irq_ops, NULL); + + if (!db8500_irq_domain) { +@@ -3114,10 +3111,10 @@ + } + + static int db8500_prcmu_register_ab8500(struct device *parent, +- struct ab8500_platform_data *pdata, +- int irq) ++ struct ab8500_platform_data *pdata) + { +- struct resource ab8500_resource = DEFINE_RES_IRQ(irq); ++ struct device_node *np; ++ struct resource ab8500_resource; + struct mfd_cell ab8500_cell = { + .name = "ab8500-core", + .of_compatible = "stericsson,ab8500", +@@ -3128,6 +3125,20 @@ + .num_resources = 1, + }; + ++ if (!parent->of_node) ++ return -ENODEV; ++ ++ /* Look up the device node, sneak the IRQ out of it */ ++ for_each_child_of_node(parent->of_node, np) { ++ if (of_device_is_compatible(np, ab8500_cell.of_compatible)) ++ break; ++ } ++ if (!np) { ++ dev_info(parent, "could not find AB8500 node in the device tree\n"); ++ return -ENODEV; ++ } ++ of_irq_to_resource_table(np, &ab8500_resource, 1); ++ + return mfd_add_devices(parent, 0, &ab8500_cell, 1, NULL, 0, NULL); + } + +@@ -3180,7 +3191,7 @@ + goto no_irq_return; + } + +- db8500_irq_init(np, pdata->irq_base); ++ db8500_irq_init(np); + + prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); + +@@ -3205,8 +3216,7 @@ + } + } + +- err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata, +- pdata->ab_irq); ++ err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata); + if (err) { + mfd_remove_devices(&pdev->dev); + pr_err("prcmu: Failed to add ab8500 subdevice\n"); +diff -Nur linux-3.14.14/drivers/mfd/Kconfig linux-imx6-3.14/drivers/mfd/Kconfig +--- linux-3.14.14/drivers/mfd/Kconfig 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mfd/Kconfig 2014-12-08 00:31:53.376418001 -0600 +@@ -163,6 +163,14 @@ + Additional drivers must be enabled in order to use the functionality + of the device. + ++config MFD_MXC_HDMI ++ tristate "Freescale HDMI Core" ++ select MFD_CORE ++ help ++ This is the core driver for the Freescale i.MX6 on-chip HDMI. ++ This MFD driver connects with the video and audio drivers for HDMI. ++ ++ + config MFD_MC13XXX + tristate + depends on (SPI_MASTER || I2C) +@@ -1226,3 +1234,4 @@ + help + Platform configuration infrastructure for the ARM Ltd. + Versatile Express. ++ +diff -Nur linux-3.14.14/drivers/mfd/Makefile linux-imx6-3.14/drivers/mfd/Makefile +--- linux-3.14.14/drivers/mfd/Makefile 2014-07-28 10:07:25.000000000 -0500 ++++ linux-imx6-3.14/drivers/mfd/Makefile 2014-12-08 00:31:53.376418001 -0600 +@@ -166,3 +166,4 @@ + obj-$(CONFIG_MFD_AS3711) += as3711.o + obj-$(CONFIG_MFD_AS3722) += as3722.o + obj-$(CONFIG_MFD_STW481X) += stw481x.o ++obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o +diff -Nur linux-3.14.14/drivers/mfd/mxc-hdmi-core.c linux-imx6-3.14/drivers/mfd/mxc-hdmi-core.c +--- linux-3.14.14/drivers/mfd/mxc-hdmi-core.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-imx6-3.14/drivers/mfd/mxc-hdmi-core.c 2014-12-08 00:31:53.384418001 -0600 +@@ -0,0 +1,798 @@ ++/* ++ * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include