Merge "gpu: ion: Set dma length in sg_list"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 812a895..4f31f07 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -30,7 +30,7 @@
- qcom,ctrl-delay-us: delay in activation of led
- qcom,dig-mod-gen-en: digital module generator
- qcom,cs-out-en: current sink output enable
-- qcom,op-fdbck: selection of output as feedback for the boost
+- qcom,op-fdbck: selection of output as feedback for the boost, 00 = automatic selection, 01 = select LED1 output, 02 = select LED2 output, 03 = select LED3 output
- qcom,cp-select: high pole capacitance
- linux,default-trigger: trigger the led from external modules such as display
- qcom,default-state: default state of the led, should be "on" or "off"
@@ -138,7 +138,7 @@
linux,default-trigger = "bkl-trigger"
label = "wled";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state "off";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 2b1a352..9c0959d 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -839,7 +839,7 @@
qcom,scale-function = <1>;
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x88>;
+ qcom,btm-channel-number = <0x70>;
};
chan@6 {
@@ -848,10 +848,10 @@
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <1>;
qcom,calibration-type = "absolute";
- qcom,scale-function = <3>;
+ qcom,scale-function = <0>;
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x90>;
+ qcom,btm-channel-number = <0x78>;
};
chan@b5 {
@@ -863,7 +863,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x70>;
+ qcom,btm-channel-number = <0x80>;
qcom,thermal-node;
};
@@ -876,7 +876,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x78>;
+ qcom,btm-channel-number = <0x88>;
qcom,thermal-node;
};
@@ -889,7 +889,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <3>;
- qcom,btm-channel-number = <0x80>;
+ qcom,btm-channel-number = <0x90>;
qcom,thermal-node;
};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 8d8aa79..eab8b07 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -189,7 +189,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 32d9a95..5c6fbd5 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -182,7 +182,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index ae97be9..df74bf9 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -185,7 +185,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
index 1b08246..bdfc768 100644
--- a/arch/arm/boot/dts/msm8226-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -34,7 +34,6 @@
interrupts = <0 143 1>;
};
- /* SMP2P Test Driver for inbound entries */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -51,7 +50,6 @@
gpios = <&smp2pgpio_smp2p_7_in 0 0>;
};
- /* SMP2P Test Driver for outbound entries */
smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -67,7 +65,6 @@
gpios = <&smp2pgpio_smp2p_7_out 0 0>;
};
- /* SMP2P Test Driver for modem inbound */
smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -84,7 +81,6 @@
gpios = <&smp2pgpio_smp2p_1_in 0 0>;
};
- /* SMP2P Test Driver for modem output */
smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -100,7 +96,6 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
- /* SMP2P SSR Driver for inbound entry from modem. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "slave-kernel";
@@ -112,7 +107,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P SSR Driver for outbound entry to modem */
smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "master-kernel";
@@ -123,7 +117,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -140,7 +133,6 @@
gpios = <&smp2pgpio_smp2p_2_in 0 0>;
};
- /* SMP2P Test Driver for adsp output */
smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -156,7 +148,6 @@
gpios = <&smp2pgpio_smp2p_2_out 0 0>;
};
- /* SMP2P Test Driver for wcnss inbound */
smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -173,7 +164,6 @@
gpios = <&smp2pgpio_smp2p_4_in 0 0>;
};
- /* SMP2P Test Driver for wcnss output */
smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
new file mode 100644
index 0000000..f3a8259
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -0,0 +1,168 @@
+/* Copyright (c) 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
+ * only 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.
+ */
+/ {
+ msm_gpu: qcom,kgsl-3d0@fdc00000 {
+ label = "kgsl-3d0";
+ compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+ reg = <0xfdc00000 0x10000
+ 0xfdc10000 0x10000>;
+ reg-names = "kgsl_3d0_reg_memory", "kgsl_3d0_shader_memory";
+ interrupts = <0 33 0>;
+ interrupt-names = "kgsl_3d0_irq";
+ qcom,id = <0>;
+
+ qcom,chipid = <0x03000520>;
+
+ qcom,initial-pwrlevel = <1>;
+
+ qcom,idle-timeout = <8>; /* <HZ/12> */
+ qcom,nap-allowed = <1>;
+ qcom,strtstp-sleepwake;
+ qcom,clk-map = <0x000001E>; /* KGSL_CLK_CORE |
+ KGSL_CLK_IFACE | KGSL_CLK_MEM | KGSL_CLK_MEM_IFACE */
+
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "grp3d";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <26 512 0 0>,
+ <26 512 0 800000>,
+ <26 512 0 1600000>,
+ <26 512 0 2128000>;
+
+ /* GDSC oxili regulators */
+ vdd-supply = <&gdsc_oxili_cx>;
+
+ /* IOMMU Data */
+ iommu = <&gfx_iommu>;
+
+ /* Power levels */
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <400000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <0>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <300000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <150000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
+
+ /* DVCS Info */
+ qcom,dcvs-core-info {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,dcvs-core-info";
+
+ qcom,num-cores = <1>;
+ qcom,sensors = <0>;
+
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
+ qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
+
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
+ qcom,dcvs-freq@0 {
+ reg = <0>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@1 {
+ reg = <1>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@2 {
+ reg = <2>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@3 {
+ reg = <3>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
new file mode 100644
index 0000000..4a5273b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-smp2p.dtsi
@@ -0,0 +1,184 @@
+/* Copyright (c) 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
+ * only 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.
+ */
+/ {
+ qcom,smp2p-modem {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-adsp {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 158 1>;
+ };
+
+ qcom,smp2p-wcnss {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <4>;
+ qcom,irq-bitmask = <0x40000>;
+ interrupts = <0 143 1>;
+ };
+
+ smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+ gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+ gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+ gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+ gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index a7d22d9c..91dfdbe 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -13,9 +13,11 @@
/include/ "skeleton.dtsi"
/include/ "msm-iommu-v0.dtsi"
/include/ "msm8610-ion.dtsi"
+/include/ "msm8610-gpu.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8610-coresight.dtsi"
/include/ "msm8610-pm.dtsi"
+/include/ "msm8610-smp2p.dtsi"
/ {
model = "Qualcomm MSM 8610";
@@ -475,7 +477,7 @@
interrupts = <0 184 0>;
qcom,sensors = <2>;
qcom,slope = <2901 2846>;
- qcom,calib-mode = "fuse_map2";
+ qcom,calib-mode = "fuse_map3";
qcom,calibration-less-mode;
qcom,tsens-local-init;
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index adab873..2919709 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -247,7 +247,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -298,6 +298,10 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
&sdcc2 {
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -310,6 +314,7 @@
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
wp-gpios = <&pm8941_gpios 29 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -331,6 +336,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -358,6 +364,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&uart7 {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index e70d5d8..046939e 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -224,7 +224,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -277,6 +277,7 @@
&sdcc1 {
qcom,bus-width = <4>;
+ status = "disabled";
};
&sdcc2 {
@@ -290,6 +291,7 @@
2 &msmgpio 62 0x3>;
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -311,6 +313,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -338,6 +341,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&usb3 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 8a8a8b7..0f38e44 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -764,6 +764,14 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
+&sdcc2 {
+ status = "disabled";
+};
+
&sdhc_1 {
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
@@ -783,6 +791,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -799,4 +808,5 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index d61de02..8fa1d75 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -199,7 +199,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -250,6 +250,10 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
&sdcc2 {
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -261,6 +265,7 @@
2 &msmgpio 62 0x3>;
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -282,6 +287,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -309,6 +315,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&usb_otg {
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
index 1b08246..91029e2 100644
--- a/arch/arm/boot/dts/msm8974-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -34,7 +34,6 @@
interrupts = <0 143 1>;
};
- /* SMP2P Test Driver for inbound entries */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -51,7 +50,6 @@
gpios = <&smp2pgpio_smp2p_7_in 0 0>;
};
- /* SMP2P Test Driver for outbound entries */
smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -67,7 +65,6 @@
gpios = <&smp2pgpio_smp2p_7_out 0 0>;
};
- /* SMP2P Test Driver for modem inbound */
smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -84,7 +81,6 @@
gpios = <&smp2pgpio_smp2p_1_in 0 0>;
};
- /* SMP2P Test Driver for modem output */
smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -100,7 +96,6 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
- /* SMP2P SSR Driver for inbound entry from modem. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "slave-kernel";
@@ -112,7 +107,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P SSR Driver for outbound entry to modem */
smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "master-kernel";
@@ -123,7 +117,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -140,7 +133,6 @@
gpios = <&smp2pgpio_smp2p_2_in 0 0>;
};
- /* SMP2P Test Driver for adsp output */
smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -156,7 +148,6 @@
gpios = <&smp2pgpio_smp2p_2_out 0 0>;
};
- /* SMP2P Test Driver for wcnss inbound */
smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -173,7 +164,6 @@
gpios = <&smp2pgpio_smp2p_4_in 0 0>;
};
- /* SMP2P Test Driver for wcnss output */
smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -184,6 +174,27 @@
#interrupt-cells = <2>;
};
+ smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
qcom,smp2pgpio_test_smp2p_4_out {
compatible = "qcom,smp2pgpio_test_smp2p_4_out";
gpios = <&smp2pgpio_smp2p_4_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 52436b3..c16feee 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -210,6 +210,7 @@
<78 512 2048000 4096000>; /* Max. bandwidth */
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>;
qcom,dat1-mpm-int = <42>;
+ status = "disable";
};
sdcc2: qcom,sdcc@f98a4000 {
@@ -256,6 +257,7 @@
<81 512 2048000 4096000>; /* Max. bandwidth */
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>;
qcom,dat1-mpm-int = <44>;
+ status = "disable";
};
sdcc3: qcom,sdcc@f9864000 {
@@ -1021,6 +1023,12 @@
vdd_pronto_pll-supply = <&pm8941_l12>;
qcom,firmware-name = "wcnss";
+
+ /* GPIO input from wcnss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+ /* GPIO output to wcnss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
qcom,iris-fm {
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 85738d0..590692c 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -59,6 +59,7 @@
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 8d6bc81..42acd99 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -53,6 +53,7 @@
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_RTB=y
CONFIG_MSM_UARTDM_Core_v14=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 9e9bba9..041e89a 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -53,6 +53,7 @@
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_RTB=y
CONFIG_MSM_UARTDM_Core_v14=y
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 2b3667f..366debb 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -381,6 +381,8 @@
.stop = arch_timer_stop,
};
+static struct clock_event_device arch_timer_global_evt;
+
static int __init arch_timer_common_register(void)
{
int err;
@@ -431,9 +433,19 @@
}
err = local_timer_register(&arch_timer_ops);
+ if (err) {
+ /*
+ * We couldn't register as a local timer (could be
+ * because we're on a UP platform, or because some
+ * other local timer is already present...). Try as a
+ * global timer instead.
+ */
+ arch_timer_global_evt.cpumask = cpumask_of(0);
+ err = arch_timer_setup(&arch_timer_global_evt);
+ }
+
if (err)
goto out_free_irq;
- percpu_timer_setup();
/* Use the architected timer for the delay loop. */
arch_delay_timer.read_current_timer = &arch_timer_read_current_timer;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index cef66ec..c440f47 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -742,6 +742,7 @@
static struct of_device_id armpmu_of_device_ids[] = {
{.compatible = "arm,cortex-a9-pmu"},
{.compatible = "arm,cortex-a8-pmu"},
+ {.compatible = "arm,cortex-a5-pmu"},
{.compatible = "arm,arm1136-pmu"},
{.compatible = "arm,arm1176-pmu"},
{.compatible = "qcom,krait-pmu"},
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index db53ae5..54806ae 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -368,10 +368,8 @@
select ARM_GIC
select MIGHT_HAVE_CACHE_L2X0
select ARCH_MSM_CORTEX_A5
- select SMP
- select MSM_SMP
select CPU_V7
- select MSM_SCM if SMP
+ select MSM_SCM
select MSM_GPIOMUX
select MSM_RPM_SMD
select MSM_NATIVE_RESTART
@@ -428,6 +426,7 @@
select REGULATOR
select MSM_RPM_REGULATOR_SMD
select MSM_SPM_REGULATOR
+ select MSM_JTAG_MM if CORESIGHT_ETM
select MSM_CPR_REGULATOR
config ARCH_MSM8226
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index d8e4ed5..6817c6c 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -147,6 +147,7 @@
#define USB_HSIC_SYSTEM_CBCR 0x040C
#define USB_HSIC_CBCR 0x0410
#define USB_HSIC_IO_CAL_CBCR 0x0414
+#define USB_HSIC_IO_CAL_SLEEP_CBCR 0x0418
#define USB_HSIC_XCVR_FS_CBCR 0x042C
#define USB_HS_SYSTEM_CBCR 0x0484
#define USB_HS_AHB_CBCR 0x0488
@@ -187,6 +188,7 @@
#define PDM2_CBCR 0x0CCC
#define PRNG_AHB_CBCR 0x0D04
#define BAM_DMA_AHB_CBCR 0x0D44
+#define BAM_DMA_INACTIVITY_TIMERS_CBCR 0x0D48
#define MSG_RAM_AHB_CBCR 0x0E44
#define CE1_CBCR 0x1044
#define CE1_AXI_CBCR 0x1048
@@ -1002,6 +1004,18 @@
},
};
+static struct local_vote_clk gcc_bam_dma_inactivity_timers_clk = {
+ .cbcr_reg = BAM_DMA_INACTIVITY_TIMERS_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(11),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_bam_dma_inactivity_timers_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_bam_dma_inactivity_timers_clk.c),
+ },
+};
+
static struct local_vote_clk gcc_blsp1_ahb_clk = {
.cbcr_reg = BLSP1_AHB_CBCR,
.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
@@ -1517,6 +1531,17 @@
},
};
+static struct branch_clk gcc_usb_hsic_io_cal_sleep_clk = {
+ .cbcr_reg = USB_HSIC_IO_CAL_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb_hsic_io_cal_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb_hsic_io_cal_sleep_clk.c),
+ },
+};
+
static struct branch_clk gcc_usb_hsic_system_clk = {
.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
.bcr_reg = USB_HS_HSIC_BCR,
@@ -1554,6 +1579,7 @@
struct measure_mux_entry measure_mux_common[] __initdata = {
{&gcc_pdm_ahb_clk.c, GCC_BASE, 0x00d0},
+ {&gcc_usb_hsic_io_cal_sleep_clk.c, GCC_BASE, 0x005c},
{&gcc_usb_hsic_xcvr_fs_clk.c, GCC_BASE, 0x005d},
{&gcc_usb_hsic_system_clk.c, GCC_BASE, 0x0059},
{&gcc_usb_hsic_io_cal_clk.c, GCC_BASE, 0x005b},
@@ -1583,6 +1609,7 @@
{&gcc_sdcc2_apps_clk.c, GCC_BASE, 0x0070},
{&gcc_blsp1_uart1_apps_clk.c, GCC_BASE, 0x008c},
{&gcc_blsp1_qup4_i2c_apps_clk.c, GCC_BASE, 0x0099},
+ {&gcc_bam_dma_inactivity_timers_clk.c, GCC_BASE, 0x00E1},
{&gcc_boot_rom_ahb_clk.c, GCC_BASE, 0x00f8},
{&gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a},
{&gcc_pdm2_clk.c, GCC_BASE, 0x00d2},
@@ -1786,6 +1813,8 @@
CLK_LOOKUP("pll14", apcspll_clk_src.c, "f9010008.qcom,acpuclk"),
CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
+ CLK_LOOKUP("inactivity_clk", gcc_bam_dma_inactivity_timers_clk.c,
+ "msm_sps"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9924000.spi"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9925000.i2c"),
@@ -1842,6 +1871,8 @@
CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c, ""),
+ CLK_LOOKUP("inactivity_clk", gcc_usb_hsic_io_cal_sleep_clk.c,
+ "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "fd400000.qcom,qcedev"),
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "fd400000.qcom,qcedev"),
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 6240195..e5b9d93 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -36,7 +36,7 @@
#define EN_FEW_WAIT_VAL (0x8 << 16)
#define CLK_DIS_WAIT_VAL (0x2 << 12)
-#define TIMEOUT_US 10
+#define TIMEOUT_US 100
struct gdsc {
struct regulator_dev *rdev;
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 868fd1a..8afe695 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -377,6 +377,7 @@
static int destroy_region(struct ocmem_region *region)
{
+ idr_destroy(®ion->region_idr);
kfree(region);
return 0;
}
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 7f2f528..96122de 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -28,6 +28,7 @@
"3 Perf: Correct irq for CPU hotplug detection\n"
"4 Perf: Check perf activity on correct CPU\n"
"5 Perf: Add DT support for L1 and L2 PMU\n"
+ "6 Perf: Add cortex A5 device tree support\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 555ffa0..6f37608 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -270,6 +270,7 @@
unsigned char *hdlc_buf;
unsigned hdlc_count;
unsigned hdlc_escape;
+ int in_busy_pktdata;
#ifdef CONFIG_DIAG_OVER_USB
int usb_connected;
struct usb_diag_ch *legacy_ch;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index fb8efe4..a0c32f5 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1310,6 +1310,7 @@
COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
driver->pkt_length);
driver->data_ready[index] ^= PKT_TYPE;
+ driver->in_busy_pktdata = 0;
goto exit;
}
@@ -1397,6 +1398,117 @@
payload_size);
return err;
}
+ if (pkt_type == CALLBACK_DATA_TYPE) {
+ err = copy_from_user(driver->user_space_data, buf + 4,
+ payload_size);
+ if (err) {
+ pr_err("diag: copy failed for user space data\n");
+ return -EIO;
+ }
+ /* Check for proc_type */
+ remote_proc = diag_get_remote(*(int *)driver->user_space_data);
+
+ if (!remote_proc) {
+ wait_event_interruptible(driver->wait_q,
+ (driver->in_busy_pktdata == 0));
+ return diag_process_apps_pkt(driver->user_space_data,
+ payload_size);
+ }
+ /* The packet is for the remote processor */
+ token_offset = 4;
+ payload_size -= 4;
+ buf += 4;
+ /* Perform HDLC encoding on incoming data */
+ send.state = DIAG_STATE_START;
+ send.pkt = (void *)(driver->user_space_data + token_offset);
+ send.last = (void *)(driver->user_space_data + token_offset -
+ 1 + payload_size);
+ send.terminate = 1;
+
+ mutex_lock(&driver->diagchar_mutex);
+ if (!buf_hdlc)
+ buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
+ POOL_TYPE_HDLC);
+ if (!buf_hdlc) {
+ ret = -ENOMEM;
+ goto fail_free_hdlc;
+ }
+ if (HDLC_OUT_BUF_SIZE < (2 * payload_size) + 3) {
+ pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
+ ((2*payload_size) + 3));
+ driver->dropped_count++;
+ ret = -EBADMSG;
+ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
+ goto fail_free_hdlc;
+ }
+ enc.dest = buf_hdlc + driver->used;
+ enc.dest_last = (void *)(buf_hdlc + driver->used +
+ (2 * payload_size) + token_offset - 1);
+ diag_hdlc_encode(&send, &enc);
+
+#ifdef CONFIG_DIAG_SDIO_PIPE
+ /* send masks to 9k too */
+ if (driver->sdio_ch && (remote_proc == MDM)) {
+ wait_event_interruptible(driver->wait_q,
+ (sdio_write_avail(driver->sdio_ch) >=
+ payload_size));
+ if (driver->sdio_ch && (payload_size > 0)) {
+ sdio_write(driver->sdio_ch, (void *)
+ (char *)buf_hdlc, payload_size + 3);
+ }
+ }
+#endif
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ /* send masks to All 9k */
+ if ((remote_proc >= MDM) && (remote_proc <= MDM4)) {
+ index = remote_proc - MDM;
+ if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
+ /* wait sending mask updates
+ * if HSIC ch not ready */
+ if (diag_hsic[index].in_busy_hsic_write)
+ wait_event_interruptible(driver->wait_q,
+ (diag_hsic[index].
+ in_busy_hsic_write != 1));
+ diag_hsic[index].in_busy_hsic_write = 1;
+ diag_hsic[index].in_busy_hsic_read_on_device =
+ 0;
+ err = diag_bridge_write(index,
+ (char *)buf_hdlc, payload_size + 3);
+ if (err) {
+ pr_err("diag: err sending mask to MDM: %d\n",
+ err);
+ /*
+ * If the error is recoverable, then
+ * clear the write flag, so we will
+ * resubmit a write on the next frame.
+ * Otherwise, don't resubmit a write
+ * on the next frame.
+ */
+ if ((-ESHUTDOWN) != err)
+ diag_hsic[index].
+ in_busy_hsic_write = 0;
+ }
+ }
+ }
+ if (driver->diag_smux_enabled && (remote_proc == QSC)
+ && driver->lcid) {
+ if (payload_size > 0) {
+ err = msm_smux_write(driver->lcid, NULL,
+ (char *)buf_hdlc, payload_size + 3);
+ if (err) {
+ pr_err("diag:send mask to MDM err %d",
+ err);
+ ret = err;
+ }
+ }
+ }
+#endif
+ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
+ buf_hdlc = NULL;
+ driver->used = 0;
+ mutex_unlock(&driver->diagchar_mutex);
+ return ret;
+ }
if (pkt_type == USER_SPACE_DATA_TYPE) {
err = copy_from_user(driver->user_space_data, buf + 4,
payload_size);
@@ -1839,6 +1951,7 @@
driver->socket_process = NULL;
driver->callback_process = NULL;
driver->mask_check = 0;
+ driver->in_busy_pktdata = 0;
mutex_init(&driver->diagchar_mutex);
init_waitqueue_head(&driver->wait_q);
init_waitqueue_head(&driver->smd_wait_q);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index bb74370..5b929d7 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -641,9 +641,10 @@
unsigned char *temp = buf;
mutex_lock(&driver->diagchar_mutex);
- if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
+ if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length)) {
memcpy(ptr, temp , driver->pkt_length);
- else
+ driver->in_busy_pktdata = 1;
+ } else
printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
mutex_unlock(&driver->diagchar_mutex);
}
@@ -718,7 +719,7 @@
}
}
-static int diag_process_apps_pkt(unsigned char *buf, int len)
+int diag_process_apps_pkt(unsigned char *buf, int len)
{
uint16_t subsys_cmd_code;
int subsys_id, ssid_first, ssid_last, ssid_range;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 8cf15de..09f2f5e 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -48,6 +48,7 @@
int diag_command_reg(unsigned long);
void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode);
void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
+int diag_process_apps_pkt(unsigned char *buf, int len);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 4ddd78a..c3ff7dc 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -86,14 +86,15 @@
range = buf+HDR_SIZ+
sizeof(struct diag_ctrl_msg);
pkt_params->count = msg->count_entries;
- temp = kzalloc(pkt_params->count * sizeof(struct
- bindpkt_params), GFP_KERNEL);
- if (temp == NULL) {
+ pkt_params->params = kzalloc(pkt_params->count *
+ sizeof(struct bindpkt_params), GFP_KERNEL);
+ if (pkt_params->params == NULL) {
pr_alert("diag: In %s, Memory alloc fail\n",
__func__);
kfree(pkt_params);
return flag;
}
+ temp = pkt_params->params;
for (j = 0; j < pkt_params->count; j++) {
temp->cmd_code = msg->cmd_code;
temp->subsys_id = msg->subsysid;
@@ -104,8 +105,6 @@
range++;
temp++;
}
- temp -= pkt_params->count;
- pkt_params->params = temp;
flag = 1;
/* peripheral undergoing SSR should not
* record new registration
@@ -116,7 +115,7 @@
else
pr_err("diag: drop reg proc %d\n",
smd_info->peripheral);
- kfree(temp);
+ kfree(pkt_params->params);
} else if ((type == DIAG_CTRL_MSG_FEATURE) &&
(smd_info->peripheral == MODEM_DATA)) {
feature_mask_len = *(int *)(buf + 8);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 05c70a7..a2f0e60 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -667,6 +667,7 @@
/* RBBM_CLOCK_CTL default value */
#define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
+#define A305C_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 5130a09..6f7e61d 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -213,6 +213,9 @@
{ ADRENO_REV_A305B, 3, 0, 5, 0x10,
"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_128K, NO_VER, NO_VER },
+ { ADRENO_REV_A305C, 3, 0, 5, 0x20,
+ "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
+ 512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
};
/**
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 68133d4..90d6027 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -73,6 +73,7 @@
ADRENO_REV_A220 = 220,
ADRENO_REV_A225 = 225,
ADRENO_REV_A305 = 305,
+ ADRENO_REV_A305C = 306,
ADRENO_REV_A320 = 320,
ADRENO_REV_A330 = 330,
ADRENO_REV_A305B = 335,
@@ -367,6 +368,11 @@
return (adreno_dev->gpurev == ADRENO_REV_A305B);
}
+static inline int adreno_is_a305c(struct adreno_device *adreno_dev)
+{
+ return (adreno_dev->gpurev == ADRENO_REV_A305C);
+}
+
static inline int adreno_is_a320(struct adreno_device *adreno_dev)
{
return (adreno_dev->gpurev == ADRENO_REV_A320);
@@ -491,6 +497,7 @@
*cmds++ = 0;
if ((adreno_dev->gpurev == ADRENO_REV_A305) ||
+ (adreno_dev->gpurev == ADRENO_REV_A305C) ||
(adreno_dev->gpurev == ADRENO_REV_A320)) {
*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
*cmds++ = 0;
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index a825e90..19d9ca2 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -450,6 +450,8 @@
{
if (adreno_is_a305(adreno_dev))
return A305_RBBM_CLOCK_CTL_DEFAULT;
+ else if (adreno_is_a305c(adreno_dev))
+ return A305C_RBBM_CLOCK_CTL_DEFAULT;
else if (adreno_is_a320(adreno_dev))
return A320_RBBM_CLOCK_CTL_DEFAULT;
else if (adreno_is_a330v2(adreno_dev))
@@ -2964,6 +2966,19 @@
{0, 0},
};
+static struct a3xx_vbif_data a305c_vbif[] = {
+ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00101010 },
+ { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00101010 },
+ { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010 },
+ { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010 },
+ { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000101 },
+ { A3XX_VBIF_ARB_CTL, 0x00000010 },
+ /* Set up AOOO */
+ { A3XX_VBIF_OUT_AXI_AOOO_EN, 0x00000007 },
+ { A3XX_VBIF_OUT_AXI_AOOO, 0x00070007 },
+ {0, 0},
+};
+
static struct a3xx_vbif_data a320_vbif[] = {
/* Set up 16 deep read/write request queues */
{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 },
@@ -3035,6 +3050,7 @@
struct a3xx_vbif_data *vbif;
} a3xx_vbif_platforms[] = {
{ adreno_is_a305, a305_vbif },
+ { adreno_is_a305c, a305c_vbif },
{ adreno_is_a320, a320_vbif },
/* A330v2 needs to be ahead of A330 so the right device matches */
{ adreno_is_a330v2, a330v2_vbif },
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index b746671..8c23a13 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -430,7 +430,8 @@
return status;
/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
- if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
+ if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) ||
+ adreno_is_a320(adreno_dev))
adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev))
adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 202edc0..ac06fc5 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -61,6 +61,7 @@
#define WLED_MAX_CURR_MASK 0x19
#define WLED_OP_FDBCK_MASK 0x07
#define WLED_OP_FDBCK_BIT_SHFT 0x00
+#define WLED_OP_FDBCK_DEFAULT 0x00
#define WLED_MAX_LEVEL 4095
#define WLED_8_BIT_MASK 0xFF
@@ -90,6 +91,8 @@
#define FLASH_VREG_OK_FORCE(base) (base + 0x4F)
#define FLASH_ENABLE_CONTROL(base) (base + 0x46)
#define FLASH_LED_STROBE_CTRL(base) (base + 0x47)
+#define FLASH_LED_UNLOCK_SECURE(base) (base + 0xD0)
+#define FLASH_LED_TORCH(base) (base + 0xE4)
#define FLASH_MAX_LEVEL 0x4F
#define FLASH_NO_MASK 0x00
@@ -99,6 +102,7 @@
#define FLASH_HEADROOM_MASK 0x03
#define FLASH_SAFETY_TIMER_MASK 0x7F
#define FLASH_CURRENT_MASK 0xFF
+#define FLASH_MAX_CURRENT_MASK 0x7F
#define FLASH_TMR_MASK 0x03
#define FLASH_TMR_WATCHDOG 0x03
#define FLASH_TMR_SAFETY 0x00
@@ -117,17 +121,26 @@
#define FLASH_ENABLE_LED_1 0x20
#define FLASH_INIT_MASK 0xE0
-#define FLASH_STROBE_ALL 0xC0
-#define FLASH_STROBE_MASK 0xC0
+#define FLASH_STROBE_SW 0xC0
+#define FLASH_STROBE_HW 0xC4
+#define FLASH_STROBE_MASK 0xC7
#define FLASH_LED_0_OUTPUT 0x80
#define FLASH_LED_1_OUTPUT 0x40
#define FLASH_CURRENT_PRGM_MIN 1
#define FLASH_CURRENT_PRGM_SHIFT 1
+#define FLASH_CURRENT_MAX 0x4F
+#define FLASH_CURRENT_TORCH 0x0F
#define FLASH_DURATION_200ms 0x13
#define FLASH_CLAMP_200mA 0x0F
+#define FLASH_TORCH_MASK 0x03
+#define FLASH_LED_TORCH_ENABLE 0x00
+#define FLASH_LED_TORCH_DISABLE 0x03
+#define FLASH_UNLOCK_SECURE 0xA5
+#define FLASH_SECURE_MASK 0xFF
+
#define LED_TRIGGER_DEFAULT "none"
#define RGB_LED_SRC_SEL(base) (base + 0x45)
@@ -245,9 +258,9 @@
u8 cp_select;
u8 ctrl_delay_us;
u8 switch_freq;
+ u8 op_fdbck;
bool dig_mod_gen_en;
bool cs_out_en;
- bool op_fdbck;
};
/**
@@ -259,9 +272,11 @@
* @enable_module - enable address for particular flash
* @trigger_flash - trigger flash
* @startup_dly - startup delay for flash
+ * @strobe_type - select between sw and hw strobe
* @current_addr - address to write for current
* @second_addr - address of secondary flash to be written
* @safety_timer - enable safety timer or watchdog timer
+ * @torch_enable - enable flash LED torch mode
*/
struct flash_config_data {
u8 current_prgm;
@@ -271,9 +286,11 @@
u8 enable_module;
u8 trigger_flash;
u8 startup_dly;
+ u8 strobe_type;
u16 current_addr;
u16 second_addr;
bool safety_timer;
+ bool torch_enable;
};
/**
@@ -456,62 +473,176 @@
/* Set led current */
if (val > 0) {
- rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- return rc;
+ if (led->flash_cfg->torch_enable) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_UNLOCK_SECURE(led->base),
+ FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Secure reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_TORCH(led->base),
+ FLASH_TORCH_MASK, FLASH_LED_TORCH_ENABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Torch reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ qpnp_led_masked_write(led, FLASH_MAX_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Max current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->current_addr,
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->second_addr,
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "2nd Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
+ } else {
+ rc = qpnp_led_masked_write(led,
+ FLASH_MAX_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_MAX);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Max current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ /* Write 0x80 to MODULE_ENABLE before writing 0xE0
+ * in order to avoid reg value goes from 0x00 to
+ * 0xE0. This causes a hardware bug.
+ */
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->current_addr,
+ FLASH_CURRENT_MASK,
+ led->flash_cfg->current_prgm);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->second_addr,
+ FLASH_CURRENT_MASK,
+ led->flash_cfg->current_prgm);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "2nd Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_CLAMP_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Clamp Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK, FLASH_ENABLE_ALL);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
}
- rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
- FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Current reg write failed(%d)\n", rc);
- return rc;
- }
-
- rc = qpnp_led_masked_write(led, led->flash_cfg->second_addr,
- FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Current reg write failed(%d)\n", rc);
- return rc;
- }
-
- rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MASK,
- FLASH_ENABLE_ALL);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- return rc;
- }
- rc = qpnp_led_masked_write(led,
- FLASH_LED_STROBE_CTRL(led->base),
- FLASH_STROBE_MASK, FLASH_STROBE_ALL);
-
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "LED %d flash write failed(%d)\n", led->id, rc);
- return rc;
- }
- rc = qpnp_led_masked_write(led, FLASH_VREG_OK_FORCE(led->base),
- FLASH_VREG_MASK, FLASH_HW_VREG_OK);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Vreg OK reg write failed(%d)\n", rc);
- return rc;
+ if (!led->flash_cfg->strobe_type) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_STROBE_CTRL(led->base),
+ FLASH_STROBE_MASK, FLASH_STROBE_SW);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "LED %d strobe reg write failed(%d)\n",
+ led->id, rc);
+ return rc;
+ }
+ } else {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_STROBE_CTRL(led->base),
+ FLASH_STROBE_MASK, FLASH_STROBE_HW);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "LED %d strobe reg write failed(%d)\n",
+ led->id, rc);
+ return rc;
+ }
}
} else {
- rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MASK,
- FLASH_DISABLE_ALL);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- return rc;
+ if (led->flash_cfg->torch_enable) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_UNLOCK_SECURE(led->base),
+ FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Secure reg write failed(%d)\n", rc);
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_TORCH(led->base),
+ FLASH_TORCH_MASK, FLASH_LED_TORCH_DISABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Torch reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_SAFETY_TIMER(led->base),
+ FLASH_SAFETY_TIMER_MASK,
+ led->flash_cfg->duration);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Safety timer reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
}
rc = qpnp_led_masked_write(led,
@@ -523,6 +654,15 @@
"LED %d flash write failed(%d)\n", led->id, rc);
return rc;
}
+
+ rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK,
+ FLASH_DISABLE_ALL);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
}
qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
@@ -797,6 +937,66 @@
return 0;
}
+static ssize_t led_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct qpnp_led_data *led;
+ unsigned long state;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ /* '1' to enable torch mode; '0' to switch to flash mode */
+ if (state == 1)
+ led->flash_cfg->torch_enable = true;
+ else
+ led->flash_cfg->torch_enable = false;
+
+ return count;
+}
+
+static ssize_t led_strobe_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct qpnp_led_data *led;
+ unsigned long state;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ /* '0' for sw strobe; '1' for hw strobe */
+ if (state == 1)
+ led->flash_cfg->strobe_type = 1;
+ else
+ led->flash_cfg->strobe_type = 0;
+
+ return count;
+}
+
+static DEVICE_ATTR(led_mode, 0664, NULL, led_mode_store);
+static DEVICE_ATTR(strobe, 0664, NULL, led_strobe_type_store);
+
+static struct attribute *led_attrs[] = {
+ &dev_attr_led_mode.attr,
+ &dev_attr_strobe.attr,
+};
+
+static const struct attribute_group led_attr_group = {
+ .attrs = led_attrs,
+};
+
static int __devinit qpnp_flash_init(struct qpnp_led_data *led)
{
int rc;
@@ -890,7 +1090,7 @@
return rc;
}
- /* Set led current and enable module */
+ /* Set led current and disable module */
rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
if (rc) {
@@ -906,6 +1106,10 @@
"Enable reg write failed(%d)\n", rc);
return rc;
}
+
+ led->flash_cfg->torch_enable = false;
+ led->flash_cfg->strobe_type = 0;
+
/* dump flash registers */
qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
@@ -1099,6 +1303,13 @@
else if (rc != -EINVAL)
return rc;
+ led->wled_cfg->op_fdbck = WLED_OP_FDBCK_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,op-fdbck", &val);
+ if (!rc)
+ led->wled_cfg->op_fdbck = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
led->wled_cfg->switch_freq = WLED_SWITCH_FREQ_DEFAULT;
rc = of_property_read_u32(node, "qcom,switch-freq", &val);
if (!rc)
@@ -1112,9 +1323,6 @@
led->wled_cfg->cs_out_en =
of_property_read_bool(node, "qcom,cs-out-en");
- led->wled_cfg->op_fdbck =
- of_property_read_bool(node, "qcom,op-fdbck");
-
return 0;
}
@@ -1451,6 +1659,16 @@
led->id, rc);
goto fail_id_check;
}
+
+ if (led->id == QPNP_ID_FLASH1_LED0 ||
+ led->id == QPNP_ID_FLASH1_LED1) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &led_attr_group);
+ if (rc)
+ goto fail_id_check;
+
+ }
+
/* configure default state */
if (led->default_on) {
led->cdev.brightness = led->cdev.max_brightness;
@@ -1477,8 +1695,26 @@
struct qpnp_led_data *led_array = dev_get_drvdata(&spmi->dev);
int i, parsed_leds = led_array->num_leds;
- for (i = 0; i < parsed_leds; i++)
+ for (i = 0; i < parsed_leds; i++) {
led_classdev_unregister(&led_array[i].cdev);
+ switch (led_array[i].id) {
+ case QPNP_ID_WLED:
+ break;
+ case QPNP_ID_FLASH1_LED0:
+ case QPNP_ID_FLASH1_LED1:
+ sysfs_remove_group(&led_array[i].cdev.dev->kobj,
+ &led_attr_group);
+ break;
+ case QPNP_ID_RGB_RED:
+ case QPNP_ID_RGB_GREEN:
+ case QPNP_ID_RGB_BLUE:
+ default:
+ dev_err(&led_array[i].spmi_dev->dev,
+ "Invalid LED(%d)\n",
+ led_array[i].id);
+ return -EINVAL;
+ }
+ }
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 2a0cde9..0fef315 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1876,13 +1876,13 @@
if (dvbdemux->dmx.debugfs_demux_dir != NULL) {
debugfs_create_u32(
"total_processing_time",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_process_time);
debugfs_create_u32(
"total_crc_time",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_crc_time);
}
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 85788e9..22ce35b 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -78,7 +78,7 @@
{"camss_csi_vfe_clk1", -1},
};
-static int msm_ispif_clk_enable(struct ispif_device *ispif,
+static int msm_ispif_clk_enable_one(struct ispif_device *ispif,
enum msm_ispif_vfe_intf vfe_intf, int enable)
{
int rc = 0;
@@ -119,8 +119,8 @@
ARRAY_SIZE(ispif_8974_clk_info_vfe1), enable);
}
if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
+ pr_err("%s: cannot enable clock, error = %d, vfeid = %d\n",
+ __func__, rc, vfe_intf);
goto end;
}
} else {
@@ -133,17 +133,56 @@
return rc;
}
+static int msm_ispif_clk_enable(struct ispif_device *ispif,
+ struct msm_ispif_param_data *params, int enable)
+{
+ int rc = 0;
+ int i, j;
+ uint32_t vfe_intf_mask = 0;
+
+ for (i = 0; i < params->num; i++) {
+ if (vfe_intf_mask & (1 << params->entries[i].vfe_intf))
+ continue;
+ rc = msm_ispif_clk_enable_one(ispif,
+ params->entries[i].vfe_intf, 1);
+ if (rc < 0 && enable) {
+ pr_err("%s: unable to enable clocks for VFE %d",
+ __func__, params->entries[i].vfe_intf);
+ for (j = 0; j < i; j++) {
+ /* if VFE clock is not enabled do
+ * not disable the clock */
+ if (!(vfe_intf_mask & (1 <<
+ params->entries[i].vfe_intf)))
+ continue;
+ msm_ispif_clk_enable_one(ispif,
+ params->entries[j].vfe_intf, 0);
+ /* remove the VFE ID from the mask */
+ vfe_intf_mask &=
+ ~(1 << params->entries[i].vfe_intf);
+ }
+ break;
+ }
+ vfe_intf_mask |= 1 << params->entries[i].vfe_intf;
+ }
+ return rc;
+}
+
static int msm_ispif_intf_reset(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
int i, rc = 0;
enum msm_ispif_intftype intf_type;
- uint32_t data = STROBED_RST_EN;
+ int vfe_intf = 0;
+ uint32_t data = 0;
for (i = 0; i < params->num; i++) {
+ data = STROBED_RST_EN;
+ vfe_intf = params->entries[i].vfe_intf;
intf_type = params->entries[i].intftype;
- ispif->sof_count[params->vfe_intf].sof_cnt[intf_type] = 0;
+ ispif->sof_count[params->entries[i].vfe_intf].
+ sof_cnt[intf_type] = 0;
+
switch (intf_type) {
case PIX0:
data |= (PIX_0_VFE_RST_STB | PIX_0_CSID_RST_STB);
@@ -164,35 +203,40 @@
rc = -EINVAL;
break;
}
- }
- if (data > 0x1) {
- unsigned long jiffes = msecs_to_jiffies(500);
- long lrc = 0;
- unsigned long flags;
+ if (data > 0x1) {
+ unsigned long jiffes = msecs_to_jiffies(500);
+ long lrc = 0;
+ unsigned long flags;
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[params->vfe_intf] = 0;
- init_completion(&ispif->reset_complete[params->vfe_intf]);
- spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
-
- if (params->vfe_intf == VFE0)
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- else
- msm_camera_io_w(data, ispif->base +
- ISPIF_RST_CMD_1_ADDR);
-
- lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete[params->vfe_intf], jiffes);
- if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
- rc = -EIO;
-
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[params->vfe_intf] = 1;
+ spin_lock_irqsave(
+ &ispif->auto_complete_lock, flags);
+ ispif->wait_timeout[vfe_intf] = 0;
+ init_completion(&ispif->reset_complete[vfe_intf]);
spin_unlock_irqrestore(
&ispif->auto_complete_lock, flags);
+
+ if (vfe_intf == VFE0)
+ msm_camera_io_w(data, ispif->base +
+ ISPIF_RST_CMD_ADDR);
+ else
+ msm_camera_io_w(data, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
+ lrc = wait_for_completion_interruptible_timeout(
+ &ispif->reset_complete[vfe_intf], jiffes);
+ if (lrc < 0 || !lrc) {
+ pr_err("%s: wait timeout ret = %ld, vfe_id = %d\n",
+ __func__, lrc, vfe_intf);
+ rc = -EIO;
+
+ spin_lock_irqsave(
+ &ispif->auto_complete_lock, flags);
+ ispif->wait_timeout[vfe_intf] = 1;
+ spin_unlock_irqrestore(
+ &ispif->auto_complete_lock, flags);
+ }
}
}
+
return rc;
}
@@ -223,7 +267,8 @@
&ispif->reset_complete[VFE0], jiffes);
if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+ pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
+ __func__, lrc, VFE0);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -242,7 +287,8 @@
&ispif->reset_complete[VFE1], jiffes);
if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+ pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
+ __func__, lrc, VFE1);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -320,6 +366,36 @@
ISPIF_VFE_m_INPUT_SEL(vfe_intf));
}
+static void msm_ispif_enable_crop(struct ispif_device *ispif,
+ uint8_t intftype, uint8_t vfe_intf, uint16_t start_pixel,
+ uint16_t end_pixel)
+{
+ uint32_t data;
+ BUG_ON(!ispif);
+
+ if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return;
+ }
+
+ data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
+ data |= (1 << (intftype + 7));
+ msm_camera_io_w(data,
+ ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
+
+ if (intftype == PIX0)
+ msm_camera_io_w_mb(start_pixel | (end_pixel << 16),
+ ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 0));
+ else if (intftype == PIX1)
+ msm_camera_io_w_mb(start_pixel | (end_pixel << 16),
+ ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 1));
+ else {
+ pr_err("%s: invalid intftype=%d\n", __func__, intftype);
+ BUG_ON(1);
+ return;
+ }
+}
+
static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable)
{
@@ -427,28 +503,30 @@
BUG_ON(!ispif);
BUG_ON(!params);
- vfe_intf = params->vfe_intf;
-
- rc = msm_ispif_clk_enable(ispif, vfe_intf, 1);
+ rc = msm_ispif_clk_enable(ispif, params, 1);
if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- vfe_intf);
+ pr_err("%s: unable to enable clocks", __func__);
return rc;
}
-
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return -EINVAL;
+ for (i = 0; i < params->num; i++) {
+ vfe_intf = params->entries[i].vfe_intf;
+ if (!msm_ispif_is_intf_valid(ispif->csid_version,
+ vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return -EINVAL;
+ }
+ msm_camera_io_w(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
+ msm_camera_io_w(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
+ msm_camera_io_w_mb(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
}
- msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
- msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
- msm_camera_io_w_mb(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
-
for (i = 0; i < params->num; i++) {
intftype = params->entries[i].intftype;
- vfe_intf = params->vfe_intf;
+ vfe_intf = params->entries[i].vfe_intf;
CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
intftype, vfe_intf, params->entries[i].csid);
@@ -475,31 +553,36 @@
¶ms->entries[i]);
msm_ispif_enable_intf_cids(ispif, intftype,
cid_mask, vfe_intf, 1);
+ if (params->entries[i].crop_enable)
+ msm_ispif_enable_crop(ispif, intftype, vfe_intf,
+ params->entries[i].crop_start_pixel,
+ params->entries[i].crop_end_pixel);
}
- msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
+ for (vfe_intf = 0; vfe_intf < 2; vfe_intf++) {
+ msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf));
+ }
msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
-
- rc = msm_ispif_clk_enable(ispif, vfe_intf, 0);
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -511,18 +594,22 @@
int i, k;
enum msm_ispif_intftype intf_type;
enum msm_ispif_cid cid;
- enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
+ enum msm_ispif_vfe_intf vfe_intf;
BUG_ON(!ispif);
BUG_ON(!params);
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return;
+ for (i = 0; i < params->num; i++) {
+ vfe_intf = params->entries[i].vfe_intf;
+ if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return;
+ }
}
for (i = 0; i < params->num; i++) {
intf_type = params->entries[i].intftype;
+ vfe_intf = params->entries[i].vfe_intf;
for (k = 0; k < params->entries[i].num_cids; k++) {
cid = params->entries[i].cids[k];
vc = cid % 4;
@@ -542,16 +629,19 @@
(cmd_bits << (vc * 2 + intf_type * 8));
}
}
+
+ /* cmd for PIX0, PIX1, RDI0, RDI1 */
+ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF)
+ msm_camera_io_w_mb(
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf));
+
+ /* cmd for RDI2 */
+ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
+ msm_camera_io_w_mb(
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf));
}
- /* cmd for PIX0, PIX1, RDI0, RDI1 */
- if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF) {
- msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd,
- ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf));
- }
- /* cmd for RDI2 */
- if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
- msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
- ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf));
}
static int msm_ispif_stop_immediately(struct ispif_device *ispif,
@@ -570,7 +660,7 @@
cid_mask = msm_ispif_get_cids_mask_from_cfg(
¶ms->entries[i]);
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
- cid_mask, params->vfe_intf, 0);
+ cid_mask, params->entries[i].vfe_intf, 0);
}
return rc;
@@ -581,10 +671,9 @@
{
int rc;
- rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
+ rc = msm_ispif_clk_enable(ispif, params, 1);
if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- params->vfe_intf);
+ pr_err("%s: unable to enable clocks", __func__);
return rc;
}
@@ -592,13 +681,13 @@
if (rc) {
pr_err("%s: msm_ispif_intf_reset failed. rc=%d\n",
__func__, rc);
- return rc;
+ goto end;
}
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
- msm_ispif_clk_enable(ispif, params->vfe_intf, 0);
-
+end:
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -613,18 +702,20 @@
BUG_ON(!ispif);
BUG_ON(!params);
- vfe_intf = params->vfe_intf;
- rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
+ rc = msm_ispif_clk_enable(ispif, params, 1);
if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- params->vfe_intf);
+ pr_err("%s: unable to enable clocks", __func__);
return rc;
}
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return -EINVAL;
+ for (i = 0; i < params->num; i++) {
+ if (!msm_ispif_is_intf_valid(ispif->csid_version,
+ params->entries[i].vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
}
msm_ispif_intf_cmd(ispif,
@@ -633,6 +724,7 @@
for (i = 0; i < params->num; i++) {
cid_mask =
msm_ispif_get_cids_mask_from_cfg(¶ms->entries[i]);
+ vfe_intf = params->entries[i].vfe_intf;
switch (params->entries[i].intftype) {
case PIX0:
@@ -653,7 +745,8 @@
default:
pr_err("%s: invalid intftype=%d\n", __func__,
params->entries[i].intftype);
- return -EPERM;
+ rc = -EPERM;
+ goto end;
}
/* todo_bug_fix? very bad. use readl_poll_timeout */
@@ -666,7 +759,8 @@
cid_mask, vfe_intf, 0);
}
- msm_ispif_clk_enable(ispif, vfe_intf, 0);
+end:
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -718,6 +812,25 @@
msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2,
ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE0));
+ if (ispif->vfe_info.num_vfe > 1) {
+ out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_0(VFE1));
+ msm_camera_io_w(out[VFE1].ispifIrqStatus0,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1));
+
+ out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_1(VFE1));
+ msm_camera_io_w(out[VFE1].ispifIrqStatus1,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1));
+
+ out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_2(VFE1));
+ msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1));
+ }
+ msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+
if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ) {
unsigned long flags;
@@ -742,24 +855,7 @@
ispif_process_irq(ispif, out, VFE0);
}
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1) {
- out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_0(VFE1));
- msm_camera_io_w(out[VFE1].ispifIrqStatus0,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1));
-
- out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_1(VFE1));
- msm_camera_io_w(out[VFE1].ispifIrqStatus1,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1));
-
- out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_2(VFE1));
- msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1));
-
-
+ if (ispif->vfe_info.num_vfe > 1) {
if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ) {
unsigned long flags;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -783,8 +879,6 @@
ispif_process_irq(ispif, out, VFE1);
}
- msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
- ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
@@ -825,7 +919,7 @@
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
ispif->csid_version = csid_version;
- rc = msm_ispif_clk_enable(ispif, VFE0, 1);
+ rc = msm_ispif_clk_enable_one(ispif, VFE0, 1);
if (rc < 0) {
pr_err("%s: unable to enable clocks for VFE0", __func__);
goto error_clk0;
@@ -833,7 +927,7 @@
if (ispif->csid_version >= CSID_VERSION_V3 &&
ispif->vfe_info.num_vfe > 1) {
- rc = msm_ispif_clk_enable(ispif, VFE1, 1);
+ rc = msm_ispif_clk_enable_one(ispif, VFE1, 1);
if (rc < 0) {
pr_err("%s: unable to enable clocks for VFE1",
__func__);
@@ -868,10 +962,10 @@
end:
if (ispif->csid_version >= CSID_VERSION_V3 &&
ispif->vfe_info.num_vfe > 1)
- msm_ispif_clk_enable(ispif, VFE1, 0);
+ msm_ispif_clk_enable_one(ispif, VFE1, 0);
error_clk1:
- msm_ispif_clk_enable(ispif, VFE0, 0);
+ msm_ispif_clk_enable_one(ispif, VFE0, 0);
error_clk0:
return rc;
@@ -889,7 +983,7 @@
}
for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable(ispif, i, 1);
+ msm_ispif_clk_enable_one(ispif, i, 1);
/* make sure no streaming going on */
msm_ispif_reset(ispif);
@@ -899,7 +993,7 @@
iounmap(ispif->base);
for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable(ispif, i, 0);
+ msm_ispif_clk_enable_one(ispif, i, 0);
ispif->ispif_state = ISPIF_POWER_DOWN;
}
@@ -961,7 +1055,7 @@
case VIDIOC_MSM_ISPIF_CFG:
return msm_ispif_cmd(sd, arg);
default:
- pr_err("%s: invalid cmd received\n", __func__);
+ pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd);
return -ENOIOCTLCMD;
}
}
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index fbc2b93..e50ac3a 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -277,6 +277,7 @@
{
struct msm_session *session = NULL;
struct msm_stream *stream = NULL;
+ unsigned long flags;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
@@ -287,9 +288,10 @@
list, __msm_queue_find_stream, &stream_id);
if (!stream)
return;
-
+ spin_lock_irqsave(&(session->stream_q.lock), flags);
list_del_init(&stream->list);
session->stream_q.len--;
+ spin_unlock_irqrestore(&(session->stream_q.lock), flags);
kzfree(stream);
}
@@ -426,6 +428,7 @@
{
struct msm_session *session;
struct msm_command_ack *cmd_ack;
+ unsigned long flags;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
@@ -439,6 +442,11 @@
return;
msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
+
+ spin_lock_irqsave(&(session->command_ack_q.lock), flags);
+ list_del_init(&cmd_ack->list);
+ session->command_ack_q.len--;
+ spin_unlock_irqrestore(&(session->command_ack_q.lock), flags);
}
static inline int __msm_v4l2_subdev_shutdown(struct v4l2_subdev *sd)
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 8a21512..35210a0 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -13,9 +13,15 @@
static struct msm_buf_mngr_device *msm_buf_mngr_dev;
+struct v4l2_subdev *msm_buf_mngr_get_subdev(void)
+{
+ return &msm_buf_mngr_dev->subdev.sd;
+}
+
static int msm_buf_mngr_get_buf(struct msm_buf_mngr_device *buf_mngr_dev,
void __user *argp)
{
+ unsigned long flags;
struct msm_buf_mngr_info *buf_info =
(struct msm_buf_mngr_info *)argp;
struct msm_get_bufs *new_entry =
@@ -35,9 +41,9 @@
}
new_entry->session_id = buf_info->session_id;
new_entry->stream_id = buf_info->stream_id;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_add_tail(&new_entry->entry, &buf_mngr_dev->buf_qhead);
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
buf_info->index = new_entry->vb2_buf->v4l2_buf.index;
return 0;
}
@@ -45,10 +51,11 @@
static int msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev,
struct msm_buf_mngr_info *buf_info)
{
+ unsigned long flags;
struct msm_get_bufs *bufs, *save;
int ret = -EINVAL;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_for_each_entry_safe(bufs, save, &buf_mngr_dev->buf_qhead, entry) {
if ((bufs->session_id == buf_info->session_id) &&
(bufs->stream_id == buf_info->stream_id) &&
@@ -64,7 +71,7 @@
break;
}
}
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
return ret;
}
@@ -72,10 +79,11 @@
static int msm_buf_mngr_put_buf(struct msm_buf_mngr_device *buf_mngr_dev,
struct msm_buf_mngr_info *buf_info)
{
+ unsigned long flags;
struct msm_get_bufs *bufs, *save;
int ret = -EINVAL;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_for_each_entry_safe(bufs, save, &buf_mngr_dev->buf_qhead, entry) {
if ((bufs->session_id == buf_info->session_id) &&
(bufs->stream_id == buf_info->stream_id) &&
@@ -87,7 +95,7 @@
break;
}
}
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
return ret;
}
@@ -163,14 +171,13 @@
&msm_buf_mngr_dev->vb2_ops);
INIT_LIST_HEAD(&msm_buf_mngr_dev->buf_qhead);
- mutex_init(&msm_buf_mngr_dev->buf_q_lock);
+ spin_lock_init(&msm_buf_mngr_dev->buf_q_spinlock);
end:
return rc;
}
static void __exit msm_buf_mngr_exit(void)
{
- mutex_destroy(&msm_buf_mngr_dev->buf_q_lock);
kfree(msm_buf_mngr_dev);
}
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
index a2b3a7e..56886cd 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
@@ -33,7 +33,7 @@
struct msm_buf_mngr_device {
struct list_head buf_qhead;
- struct mutex buf_q_lock;
+ spinlock_t buf_q_spinlock;
struct msm_sd_subdev subdev;
struct msm_sd_req_vb2_q vb2_ops;
};
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 8f63d33..c06b009 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -22,7 +22,6 @@
#include <linux/regulator/consumer.h>
#include <linux/ion.h>
#include <linux/proc_fs.h>
-#include <linux/debugfs.h>
#include <linux/msm_ion.h>
#include <linux/iommu.h>
#include <mach/iommu_domains.h>
@@ -33,11 +32,14 @@
#include <media/v4l2-ioctl.h>
#include <media/msmb_camera.h>
#include <media/msmb_pproc.h>
+#include <media/msmb_generic_buf_mgr.h>
#include "msm_cpp.h"
#include "msm_camera_io_util.h"
#define MSM_CPP_DRV_NAME "msm_cpp"
+#define MSM_CPP_MAX_BUFF_QUEUE 16
+
#define CONFIG_MSM_CPP_DBG 0
#if CONFIG_MSM_CPP_DBG
@@ -126,6 +128,278 @@
return tmp;
}
+static struct msm_cpp_buff_queue_info_t *msm_cpp_get_buff_queue_entry(
+ struct cpp_device *cpp_dev, uint32_t session_id, uint32_t stream_id)
+{
+ uint32_t i = 0;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info = NULL;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if ((cpp_dev->buff_queue[i].used == 1) &&
+ (cpp_dev->buff_queue[i].session_id == session_id) &&
+ (cpp_dev->buff_queue[i].stream_id == stream_id)) {
+ buff_queue_info = &cpp_dev->buff_queue[i];
+ break;
+ }
+ }
+
+ if (buff_queue_info == NULL) {
+ pr_err("error buffer queue entry for sess:%d strm:%d not found\n",
+ session_id, stream_id);
+ }
+ return buff_queue_info;
+}
+
+static unsigned long msm_cpp_get_phy_addr(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue_info, uint32_t buff_index,
+ uint8_t native_buff)
+{
+ unsigned long phy_add = 0;
+ struct list_head *buff_head;
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+
+ if (native_buff)
+ buff_head = &buff_queue_info->native_buff_head;
+ else
+ buff_head = &buff_queue_info->vb2_buff_head;
+
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ if (buff->map_info.buff_info.index == buff_index) {
+ phy_add = buff->map_info.phy_addr;
+ break;
+ }
+ }
+
+ return phy_add;
+}
+
+static unsigned long msm_cpp_queue_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue,
+ struct msm_cpp_buffer_info_t *buffer_info)
+{
+ struct list_head *buff_head;
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+ int rc = 0;
+
+ if (buffer_info->native_buff)
+ buff_head = &buff_queue->native_buff_head;
+ else
+ buff_head = &buff_queue->vb2_buff_head;
+
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ if (buff->map_info.buff_info.index == buffer_info->index) {
+ pr_err("error buffer index already queued\n");
+ return -EINVAL;
+ }
+ }
+
+ buff = kzalloc(
+ sizeof(struct msm_cpp_buffer_map_list_t), GFP_KERNEL);
+ if (!buff) {
+ pr_err("error allocating memory\n");
+ return -EINVAL;
+ }
+
+ buff->map_info.buff_info = *buffer_info;
+ buff->map_info.ion_handle = ion_import_dma_buf(cpp_dev->client,
+ buffer_info->fd);
+ if (IS_ERR_OR_NULL(buff->map_info.ion_handle)) {
+ pr_err("ION import failed\n");
+ goto QUEUE_BUFF_ERROR1;
+ }
+
+ rc = ion_map_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0, SZ_4K, 0,
+ (unsigned long *)&buff->map_info.phy_addr,
+ &buff->map_info.len, 0, 0);
+ if (rc < 0) {
+ pr_err("ION mmap failed\n");
+ goto QUEUE_BUFF_ERROR2;
+ }
+
+ INIT_LIST_HEAD(&buff->entry);
+ list_add_tail(&buff->entry, buff_head);
+
+ return buff->map_info.phy_addr;
+
+QUEUE_BUFF_ERROR2:
+ ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0);
+QUEUE_BUFF_ERROR1:
+ ion_free(cpp_dev->client, buff->map_info.ion_handle);
+ buff->map_info.ion_handle = NULL;
+ kzfree(buff);
+
+ return 0;
+}
+
+static void msm_cpp_dequeue_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buffer_map_list_t *buff)
+{
+ ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0);
+ ion_free(cpp_dev->client, buff->map_info.ion_handle);
+ buff->map_info.ion_handle = NULL;
+
+ list_del_init(&buff->entry);
+ kzfree(buff);
+
+ return;
+}
+
+static unsigned long msm_cpp_fetch_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buffer_info_t *buffer_info, uint32_t session_id,
+ uint32_t stream_id)
+{
+ unsigned long phy_addr = 0;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+ uint8_t native_buff = buffer_info->native_buff;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev, session_id,
+ stream_id);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ session_id, stream_id);
+ return phy_addr;
+ }
+
+ phy_addr = msm_cpp_get_phy_addr(cpp_dev, buff_queue_info,
+ buffer_info->index, native_buff);
+ if ((phy_addr == 0) && (native_buff)) {
+ phy_addr = msm_cpp_queue_buffer_info(cpp_dev, buff_queue_info,
+ buffer_info);
+ }
+ return phy_addr;
+}
+
+static int32_t msm_cpp_enqueue_buff_info_list(struct cpp_device *cpp_dev,
+ struct msm_cpp_stream_buff_info_t *stream_buff_info)
+{
+ uint32_t j;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev,
+ (stream_buff_info->identity >> 16) & 0xFFFF,
+ stream_buff_info->identity & 0xFFFF);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ (stream_buff_info->identity >> 16) & 0xFFFF,
+ stream_buff_info->identity & 0xFFFF);
+ return -EINVAL;
+ }
+
+ for (j = 0; j < stream_buff_info->num_buffs; j++) {
+ msm_cpp_queue_buffer_info(cpp_dev, buff_queue_info,
+ &stream_buff_info->buffer_info[j]);
+ }
+ return 0;
+}
+
+static int32_t msm_cpp_dequeue_buff_info_list(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue_info)
+{
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+ struct list_head *buff_head;
+
+ buff_head = &buff_queue_info->native_buff_head;
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ }
+
+ buff_head = &buff_queue_info->vb2_buff_head;
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ }
+
+ return 0;
+}
+
+static int32_t msm_cpp_add_buff_queue_entry(struct cpp_device *cpp_dev,
+ uint16_t session_id, uint16_t stream_id)
+{
+ uint32_t i;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if (cpp_dev->buff_queue[i].used == 0) {
+ buff_queue_info = &cpp_dev->buff_queue[i];
+ buff_queue_info->used = 1;
+ buff_queue_info->session_id = session_id;
+ buff_queue_info->stream_id = stream_id;
+ INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+ INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+ return 0;
+ }
+ }
+ pr_err("buffer queue full. error for sessionid: %d streamid: %d\n",
+ session_id, stream_id);
+ return -EINVAL;
+}
+
+static int32_t msm_cpp_free_buff_queue_entry(struct cpp_device *cpp_dev,
+ uint32_t session_id, uint32_t stream_id)
+{
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev, session_id,
+ stream_id);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ session_id, stream_id);
+ return -EINVAL;
+ }
+
+ buff_queue_info->used = 0;
+ buff_queue_info->session_id = 0;
+ buff_queue_info->stream_id = 0;
+ INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+ INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+ return 0;
+}
+
+static int32_t msm_cpp_create_buff_queue(struct cpp_device *cpp_dev,
+ uint32_t num_buffq)
+{
+ struct msm_cpp_buff_queue_info_t *buff_queue;
+ buff_queue = kzalloc(
+ sizeof(struct msm_cpp_buff_queue_info_t) * num_buffq,
+ GFP_KERNEL);
+ if (!buff_queue) {
+ pr_err("Buff queue allocation failure\n");
+ return -ENOMEM;
+ }
+
+ if (cpp_dev->buff_queue) {
+ pr_err("Buff queue not empty\n");
+ kzfree(buff_queue);
+ return -EINVAL;
+ } else {
+ cpp_dev->buff_queue = buff_queue;
+ cpp_dev->num_buffq = num_buffq;
+ }
+ return 0;
+}
+
+static void msm_cpp_delete_buff_queue(struct cpp_device *cpp_dev)
+{
+ uint32_t i;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if (cpp_dev->buff_queue[i].used == 1) {
+ pr_err("Queue not free sessionid: %d, streamid: %d\n",
+ cpp_dev->buff_queue[i].session_id,
+ cpp_dev->buff_queue[i].stream_id);
+ msm_cpp_free_buff_queue_entry(cpp_dev,
+ cpp_dev->buff_queue[i].session_id,
+ cpp_dev->buff_queue[i].stream_id);
+ }
+ }
+ kzfree(cpp_dev->buff_queue);
+ cpp_dev->buff_queue = NULL;
+ cpp_dev->num_buffq = 0;
+ return;
+}
+
static void msm_cpp_poll(void __iomem *cpp_base, u32 val)
{
uint32_t tmp, retry = 0;
@@ -176,12 +450,13 @@
static irqreturn_t msm_cpp_irq(int irq_num, void *data)
{
+ unsigned long flags;
uint32_t tx_level;
uint32_t irq_status;
- uint32_t msg_id, cmd_len;
uint32_t i;
- uint32_t tx_fifo[16];
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
struct cpp_device *cpp_dev = data;
+ struct msm_cpp_tasklet_queue_cmd *queue_cmd;
irq_status = msm_camera_io_r(cpp_dev->base + MSM_CPP_MICRO_IRQGEN_STAT);
CPP_DBG("status: 0x%x\n", irq_status);
if (irq_status & 0x8) {
@@ -192,6 +467,62 @@
MSM_CPP_MICRO_FIFO_TX_DATA);
}
+ spin_lock_irqsave(&cpp_dev->tasklet_lock, flags);
+ queue_cmd = &cpp_dev->tasklet_queue_cmd[cpp_dev->taskletq_idx];
+ if (queue_cmd->cmd_used) {
+ pr_err("%s: cpp tasklet queue overflow\n", __func__);
+ list_del(&queue_cmd->list);
+ } else {
+ atomic_add(1, &cpp_dev->irq_cnt);
+ }
+ queue_cmd->irq_status = irq_status;
+ queue_cmd->tx_level = tx_level;
+ memset(&queue_cmd->tx_fifo[0], 0, sizeof(queue_cmd->tx_fifo));
+ for (i = 0; i < tx_level; i++)
+ queue_cmd->tx_fifo[i] = tx_fifo[i];
+
+ queue_cmd->cmd_used = 1;
+ cpp_dev->taskletq_idx =
+ (cpp_dev->taskletq_idx + 1) % MSM_CPP_TASKLETQ_SIZE;
+ list_add_tail(&queue_cmd->list, &cpp_dev->tasklet_q);
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+
+ tasklet_schedule(&cpp_dev->cpp_tasklet);
+ }
+ msm_camera_io_w(irq_status, cpp_dev->base + MSM_CPP_MICRO_IRQGEN_CLR);
+ return IRQ_HANDLED;
+}
+
+void msm_cpp_do_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ uint32_t irq_status;
+ uint32_t tx_level;
+ uint32_t msg_id, cmd_len;
+ uint32_t i;
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
+ struct cpp_device *cpp_dev = (struct cpp_device *) data;
+ struct msm_cpp_tasklet_queue_cmd *queue_cmd;
+
+ while (atomic_read(&cpp_dev->irq_cnt)) {
+ spin_lock_irqsave(&cpp_dev->tasklet_lock, flags);
+ queue_cmd = list_first_entry(&cpp_dev->tasklet_q,
+ struct msm_cpp_tasklet_queue_cmd, list);
+ if (!queue_cmd) {
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+ return;
+ }
+ atomic_sub(1, &cpp_dev->irq_cnt);
+ list_del(&queue_cmd->list);
+ queue_cmd->cmd_used = 0;
+ irq_status = queue_cmd->irq_status;
+ tx_level = queue_cmd->tx_level;
+ for (i = 0; i < tx_level; i++)
+ tx_fifo[i] = queue_cmd->tx_fifo[i];
+
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+
for (i = 0; i < tx_level; i++) {
if (tx_fifo[i] == MSM_CPP_MSG_ID_CMD) {
cmd_len = tx_fifo[i+1];
@@ -204,8 +535,6 @@
}
}
}
- msm_camera_io_w(irq_status, cpp_dev->base + MSM_CPP_MICRO_IRQGEN_CLR);
- return IRQ_HANDLED;
}
static void msm_cpp_boot_hw(struct cpp_device *cpp_dev)
@@ -309,6 +638,7 @@
rc = -EBUSY;
goto req_irq_fail;
}
+ cpp_dev->buf_mgr_subdev = msm_buf_mngr_get_subdev();
}
cpp_dev->hw_info.cpp_hw_version =
@@ -318,6 +648,9 @@
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x4);
pr_debug("CPP HW Caps: 0x%x\n", cpp_dev->hw_info.cpp_hw_caps);
msm_camera_io_w(0x1, cpp_dev->vbif_base + 0x4);
+ cpp_dev->taskletq_idx = 0;
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ msm_cpp_create_buff_queue(cpp_dev, MSM_CPP_MAX_BUFF_QUEUE);
if (cpp_dev->is_firmware_loaded == 1)
msm_cpp_boot_hw(cpp_dev);
return rc;
@@ -339,9 +672,12 @@
static void cpp_release_hardware(struct cpp_device *cpp_dev)
{
- if (cpp_dev->state != CPP_STATE_BOOT)
+ if (cpp_dev->state != CPP_STATE_BOOT) {
free_irq(cpp_dev->irq->start, cpp_dev);
-
+ tasklet_kill(&cpp_dev->cpp_tasklet);
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ }
+ msm_cpp_delete_buff_queue(cpp_dev);
iounmap(cpp_dev->base);
iounmap(cpp_dev->vbif_base);
iounmap(cpp_dev->cpp_hw_base);
@@ -504,6 +840,18 @@
.close = cpp_close_node,
};
+static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev,
+ uint32_t buff_mgr_ops, struct msm_buf_mngr_info *buff_mgr_info)
+{
+ int rc = -EINVAL;
+
+ rc = v4l2_subdev_call(cpp_dev->buf_mgr_subdev, core, ioctl,
+ buff_mgr_ops, buff_mgr_info);
+ if (rc < 0)
+ pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+ return rc;
+}
+
static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev)
{
struct v4l2_event v4l2_evt;
@@ -511,10 +859,13 @@
struct msm_queue_cmd *event_qcmd;
struct msm_cpp_frame_info_t *processed_frame;
struct msm_device_queue *queue = &cpp_dev->processing_q;
+ struct msm_buf_mngr_info buff_mgr_info;
+ int rc = 0;
if (queue->len > 0) {
frame_qcmd = msm_dequeue(queue, list_frame);
processed_frame = frame_qcmd->command;
+ do_gettimeofday(&(processed_frame->out_time));
kfree(frame_qcmd);
event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
if (!event_qcmd) {
@@ -526,78 +877,55 @@
CPP_DBG("fid %d\n", processed_frame->frame_id);
msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
+ if (!processed_frame->output_buffer_info.processed_divert) {
+ memset(&buff_mgr_info, 0 ,
+ sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id =
+ ((processed_frame->identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id =
+ (processed_frame->identity & 0xFFFF);
+ buff_mgr_info.frame_id = processed_frame->frame_id;
+ buff_mgr_info.timestamp = processed_frame->timestamp;
+ buff_mgr_info.index =
+ processed_frame->output_buffer_info.index;
+ rc = msm_cpp_buffer_ops(cpp_dev,
+ VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+ &buff_mgr_info);
+ if (rc < 0) {
+ pr_err("error putting buffer\n");
+ rc = -EINVAL;
+ }
+ }
v4l2_evt.id = processed_frame->inst_id;
v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
}
- return 0;
+ return rc;
}
-static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev)
+static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev,
+ struct msm_queue_cmd *frame_qcmd)
{
uint32_t i;
- struct msm_queue_cmd *frame_qcmd;
+ int32_t rc = -EINVAL;
struct msm_cpp_frame_info_t *process_frame;
- struct msm_device_queue *queue;
if (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
- while (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
- if (cpp_dev->realtime_q.len != 0) {
- queue = &cpp_dev->realtime_q;
- } else if (cpp_dev->offline_q.len != 0) {
- queue = &cpp_dev->offline_q;
- } else {
- pr_debug("All frames queued\n");
- break;
- }
- frame_qcmd = msm_dequeue(queue, list_frame);
- process_frame = frame_qcmd->command;
- msm_enqueue(&cpp_dev->processing_q,
- &frame_qcmd->list_frame);
- msm_cpp_write(0x6, cpp_dev->base);
- for (i = 0; i < process_frame->msg_len; i++)
- msm_cpp_write(process_frame->cpp_cmd_msg[i],
- cpp_dev->base);
- }
+ process_frame = frame_qcmd->command;
+ msm_enqueue(&cpp_dev->processing_q,
+ &frame_qcmd->list_frame);
+ msm_cpp_write(0x6, cpp_dev->base);
+ for (i = 0; i < process_frame->msg_len; i++)
+ msm_cpp_write(process_frame->cpp_cmd_msg[i],
+ cpp_dev->base);
+ do_gettimeofday(&(process_frame->in_time));
+ rc = 0;
}
- return 0;
+ return rc;
}
static int msm_cpp_flush_frames(struct cpp_device *cpp_dev)
{
- struct v4l2_event v4l2_evt;
- struct msm_queue_cmd *frame_qcmd;
- struct msm_cpp_frame_info_t *process_frame;
- struct msm_device_queue *queue;
- struct msm_queue_cmd *event_qcmd;
-
- do {
- if (cpp_dev->realtime_q.len != 0) {
- queue = &cpp_dev->realtime_q;
- } else if (cpp_dev->offline_q.len != 0) {
- queue = &cpp_dev->offline_q;
- } else {
- pr_debug("All frames flushed\n");
- break;
- }
- frame_qcmd = msm_dequeue(queue, list_frame);
- process_frame = frame_qcmd->command;
- kfree(frame_qcmd);
- event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
- if (!event_qcmd) {
- pr_err("Insufficient memory. return");
- return -ENOMEM;
- }
- atomic_set(&event_qcmd->on_heap, 1);
- event_qcmd->command = process_frame;
- CPP_DBG("fid %d\n", process_frame->frame_id);
- msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
-
- v4l2_evt.id = process_frame->inst_id;
- v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
- v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
- } while ((cpp_dev->realtime_q.len != 0) ||
- (cpp_dev->offline_q.len != 0));
return 0;
}
@@ -609,9 +937,9 @@
struct msm_cpp_frame_info_t *new_frame =
kzalloc(sizeof(struct msm_cpp_frame_info_t), GFP_KERNEL);
uint32_t *cpp_frame_msg;
- unsigned long len;
unsigned long in_phyaddr, out_phyaddr;
uint16_t num_stripes = 0;
+ struct msm_buf_mngr_info buff_mgr_info;
int i = 0;
if (!new_frame) {
@@ -646,44 +974,40 @@
new_frame->cpp_cmd_msg = cpp_frame_msg;
- CPP_DBG("CPP in_fd: %d out_fd: %d\n", new_frame->src_fd,
- new_frame->dst_fd);
-
- new_frame->src_ion_handle = ion_import_dma_buf(cpp_dev->client,
- new_frame->src_fd);
- if (IS_ERR_OR_NULL(new_frame->src_ion_handle)) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->src_ion_handle);
+ in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->input_buffer_info,
+ ((new_frame->identity >> 16) & 0xFFFF),
+ (new_frame->identity & 0xFFFF));
+ if (!in_phyaddr) {
+ pr_err("error gettting input physical address\n");
+ rc = -EINVAL;
goto ERROR2;
}
- rc = ion_map_iommu(cpp_dev->client, new_frame->src_ion_handle,
- cpp_dev->domain_num, 0, SZ_4K, 0,
- (unsigned long *)&in_phyaddr, &len, 0, 0);
+ memset(&new_frame->output_buffer_info, 0,
+ sizeof(struct msm_cpp_buffer_info_t));
+ memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id = ((new_frame->identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id = (new_frame->identity & 0xFFFF);
+ rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
+ &buff_mgr_info);
if (rc < 0) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->src_ion_handle);
+ pr_err("error getting buffer\n");
+ rc = -EINVAL;
+ goto ERROR2;
+ }
+
+ new_frame->output_buffer_info.index = buff_mgr_info.index;
+ out_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->output_buffer_info,
+ ((new_frame->identity >> 16) & 0xFFFF),
+ (new_frame->identity & 0xFFFF));
+ if (!out_phyaddr) {
+ pr_err("error gettting output physical address\n");
+ rc = -EINVAL;
goto ERROR3;
}
- CPP_DBG("in phy addr: 0x%x len: %ld\n", (uint32_t) in_phyaddr, len);
- new_frame->dest_ion_handle = ion_import_dma_buf(cpp_dev->client,
- new_frame->dst_fd);
- if (IS_ERR_OR_NULL(new_frame->dest_ion_handle)) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->dest_ion_handle);
- goto ERROR4;
- }
-
- rc = ion_map_iommu(cpp_dev->client, new_frame->dest_ion_handle,
- cpp_dev->domain_num, 0, SZ_4K, 0,
- (unsigned long *)&out_phyaddr, &len, 0, 0);
- if (rc < 0) {
- rc = PTR_ERR(new_frame->dest_ion_handle);
- goto ERROR5;
- }
-
- CPP_DBG("out phy addr: 0x%x len: %ld\n", (uint32_t)out_phyaddr, len);
num_stripes = ((cpp_frame_msg[12] >> 20) & 0x3FF) +
((cpp_frame_msg[12] >> 10) & 0x3FF) +
(cpp_frame_msg[12] & 0x3FF);
@@ -700,44 +1024,29 @@
if (!frame_qcmd) {
pr_err("Insufficient memory. return\n");
rc = -ENOMEM;
- goto ERROR6;
+ goto ERROR3;
}
atomic_set(&frame_qcmd->on_heap, 1);
frame_qcmd->command = new_frame;
- if (new_frame->frame_type == MSM_CPP_REALTIME_FRAME) {
- msm_enqueue(&cpp_dev->realtime_q,
- &frame_qcmd->list_frame);
- } else if (new_frame->frame_type == MSM_CPP_OFFLINE_FRAME) {
- msm_enqueue(&cpp_dev->offline_q,
- &frame_qcmd->list_frame);
- } else {
- pr_err("Invalid frame type\n");
+ rc = msm_cpp_send_frame_to_hardware(cpp_dev, frame_qcmd);
+ if (rc < 0) {
+ pr_err("error cannot send frame to hardware\n");
rc = -EINVAL;
- goto ERROR7;
+ goto ERROR4;
}
- msm_cpp_send_frame_to_hardware(cpp_dev);
+
return rc;
-ERROR7:
- kfree(frame_qcmd);
-ERROR6:
- ion_unmap_iommu(cpp_dev->client, new_frame->dest_ion_handle,
- cpp_dev->domain_num, 0);
-ERROR5:
- ion_free(cpp_dev->client, new_frame->dest_ion_handle);
- new_frame->dest_ion_handle = NULL;
ERROR4:
- ion_unmap_iommu(cpp_dev->client, new_frame->src_ion_handle,
- cpp_dev->domain_num, 0);
+ kfree(frame_qcmd);
ERROR3:
- ion_free(cpp_dev->client, new_frame->src_ion_handle);
- new_frame->src_ion_handle = NULL;
+ msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+ &buff_mgr_info);
ERROR2:
kfree(cpp_frame_msg);
ERROR1:
kfree(new_frame);
return rc;
-
}
long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
@@ -795,6 +1104,97 @@
case VIDIOC_MSM_CPP_FLUSH_QUEUE:
rc = msm_cpp_flush_frames(cpp_dev);
break;
+ case VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO: {
+ struct msm_cpp_stream_buff_info_t *u_stream_buff_info;
+ struct msm_cpp_stream_buff_info_t k_stream_buff_info;
+ if (sizeof(struct msm_cpp_stream_buff_info_t) !=
+ ioctl_ptr->len) {
+ pr_err("%s:%d: invalid length\n", __func__, __LINE__);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ u_stream_buff_info = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+ if (!u_stream_buff_info) {
+ pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = (copy_from_user(u_stream_buff_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ ioctl_ptr->len) ? -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ k_stream_buff_info.num_buffs = u_stream_buff_info->num_buffs;
+ k_stream_buff_info.identity = u_stream_buff_info->identity;
+ k_stream_buff_info.buffer_info =
+ kzalloc(k_stream_buff_info.num_buffs *
+ sizeof(struct msm_cpp_buffer_info_t), GFP_KERNEL);
+ if (!k_stream_buff_info.buffer_info) {
+ pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = (copy_from_user(k_stream_buff_info.buffer_info,
+ (void __user *)u_stream_buff_info->buffer_info,
+ k_stream_buff_info.num_buffs *
+ sizeof(struct msm_cpp_buffer_info_t)) ?
+ -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(k_stream_buff_info.buffer_info);
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = msm_cpp_add_buff_queue_entry(cpp_dev,
+ ((k_stream_buff_info.identity >> 16) & 0xFFFF),
+ (k_stream_buff_info.identity & 0xFFFF));
+ if (!rc)
+ rc = msm_cpp_enqueue_buff_info_list(cpp_dev,
+ &k_stream_buff_info);
+
+ kfree(k_stream_buff_info.buffer_info);
+ kfree(u_stream_buff_info);
+ break;
+ }
+ case VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO: {
+ uint32_t identity;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ rc = (copy_from_user(&identity,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ ioctl_ptr->len) ? -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev,
+ ((identity >> 16) & 0xFFFF), (identity & 0xFFFF));
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for identity:%d\n",
+ identity);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ msm_cpp_dequeue_buff_info_list(cpp_dev, buff_queue_info);
+ rc = msm_cpp_free_buff_queue_entry(cpp_dev,
+ buff_queue_info->session_id,
+ buff_queue_info->stream_id);
+ break;
+ }
case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
struct msm_device_queue *queue = &cpp_dev->eventData_q;
struct msm_queue_cmd *event_qcmd;
@@ -808,23 +1208,6 @@
mutex_unlock(&cpp_dev->mutex);
return -EINVAL;
}
- if (process_frame->dest_ion_handle) {
- ion_unmap_iommu(cpp_dev->client,
- process_frame->dest_ion_handle,
- cpp_dev->domain_num, 0);
- ion_free(cpp_dev->client,
- process_frame->dest_ion_handle);
- process_frame->dest_ion_handle = NULL;
- }
-
- if (process_frame->src_ion_handle) {
- ion_unmap_iommu(cpp_dev->client,
- process_frame->src_ion_handle,
- cpp_dev->domain_num, 0);
- ion_free(cpp_dev->client,
- process_frame->src_ion_handle);
- process_frame->src_ion_handle = NULL;
- }
kfree(process_frame->cpp_cmd_msg);
kfree(process_frame);
@@ -834,7 +1217,7 @@
}
mutex_unlock(&cpp_dev->mutex);
CPP_DBG("X\n");
- return 0;
+ return rc;
}
int msm_cpp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -861,8 +1244,6 @@
.core = &msm_cpp_subdev_core_ops,
};
-static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev);
-
static struct v4l2_file_operations msm_cpp_v4l2_subdev_fops;
static long msm_cpp_subdev_do_ioctl(
@@ -960,6 +1341,7 @@
v4l2_set_subdevdata(&cpp_dev->msm_sd.sd, cpp_dev);
platform_set_drvdata(pdev, &cpp_dev->msm_sd.sd);
mutex_init(&cpp_dev->mutex);
+ spin_lock_init(&cpp_dev->tasklet_lock);
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
@@ -1054,14 +1436,13 @@
cpp_release_hardware(cpp_dev);
cpp_dev->state = CPP_STATE_OFF;
- msm_cpp_enable_debugfs(cpp_dev);
msm_queue_init(&cpp_dev->eventData_q, "eventdata");
- msm_queue_init(&cpp_dev->offline_q, "frame");
- msm_queue_init(&cpp_dev->realtime_q, "frame");
msm_queue_init(&cpp_dev->processing_q, "frame");
+ INIT_LIST_HEAD(&cpp_dev->tasklet_q);
+ tasklet_init(&cpp_dev->cpp_tasklet, msm_cpp_do_tasklet,
+ (unsigned long)cpp_dev);
cpp_dev->cpp_open_cnt = 0;
cpp_dev->is_firmware_loaded = 0;
-
return rc;
ERROR3:
@@ -1126,65 +1507,6 @@
platform_driver_unregister(&cpp_driver);
}
-static int msm_cpp_debugfs_stream_s(void *data, u64 val)
-{
- struct cpp_device *cpp_dev = data;
- CPP_DBG("CPP processing frame E\n");
- while (1) {
- mutex_lock(&cpp_dev->mutex);
- msm_cpp_notify_frame_done(cpp_dev);
- msm_cpp_send_frame_to_hardware(cpp_dev);
- mutex_unlock(&cpp_dev->mutex);
- msleep(20);
- }
- CPP_DBG("CPP processing frame X\n");
- return 0;
-}
-
-static int msm_cpp_debugfs_load_fw(void *data, u64 val)
-{
- const struct firmware *fw = NULL;
- struct cpp_device *cpp_dev = data;
- int rc = 0;
- CPP_DBG("%s\n", __func__);
- rc = request_firmware(&fw, "FIRMWARE.bin", &cpp_dev->pdev->dev);
- if (rc) {
- pr_err("request_fw failed\n");
- } else {
- CPP_DBG("request ok\n");
- release_firmware(fw);
- }
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_stream, NULL,
- msm_cpp_debugfs_stream_s, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_fw, NULL,
- msm_cpp_debugfs_load_fw, "%llu\n");
-
-static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev)
-{
- struct dentry *debugfs_base, *debugfs_test;
- debugfs_base = debugfs_create_dir("msm_camera", NULL);
- if (!debugfs_base)
- return -ENOMEM;
-
- debugfs_test = debugfs_create_file("test", S_IRUGO | S_IWUSR,
- debugfs_base, (void *)cpp_dev, &cpp_debugfs_stream);
- if (!debugfs_test) {
- debugfs_remove(debugfs_base);
- return -ENOMEM;
- }
-
- if (!debugfs_create_file("fw", S_IRUGO | S_IWUSR, debugfs_base,
- (void *)cpp_dev, &cpp_debugfs_fw)) {
- debugfs_remove(debugfs_test);
- debugfs_remove(debugfs_base);
- return -ENOMEM;
- }
- return 0;
-}
-
module_init(msm_cpp_init_module);
module_exit(msm_cpp_exit_module);
MODULE_DESCRIPTION("MSM CPP driver");
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 0c586ca..36a5fa5 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <media/v4l2-subdev.h>
#include "msm_sd.h"
@@ -70,6 +71,8 @@
#define MSM_CPP_END_ADDRESS 0x3F00
#define MSM_CPP_POLL_RETRIES 20
+#define MSM_CPP_TASKLETQ_SIZE 16
+#define MSM_CPP_TX_FIFO_LEVEL 16
struct cpp_subscribe_info {
struct v4l2_fh *vfh;
@@ -116,6 +119,34 @@
const char *name;
};
+struct msm_cpp_tasklet_queue_cmd {
+ struct list_head list;
+ uint32_t irq_status;
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
+ uint32_t tx_level;
+ uint8_t cmd_used;
+};
+
+struct msm_cpp_buffer_map_info_t {
+ unsigned long len;
+ unsigned long phy_addr;
+ struct ion_handle *ion_handle;
+ struct msm_cpp_buffer_info_t buff_info;
+};
+
+struct msm_cpp_buffer_map_list_t {
+ struct msm_cpp_buffer_map_info_t map_info;
+ struct list_head entry;
+};
+
+struct msm_cpp_buff_queue_info_t {
+ uint32_t used;
+ uint16_t session_id;
+ uint16_t stream_id;
+ struct list_head vb2_buff_head;
+ struct list_head native_buff_head;
+};
+
struct cpp_device {
struct platform_device *pdev;
struct msm_sd_subdev msm_sd;
@@ -141,19 +172,28 @@
struct ion_client *client;
struct kref refcount;
+ /* Reusing proven tasklet from msm isp */
+ atomic_t irq_cnt;
+ uint8_t taskletq_idx;
+ spinlock_t tasklet_lock;
+ struct list_head tasklet_q;
+ struct tasklet_struct cpp_tasklet;
+ struct msm_cpp_tasklet_queue_cmd
+ tasklet_queue_cmd[MSM_CPP_TASKLETQ_SIZE];
+
struct cpp_subscribe_info cpp_subscribe_list[MAX_ACTIVE_CPP_INSTANCE];
uint32_t cpp_open_cnt;
struct cpp_hw_info hw_info;
struct msm_device_queue eventData_q; /* V4L2 Event Payload Queue */
- /* Offline Frame Queue process when realtime queue is empty */
- struct msm_device_queue offline_q;
- /* Realtime Frame Queue process with highest priority */
- struct msm_device_queue realtime_q;
/* Processing Queue
* store frame info for frames sent to microcontroller
*/
struct msm_device_queue processing_q;
+
+ struct msm_cpp_buff_queue_info_t *buff_queue;
+ uint32_t num_buffq;
+ struct v4l2_subdev *buf_mgr_subdev;
};
#endif /* __MSM_CPP_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 0df0488..fbd4a2e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -24,7 +24,7 @@
#define CSID_VERSION_V3 0x30000000
#define MSM_CSID_DRV_NAME "msm_csid"
-#define DBG_CSID 1
+#define DBG_CSID 0
#define TRUE 1
#define FALSE 0
@@ -36,8 +36,6 @@
#define CDBG(fmt, args...) do { } while (0)
#endif
-static uint32_t irq_count;
-
static int msm_csid_cid_lut(
struct msm_camera_csid_lut_params *csid_lut_params,
void __iomem *csidbase)
@@ -84,8 +82,8 @@
{
uint32_t val = 0;
val = ((1 << csid_params->lane_cnt) - 1) << 20;
- msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_MASK_ADDR);
- msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+ msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_MASK_ADDR);
+ msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
}
#else
static void msm_csid_set_debug_reg(void __iomem *csidbase,
@@ -94,11 +92,8 @@
static void msm_csid_reset(struct csid_device *csid_dev)
{
- CDBG("%s:%d called\n", __func__, __LINE__);
msm_camera_io_w(CSID_RST_STB_ALL, csid_dev->base + CSID_RST_CMD_ADDR);
- CDBG("%s:%d called\n", __func__, __LINE__);
wait_for_completion_interruptible(&csid_dev->reset_complete);
- CDBG("%s:%d called\n", __func__, __LINE__);
return;
}
@@ -159,11 +154,6 @@
__func__, csid_dev->pdev->id, irq);
if (irq & (0x1 << CSID_RST_DONE_IRQ_BITSHIFT))
complete(&csid_dev->reset_complete);
- if (irq & 0x1) {
- pr_debug("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
- __func__, csid_dev->pdev->id, irq);
- irq_count++;
- }
msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
return IRQ_HANDLED;
}
@@ -253,13 +243,11 @@
int rc = 0;
uint8_t core_id = 0;
- CDBG("%s:%d called\n", __func__, __LINE__);
if (!csid_version) {
pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
rc = -EINVAL;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
if (csid_dev->csid_state == CSID_POWER_UP) {
pr_err("%s: csid invalid state %d\n", __func__,
@@ -267,7 +255,6 @@
rc = -EINVAL;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->base = ioremap(csid_dev->mem->start,
resource_size(csid_dev->mem));
@@ -276,10 +263,8 @@
rc = -ENOMEM;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
if (CSID_VERSION <= CSID_VERSION_V2) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
@@ -287,7 +272,6 @@
pr_err("%s: regulator on failed\n", __func__);
goto vreg_config_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
@@ -296,7 +280,6 @@
pr_err("%s: regulator enable failed\n", __func__);
goto vreg_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8960_clk_info, csid_dev->csid_clk,
@@ -305,9 +288,7 @@
pr_err("%s: clock enable failed\n", __func__);
goto clk_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
} else if (CSID_VERSION >= CSID_VERSION_V3) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
@@ -315,7 +296,6 @@
pr_err("%s: regulator on failed\n", __func__);
goto vreg_config_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
@@ -324,7 +304,6 @@
pr_err("%s: regulator enable failed\n", __func__);
goto vreg_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
@@ -333,10 +312,8 @@
pr_err("%s: clock enable failed\n", __func__);
goto csid0_clk_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
core_id = csid_dev->pdev->id;
if (core_id) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8974_clk_info[core_id].clk_info,
csid_dev->csid_clk,
@@ -348,7 +325,6 @@
}
}
}
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->hw_version =
msm_camera_io_r(csid_dev->base + CSID_HW_VERSION_ADDR);
@@ -356,17 +332,12 @@
csid_dev->hw_version);
*csid_version = csid_dev->hw_version;
- CDBG("%s:%d called\n", __func__, __LINE__);
init_completion(&csid_dev->reset_complete);
- CDBG("%s:%d called\n", __func__, __LINE__);
enable_irq(csid_dev->irq->start);
- CDBG("%s:%d called\n", __func__, __LINE__);
msm_csid_reset(csid_dev);
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->csid_state = CSID_POWER_UP;
- irq_count = 0;
return rc;
clk_enable_failed:
@@ -578,7 +549,6 @@
struct csid_device *new_csid_dev;
uint32_t csi_vdd_voltage = 0;
int rc = 0;
- CDBG("%s:%d called\n", __func__, __LINE__);
new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
if (!new_csid_dev) {
pr_err("%s: no enough memory\n", __func__);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 83b9bb3..b6bc0d7 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -640,109 +640,109 @@
debugfs_create_u32(
"hw_notification_interval",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_interval);
debugfs_create_u32(
"hw_notification_min_interval",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_min_interval);
debugfs_create_u32(
"hw_notification_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_count);
debugfs_create_u32(
"hw_notification_size",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_size);
debugfs_create_u32(
"hw_notification_min_size",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_min_size);
debugfs_create_u32(
"decoder_drop_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_drop_count);
debugfs_create_u32(
"decoder_out_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_count);
debugfs_create_u32(
"decoder_out_interval_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_sum);
debugfs_create_u32(
"decoder_out_interval_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_average);
debugfs_create_u32(
"decoder_out_interval_max",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_max);
debugfs_create_u32(
"decoder_ts_errors",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_ts_errors);
debugfs_create_u32(
"sdmx_process_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_count);
debugfs_create_u32(
"sdmx_process_time_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_sum);
debugfs_create_u32(
"sdmx_process_time_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_average);
debugfs_create_u32(
"sdmx_process_time_max",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_max);
debugfs_create_u32(
"sdmx_process_packets_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_sum);
debugfs_create_u32(
"sdmx_process_packets_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_average);
debugfs_create_u32(
"sdmx_process_packets_min",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_min);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index babefd3..8eecb98 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -22,7 +22,7 @@
#include "msm_smem.h"
#include "msm_vidc_debug.h"
-#define HW_RESPONSE_TIMEOUT msecs_to_jiffies(200)
+#define HW_RESPONSE_TIMEOUT 200
#define IS_ALREADY_IN_STATE(__p, __d) ({\
int __rc = (__p >= __d);\
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 2659efc..8031c74 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -386,11 +386,22 @@
msm_smem_free(clnt, mem);
}
-static void venus_hfi_write_register(u8 *base_addr, u32 reg,
+static void venus_hfi_write_register(struct venus_hfi_device *device, u32 reg,
u32 value, u8 *vaddr)
{
u32 hwiosymaddr = reg;
+ u8 *base_addr;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ base_addr = device->hal_data->register_base_addr;
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_WARN,
+ "HFI Write register failed : Clocks are OFF\n");
+ return;
+ }
reg &= REG_ADDR_OFFSET_BITMASK;
if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
/* workaround to offset of FW bias */
@@ -416,14 +427,26 @@
wmb();
}
-static int venus_hfi_read_register(u8 *base_addr, u32 reg)
+static int venus_hfi_read_register(struct venus_hfi_device *device, u32 reg)
{
- int rc = readl_relaxed((u32)base_addr + reg);
+ int rc ;
+ u8 *base_addr;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+
+ base_addr = device->hal_data->register_base_addr;
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_WARN,
+ "HFI Read register failed : Clocks are OFF\n");
+ return -EINVAL;
+ }
+ rc = readl_relaxed((u32)base_addr + reg);
rmb();
return rc;
}
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device,
- enum vidc_clocks clk_level)
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
{
int i;
struct venus_core_clock *cl;
@@ -431,19 +454,18 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return;
}
- if (device->clocks_enabled == 0) {
- dprintk(VIDC_DBG, "VCODEC clocks are already disabled");
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already disabled");
goto already_disabled;
}
- for (i = 0; i < clk_level; i++) {
+ for (i = 0; i <= device->clk_gating_level; i++) {
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_disable(cl->clk);
}
already_disabled:
device->clocks_enabled = 0;
}
-static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device,
- enum vidc_clocks clk_level)
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
{
int i;
struct venus_core_clock *cl;
@@ -452,13 +474,13 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return -EINVAL;
}
- if (device->clocks_enabled == 1) {
- dprintk(VIDC_DBG, "VCODEC clocks are already enabled");
+ if (device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already enabled");
goto already_enabled;
}
- for (i = 0; i < clk_level; i++) {
+ for (i = 0; i <= device->clk_gating_level; i++) {
cl = &device->resources.clock[i];
- rc = clk_prepare_enable(cl->clk);
+ rc = clk_enable(cl->clk);
if (rc) {
dprintk(VIDC_ERR, "Failed to enable clocks\n");
goto fail_clk_enable;
@@ -472,7 +494,7 @@
fail_clk_enable:
for (; i >= 0; i--) {
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_disable(cl->clk);
}
return rc;
}
@@ -497,11 +519,11 @@
{
int rc = 0;
struct venus_hfi_device *device = dev;
- device->load = load;
if (!device) {
dprintk(VIDC_ERR, "Invalid args: %p\n", device);
return -EINVAL;
}
+ device->load = load;
rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
load));
@@ -527,20 +549,22 @@
dprintk(VIDC_ERR, "cannot write to shared Q's");
goto err_q_write;
}
- result = venus_hfi_clk_gating_off(device, VCODEC_CLK);
+ mutex_lock(&device->clock_lock);
+ result = venus_hfi_clk_gating_off(device);
if (result) {
- dprintk(VIDC_ERR, "VCODEC clock enable failed\n");
+ dprintk(VIDC_ERR, "%s : Clock enable failed\n",
+ __func__);
goto err_q_write;
}
result = venus_hfi_scale_clocks(device, device->load);
if (result) {
- dprintk(VIDC_ERR, "VCODEC clock scaling failed\n");
+ dprintk(VIDC_ERR, "Clock scaling failed\n");
goto err_q_write;
}
if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
if (rx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
result = 0;
@@ -549,6 +573,7 @@
}
err_q_write:
mutex_unlock(&device->write_lock);
+ mutex_unlock(&device->clock_lock);
return result;
}
@@ -570,11 +595,17 @@
goto read_error;
}
q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ goto read_error;
+ }
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
if (tx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
@@ -584,6 +615,7 @@
}
read_error:
mutex_unlock(&device->read_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -604,11 +636,18 @@
rc = -ENODATA;
goto dbg_error;
}
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ goto dbg_error;
+ }
q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
if (tx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
@@ -618,6 +657,7 @@
}
dbg_error:
mutex_unlock(&device->read_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -822,16 +862,16 @@
iface_q->q_array.align_device_addr;
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_UC_REGION_ADDR,
(u32) dev->iface_q_table.align_device_addr, 0);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_UC_REGION_SIZE, SHARED_QSIZE, 0);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG2,
(u32) dev->iface_q_table.align_device_addr,
dev->iface_q_table.align_virtual_addr);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG1, 0x01,
dev->iface_q_table.align_virtual_addr);
@@ -851,14 +891,14 @@
dev->qdss.mem_data = NULL;
}
if (!IS_ERR_OR_NULL(dev->qdss.align_device_addr))
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_MMAP_ADDR,
(u32) dev->qdss.align_device_addr, 0);
vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
vsfr->bufSize = SFR_SIZE;
if (!IS_ERR_OR_NULL(dev->sfr.align_device_addr))
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
return 0;
fail_alloc_queue:
@@ -869,14 +909,14 @@
{
u32 ctrl_status = 0, count = 0, rc = 0;
int max_tries = 100;
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_MASK, 0x8, 0);
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_CPU_CS_SCIACMDARG3, 1, 0);
while (!ctrl_status && count < max_tries) {
ctrl_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_CS_SCIACMDARG0);
if ((ctrl_status & 0xFE) == 0x4) {
dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
@@ -903,7 +943,7 @@
reg_set = &device->res->reg_set;
for (i = 0; i < reg_set->count; i++) {
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
reg_set->reg_tbl[i].reg,
reg_set->reg_tbl[i].value, 0);
}
@@ -981,7 +1021,7 @@
goto err_core_init;
}
enable_irq(dev->hal_data->irq);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CTRL_INIT, 0x1, 0);
rc = venus_hfi_core_start_cpu(dev);
if (rc) {
@@ -1008,6 +1048,7 @@
static int venus_hfi_core_release(void *device)
{
struct venus_hfi_device *dev;
+ int rc = 0;
if (device) {
dev = device;
} else {
@@ -1015,13 +1056,22 @@
return -ENODEV;
}
if (dev->hal_client) {
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ mutex_lock(&dev->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&dev->clock_lock);
+ return -EIO;
+ }
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG3, 0, 0);
if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
disable_irq_nosync(dev->hal_data->irq);
dev->intr_status = 0;
venus_hfi_interface_queues_release(dev);
}
+ mutex_unlock(&dev->clock_lock);
dprintk(VIDC_INFO, "HAL exited\n");
return 0;
}
@@ -1055,16 +1105,26 @@
static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
{
u32 intr_status = 0;
+ int rc = 0;
if (!device->callback)
return;
-
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&device->clock_lock);
+ return;
+ }
intr_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_WRAPPER_INTR_STATUS);
if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
- (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
+ (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK) ||
+ (intr_status &
+ VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)) {
device->intr_status |= intr_status;
dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
"times: %d interrupt_status: %d",
@@ -1074,10 +1134,11 @@
"times: %d interrupt_status: %d",
(u32) device, ++device->spur_count, intr_status);
}
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
+ mutex_unlock(&device->clock_lock);
dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
}
@@ -1798,14 +1859,16 @@
return -ENODEV;
}
mutex_lock(&device->write_lock);
+ mutex_lock(&device->clock_lock);
rc = venus_hfi_is_cmd_pending(device);
ctrl_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_CS_SCIACMDARG0);
if (((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
!= 0) && !rc)
- venus_hfi_clk_gating_on(device, VCODEC_CLK);
+ venus_hfi_clk_gating_on(device);
mutex_unlock(&device->write_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -1826,15 +1889,14 @@
rc = hfi_process_msg_packet(device->callback,
device->device_id,
(struct vidc_hal_msg_pkt_hdr *) packet);
- if (rc == HFI_MSG_SYS_IDLE)
- rc = venus_hfi_try_clk_gating(device);
-
}
while (!venus_hfi_iface_dbgq_read(device, packet)) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
}
+ if (rc == HFI_MSG_SYS_IDLE)
+ rc = venus_hfi_try_clk_gating(device);
} else {
dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
}
@@ -2015,12 +2077,23 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return;
}
-
+ if (device->clocks_enabled) {
+ for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable(cl->clk);
+ }
+ } else {
+ for (i = device->clk_gating_level + 1;
+ i < VCODEC_MAX_CLKS; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable(cl->clk);
+ }
+ }
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
continue;
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_unprepare(cl->clk);
}
device->clocks_enabled = 0;
}
@@ -2311,6 +2384,7 @@
struct vidc_resource_hdr rhdr;
struct venus_hfi_device *device = dev;
int rc = 0;
+
if (!device) {
dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
__func__, device);
@@ -2323,7 +2397,6 @@
rc = -EINVAL;
goto ocmem_unset_failed;
}
-
rhdr.resource_id = VIDC_RESOURCE_OCMEM;
rhdr.resource_handle = (u32) &device->resources.ocmem;
rc = venus_hfi_core_release_resource(device, &rhdr);
@@ -2625,7 +2698,8 @@
__func__, device);
return -EINVAL;
}
-
+ mutex_init(&device->clock_lock);
+ device->clk_gating_level = VCODEC_CLK;
rc = venus_hfi_iommu_attach(device);
if (rc) {
dprintk(VIDC_ERR, "Failed to attach iommu");
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 7a96ff4..197c754 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -176,8 +176,10 @@
u32 device_id;
u32 load;
u32 clocks_enabled;
+ enum vidc_clocks clk_gating_level;
struct mutex read_lock;
struct mutex write_lock;
+ struct mutex clock_lock;
msm_vidc_callback callback;
struct vidc_mem_addr iface_q_table;
struct vidc_mem_addr qdss;
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 9598d45..9ef86a7 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -2582,28 +2582,27 @@
debugfs_create_u32(
"stat_rx_chunks",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_rx);
debugfs_create_u32(
"stat_overflow",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_overflow);
debugfs_create_u32(
"stat_lost_sync",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_lost_sync);
debugfs_create_u32(
"stat_timeout",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_timeout);
-
}
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index bea8428..ae47975 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -820,7 +820,15 @@
context_info->is_done_rcv = false;
break; /* return err */
} else {
+ /*
+ * We have stopped the ongoing request
+ * and are sure that mmc_request_done()
+ * is not going to get called. Update
+ * stuff that we ought to do when the
+ * request actually completes.
+ */
mmc_update_clk_scaling(host);
+ mmc_host_clk_release(host);
}
err = host->areq->update_interrupted_req(
host->card, host->areq);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index dc129f7..60e0640 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1166,6 +1166,7 @@
if (!retries) {
printk(KERN_ERR "%s(%s): Unable to re-detect card (%d)\n",
__func__, mmc_hostname(host), err);
+ err = _mmc_detect_card_removed(host);
}
#else
err = _mmc_detect_card_removed(host);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2769709..5090eea 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2253,7 +2253,6 @@
MMC_CAP2_DETECT_ON_ERR);
msm_host->mmc->caps2 |= MMC_CAP2_SANITIZE;
msm_host->mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
- msm_host->mmc->caps2 |= MMC_CAP2_INIT_BKOPS;
msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 91aaf3c..c09373a 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -2514,6 +2514,65 @@
return last_soc;
}
+void pm8921_bms_battery_removed(void)
+{
+ if (!the_chip) {
+ pr_err("called before initialization\n");
+ return;
+ }
+ pr_info("Battery Removed Cleaning up\n");
+
+ cancel_delayed_work_sync(&the_chip->calculate_soc_delayed_work);
+ calculated_soc = 0;
+ the_chip->start_percent = -EINVAL;
+ the_chip->end_percent = -EINVAL;
+ /* cleanup for charge time catchup */
+ the_chip->charge_time_us = 0;
+ the_chip->catch_up_time_us = 0;
+ /* cleanup for charge time adjusting */
+ the_chip->soc_at_cv = -EINVAL;
+ the_chip->soc_at_cv = -EINVAL;
+ the_chip->prev_chg_soc = -EINVAL;
+ the_chip->ibat_at_cv_ua = 0;
+ the_chip->prev_vbat_batt_terminal_uv = 0;
+ /* ocv cleanups */
+ the_chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
+ the_chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
+ the_chip->last_ocv_temp_decidegc = -EINVAL;
+
+ /* cleanup delta time */
+ the_chip->tm_sec = 0;
+
+ /* cc and avg current cleanups */
+ the_chip->prev_iavg_ua = 0;
+ the_chip->last_cc_uah = INT_MIN;
+
+ /* report SOC cleanups */
+ the_chip->t_soc_queried.tv_sec = 0;
+ the_chip->t_soc_queried.tv_nsec = 0;
+
+ last_soc = -EINVAL;
+ /* store invalid soc */
+ pm8xxx_writeb(the_chip->dev->parent, TEMP_SOC_STORAGE, 0);
+
+ /* UUC related data is left as is - use the same historical load avg */
+ update_power_supply(the_chip);
+}
+EXPORT_SYMBOL(pm8921_bms_battery_removed);
+
+void pm8921_bms_battery_inserted(void)
+{
+ if (!the_chip) {
+ pr_err("called before initialization\n");
+ return;
+ }
+
+ pr_info("Battery Inserted\n");
+ the_chip->last_ocv_uv = estimate_ocv(the_chip);
+ schedule_delayed_work(&the_chip->calculate_soc_delayed_work, 0);
+}
+EXPORT_SYMBOL(pm8921_bms_battery_inserted);
+
void pm8921_bms_invalidate_shutdown_soc(void)
{
int calculate_soc = 0;
@@ -3012,6 +3071,7 @@
STOP_OCV,
START_OCV,
SET_OCV,
+ BATT_PRESENT,
};
static int test_batt_temp = 5;
@@ -3255,6 +3315,8 @@
(void *)START_OCV, &calc_fops);
debugfs_create_file("set_ocv", 0644, chip->dent,
(void *)SET_OCV, &calc_fops);
+ debugfs_create_file("batt_present", 0644, chip->dent,
+ (void *)BATT_PRESENT, &calc_fops);
debugfs_create_file("simultaneous", 0644, chip->dent,
(void *)GET_VBAT_VSENSE_SIMULTANEOUS, &calc_fops);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 5136fdf..e9cf973 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3181,6 +3181,7 @@
static int ichg_threshold_ua = -400000;
module_param(ichg_threshold_ua, int, 0644);
+#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
#define PM8921_CHG_VDDMAX_RES_MV 10
static void adjust_vdd_max_for_fastchg(struct pm8921_chg_chip *chip,
int vbat_batt_terminal_uv)
@@ -3212,6 +3213,14 @@
delta_mv = chip->max_voltage_mv - vbat_batt_terminal_mv;
+ if (delta_mv > 0) /* meaning we want to increase the vddmax */ {
+ if (delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
+ pr_debug("vterm = %d is not low enough to inc vdd\n",
+ vbat_batt_terminal_mv);
+ return;
+ }
+ }
+
adj_vdd_max_mv = programmed_vdd_max + delta_mv;
pr_debug("vdd_max needs to be changed by %d mv from %d to %d\n",
delta_mv,
@@ -3223,8 +3232,8 @@
return;
}
- adj_vdd_max_mv = DIV_ROUND_UP(adj_vdd_max_mv, PM8921_CHG_VDDMAX_RES_MV)
- * PM8921_CHG_VDDMAX_RES_MV;
+ adj_vdd_max_mv = (adj_vdd_max_mv / PM8921_CHG_VDDMAX_RES_MV)
+ * PM8921_CHG_VDDMAX_RES_MV;
if (adj_vdd_max_mv > (chip->max_voltage_mv + vdd_max_increase_mv))
adj_vdd_max_mv = chip->max_voltage_mv + vdd_max_increase_mv;
@@ -3382,9 +3391,11 @@
else
vbat_intended = chip->max_voltage_mv;
- if (vbat_batt_terminal_uv / 1000 < vbat_intended) {
- pr_debug("terminal_uv:%d < vbat_intended:%d.\n",
+ if (vbat_batt_terminal_uv / 1000
+ < vbat_intended - MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
+ pr_debug("terminal_uv:%d < vbat_intended:%d-hyst:%d\n",
vbat_batt_terminal_uv,
+ vbat_intended,
vbat_intended);
return CHG_IN_PROGRESS;
}
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 35d8df9..b479477 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1025,13 +1025,15 @@
/* Only honour requests while USB is present */
if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
+ chip->usb_psy->get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
if (ret.intval <= 2 && !chip->use_default_batt_values &&
get_prop_batt_present(chip)) {
- qpnp_chg_usb_suspend_enable(chip, 1);
qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
+ qpnp_chg_usb_suspend_enable(chip, 1);
} else {
- qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
qpnp_chg_usb_suspend_enable(chip, 0);
+ qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
}
}
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 9b2f554..4251968 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -39,6 +39,13 @@
#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/swap.h>
+
+#ifdef CONFIG_HIGHMEM
+#define _ZONE ZONE_HIGHMEM
+#else
+#define _ZONE ZONE_NORMAL
+#endif
static uint32_t lowmem_debug_level = 1;
static int lowmem_adj[6] = {
@@ -55,6 +62,7 @@
16 * 1024, /* 64MB */
};
static int lowmem_minfree_size = 4;
+static int lmk_fast_run = 1;
static unsigned long lowmem_deathpending_timeout;
@@ -82,6 +90,141 @@
static DEFINE_MUTEX(scan_mutex);
+int can_use_cma_pages(gfp_t gfp_mask)
+{
+ int can_use = 0;
+ int mtype = allocflags_to_migratetype(gfp_mask);
+ int i = 0;
+ int *mtype_fallbacks = get_migratetype_fallbacks(mtype);
+
+ if (is_migrate_cma(mtype)) {
+ can_use = 1;
+ } else {
+ for (i = 0;; i++) {
+ int fallbacktype = mtype_fallbacks[i];
+
+ if (is_migrate_cma(fallbacktype)) {
+ can_use = 1;
+ break;
+ }
+
+ if (fallbacktype == MIGRATE_RESERVE)
+ break;
+ }
+ }
+ return can_use;
+}
+
+void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx,
+ int *other_free, int *other_file,
+ int use_cma_pages)
+{
+ struct zone *zone;
+ struct zoneref *zoneref;
+ int zone_idx;
+
+ for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) {
+ zone_idx = zonelist_zone_idx(zoneref);
+ if (zone_idx == ZONE_MOVABLE) {
+ if (!use_cma_pages)
+ *other_free -=
+ zone_page_state(zone, NR_FREE_CMA_PAGES);
+ continue;
+ }
+
+ if (zone_idx > classzone_idx) {
+ if (other_free != NULL)
+ *other_free -= zone_page_state(zone,
+ NR_FREE_PAGES);
+ if (other_file != NULL)
+ *other_file -= zone_page_state(zone,
+ NR_FILE_PAGES)
+ - zone_page_state(zone, NR_SHMEM);
+ } else if (zone_idx < classzone_idx) {
+ if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) {
+ if (!use_cma_pages) {
+ *other_free -= min(
+ zone->lowmem_reserve[classzone_idx] +
+ zone_page_state(
+ zone, NR_FREE_CMA_PAGES),
+ zone_page_state(
+ zone, NR_FREE_PAGES));
+ } else {
+ *other_free -=
+ zone->lowmem_reserve[classzone_idx];
+ }
+ } else {
+ *other_free -=
+ zone_page_state(zone, NR_FREE_PAGES);
+ }
+ }
+ }
+}
+
+void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc)
+{
+ gfp_t gfp_mask;
+ struct zone *preferred_zone;
+ struct zonelist *zonelist;
+ enum zone_type high_zoneidx, classzone_idx;
+ unsigned long balance_gap;
+ int use_cma_pages;
+
+ gfp_mask = sc->gfp_mask;
+ zonelist = node_zonelist(0, gfp_mask);
+ high_zoneidx = gfp_zone(gfp_mask);
+ first_zones_zonelist(zonelist, high_zoneidx, NULL, &preferred_zone);
+ classzone_idx = zone_idx(preferred_zone);
+ use_cma_pages = can_use_cma_pages(gfp_mask);
+
+ balance_gap = min(low_wmark_pages(preferred_zone),
+ (preferred_zone->present_pages +
+ KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
+ KSWAPD_ZONE_BALANCE_GAP_RATIO);
+
+ if (likely(current_is_kswapd() && zone_watermark_ok(preferred_zone, 0,
+ high_wmark_pages(preferred_zone) + SWAP_CLUSTER_MAX +
+ balance_gap, 0, 0))) {
+ if (lmk_fast_run)
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ other_file, use_cma_pages);
+ else
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ NULL, use_cma_pages);
+
+ if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) {
+ if (!use_cma_pages) {
+ *other_free -= min(
+ preferred_zone->lowmem_reserve[_ZONE]
+ + zone_page_state(
+ preferred_zone, NR_FREE_CMA_PAGES),
+ zone_page_state(
+ preferred_zone, NR_FREE_PAGES));
+ } else {
+ *other_free -=
+ preferred_zone->lowmem_reserve[_ZONE];
+ }
+ } else {
+ *other_free -= zone_page_state(preferred_zone,
+ NR_FREE_PAGES);
+ }
+
+ lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem "
+ "ofree %d, %d\n", *other_free, *other_file);
+ } else {
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ other_file, use_cma_pages);
+
+ if (!use_cma_pages) {
+ *other_free -=
+ zone_page_state(preferred_zone, NR_FREE_CMA_PAGES);
+ }
+
+ lowmem_print(4, "lowmem_shrink tunning for others ofree %d, "
+ "%d\n", *other_free, *other_file);
+ }
+}
+
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -106,6 +249,8 @@
other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
+ tune_lmk_param(&other_free, &other_file, sc);
+
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
@@ -311,6 +456,7 @@
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
S_IRUGO | S_IWUSR);
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
+module_param_named(lmk_fast_run, lmk_fast_run, int, S_IRUGO | S_IWUSR);
module_init(lowmem_init);
module_exit(lowmem_exit);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 7d3664a..f7e5eee 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -74,6 +74,9 @@
#define TSENS_EEPROM_8X26_2(n) ((n) + 0x444)
#define TSENS_8X26_MAIN_CALIB_ADDR_RANGE 4
+#define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4)
+#define TSENS_EEPROM_8X10_1_OFFSET 8
+
/* TSENS calibration Mask data */
#define TSENS_BASE1_MASK 0xff
#define TSENS0_POINT1_MASK 0x3f00
@@ -191,6 +194,19 @@
#define TSENS5_8X26_POINT2_SHIFT 26
#define TSENS6_8X26_POINT2_SHIFT 17
+#define TSENS_8X10_CAL_SEL_SHIFT 28
+#define TSENS_8X10_BASE1_SHIFT 8
+#define TSENS0_8X10_POINT1_SHIFT 16
+#define TSENS0_8X10_POINT2_SHIFT 22
+#define TSENS1_8X10_POINT2_SHIFT 6
+#define TSENS_8X10_BASE0_MASK 0xf
+#define TSENS_8X10_BASE1_MASK 0xf0
+#define TSENS0_8X10_POINT1_MASK 0x3f0000
+#define TSENS0_8X10_POINT2_MASK 0xfc00000
+#define TSENS_8X10_TSENS_CAL_SEL 0x70000000
+#define TSENS1_8X10_POINT1_MASK 0x3f
+#define TSENS1_8X10_POINT2_MASK 0xfc0
+
#define TSENS_BIT_APPEND 0x3
#define TSENS_CAL_DEGC_POINT1 30
#define TSENS_CAL_DEGC_POINT2 120
@@ -599,6 +615,98 @@
TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
}
+static int tsens_calib_8x10_sensors(void)
+{
+ int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
+ int tsens0_point2 = 0, tsens1_point2 = 0;
+ int tsens_base1_data = 0, tsens_calibration_mode = 0;
+ uint32_t calib_data[2];
+ uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
+
+ if (tmdev->calibration_less_mode)
+ goto calibration_less_mode;
+
+ calib_data[0] = readl_relaxed(
+ TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
+ calib_data[1] = readl_relaxed(
+ (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+ TSENS_EEPROM_8X10_1_OFFSET));
+
+ tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
+ >> TSENS_8X10_CAL_SEL_SHIFT;
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
+ (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
+ tsens_base0_data = (calib_data[0] & TSENS_8X10_BASE0_MASK);
+ tsens0_point1 = (calib_data[0] & TSENS0_8X10_POINT1_MASK) >>
+ TSENS0_8X10_POINT1_SHIFT;
+ tsens1_point1 = calib_data[1] & TSENS1_8X10_POINT1_MASK;
+ } else
+ goto calibration_less_mode;
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = (calib_data[0] & TSENS_8X10_BASE1_MASK) >>
+ TSENS_8X10_BASE1_SHIFT;
+ tsens0_point2 = (calib_data[0] & TSENS0_8X10_POINT2_MASK) >>
+ TSENS0_8X10_POINT2_SHIFT;
+ tsens1_point2 = (calib_data[1] & TSENS1_8X10_POINT2_MASK) >>
+ TSENS1_8X10_POINT2_SHIFT;
+ }
+
+ if (tsens_calibration_mode == 0) {
+calibration_less_mode:
+ pr_debug("TSENS is calibrationless mode\n");
+ for (i = 0; i < tmdev->tsens_num_sensor; i++)
+ calib_tsens_point2_data[i] = 780;
+ calib_tsens_point1_data[0] = 595;
+ calib_tsens_point1_data[1] = 629;
+ goto compute_intercept_slope;
+ }
+
+ if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+ (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ calib_tsens_point1_data[0] =
+ ((((tsens_base0_data) + tsens0_point1) << 2) |
+ TSENS_BIT_APPEND);
+ calib_tsens_point1_data[1] =
+ ((((tsens_base0_data) + tsens1_point1) << 2) |
+ TSENS_BIT_APPEND);
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ (((tsens_base1_data + tsens0_point2) << 2) |
+ TSENS_BIT_APPEND);
+ calib_tsens_point2_data[1] =
+ (((tsens_base1_data + tsens1_point2) << 2) |
+ TSENS_BIT_APPEND);
+ }
+
+compute_intercept_slope:
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+ tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
+ tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ /* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+ temp_120_degc - temp_30_degc (x2 - x1) */
+ num = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ }
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
+ tmdev->prev_reading_avail = false;
+ }
+
+ return 0;
+}
+
static int tsens_calib_8x26_sensors(void)
{
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
@@ -627,7 +735,6 @@
if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
(tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
- pr_debug("backup one point calibrationless mode\n");
tsens_base0_data = (calib_data[0] & TSENS_8X26_BASE0_MASK)
>> TSENS_8X26_BASE0_SHIFT;
tsens0_point1 = (calib_data[0] & TSENS0_8X26_POINT1_MASK) >>
@@ -647,7 +754,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("backup two point calibrationless mode\n");
tsens_base1_data = (calib_data[3] & TSENS_8X26_BASE1_MASK);
tsens0_point2 = (calib_data[3] & TSENS0_8X26_POINT2_MASK) >>
TSENS0_8X26_POINT2_SHIFT;
@@ -670,10 +776,10 @@
pr_debug("TSENS is calibrationless mode\n");
for (i = 0; i < tmdev->tsens_num_sensor; i++)
calib_tsens_point2_data[i] = 780;
- calib_tsens_point1_data[0] = 502;
- calib_tsens_point1_data[1] = 509;
- calib_tsens_point1_data[2] = 503;
- calib_tsens_point1_data[3] = 509;
+ calib_tsens_point1_data[0] = 595;
+ calib_tsens_point1_data[1] = 625;
+ calib_tsens_point1_data[2] = 553;
+ calib_tsens_point1_data[3] = 578;
calib_tsens_point1_data[4] = 505;
calib_tsens_point1_data[5] = 509;
calib_tsens_point1_data[6] = 507;
@@ -682,7 +788,6 @@
if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("one and two point calibration calculation\n");
calib_tsens_point1_data[0] =
((((tsens_base0_data) + tsens0_point1) << 2) |
TSENS_BIT_APPEND);
@@ -800,7 +905,6 @@
TSENS_TWO_POINT_CALIB) ||
(tsens_calibration_mode ==
TSENS_ONE_POINT_CALIB_OPTION_2)) {
- pr_debug("backup one point calibrationless mode\n");
tsens_base1_data = (calib_data_backup[0] &
TSENS_BASE1_MASK);
tsens0_point1 = (calib_data_backup[0] &
@@ -833,7 +937,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("backup two point calibrationless mode\n");
tsens_base2_data = (calib_data_backup[2] &
TSENS_BASE2_BACKUP_MASK) >>
TSENS_POINT2_BASE_BACKUP_SHIFT;
@@ -879,7 +982,6 @@
(tsens_calibration_mode ==
TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("TSENS is one point calibrationless mode\n");
tsens_base1_data = (calib_data[0] & TSENS_BASE1_MASK);
tsens0_point1 = (calib_data[0] & TSENS0_POINT1_MASK) >>
TSENS0_POINT1_SHIFT;
@@ -905,7 +1007,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("TSENS is two point calibrationless mode\n");
tsens_base2_data = (calib_data[2] & TSENS_BASE2_MASK) >>
TSENS_POINT2_BASE_SHIFT;
tsens0_point2 = (calib_data[2] & TSENS0_POINT2_MASK) >>
@@ -951,7 +1052,6 @@
}
if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) {
- pr_debug("old one point calibration calculation\n");
calib_tsens_point1_data[0] =
(((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
+ tsens0_point1;
@@ -989,7 +1089,6 @@
if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("one and two point calibration calculation\n");
calib_tsens_point1_data[0] =
((((tsens_base1_data) + tsens0_point1) << 2) |
TSENS_BIT_APPEND);
@@ -1097,6 +1196,8 @@
rc = tsens_calib_8974_sensors();
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X26)
rc = tsens_calib_8x26_sensors();
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X10)
+ rc = tsens_calib_8x10_sensors();
else
rc = -ENODEV;
@@ -1163,7 +1264,7 @@
"qcom,calibration-less-mode");
tmdev->calib_mode = calib_type;
tmdev->tsens_local_init = of_property_read_bool(of_node,
- "qcom,tsens_local_init");
+ "qcom,tsens-local-init");
tmdev->tsens_irq = platform_get_irq(pdev, 0);
if (tmdev->tsens_irq < 0) {
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 8b05682..e7d2e0f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -35,7 +35,7 @@
#include <linux/platform_device.h>
/* QPNP VADC TM register definition */
-#define QPNP_REVISION3 0x3
+#define QPNP_REVISION3 0x2
#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT 2
#define QPNP_STATUS1 0x8
#define QPNP_STATUS1_OP_MODE 4
@@ -544,7 +544,7 @@
i++;
}
- if ((i == adc_tm->max_channels_available) && (!chan_found)) {
+ if (!chan_found) {
pr_err("Channel not found\n");
return -EINVAL;
}
@@ -1292,7 +1292,8 @@
{
struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
uint32_t channel, dt_index = 0, scale_type = 0;
- int rc = 0;
+ int rc = 0, i = 0;
+ bool chan_found = false;
if (!adc_tm || !adc_tm->adc_tm_initialized)
return -ENODEV;
@@ -1305,11 +1306,17 @@
mutex_lock(&adc_tm->adc->adc_lock);
channel = param->channel;
- while ((adc_tm->adc->adc_channels[dt_index].channel_num
- != channel) && (dt_index < adc_tm->max_channels_available))
- dt_index++;
+ while (i < adc_tm->max_channels_available) {
+ if (adc_tm->adc->adc_channels[i].channel_num ==
+ channel) {
+ dt_index = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
- if (dt_index >= adc_tm->max_channels_available) {
+ if (!chan_found) {
pr_err("not a valid ADC_TM channel\n");
rc = -EINVAL;
goto fail_unlock;
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 3c3fbca..67c9a1a 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -363,10 +363,13 @@
switch (status) {
case 0:
/* successful completion */
+ break;
case -ECONNRESET:
case -ESHUTDOWN:
/* connection gone */
- break;
+ dev_kfree_skb_any(skb);
+ usb_ep_free_request(ep, req);
+ return;
default:
pr_err("%s: data tx ep error %d\n",
__func__, status);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 38e5436..df5e5d3 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -198,6 +198,8 @@
u32 plane_size[MAX_PLANES];
u32 total_size;
u32 ystride[MAX_PLANES];
+ u32 rau_cnt;
+ u32 rau_h[2];
};
struct mdss_mdp_img_data {
@@ -442,7 +444,9 @@
int mdss_mdp_data_check(struct mdss_mdp_data *data,
struct mdss_mdp_plane_sizes *ps);
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
- struct mdss_mdp_plane_sizes *ps);
+ struct mdss_mdp_plane_sizes *ps, u32 bwc_mode);
+int mdss_mdp_get_rau_strides(u32 w, u32 h, struct mdss_mdp_format_params *fmt,
+ struct mdss_mdp_plane_sizes *ps);
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 108340d..97998d8c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -200,6 +200,20 @@
total_ib_quota += ib_quota;
if (clk_rate > max_clk_rate)
max_clk_rate = clk_rate;
+
+ if (ctl->intf_type) {
+ struct mdss_panel_info *pinfo;
+
+ pinfo = &ctl->panel_data->panel_info;
+ clk_rate = (ctl->intf_type == MDSS_INTF_DSI) ?
+ pinfo->mipi.dsi_pclk_rate :
+ pinfo->clk_rate;
+
+ /* minimum clock rate due to inefficiency in 3dmux */
+ clk_rate = mult_frac(clk_rate >> 1, 9, 8);
+ if (clk_rate > max_clk_rate)
+ max_clk_rate = clk_rate;
+ }
}
/* request minimum bandwidth to have bus clock on when display is on */
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index b7b3c23..7fbb031 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -37,7 +37,7 @@
u16 width;
u16 height;
u8 rot90;
-
+ u32 bwc_mode;
int initialized;
struct mdss_mdp_plane_sizes dst_planes;
@@ -90,6 +90,9 @@
pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data->p[0].addr);
+ if (ctx->bwc_mode)
+ data->bwc_enabled = 1;
+
ret = mdss_mdp_data_check(data, &ctx->dst_planes);
if (ret)
return ret;
@@ -112,7 +115,8 @@
pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
mdss_mdp_get_plane_sizes(ctx->format, ctx->width, ctx->height,
- &ctx->dst_planes);
+ &ctx->dst_planes,
+ ctx->opmode & MDSS_MDP_OP_BWC_EN);
fmt = mdss_mdp_get_format_params(ctx->format);
if (!fmt) {
@@ -252,7 +256,8 @@
if (ctl->mdata->rot_block_size == 128)
ctx->opmode |= BIT(4); /* block size 128 */
- ctx->opmode |= rot->bwc_mode;
+ ctx->bwc_mode = rot->bwc_mode;
+ ctx->opmode |= ctx->bwc_mode;
ctx->width = rot->src_rect.w;
ctx->height = rot->src_rect.h;
@@ -260,12 +265,15 @@
ctx->format = rot->format;
ctx->rot90 = !!(rot->flags & MDP_ROT_90);
+
+ if (ctx->bwc_mode || ctx->rot90)
+ ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+ else
+ ctx->format = rot->format;
+
if (ctx->rot90) {
ctx->opmode |= BIT(5); /* ROT 90 */
swap(ctx->width, ctx->height);
- ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
- } else {
- ctx->format = rot->format;
}
return mdss_mdp_writeback_format_setup(ctx);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 5d23315..dae3e05 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -213,6 +213,7 @@
rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
MDP_SECURE_OVERLAY_SESSION);
+ rot->bwc_mode = (req->flags & MDP_BWC_EN) ? 1 : 0;
rot->format = fmt->format;
rot->img_width = req->src.width;
rot->img_height = req->src.height;
@@ -261,7 +262,7 @@
}
src_format = req->src.format;
- if (req->flags & MDP_SOURCE_ROTATED_90)
+ if (req->flags & (MDP_SOURCE_ROTATED_90 | MDP_BWC_EN))
src_format = mdss_mdp_get_rotator_dst_format(src_format);
fmt = mdss_mdp_get_format_params(src_format);
@@ -345,7 +346,8 @@
}
pipe->flags = req->flags;
-
+ pipe->bwc_mode = pipe->mixer->rotator_mode ?
+ 0 : (req->flags & MDP_BWC_EN ? 1 : 0) ;
pipe->img_width = req->src.width & 0x3fff;
pipe->img_height = req->src.height & 0x3fff;
pipe->src.x = req->src_rect.x;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index ca741b1..b169c43 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -119,25 +119,32 @@
u32 num_blks = 0, reserved = 0;
struct mdss_mdp_plane_sizes ps;
int i, rc;
+ u32 nlines;
- if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+ if (pipe->bwc_mode) {
+ rc = mdss_mdp_get_rau_strides(pipe->src.w, pipe->src.h,
+ pipe->src_fmt, &ps);
+ if (rc)
+ return rc;
+ pr_debug("BWC SMP strides ystride0=%x ystride1=%x\n",
+ ps.ystride[0], ps.ystride[1]);
+ } else if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
pipe->src_fmt->is_yuv) {
ps.num_planes = 2;
ps.ystride[0] = pipe->src.w;
ps.ystride[1] = pipe->src.w;
} else {
rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
- pipe->src.w, pipe->src.h, &ps);
+ pipe->src.w, pipe->src.h, &ps, 0);
if (rc)
return rc;
}
- if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
- return -EINVAL;
-
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < ps.num_planes; i++) {
- num_blks = DIV_ROUND_UP(2 * ps.ystride[i], SMP_MB_SIZE);
+ nlines = pipe->bwc_mode ? ps.rau_h[i] : 2;
+ num_blks = DIV_ROUND_UP(nlines * ps.ystride[i],
+ mdss_res->smp_mb_size);
if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
num_blks = roundup_pow_of_two(num_blks);
@@ -341,6 +348,8 @@
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_pipe_sspp_term(pipe);
mdss_mdp_smp_free(pipe);
+ pipe->flags = 0;
+ pipe->bwc_mode = 0;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return 0;
@@ -376,7 +385,7 @@
width = pipe->img_width;
height = pipe->img_height;
mdss_mdp_get_plane_sizes(pipe->src_fmt->format, width, height,
- &pipe->src_planes);
+ &pipe->src_planes, pipe->bwc_mode);
if ((pipe->flags & MDP_DEINTERLACE) &&
!(pipe->flags & MDP_SOURCE_ROTATED_90)) {
@@ -416,8 +425,9 @@
static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe)
{
struct mdss_mdp_format_params *fmt;
- u32 opmode, chroma_samp, unpack, src_format;
+ u32 chroma_samp, unpack, src_format;
u32 secure = 0;
+ u32 opmode;
fmt = pipe->src_fmt;
@@ -554,8 +564,7 @@
pr_debug("pnum=%d\n", pipe->num);
- if (!is_rot)
- data->bwc_enabled = pipe->bwc_mode;
+ data->bwc_enabled = pipe->bwc_mode;
ret = mdss_mdp_data_check(data, &pipe->src_planes);
if (ret)
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 8bff5cb..5711653 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -203,7 +203,6 @@
rot_pipe->img_height = rot->img_height;
rot_pipe->src = rot->src_rect;
rot_pipe->dst = rot->src_rect;
- rot_pipe->bwc_mode = rot->bwc_mode;
rot_pipe->params_changed++;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index c46f271..21ee9bb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -45,10 +45,14 @@
static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
{
switch (in_format) {
+ case MDP_RGB_565:
+ case MDP_BGR_565:
+ return MDP_RGB_888;
case MDP_Y_CBCR_H2V2_VENUS:
- return MDP_Y_CBCR_H2V2;
+ case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_GH2V2:
- return MDP_Y_CR_CB_H2V2;
+ case MDP_Y_CR_CB_H2V2:
+ return MDP_Y_CRCB_H2V2;
default:
return in_format;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 8ce5ab5..5915f61 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -221,11 +221,48 @@
return NULL;
}
+int mdss_mdp_get_rau_strides(u32 w, u32 h,
+ struct mdss_mdp_format_params *fmt,
+ struct mdss_mdp_plane_sizes *ps)
+{
+ u32 stride_off;
+ if (fmt->is_yuv) {
+ ps->rau_cnt = DIV_ROUND_UP(w, 64);
+ ps->ystride[0] = 64 * 4;
+ ps->rau_h[0] = 4;
+ ps->rau_h[1] = 2;
+ if (fmt->chroma_sample == MDSS_MDP_CHROMA_H1V2)
+ ps->ystride[1] = 64 * 2;
+ else if (fmt->chroma_sample == MDSS_MDP_CHROMA_H2V1) {
+ ps->ystride[1] = 32 * 4;
+ ps->rau_h[1] = 4;
+ } else
+ ps->ystride[1] = 32 * 2;
+ } else if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+ ps->rau_cnt = DIV_ROUND_UP(w, 32);
+ ps->ystride[0] = 32 * 4;
+ ps->ystride[1] = 0;
+ ps->rau_h[0] = 4;
+ ps->rau_h[1] = 0;
+ } else {
+ pr_err("Invalid format=%d\n", fmt->format);
+ return -EINVAL;
+ }
+
+ stride_off = DIV_ROUND_UP(ps->rau_cnt, 8);
+ ps->ystride[0] = ps->ystride[0] * ps->rau_cnt * fmt->bpp + stride_off;
+ ps->ystride[1] = ps->ystride[1] * ps->rau_cnt * fmt->bpp + stride_off;
+ ps->num_planes = 2;
+
+ return 0;
+}
+
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
- struct mdss_mdp_plane_sizes *ps)
+ struct mdss_mdp_plane_sizes *ps, u32 bwc_mode)
{
struct mdss_mdp_format_params *fmt;
- int i;
+ int i, rc;
+ u32 bpp, stride_off;
if (ps == NULL)
return -EINVAL;
@@ -237,55 +274,69 @@
if (!fmt)
return -EINVAL;
+ bpp = fmt->bpp;
memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes));
- if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
- u32 bpp = fmt->bpp;
- ps->num_planes = 1;
- ps->plane_size[0] = w * h * bpp;
- ps->ystride[0] = w * bpp;
- } else if (format == MDP_Y_CBCR_H2V2_VENUS) {
- int cf = COLOR_FMT_NV12;
- ps->num_planes = 2;
- ps->ystride[0] = VENUS_Y_STRIDE(cf, w);
- ps->ystride[1] = VENUS_UV_STRIDE(cf, w);
- ps->plane_size[0] = VENUS_Y_SCANLINES(cf, h) * ps->ystride[0];
- ps->plane_size[1] = VENUS_UV_SCANLINES(cf, h) * ps->ystride[1];
+ if (bwc_mode) {
+ rc = mdss_mdp_get_rau_strides(w, h, fmt, ps);
+ if (rc)
+ return rc;
+ stride_off = DIV_ROUND_UP(h, ps->rau_h[0]);
+ ps->ystride[0] = ps->ystride[0] + ps->ystride[1];
+ ps->plane_size[0] = ps->ystride[0] * stride_off;
+ ps->ystride[1] = 2;
+ ps->plane_size[1] = ps->rau_cnt * ps->ystride[1] * stride_off;
+
} else {
- u8 hmap[] = { 1, 2, 1, 2 };
- u8 vmap[] = { 1, 1, 2, 2 };
- u8 horiz, vert, stride_align, height_align;
-
- horiz = hmap[fmt->chroma_sample];
- vert = vmap[fmt->chroma_sample];
-
- switch (format) {
- case MDP_Y_CR_CB_GH2V2:
- stride_align = 16;
- height_align = 1;
- break;
- default:
- stride_align = 1;
- height_align = 1;
- break;
- }
-
- ps->ystride[0] = ALIGN(w, stride_align);
- ps->ystride[1] = ALIGN(w / horiz, stride_align);
- ps->plane_size[0] = ps->ystride[0] * ALIGN(h, height_align);
- ps->plane_size[1] = ps->ystride[1] * (h / vert);
-
- if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) {
+ if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+ ps->num_planes = 1;
+ ps->plane_size[0] = w * h * bpp;
+ ps->ystride[0] = w * bpp;
+ } else if (format == MDP_Y_CBCR_H2V2_VENUS) {
+ int cf = COLOR_FMT_NV12;
ps->num_planes = 2;
- ps->plane_size[1] *= 2;
- ps->ystride[1] *= 2;
- } else { /* planar */
- ps->num_planes = 3;
- ps->plane_size[2] = ps->plane_size[1];
- ps->ystride[2] = ps->ystride[1];
+ ps->ystride[0] = VENUS_Y_STRIDE(cf, w);
+ ps->ystride[1] = VENUS_UV_STRIDE(cf, w);
+ ps->plane_size[0] = VENUS_Y_SCANLINES(cf, h) *
+ ps->ystride[0];
+ ps->plane_size[1] = VENUS_UV_SCANLINES(cf, h) *
+ ps->ystride[1];
+ } else {
+ u8 hmap[] = { 1, 2, 1, 2 };
+ u8 vmap[] = { 1, 1, 2, 2 };
+ u8 horiz, vert, stride_align, height_align;
+
+ horiz = hmap[fmt->chroma_sample];
+ vert = vmap[fmt->chroma_sample];
+
+ switch (format) {
+ case MDP_Y_CR_CB_GH2V2:
+ stride_align = 16;
+ height_align = 1;
+ break;
+ default:
+ stride_align = 1;
+ height_align = 1;
+ break;
+ }
+
+ ps->ystride[0] = ALIGN(w, stride_align);
+ ps->ystride[1] = ALIGN(w / horiz, stride_align);
+ ps->plane_size[0] = ps->ystride[0] *
+ ALIGN(h, height_align);
+ ps->plane_size[1] = ps->ystride[1] * (h / vert);
+
+ if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) {
+ ps->num_planes = 2;
+ ps->plane_size[1] *= 2;
+ ps->ystride[1] *= 2;
+ } else { /* planar */
+ ps->num_planes = 3;
+ ps->plane_size[2] = ps->plane_size[1];
+ ps->ystride[2] = ps->ystride[1];
+ }
}
}
-
for (i = 0; i < ps->num_planes; i++)
ps->total_size += ps->plane_size[i];
@@ -302,7 +353,8 @@
return -ENOMEM;
if (data->bwc_enabled) {
- return -EPERM; /* not supported */
+ data->num_planes = ps->num_planes;
+ data->p[1].addr = data->p[0].addr + ps->plane_size[0];
} else {
struct mdss_mdp_img_data *prev, *curr;
int i;
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7939832..969b400 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -20,6 +20,7 @@
#define DEINIT_TYPE 16
#define USER_SPACE_DATA_TYPE 32
#define DCI_DATA_TYPE 64
+#define CALLBACK_DATA_TYPE 128
#define USB_MODE 1
#define MEMORY_DEVICE_MODE 2
#define NO_LOGGING_MODE 3
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 5e6a8c3..a19c0b6 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -167,6 +167,19 @@
* value upon wakeup from sleep.
*/
int pm8921_bms_cc_uah(int *cc_uah);
+
+/**
+ * pm8921_bms_battery_removed - function to be called to tell the bms that
+ * the battery is removed. The bms resets its internal
+ * history data used to report soc.
+ */
+void pm8921_bms_battery_removed(void);
+/**
+ * pm8921_bms_battery_inseted - function to be called to tell the bms that
+ * the battery was inserted. The bms initiates calculations
+ * for reporting soc.
+ */
+void pm8921_bms_battery_inserted(void);
#else
static inline int pm8921_bms_get_vsense_avg(int *result)
{
@@ -213,6 +226,8 @@
{
return -ENXIO;
}
+static inline void pm8921_bms_battery_removed(void) {}
+static inline void pm8921_bms_battery_inserted(void) {}
#endif
#endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5dc65bd..ca7a586 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -61,6 +61,14 @@
MIGRATE_TYPES
};
+/*
+ * Returns a list which contains the migrate types on to which
+ * an allocation falls back when the free list for the migrate
+ * type mtype is depleted.
+ * The end of the list is delimited by the type MIGRATE_RESERVE.
+ */
+extern int *get_migratetype_fallbacks(int mtype);
+
#ifdef CONFIG_CMA
bool is_cma_pageblock(struct page *page);
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 5deff7a..7e1a709 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -170,7 +170,7 @@
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
#define MDP_OV_PIPE_FORCE_DMA 0x00004000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
-
+#define MDP_BWC_EN 0x00000400
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
diff --git a/include/media/msmb_generic_buf_mgr.h b/include/media/msmb_generic_buf_mgr.h
index 17cb947..efcb425 100644
--- a/include/media/msmb_generic_buf_mgr.h
+++ b/include/media/msmb_generic_buf_mgr.h
@@ -9,6 +9,7 @@
uint32_t index;
};
+struct v4l2_subdev *msm_buf_mngr_get_subdev(void);
#define VIDIOC_MSM_BUF_MNGR_GET_BUF \
_IOWR('V', BASE_VIDIOC_PRIVATE + 33, struct msm_buf_mngr_info)
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
index 3546004..f0f015e 100644
--- a/include/media/msmb_ispif.h
+++ b/include/media/msmb_ispif.h
@@ -64,14 +64,17 @@
};
struct msm_ispif_params_entry {
+ enum msm_ispif_vfe_intf vfe_intf;
enum msm_ispif_intftype intftype;
int num_cids;
enum msm_ispif_cid cids[3];
enum msm_ispif_csid csid;
+ int crop_enable;
+ uint16_t crop_start_pixel;
+ uint16_t crop_end_pixel;
};
struct msm_ispif_param_data {
- enum msm_ispif_vfe_intf vfe_intf;
uint32_t num;
struct msm_ispif_params_entry entries[INTF_MAX];
};
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 6f8e865..9000774 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -11,6 +11,7 @@
#define MAX_PLANES VIDEO_MAX_PLANES
#define MAX_NUM_CPP_STRIPS 8
+#define MSM_CPP_MAX_NUM_PLANES 3
enum msm_cpp_frame_type {
MSM_CPP_OFFLINE_FRAME,
@@ -74,9 +75,25 @@
int postscale_crop_en;
};
+struct msm_cpp_buffer_info_t {
+ int fd;
+ uint32_t index;
+ uint32_t offset;
+ uint8_t native_buff;
+ uint8_t processed_divert;
+};
+
+struct msm_cpp_stream_buff_info_t {
+ uint32_t identity;
+ uint32_t num_buffs;
+ struct msm_cpp_buffer_info_t *buffer_info;
+};
+
struct msm_cpp_frame_info_t {
int32_t frame_id;
+ struct timeval timestamp;
uint32_t inst_id;
+ uint32_t identity;
uint32_t client_id;
enum msm_cpp_frame_type frame_type;
uint32_t num_strips;
@@ -87,6 +104,11 @@
int dst_fd;
struct ion_handle *src_ion_handle;
struct ion_handle *dest_ion_handle;
+ struct timeval in_time, out_time;
+ void *cookie;
+
+ struct msm_cpp_buffer_info_t input_buffer_info;
+ struct msm_cpp_buffer_info_t output_buffer_info;
};
struct cpp_hw_info {
@@ -112,6 +134,12 @@
#define VIDIOC_MSM_CPP_FLUSH_QUEUE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
+#define VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_v4l2_ioctl_t)
+
#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
struct msm_camera_v4l2_ioctl_t {
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d1e73a4..edd656c 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -641,21 +641,9 @@
* and expiry check is done in the hrtimer_interrupt or in the softirq.
*/
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
- struct hrtimer_clock_base *base,
- int wakeup)
+ struct hrtimer_clock_base *base)
{
- if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
- if (wakeup) {
- raw_spin_unlock(&base->cpu_base->lock);
- raise_softirq_irqoff(HRTIMER_SOFTIRQ);
- raw_spin_lock(&base->cpu_base->lock);
- } else
- __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-
- return 1;
- }
-
- return 0;
+ return base->cpu_base->hres_active && hrtimer_reprogram(timer, base);
}
/*
@@ -726,8 +714,7 @@
static inline void
hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
- struct hrtimer_clock_base *base,
- int wakeup)
+ struct hrtimer_clock_base *base)
{
return 0;
}
@@ -986,8 +973,21 @@
*
* XXX send_remote_softirq() ?
*/
- if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
- hrtimer_enqueue_reprogram(timer, new_base, wakeup);
+ if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)
+ && hrtimer_enqueue_reprogram(timer, new_base)) {
+ if (wakeup) {
+ /*
+ * We need to drop cpu_base->lock to avoid a
+ * lock ordering issue vs. rq->lock.
+ */
+ raw_spin_unlock(&new_base->cpu_base->lock);
+ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+ local_irq_restore(flags);
+ return ret;
+ } else {
+ __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+ }
+ }
unlock_hrtimer_base(timer, &flags);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b179e71..d6dd07a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -926,6 +926,11 @@
[MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
};
+int *get_migratetype_fallbacks(int mtype)
+{
+ return fallbacks[mtype];
+}
+
/*
* Move the free pages in a range to the free lists of the requested type.
* Note that start_page and end_pages are not aligned on a pageblock
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 764f4c6..cbfff1c 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -604,8 +604,12 @@
ins ? "insert" : "removal");
/* Disable detection to avoid glitch */
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 0);
- snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
- (0x68 | (ins ? (1 << 1) : 0)));
+ if (mbhc->mbhc_cfg->gpio_level_insert)
+ snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
+ (0x68 | (ins ? (1 << 1) : 0)));
+ else
+ snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
+ (0x6C | (ins ? (1 << 1) : 0)));
/* Re-enable detection */
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 1);
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 64f19ad..c8de460 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -349,7 +349,7 @@
atomic_set(&lpa_audio.audio_ocmem_req, 0);
runtime->private_data = prtd;
lpa_audio.prtd = prtd;
- lpa_set_volume(lpa_audio.volume);
+ lpa_set_volume(0);
ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
if (ret < 0)
pr_err("%s: Send SoftPause Param failed ret=%d\n",
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index babfddc..ef5c6e3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1339,7 +1339,7 @@
#define VOLTE_SESSION_NAME "VoLTE session"
#define VOICE2_SESSION_NAME "Voice2 session"
-#define VOICE2_SESSION_VSID "10dc1000"
+#define VOICE2_SESSION_VSID "10DC1000"
/* called by alsa driver */
int voc_set_pp_enable(uint16_t session_id, uint32_t module_id,