Merge "arm/dt: msm8610: add ipc-spinlock entry"
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index ad35985..199862f 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -14,6 +14,8 @@
- vdd_pronto_pll-supply: regulator to supply pronto pll.
- qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
- qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
+- qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
+ the Apps
- qcom,gpio-force-stop: GPIO used by the Apps to force the wcnss to shutdown.
Example:
@@ -30,6 +32,7 @@
/* GPIO input from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 30d34f6..eb62ea1 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -11,6 +11,9 @@
Optional properties:
- parent-supply: phandle to the parent supply/regulator node
+ - qcom,retain-mems: For Oxili GDSCs only: Presence currently denotes a hardware
+ requirement to assert the forced memory retention signals
+ in the core's clock branch control register.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index a51d4b8..4748ecb 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -642,8 +642,9 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
@@ -798,6 +799,24 @@
reg = <0xfd484000 0x400>;
qcom,num-locks = <8>;
};
+
+ qcom,qseecom@d980000 {
+ compatible = "qcom,qseecom";
+ reg = <0xd980000 0x256000>;
+ reg-names = "secapp-region";
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 3936000 393600>,
+ <55 512 3936000 393600>,
+ <55 512 3936000 393600>;
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index c762405..5b0eb33 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -19,7 +19,7 @@
compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
qcom,msm-id = <147 1 0>, <165 1 0>;
- serial@f991f000 {
+ serial@f991e000 {
status = "ok";
};
};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 89a00f1..a0a2c14 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -113,7 +113,7 @@
coresight-nr-inports = <4>;
coresight-outports = <0>;
coresight-child-list = <&funnel_in1>;
- coresight-child-ports = <5>;
+ coresight-child-ports = <6>;
};
stm: stm@fc302000 {
@@ -126,7 +126,7 @@
coresight-name = "coresight-stm";
coresight-nr-inports = <0>;
coresight-outports = <0>;
- coresight-child-list = <&funnel_in1>;
+ coresight-child-list = <&funnel_in0>;
coresight-child-ports = <7>;
};
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
index 9690d12..91029e2 100644
--- a/arch/arm/boot/dts/msm8610-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8610-smp2p.dtsi
@@ -12,8 +12,7 @@
/ {
qcom,smp2p-modem {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <1>;
qcom,irq-bitmask = <0x4000>;
interrupts = <0 27 1>;
@@ -21,8 +20,7 @@
qcom,smp2p-adsp {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <2>;
qcom,irq-bitmask = <0x400>;
interrupts = <0 158 1>;
@@ -30,8 +28,7 @@
qcom,smp2p-wcnss {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <4>;
qcom,irq-bitmask = <0x40000>;
interrupts = <0 143 1>;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index cc0c6cf..595fabd 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -74,6 +74,13 @@
status = "disabled";
};
+ serial@f991e000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991e000 0x1000>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ };
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
qcom,vidc-ns-map = <0x40000000 0x40000000>;
@@ -371,13 +378,18 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
+ qcom,iris-fm {
+ compatible = "qcom,iris_fm";
+ };
+
sound {
compatible = "qcom,msm8x10-audio-codec";
qcom,model = "msm8x10-snd-card";
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index ec8a459..de370e7 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -276,7 +276,6 @@
};
&sdcc1 {
- qcom,bus-width = <4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 5c42b2c..88641f9 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -49,7 +49,7 @@
<0x017C 0x0FFF0FFF>,
<0x0160 0x22222222>,
<0x0164 0x00002222>;
- qcom,mdp-settings = <0x02E0 0x000000AA>,
+ qcom,mdp-settings = <0x02E0 0x000000E9>,
<0x02E4 0x00000055>,
<0x03AC 0xC0000CCC>,
<0x03B4 0xC0000CCC>,
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 5970e6b..a81fc20 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -369,57 +369,99 @@
&pm8941_gpios {
gpio@c000 { /* GPIO 1 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c100 { /* GPIO 2 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c200 { /* GPIO 3 */
- qcom,mode = <0>;
- qcom,pull = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c300 { /* GPIO 4 */
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c400 { /* GPIO 5 */
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c500 { /* GPIO 6 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c600 { /* GPIO 7 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c700 { /* GPIO 8 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c800 { /* GPIO 9 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@c900 { /* GPIO 10 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@ca00 { /* GPIO 11 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cb00 { /* GPIO 12 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cc00 { /* GPIO 13 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cd00 { /* GPIO 14 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@ce00 { /* GPIO 15 */
@@ -438,7 +480,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-sel = <2>;
+ qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
qcom,master-en = <1>;
};
@@ -453,60 +495,102 @@
qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
- qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
gpio@d300 { /* GPIO 20 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d400 { /* GPIO 21 */
};
gpio@d500 { /* GPIO 22 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@d600 { /* GPIO 23 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d700 { /* GPIO 24 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d800 { /* GPIO 25 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d900 { /* GPIO 26 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@da00 { /* GPIO 27 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@db00 { /* GPIO 28 */
};
gpio@dc00 { /* GPIO 29 */
- qcom,pull = <0>; /* set to default pull */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
qcom,master-en = <1>;
- qcom,vin-sel = <2>; /* select 1.8 V source */
};
gpio@dd00 { /* GPIO 30 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@de00 { /* GPIO 31 */
};
gpio@df00 { /* GPIO 32 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e000 { /* GPIO 33 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e100 { /* GPIO 34 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e200 { /* GPIO 35 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e300 { /* GPIO 36 */
@@ -520,6 +604,9 @@
};
mpp@a100 { /* MPP 2 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
mpp@a200 { /* MPP 3 */
@@ -534,6 +621,7 @@
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
qcom,src-sel = <0>; /* CONSTANT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -543,13 +631,20 @@
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
qcom,src-sel = <0>; /* CONSTANT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,master-en = <1>; /* ENABLE MPP */
};
mpp@a600 { /* MPP 7 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
mpp@a700 { /* MPP 8 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 0f762a8..8f2ef31 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -25,3 +25,7 @@
&pm8941_chg {
qcom,chg-charging-disabled;
};
+
+&sdcc1 {
+ qcom,bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 50fb380..777d26c 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -57,8 +57,6 @@
&mdss_mdp {
qcom,vbif-settings = <0x0004 0x00000001>;
- qcom,mdp-settings = <0x02E0 0x000000A9>,
- <0x02E4 0x00000055>;
qcom,mdss-wb-off = <0x00011100 0x00011500
0x00011900 0x00011D00 0x00012100>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 56234a1..2f958aeeb1 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1055,8 +1055,9 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
@@ -1455,6 +1456,7 @@
};
&gdsc_oxili_gx {
+ qcom,retain-mems;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msmkrypton-sim.dts b/arch/arm/boot/dts/msmkrypton-sim.dts
new file mode 100644
index 0000000..1872a36
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton-sim.dts
@@ -0,0 +1,25 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msmkrypton.dtsi"
+
+/ {
+ model = "Qualcomm MSM KRYPTON SIM";
+ compatible = "qcom,msmkrypton-sim", "qcom,msmkrypton", "qcom,sim";
+ qcom,msm-id = <187 16 0>;
+};
+
+&uartdm3{
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
new file mode 100644
index 0000000..db61dab
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -0,0 +1,54 @@
+/* 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.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Qualcomm MSM KRYPTON";
+ compatible = "qcom,msmkrypton";
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@f9000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0xf9000000 0x1000>,
+ <0xf9002000 0x1000>;
+ };
+
+ msmgpio: gpio@fd510000 {
+ compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0xfd510000 0x4000>;
+ ngpio = <89>;
+ interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
+ };
+
+ timer: msm-qtimer@f9021000 {
+ compatible = "arm,armv7-timer";
+ reg = <0xf9021000 0x1000>;
+ interrupts = <0 7 0>;
+ irq-is-not-percpu;
+ clock-frequency = <19200000>;
+ };
+
+ uartdm3: serial@f991f000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991f000 0x1000>;
+ interrupts = <0 109 0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 45f0868..f23a096 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -375,3 +375,4 @@
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QSEECOM=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
new file mode 100644
index 0000000..69bc36e
--- /dev/null
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -0,0 +1,116 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+# CONFIG_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSMKRYPTON=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_LOGGING=y
+CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_RUNTIME=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_MTD_MSM_NAND is not set
+CONFIG_MTD_MSM_QPIC_NAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_ANDROID_PMEM is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_MSM=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_EXT3_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 601fcfa..c510889 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -391,6 +391,21 @@
select MEMORY_HOLE_CARVEOUT
select MSM_RPM_LOG
+config ARCH_MSMKRYPTON
+ bool "MSMKRYPTON"
+ select ARM_GIC
+ select CPU_V7
+ select MSM_GPIOMUX
+ select MSM_RPM_SMD
+ select MSM_NATIVE_RESTART
+ select MSM_RESTART_V2
+ select MSM_SPM_V2
+ select MSM_PM8X60 if PM
+ select MULTI_IRQ_HANDLER
+ select GPIO_MSM_V3
+ select MAY_HAVE_SPARSE_IRQ
+ select SPARSE_IRQ
+
config ARCH_MSM8610
bool "MSM8610"
select ARM_GIC
@@ -1074,6 +1089,7 @@
default "0x00000000" if ARCH_MSM8610
default "0x10000000" if ARCH_FSM9XXX
default "0x00200000" if ARCH_MSM9625
+ default "0x00200000" if ARCH_MSMKRYPTON
default "0x00200000" if !MSM_STACKED_MEMORY
default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
default "0x20000000" if ARCH_QSD8X50
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c14ac6..7c78395 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
ifndef CONFIG_ARCH_MPQ8092
ifndef CONFIG_ARCH_MSM8610
ifndef CONFIG_ARCH_MSMZINC
+ifndef CONFIG_ARCH_MSMKRYPTON
obj-y += nand_partitions.o
endif
endif
@@ -131,6 +132,7 @@
endif
endif
endif
+endif
obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -304,6 +306,7 @@
obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
@@ -368,6 +371,7 @@
obj-$(CONFIG_ARCH_MSM9615) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8974) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index e3b8d73..f20f6ae 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -62,6 +62,9 @@
zreladdr-$(CONFIG_ARCH_MSMZINC) := 0x00008000
dtb-$(CONFIG_ARCH_MSMZINC) += msmzinc-sim.dtb
+# MSMKRYPTON
+ zreladdr-$(CONFIG_ARCH_MSMKRYPTON) := 0x00208000
+ dtb-$(CONFIG_ARCH_MSMKRYPTON) += msmkrypton-sim.dtb
# MSM9615
zreladdr-$(CONFIG_ARCH_MSM9615) := 0x40808000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 0533d06..c60e89a 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -653,32 +653,32 @@
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 75000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 75000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 75000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 75000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 75000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 76000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 77000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 78000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 79000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 80000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 81000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 82000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 83000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 84000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 85000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 86000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 87000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 87500, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 88500, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 89500, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 90500, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 91500, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 92000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 93000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 94000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 95000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 875000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 920000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 930000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 950000, 3200000 },
{ 0, { 0 } }
};
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 6371b9d..3582914 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -25,6 +25,7 @@
#include <linux/of_irq.h>
#include <linux/memory.h>
#include <linux/regulator/qpnp-regulator.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
@@ -112,7 +113,7 @@
msm_clock_init(&msm8226_rumi_clock_init_data);
else
msm_clock_init(&msm8226_clock_init_data);
-
+ tsens_tm_init_driver();
msm_thermal_device_init();
}
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 15d7679..0fdb298 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -35,6 +35,18 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting wcnss_5wire_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
.gpio = 10, /* BLSP1 QUP3 I2C_SDA */
@@ -74,6 +86,44 @@
},
};
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+ {
+ .gpio = 23,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 24,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 25,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 26,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 27,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+};
+
void __init msm8610_init_gpiomux(void)
{
int rc;
@@ -85,4 +135,6 @@
}
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+ msm_gpiomux_install(wcnss_5wire_interface,
+ ARRAY_SIZE(wcnss_5wire_interface));
}
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 99db345..67334d5 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -24,6 +24,7 @@
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/memory.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/arch_timer.h>
#include <asm/hardware/gic.h>
@@ -105,6 +106,7 @@
msm_lpmrs_module_init();
msm_spm_device_init();
qpnp_regulator_init();
+ tsens_tm_init_driver();
msm_thermal_device_init();
if (of_board_is_rumi())
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 9b69c8f..0ca55d1 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -22,6 +22,7 @@
#include <linux/memory.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/krait-regulator.h>
+#include <linux/msm_tsens.h>
#include <linux/msm_thermal.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
@@ -101,6 +102,7 @@
msm_clock_init(&msm8974_rumi_clock_init_data);
else
msm_clock_init(&msm8974_clock_init_data);
+ tsens_tm_init_driver();
msm_thermal_device_init();
}
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 923dc2a..3bb00bb 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/memory.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
@@ -237,6 +238,7 @@
msm_spm_device_init();
msm_clock_init(&msm9625_clock_init_data);
msm9625_init_buses();
+ tsens_tm_init_driver();
}
void __init msm9625_init(void)
diff --git a/arch/arm/mach-msm/board-krypton-gpiomux.c b/arch/arm/mach-msm/board-krypton-gpiomux.c
new file mode 100644
index 0000000..3d86ba7
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton-gpiomux.c
@@ -0,0 +1,52 @@
+/* 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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+static struct gpiomux_setting gpio_uart_config = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+ {
+ .gpio = 8, /* BLSP1 UART TX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_uart_config,
+ },
+ },
+ {
+ .gpio = 9, /* BLSP1 UART RX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_uart_config,
+ },
+ },
+};
+
+void __init msmkrypton_init_gpiomux(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init_dt();
+ if (rc) {
+ pr_err("%s failed %d\n", __func__, rc);
+ return;
+ }
+
+ msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+}
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
new file mode 100644
index 0000000..aada3b0
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -0,0 +1,84 @@
+/* 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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+ CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+ .table = msm_clocks_dummy,
+ .size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msmkrypton_add_drivers(void)
+{
+ msm_smd_init();
+ msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init msmkrypton_map_io(void)
+{
+ msm_map_msmkrypton_io();
+}
+
+void __init msmkrypton_init(void)
+{
+ if (socinfo_init() < 0)
+ pr_err("%s: socinfo_init() failed\n", __func__);
+
+ msmkrypton_init_gpiomux();
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ msmkrypton_add_drivers();
+}
+
+static const char *msmkrypton_dt_match[] __initconst = {
+ "qcom,msmkrypton",
+ NULL
+};
+
+DT_MACHINE_START(MSMKRYPTON_DT, "Qualcomm MSM Krypton (Flattened Device Tree)")
+ .map_io = msmkrypton_map_io,
+ .init_irq = msm_dt_init_irq,
+ .init_machine = msmkrypton_init,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_dt_timer,
+ .dt_compat = msmkrypton_dt_match,
+ .restart = msm_restart,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 768efe7..c9c71f0 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2782,6 +2782,9 @@
CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
CLK_LOOKUP("measure_clk", l2_m_clk, ""),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("rf_clk", cxo_a2.c, "fb000000.qcom,wcnss-wlan"),
+
CLK_LOOKUP("iface_clk", mdp_ahb_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("lcdc_clk", mdp_lcdc_clk.c, "fd900000.qcom,mdss_mdp"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e6874b7..9751ab2 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5107,6 +5107,7 @@
CLK_LOOKUP("bus_clk", venus0_axi_clk.c, "fdc00000.qcom,vidc"),
CLK_LOOKUP("mem_clk", venus0_ocmemnoc_clk.c, "fdc00000.qcom,vidc"),
+ CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fd8c4024.qcom,gdsc"),
/* LPASS clocks */
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 5da1663..0b8240c 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -756,10 +756,10 @@
spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
reg_val = readl_relaxed(b->retain_reg);
switch (flags) {
- case CLKFLAG_RETAIN:
+ case CLKFLAG_RETAIN_MEM:
reg_val |= b->retain_mask;
break;
- case CLKFLAG_NORETAIN:
+ case CLKFLAG_NORETAIN_MEM:
reg_val &= ~b->retain_mask;
break;
default:
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 8bdc496..8c2121f 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -570,6 +570,40 @@
return __branch_clk_reset(BCR_REG(branch), action);
}
+static int branch_clk_set_flags(struct clk *c, unsigned flags)
+{
+ u32 cbcr_val;
+ unsigned long irq_flags;
+ struct branch_clk *branch = to_branch_clk(c);
+ int ret = 0;
+
+ spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
+ cbcr_val = readl_relaxed(CBCR_REG(branch));
+ switch (flags) {
+ case CLKFLAG_RETAIN_PERIPH:
+ cbcr_val |= BIT(13);
+ break;
+ case CLKFLAG_NORETAIN_PERIPH:
+ cbcr_val &= ~BIT(13);
+ break;
+ case CLKFLAG_RETAIN_MEM:
+ cbcr_val |= BIT(14);
+ break;
+ case CLKFLAG_NORETAIN_MEM:
+ cbcr_val &= ~BIT(14);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ writel_relaxed(cbcr_val, CBCR_REG(branch));
+ spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
+
+ /* Make sure write is issued before returning. */
+ mb();
+
+ return ret;
+}
+
/*
* Voteable clock functions
*/
@@ -824,6 +858,7 @@
.list_rate = branch_clk_list_rate,
.round_rate = branch_clk_round_rate,
.reset = branch_clk_reset,
+ .set_flags = branch_clk_set_flags,
.handoff = branch_clk_handoff,
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 9b34465..fecb720 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -159,7 +159,7 @@
unvote_vdd_level(clk->vdd_class, level);
}
-/* Returns true if the rate is valid without voting for it */
+/* Check if the rate is within the voltage limits of the clock. */
static bool is_rate_valid(struct clk *clk, unsigned long rate)
{
int level;
@@ -171,6 +171,92 @@
return level >= 0;
}
+/**
+ * __clk_pre_reparent() - Set up the new parent before switching to it and
+ * prevent the enable state of the child clock from changing.
+ * @c: The child clock that's going to switch parents
+ * @new: The new parent that the child clock is going to switch to
+ * @flags: Pointer to scratch space to save spinlock flags
+ *
+ * Cannot be called from atomic context.
+ *
+ * Use this API to set up the @new parent clock to be able to support the
+ * current prepare and enable state of the child clock @c. Once the parent is
+ * set up, the child clock can safely switch to it.
+ *
+ * The caller shall grab the prepare_lock of clock @c before calling this API
+ * and only release it after calling __clk_post_reparent() for clock @c (or
+ * if this API fails). This is necessary to prevent the prepare state of the
+ * child clock @c from changing while the reparenting is in progress. Since
+ * this API takes care of grabbing the enable lock of @c, only atomic
+ * operation are allowed between calls to __clk_pre_reparent and
+ * __clk_post_reparent()
+ *
+ * The scratch space pointed to by @flags should not be altered before
+ * calling __clk_post_reparent() for clock @c.
+ *
+ * See also: __clk_post_reparent()
+ */
+int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags)
+{
+ int rc;
+
+ if (c->prepare_count) {
+ rc = clk_prepare(new);
+ if (rc)
+ return rc;
+ }
+
+ spin_lock_irqsave(&c->lock, *flags);
+ if (c->count) {
+ rc = clk_enable(new);
+ if (rc) {
+ spin_unlock_irqrestore(&c->lock, *flags);
+ clk_unprepare(new);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+/**
+ * __clk_post_reparent() - Release requirements on old parent after switching
+ * away from it and allow changes to the child clock's enable state.
+ * @c: The child clock that switched parents
+ * @old: The old parent that the child clock switched away from or the new
+ * parent of a failed reparent attempt.
+ * @flags: Pointer to scratch space where spinlock flags were saved
+ *
+ * Cannot be called from atomic context.
+ *
+ * This API works in tandem with __clk_pre_reparent. Use this API to
+ * - Remove prepare and enable requirements from the @old parent after
+ * switching away from it
+ * - Or, undo the effects of __clk_pre_reparent() after a failed attempt to
+ * change parents
+ *
+ * The caller shall release the prepare_lock of @c that was grabbed before
+ * calling __clk_pre_reparent() only after this API is called (or if
+ * __clk_pre_reparent() fails). This is necessary to prevent the prepare
+ * state of the child clock @c from changing while the reparenting is in
+ * progress. Since this API releases the enable lock of @c, the limit to
+ * atomic operations set by __clk_pre_reparent() is no longer present.
+ *
+ * The scratch space pointed to by @flags shall not be altered since the call
+ * to __clk_pre_reparent() for clock @c.
+ *
+ * See also: __clk_pre_reparent()
+ */
+void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags)
+{
+ if (c->count)
+ clk_disable(old);
+ spin_unlock_irqrestore(&c->lock, *flags);
+
+ if (c->prepare_count)
+ clk_unprepare(old);
+}
+
int clk_prepare(struct clk *clk)
{
int ret = 0;
@@ -357,6 +443,9 @@
if (!clk->ops->set_rate)
return -ENOSYS;
+ if (!is_rate_valid(clk, rate))
+ return -EINVAL;
+
mutex_lock(&clk->prepare_lock);
/* Return early if the rate isn't going to change */
@@ -364,31 +453,32 @@
goto out;
trace_clock_set_rate(name, rate, raw_smp_processor_id());
+
+ start_rate = clk->rate;
+
+ /* Enforce vdd requirements for target frequency. */
if (clk->prepare_count) {
- start_rate = clk->rate;
- /* Enforce vdd requirements for target frequency. */
rc = vote_rate_vdd(clk, rate);
if (rc)
goto out;
- rc = clk->ops->set_rate(clk, rate);
- if (rc)
- goto err_set_rate;
- /* Release vdd requirements for starting frequency. */
- unvote_rate_vdd(clk, start_rate);
- } else if (is_rate_valid(clk, rate)) {
- rc = clk->ops->set_rate(clk, rate);
- } else {
- rc = -EINVAL;
}
- if (!rc)
- clk->rate = rate;
+ rc = clk->ops->set_rate(clk, rate);
+ if (rc)
+ goto err_set_rate;
+ clk->rate = rate;
+
+ /* Release vdd requirements for starting frequency. */
+ if (clk->prepare_count)
+ unvote_rate_vdd(clk, start_rate);
+
out:
mutex_unlock(&clk->prepare_lock);
return rc;
err_set_rate:
- unvote_rate_vdd(clk, rate);
+ if (clk->prepare_count)
+ unvote_rate_vdd(clk, rate);
goto out;
}
EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index d5fe866..76ad9b8 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -206,7 +206,7 @@
}
/* Prevent core memory from collapsing when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
/* Return clocks to their state before this function. */
restore_clocks(fs);
@@ -238,7 +238,7 @@
return rc;
/* Allow core memory to collapse when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN_MEM);
/* Halt all bus ports in the power domain. */
if (fs->bus_port0) {
@@ -292,7 +292,7 @@
err_port2_halt:
msm_bus_axi_portunhalt(fs->bus_port0);
err:
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
restore_clocks(fs);
return rc;
}
@@ -360,7 +360,7 @@
clk_prepare_enable(fs->core_clk);
/* Prevent core memory from collapsing when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
/* Return clocks to their state before this function. */
restore_clocks(fs);
@@ -390,7 +390,7 @@
return rc;
/* Allow core memory to collapse when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN_MEM);
/* Halt all bus ports in the power domain. */
if (fs->bus_port0) {
@@ -436,7 +436,7 @@
return 0;
err:
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
restore_clocks(fs);
return rc;
}
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index e5b9d93..6665d66 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -22,6 +22,8 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
#define PWR_ON_MASK BIT(31)
#define EN_REST_WAIT_MASK (0xF << 20)
@@ -42,6 +44,7 @@
struct regulator_dev *rdev;
struct regulator_desc rdesc;
void __iomem *gdscr;
+ struct clk *core_clk;
};
static int gdsc_is_enabled(struct regulator_dev *rdev)
@@ -108,6 +111,7 @@
struct resource *res;
struct gdsc *sc;
uint32_t regval;
+ bool retain_mems;
int ret;
sc = devm_kzalloc(&pdev->dev, sizeof(struct gdsc), GFP_KERNEL);
@@ -151,6 +155,16 @@
regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
writel_relaxed(regval, sc->gdscr);
+ retain_mems = of_property_read_bool(pdev->dev.of_node,
+ "qcom,retain-mems");
+ if (retain_mems) {
+ sc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(sc->core_clk))
+ return PTR_ERR(sc->core_clk);
+ clk_set_flags(sc->core_clk, CLKFLAG_RETAIN_MEM);
+ clk_set_flags(sc->core_clk, CLKFLAG_RETAIN_PERIPH);
+ }
+
sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
pdev->dev.of_node);
if (IS_ERR(sc->rdev)) {
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 35257b2..72f5051 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -601,6 +601,7 @@
void msm_map_fsm9xxx_io(void);
void msm_map_8974_io(void);
void msm_map_zinc_io(void);
+void msm_map_msmkrypton_io(void);
void msm_map_msm8625_io(void);
void msm_map_msm9625_io(void);
void msm_init_irq(void);
@@ -611,6 +612,7 @@
void msm_8974_init_gpiomux(void);
void msmzinc_init_gpiomux(void);
void msm9625_init_gpiomux(void);
+void msmkrypton_init_gpiomux(void);
void msm_map_mpq8092_io(void);
void mpq8092_init_gpiomux(void);
void msm_map_msm8226_io(void);
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 528e9d5..2a33228 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -156,6 +156,8 @@
int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags);
+void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags);
/* Register clocks with the MSM clock driver */
int msm_clock_register(struct clk_lookup *table, size_t size);
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index 1191bb7..1809456 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -16,8 +16,10 @@
#define CLKFLAG_NOINVERT 0x00000002
#define CLKFLAG_NONEST 0x00000004
#define CLKFLAG_NORESET 0x00000008
-#define CLKFLAG_RETAIN 0x00000040
-#define CLKFLAG_NORETAIN 0x00000080
+#define CLKFLAG_RETAIN_PERIPH 0x00000010
+#define CLKFLAG_NORETAIN_PERIPH 0x00000020
+#define CLKFLAG_RETAIN_MEM 0x00000040
+#define CLKFLAG_NORETAIN_MEM 0x00000080
#define CLKFLAG_SKIP_HANDOFF 0x00000100
#define CLKFLAG_MIN 0x00000400
#define CLKFLAG_MAX 0x00000800
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
new file mode 100644
index 0000000..a8b9da5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+#define __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSMKRYPTON_SHARED_RAM_PHYS 0x00000000
+
+#define MSMKRYPTON_TLMM_PHYS 0xFD510000
+#define MSMKRYPTON_TLMM_SIZE SZ_16K
+
+#define MSMKRYPTON_MPM2_PSHOLD_PHYS 0xFC4AB000
+#define MSMKRYPTON_MPM2_PSHOLD_SIZE SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d3706cd..f27eb36 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -134,6 +134,7 @@
#include "msm_iomap-8092.h"
#include "msm_iomap-8226.h"
#include "msm_iomap-8610.h"
+#include "msm_iomap-krypton.h"
#endif
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/include/mach/ramdump.h
similarity index 100%
rename from arch/arm/mach-msm/ramdump.h
rename to arch/arm/mach-msm/include/mach/ramdump.h
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index b898fe8..7c9882e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -48,6 +48,8 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
#define early_machine_is_msmzinc() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
+#define early_machine_is_msmkrypton() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmkrypton")
#else
#define of_board_is_sim() 0
#define of_board_is_rumi() 0
@@ -62,6 +64,7 @@
#define early_machine_is_msm8610() 0
#define early_machine_is_mpq8092() 0
#define early_machine_is_msmzinc() 0
+#define early_machine_is_msmkrypton() 0
#endif
#define PLATFORM_SUBTYPE_SGLTE 6
@@ -100,6 +103,7 @@
MSM_CPU_8610,
MSM_CPU_8625Q,
MSM_CPU_ZINC,
+ MSM_CPU_KRYPTON,
};
enum pmic_model {
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 25cbc87..c5ad35d 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -258,6 +258,7 @@
enum sps_callback_case {
SPS_CALLBACK_BAM_ERROR_IRQ = 1, /* BAM ERROR IRQ */
SPS_CALLBACK_BAM_HRESP_ERR_IRQ, /* Erroneous HResponse */
+ SPS_CALLBACK_BAM_TIMER_IRQ, /* Inactivity timer */
};
/*
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 19c7acd..ecac4a5 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -507,6 +507,25 @@
}
#endif /* CONFIG_ARCH_MSM9625 */
+#ifdef CONFIG_ARCH_MSMKRYPTON
+static struct map_desc msmkrypton_io_desc[] __initdata = {
+ MSM_CHIP_DEVICE(TLMM, MSMKRYPTON),
+ MSM_CHIP_DEVICE(MPM2_PSHOLD, MSMKRYPTON),
+ {
+ .virtual = (unsigned long) MSM_SHARED_RAM_BASE,
+ .length = MSM_SHARED_RAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init msm_map_msmkrypton_io(void)
+{
+ msm_shared_ram_phys = MSMKRYPTON_SHARED_RAM_PHYS;
+ msm_map_io(msmkrypton_io_desc, ARRAY_SIZE(msmkrypton_io_desc));
+ of_scan_flat_dt(msm_scan_dt_map_imem, NULL);
+}
+#endif /* CONFIG_ARCH_MSMKRYPTON */
+
#ifdef CONFIG_ARCH_MPQ8092
static struct map_desc mpq8092_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index edfb45b..d71787c 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/memory_alloc.h>
#include <linux/memblock.h>
+#include <asm/memblock.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/mach/map.h>
@@ -160,42 +161,18 @@
static void __init reserve_memory_for_mempools(void)
{
- int memtype, memreg_type;
+ int memtype;
struct memtype_reserve *mt;
- struct memblock_region *mr, *mr_candidate = NULL;
- int ret;
+ phys_addr_t alignment;
mt = &reserve_info->memtype_reserve_table[0];
for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
continue;
-
- /* Choose the memory block with the highest physical
- * address which is large enough, so that we will not
- * take memory from the lowest memory bank which the kernel
- * is in (and cause boot problems) and so that we might
- * be able to steal memory that would otherwise become
- * highmem.
- */
- for_each_memblock(memory, mr) {
- memreg_type =
- reserve_info->paddr_to_memtype(mr->base);
- if (memtype != memreg_type)
- continue;
- if (mr->size >= mt->size
- && (mr_candidate == NULL
- || mr->base > mr_candidate->base))
- mr_candidate = mr;
- }
- BUG_ON(mr_candidate == NULL);
- /* bump mt up against the top of the region */
- mt->start = mr_candidate->base + mr_candidate->size - mt->size;
- ret = memblock_reserve(mt->start, mt->size);
- BUG_ON(ret);
- ret = memblock_free(mt->start, mt->size);
- BUG_ON(ret);
- ret = memblock_remove(mt->start, mt->size);
- BUG_ON(ret);
+ alignment = (mt->flags & MEMTYPE_FLAGS_1M_ALIGN) ?
+ SZ_1M : PAGE_SIZE;
+ mt->start = arm_memblock_steal(mt->size, alignment);
+ BUG_ON(!mt->start);
}
}
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index db67f7d..0ada902 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -36,8 +36,8 @@
#include <mach/msm_smsm.h>
#include <mach/msm_dsps.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
-#include "ramdump.h"
#include "timer.h"
#define DRV_NAME "msm_dsps"
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 4e8674c..63bb7dc 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -36,9 +36,9 @@
#include <asm-generic/io-64-nonatomic-lo-hi.h>
#include <mach/msm_iomap.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
-#include "ramdump.h"
#define pil_err(desc, fmt, ...) \
dev_err(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 65d60d6..df5ea35 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -21,10 +21,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define PPSS_RESET 0x2594
#define PPSS_RESET_PROC_RESET 0x2
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index c9e2e0d..d44add6 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -29,11 +29,11 @@
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
#include "smd_private.h"
-#include "ramdump.h"
#define GSS_CSR_AHB_CLK_SEL 0x0
#define GSS_CSR_RESET 0x4
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index e95fae8..30f480a 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,11 +24,11 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define MARM_BOOT_CONTROL 0x0010
#define MARM_RESET 0x2BD4
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index edaa60c..0df8739 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -29,10 +29,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define PRONTO_PMU_COMMON_GDSCR 0x24
#define PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE BIT(0)
@@ -410,6 +410,15 @@
int ret, err_fatal_gpio, irq;
uint32_t regval;
+ int clk_ready = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-proxy-unvote", 0);
+ if (clk_ready < 0)
+ return clk_ready;
+
+ clk_ready = gpio_to_irq(clk_ready);
+ if (clk_ready < 0)
+ return clk_ready;
+
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -460,6 +469,7 @@
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
+ desc->proxy_unvote_irq = clk_ready;
if (pas_supported(PAS_WCNSS) > 0) {
desc->ops = &pil_pronto_ops_trusted;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 66adc2b..0575a3d 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,8 +23,8 @@
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
+#include <mach/ramdump.h>
-#include "ramdump.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 1387433..f05bcdb 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012,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
@@ -24,9 +24,9 @@
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
+#include <mach/ramdump.h>
#include "smd_private.h"
-#include "ramdump.h"
#include "sysmon.h"
#include "peripheral-loader.h"
#include "pil-q6v4.h"
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index f2b090f..1821ab1 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012,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
@@ -22,9 +22,9 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "smd_private.h"
-#include "ramdump.h"
#include "peripheral-loader.h"
#include "pil-q6v4.h"
#include "scm-pas.h"
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 72253fd..3b2bbf3 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -27,11 +27,11 @@
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
#include <mach/scm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
#include "scm-pas.h"
-#include "ramdump.h"
#include "sysmon.h"
#define QDSP6SS_RST_EVB 0x010
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index cfd8daf..8f7d262 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -30,10 +30,10 @@
#include <mach/subsystem_restart.h>
#include <mach/clk.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
-#include "ramdump.h"
#include "sysmon.h"
/* Q6 Register Offsets */
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 33301de..a2665b4 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -23,10 +23,10 @@
#include <linux/wcnss_wlan.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#include "smd_private.h"
#define RIVA_PMU_A2XB_CFG 0xB8
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index b0150d4..4e9e54b 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -30,10 +30,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
/* VENUS WRAPPER registers */
#define VENUS_WRAPPER_HW_VERSION 0x0
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 7f09a56..be21025 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -25,7 +25,7 @@
#include <linux/elf.h>
#include <linux/wait.h>
-#include "ramdump.h"
+#include <mach/ramdump.h>
#define RAMDUMP_WAIT_MSECS 120000
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index f1a7185..f48b538 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -262,7 +262,7 @@
rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
- if (cpu_is_msm8974() || cpu_is_msm8226()) {
+ if (cpu_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
} else {
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 40ef20e..8a9042e 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -38,6 +38,7 @@
#include <linux/suspend.h>
#include <linux/of.h>
#include <linux/of_irq.h>
+
#include <mach/msm_smd.h>
#include <mach/msm_iomap.h>
#include <mach/system.h>
@@ -45,11 +46,12 @@
#include <mach/socinfo.h>
#include <mach/proc_comm.h>
#include <mach/msm_ipc_logging.h>
+#include <mach/ramdump.h>
+
#include <asm/cacheflush.h>
#include "smd_private.h"
#include "modem_notifier.h"
-#include "ramdump.h"
#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
|| defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 5158f8e..83f7a1d 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -351,6 +351,9 @@
/* zinc IDs */
[178] = MSM_CPU_ZINC,
+ /* krypton IDs */
+ [187] = MSM_CPU_KRYPTON,
+
/* Uninitialized IDs are not known to run Linux.
MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
considered as unknown CPU. */
@@ -854,6 +857,10 @@
dummy_socinfo.id = 178;
strlcpy(dummy_socinfo.build_id, "msmzinc - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msmkrypton()) {
+ dummy_socinfo.id = 187;
+ strlcpy(dummy_socinfo.build_id, "msmkrypton - ",
+ sizeof(dummy_socinfo.build_id));
}
strlcat(dummy_socinfo.build_id, "Dummy socinfo",
sizeof(dummy_socinfo.build_id));
diff --git a/block/row-iosched.c b/block/row-iosched.c
index 3baec8c..c8ba344 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -158,6 +158,20 @@
};
/**
+ * struct starvation_data - data for starvation management
+ * @starvation_limit: number of times this priority class
+ * can tolerate being starved
+ * @starvation_counter: number of requests from higher
+ * priority classes that were dispatched while this
+ * priority request were pending
+ *
+ */
+struct starvation_data {
+ int starvation_limit;
+ int starvation_counter;
+};
+
+/**
* struct row_queue - Per block device rqueue structure
* @dispatch_queue: dispatch rqueue
* @row_queues: array of priority request queues
@@ -170,6 +184,8 @@
* complete.
* @pending_urgent_rq: pointer to the pending urgent request
* @last_served_ioprio_class: I/O priority class that was last dispatched from
+ * @reg_prio_starvation: starvation data for REGULAR priority queues
+ * @low_prio_starvation: starvation data for LOW priority queues
* @cycle_flags: used for marking unserved queueus
*
*/
@@ -183,6 +199,12 @@
bool urgent_in_flight;
struct request *pending_urgent_rq;
int last_served_ioprio_class;
+
+#define ROW_REG_STARVATION_TOLLERANCE 50
+ struct starvation_data reg_prio_starvation;
+#define ROW_LOW_STARVATION_TOLLERANCE 1000
+ struct starvation_data low_prio_starvation;
+
unsigned int cycle_flags;
};
@@ -258,6 +280,42 @@
return HRTIMER_NORESTART;
}
+/*
+ * row_regular_req_pending() - Check if there are REGULAR priority requests
+ * Pending in scheduler
+ * @rd: pointer to struct row_data
+ *
+ * Returns True if there are REGULAR priority requests in scheduler queues.
+ * False, otherwise.
+ */
+static inline bool row_regular_req_pending(struct row_data *rd)
+{
+ int i;
+
+ for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++)
+ if (!list_empty(&rd->row_queues[i].fifo))
+ return true;
+ return false;
+}
+
+/*
+ * row_low_req_pending() - Check if there are LOW priority requests
+ * Pending in scheduler
+ * @rd: pointer to struct row_data
+ *
+ * Returns True if there are LOW priority requests in scheduler queues.
+ * False, otherwise.
+ */
+static inline bool row_low_req_pending(struct row_data *rd)
+{
+ int i;
+
+ for (i = ROWQ_LOW_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
+ if (!list_empty(&rd->row_queues[i].fifo))
+ return true;
+ return false;
+}
+
/******************* Elevator callback functions *********************/
/*
@@ -272,6 +330,7 @@
struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
struct row_queue *rqueue = RQ_ROWQ(rq);
s64 diff_ms;
+ bool queue_was_empty = list_empty(&rqueue->fifo);
list_add_tail(&rq->queuelist, &rqueue->fifo);
rd->nr_reqs[rq_data_dir(rq)]++;
@@ -316,7 +375,8 @@
!rd->pending_urgent_rq && !rd->urgent_in_flight) {
/* Handle High Priority queues */
if (rqueue->prio < ROWQ_REG_PRIO_IDX &&
- rd->last_served_ioprio_class != IOPRIO_CLASS_RT) {
+ rd->last_served_ioprio_class != IOPRIO_CLASS_RT &&
+ queue_was_empty) {
row_log_rowq(rd, rqueue->prio,
"added (high prio) urgent request");
rq->cmd_flags |= REQ_URGENT;
@@ -472,12 +532,21 @@
row_log_rowq(rd, rqueue->prio,
" Dispatched request %p nr_disp = %d", rq,
rqueue->nr_dispatched);
- if (rqueue->prio < ROWQ_REG_PRIO_IDX)
+ if (rqueue->prio < ROWQ_REG_PRIO_IDX) {
rd->last_served_ioprio_class = IOPRIO_CLASS_RT;
- else if (rqueue->prio < ROWQ_LOW_PRIO_IDX)
+ if (row_regular_req_pending(rd))
+ rd->reg_prio_starvation.starvation_counter++;
+ if (row_low_req_pending(rd))
+ rd->low_prio_starvation.starvation_counter++;
+ } else if (rqueue->prio < ROWQ_LOW_PRIO_IDX) {
rd->last_served_ioprio_class = IOPRIO_CLASS_BE;
- else
+ rd->reg_prio_starvation.starvation_counter = 0;
+ if (row_low_req_pending(rd))
+ rd->low_prio_starvation.starvation_counter++;
+ } else {
rd->last_served_ioprio_class = IOPRIO_CLASS_IDLE;
+ rd->low_prio_starvation.starvation_counter = 0;
+ }
}
/*
@@ -517,7 +586,18 @@
rd->rd_idle_data.idling_queue_idx =
ROWQ_MAX_PRIO;
}
- ret = IOPRIO_CLASS_RT;
+
+ if (row_regular_req_pending(rd) &&
+ (rd->reg_prio_starvation.starvation_counter >=
+ rd->reg_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_BE;
+ else if (row_low_req_pending(rd) &&
+ (rd->low_prio_starvation.starvation_counter >=
+ rd->low_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_IDLE;
+ else
+ ret = IOPRIO_CLASS_RT;
+
goto done;
}
}
@@ -546,7 +626,12 @@
!force && row_queues_def[i].idling_enabled)
goto initiate_idling;
} else {
- ret = IOPRIO_CLASS_BE;
+ if (row_low_req_pending(rd) &&
+ (rd->low_prio_starvation.starvation_counter >=
+ rd->low_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_IDLE;
+ else
+ ret = IOPRIO_CLASS_BE;
goto done;
}
}
@@ -716,6 +801,10 @@
ktime_set(0, 0);
}
+ rdata->reg_prio_starvation.starvation_limit =
+ ROW_REG_STARVATION_TOLLERANCE;
+ rdata->low_prio_starvation.starvation_limit =
+ ROW_LOW_STARVATION_TOLLERANCE;
/*
* Currently idling is enabled only for READ queues. If we want to
* enable it for write queues also, note that idling frequency will
@@ -865,42 +954,42 @@
return count;
}
-#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
+#define SHOW_FUNCTION(__FUNC, __VAR) \
static ssize_t __FUNC(struct elevator_queue *e, char *page) \
{ \
struct row_data *rowd = e->elevator_data; \
int __data = __VAR; \
- if (__CONV) \
- __data = jiffies_to_msecs(__data); \
return row_var_show(__data, (page)); \
}
SHOW_FUNCTION(row_hp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum);
SHOW_FUNCTION(row_rp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum);
SHOW_FUNCTION(row_hp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum);
SHOW_FUNCTION(row_rp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum);
SHOW_FUNCTION(row_rp_write_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum);
SHOW_FUNCTION(row_lp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum);
SHOW_FUNCTION(row_lp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
-SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms, 0);
-SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms, 0);
+ rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum);
+SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms);
+SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms);
+SHOW_FUNCTION(row_reg_starv_limit_show,
+ rowd->reg_prio_starvation.starvation_limit);
+SHOW_FUNCTION(row_low_starv_limit_show,
+ rowd->low_prio_starvation.starvation_limit);
#undef SHOW_FUNCTION
-#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
static ssize_t __FUNC(struct elevator_queue *e, \
const char *page, size_t count) \
{ \
struct row_data *rowd = e->elevator_data; \
int __data; \
int ret = row_var_store(&__data, (page), count); \
- if (__CONV) \
- __data = (int)msecs_to_jiffies(__data); \
if (__data < (MIN)) \
__data = (MIN); \
else if (__data > (MAX)) \
@@ -909,29 +998,35 @@
return ret; \
}
STORE_FUNCTION(row_hp_read_quantum_store,
-&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX, 0);
+&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX);
STORE_FUNCTION(row_rp_read_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_hp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rp_write_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_lp_read_quantum_store,
&rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_lp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
+STORE_FUNCTION(row_reg_starv_limit_store,
+ &rowd->reg_prio_starvation.starvation_limit,
+ 1, INT_MAX);
+STORE_FUNCTION(row_low_starv_limit_store,
+ &rowd->low_prio_starvation.starvation_limit,
+ 1, INT_MAX);
#undef STORE_FUNCTION
@@ -949,6 +1044,8 @@
ROW_ATTR(lp_swrite_quantum),
ROW_ATTR(rd_idle_data),
ROW_ATTR(rd_idle_data_freq),
+ ROW_ATTR(reg_starv_limit),
+ ROW_ATTR(low_starv_limit),
__ATTR_NULL
};
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 2440404..408e705 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1530,6 +1530,45 @@
}
+static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
+ struct qcedev_control *podev)
+{
+ /* if intending to use HW key make sure key fields are set
+ * correctly and HW key is indeed supported in target
+ */
+ if (req->encklen == 0) {
+ int i;
+ for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
+ if (req->enckey[i])
+ goto error;
+ if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
+ (req->op != QCEDEV_OPER_DEC_NO_KEY))
+ if (!podev->platform_support.hw_key_support)
+ goto error;
+ } else {
+ if (req->encklen == QCEDEV_AES_KEY_192) {
+ if (!podev->ce_support.aes_key_192)
+ goto error;
+ } else {
+ /* if not using HW key make sure key
+ * length is valid
+ */
+ if ((req->mode == QCEDEV_AES_MODE_XTS)) {
+ if (!((req->encklen == QCEDEV_AES_KEY_128*2) ||
+ (req->encklen == QCEDEV_AES_KEY_256*2)))
+ goto error;
+ } else {
+ if (!((req->encklen == QCEDEV_AES_KEY_128) ||
+ (req->encklen == QCEDEV_AES_KEY_256)))
+ goto error;
+ }
+ }
+ }
+ return 0;
+error:
+ return -EINVAL;
+}
+
static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
struct qcedev_control *podev)
{
@@ -1542,36 +1581,13 @@
if ((req->alg >= QCEDEV_ALG_LAST) ||
(req->mode >= QCEDEV_AES_DES_MODE_LAST))
goto error;
- if (req->alg == QCEDEV_ALG_AES) {
- if ((req->mode == QCEDEV_AES_MODE_XTS) &&
- (!podev->ce_support.aes_xts))
- goto error;
- /* if intending to use HW key make sure key fields are set
- * correctly and HW key is indeed supported in target
- */
- if (req->encklen == 0) {
- int i;
- for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
- if (req->enckey[i])
+
+ if ((req->mode == QCEDEV_AES_MODE_XTS) && (!podev->ce_support.aes_xts))
goto error;
- if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
- (req->op != QCEDEV_OPER_DEC_NO_KEY))
- if (!podev->platform_support.hw_key_support)
+
+ if (req->alg == QCEDEV_ALG_AES)
+ if (qcedev_check_cipher_key(req, podev))
goto error;
- } else {
- if (req->encklen == QCEDEV_AES_KEY_192) {
- if (!podev->ce_support.aes_key_192)
- goto error;
- } else {
- /* if not using HW key make sure key
- * length is valid
- */
- if (!((req->encklen == QCEDEV_AES_KEY_128) ||
- (req->encklen == QCEDEV_AES_KEY_256)))
- goto error;
- }
- }
- }
/* if using a byteoffset, make sure it is CTR mode using vbuf */
if (req->byteoffset) {
if (req->mode != QCEDEV_AES_MODE_CTR)
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 05ef87c..85c25c7 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -677,12 +677,10 @@
return 0;
};
-static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
- unsigned int len)
+
+static int _qcrypto_check_aes_keylen(struct crypto_ablkcipher *cipher,
+ struct crypto_priv *cp, unsigned int len)
{
- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
- struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
- struct crypto_priv *cp = ctx->cp;
switch (len) {
case AES_KEYSIZE_128:
@@ -695,8 +693,40 @@
crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
};
- ctx->enc_key_len = len;
- memcpy(ctx->enc_key, key, len);
+
+ return 0;
+}
+
+static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
+ unsigned int len)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_priv *cp = ctx->cp;
+
+ if (_qcrypto_check_aes_keylen(cipher, cp, len)) {
+ return -EINVAL;
+ } else {
+ ctx->enc_key_len = len;
+ memcpy(ctx->enc_key, key, len);
+ }
+ return 0;
+};
+
+static int _qcrypto_setkey_aes_xts(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int len)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_priv *cp = ctx->cp;
+
+
+ if (_qcrypto_check_aes_keylen(cipher, cp, len/2)) {
+ return -EINVAL;
+ } else {
+ ctx->enc_key_len = len;
+ memcpy(ctx->enc_key, key, len);
+ }
return 0;
};
@@ -3124,7 +3154,7 @@
.ivsize = AES_BLOCK_SIZE,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
- .setkey = _qcrypto_setkey_aes,
+ .setkey = _qcrypto_setkey_aes_xts,
.encrypt = _qcrypto_enc_aes_xts,
.decrypt = _qcrypto_dec_aes_xts,
},
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index 60a6b81..f4f9a92 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o
+obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o ion_removed_heap.o
obj-$(CONFIG_CMA) += ion_cma_heap.o ion_cma_secure_heap.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_MSM) += msm/
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 9610dfe..aeffb52 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -39,10 +39,6 @@
ion_phys_addr_t base;
unsigned long allocated_bytes;
unsigned long total_size;
- int (*request_region)(void *);
- int (*release_region)(void *);
- atomic_t map_count;
- void *bus_id;
unsigned int has_outer_cache;
};
@@ -130,79 +126,33 @@
buffer->sg_table = 0;
}
-static int ion_carveout_request_region(struct ion_carveout_heap *carveout_heap)
-{
- int ret_value = 0;
- if (atomic_inc_return(&carveout_heap->map_count) == 1) {
- if (carveout_heap->request_region) {
- ret_value = carveout_heap->request_region(
- carveout_heap->bus_id);
- if (ret_value) {
- pr_err("Unable to request SMI region");
- atomic_dec(&carveout_heap->map_count);
- }
- }
- }
- return ret_value;
-}
-
-static int ion_carveout_release_region(struct ion_carveout_heap *carveout_heap)
-{
- int ret_value = 0;
- if (atomic_dec_and_test(&carveout_heap->map_count)) {
- if (carveout_heap->release_region) {
- ret_value = carveout_heap->release_region(
- carveout_heap->bus_id);
- if (ret_value)
- pr_err("Unable to release SMI region");
- }
- }
- return ret_value;
-}
-
void *ion_carveout_heap_map_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
void *ret_value;
- if (ion_carveout_request_region(carveout_heap))
- return NULL;
-
if (ION_IS_CACHED(buffer->flags))
ret_value = ioremap_cached(buffer->priv_phys, buffer->size);
else
ret_value = ioremap(buffer->priv_phys, buffer->size);
- if (!ret_value)
- ion_carveout_release_region(carveout_heap);
return ret_value;
}
void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
-
__arm_iounmap(buffer->vaddr);
buffer->vaddr = NULL;
- ion_carveout_release_region(carveout_heap);
return;
}
int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
int ret_value = 0;
- if (ion_carveout_request_region(carveout_heap))
- return -EINVAL;
-
if (!ION_IS_CACHED(buffer->flags))
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -211,19 +161,9 @@
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
- if (ret_value)
- ion_carveout_release_region(carveout_heap);
return ret_value;
}
-void ion_carveout_heap_unmap_user(struct ion_heap *heap,
- struct ion_buffer *buffer)
-{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
- ion_carveout_release_region(carveout_heap);
-}
-
int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
@@ -473,7 +413,6 @@
.phys = ion_carveout_heap_phys,
.map_user = ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
- .unmap_user = ion_carveout_heap_unmap_user,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
.map_dma = ion_carveout_heap_map_dma,
.unmap_dma = ion_carveout_heap_unmap_dma,
@@ -511,19 +450,6 @@
carveout_heap->total_size = heap_data->size;
carveout_heap->has_outer_cache = heap_data->has_outer_cache;
- if (heap_data->extra_data) {
- struct ion_co_heap_pdata *extra_data =
- heap_data->extra_data;
-
- if (extra_data->setup_region)
- carveout_heap->bus_id = extra_data->setup_region();
- if (extra_data->request_region)
- carveout_heap->request_region =
- extra_data->request_region;
- if (extra_data->release_region)
- carveout_heap->release_region =
- extra_data->release_region;
- }
return &carveout_heap->heap;
}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 28ef1a5..8d45f9d 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -23,44 +23,9 @@
#include <linux/mutex.h>
#include <linux/rbtree.h>
#include <linux/ion.h>
-#include <linux/iommu.h>
#include <linux/seq_file.h>
-enum {
- DI_PARTITION_NUM = 0,
- DI_DOMAIN_NUM = 1,
- DI_MAX,
-};
-
-/**
- * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
- * @iova_addr - iommu virtual address
- * @node - rb node to exist in the buffer's tree of iommu mappings
- * @domain_info - contains the partition number and domain number
- * domain_info[1] = domain number
- * domain_info[0] = partition number
- * @ref - for reference counting this mapping
- * @mapped_size - size of the iova space mapped
- * (may not be the same as the buffer size)
- * @flags - iommu domain/partition specific flags.
- *
- * Represents a mapping of one ion buffer to a particular iommu domain
- * and address range. There may exist other mappings of this buffer in
- * different domains or address ranges. All mappings will have the same
- * cacheability and security.
- */
-struct ion_iommu_map {
- unsigned long iova_addr;
- struct rb_node node;
- union {
- int domain_info[DI_MAX];
- uint64_t key;
- };
- struct ion_buffer *buffer;
- struct kref ref;
- int mapped_size;
- unsigned long flags;
-};
+#include "msm_ion_priv.h"
struct ion_buffer *ion_handle_buffer(struct ion_handle *handle);
@@ -190,26 +155,6 @@
bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
/**
- * struct mem_map_data - represents information about the memory map for a heap
- * @node: rb node used to store in the tree of mem_map_data
- * @addr: start address of memory region.
- * @addr: end address of memory region.
- * @size: size of memory region
- * @client_name: name of the client who owns this buffer.
- *
- */
-struct mem_map_data {
- struct rb_node node;
- ion_phys_addr_t addr;
- ion_phys_addr_t addr_end;
- unsigned long size;
- const char *client_name;
-};
-
-#define iommu_map_domain(__m) ((__m)->domain_info[1])
-#define iommu_map_partition(__m) ((__m)->domain_info[0])
-
-/**
* ion_device_create - allocates and returns an ion device
* @custom_ioctl: arch specific ioctl function if applicable
*
@@ -251,15 +196,6 @@
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *);
void ion_carveout_heap_destroy(struct ion_heap *);
-struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
-void ion_iommu_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *);
-void ion_cp_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_reusable_heap_create(struct ion_platform_heap *);
-void ion_reusable_heap_destroy(struct ion_heap *);
-
/**
* kernel api to allocate/free from carveout -- used when carveout is
* used to back an architecture specific custom heap
@@ -269,88 +205,10 @@
void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
unsigned long size);
-#ifdef CONFIG_CMA
-struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *);
-void ion_cma_heap_destroy(struct ion_heap *);
-
-struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *);
-void ion_secure_cma_heap_destroy(struct ion_heap *);
-#endif
-
-struct ion_heap *msm_get_contiguous_heap(void);
/**
- * The carveout/cp heap returns physical addresses, since 0 may be a valid
+ * The carveout heap returns physical addresses, since 0 may be a valid
* physical address, this is used to indicate allocation failed
*/
#define ION_CARVEOUT_ALLOCATE_FAIL -1
-#define ION_CP_ALLOCATE_FAIL -1
-/**
- * The reserved heap returns physical addresses, since 0 may be a valid
- * physical address, this is used to indicate allocation failed
- */
-#define ION_RESERVED_ALLOCATE_FAIL -1
-
-/**
- * ion_map_fmem_buffer - map fmem allocated memory into the kernel
- * @buffer - buffer to map
- * @phys_base - physical base of the heap
- * @virt_base - virtual base of the heap
- * @flags - flags for the heap
- *
- * Map fmem allocated memory into the kernel address space. This
- * is designed to be used by other heaps that need fmem behavior.
- * The virtual range must be pre-allocated.
- */
-void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
- void *virt_base, unsigned long flags);
-
-/**
- * ion_do_cache_op - do cache operations.
- *
- * @client - pointer to ION client.
- * @handle - pointer to buffer handle.
- * @uaddr - virtual address to operate on.
- * @offset - offset from physical address.
- * @len - Length of data to do cache operation on.
- * @cmd - Cache operation to perform:
- * ION_IOC_CLEAN_CACHES
- * ION_IOC_INV_CACHES
- * ION_IOC_CLEAN_INV_CACHES
- *
- * Returns 0 on success
- */
-int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
- void *uaddr, unsigned long offset, unsigned long len,
- unsigned int cmd);
-
-void ion_cp_heap_get_base(struct ion_heap *heap, unsigned long *base,
- unsigned long *size);
-
-void ion_mem_map_show(struct ion_heap *heap);
-
-
-
-int ion_secure_handle(struct ion_client *client, struct ion_handle *handle,
- int version, void *data, int flags);
-
-int ion_unsecure_handle(struct ion_client *client, struct ion_handle *handle);
-
-int ion_heap_allow_secure_allocation(enum ion_heap_type type);
-
-int ion_heap_allow_heap_secure(enum ion_heap_type type);
-
-int ion_heap_allow_handle_secure(enum ion_heap_type type);
-
-/**
- * ion_create_chunked_sg_table - helper function to create sg table
- * with specified chunk size
- * @buffer_base: The starting address used for the sg dma address
- * @chunk_size: The size of each entry in the sg table
- * @total_size: The total size of the sg table (i.e. the sum of the
- * entries). This will be rounded up to the nearest
- * multiple of `chunk_size'
- */
-struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
- size_t chunk_size, size_t total_size);
#endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/ion_removed_heap.c b/drivers/gpu/ion/ion_removed_heap.c
new file mode 100644
index 0000000..4759e40
--- /dev/null
+++ b/drivers/gpu/ion/ion_removed_heap.c
@@ -0,0 +1,441 @@
+/*
+ * drivers/gpu/ion/ion_removed_heap.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/spinlock.h>
+
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/seq_file.h>
+#include "ion_priv.h"
+
+#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
+#include <linux/msm_ion.h>
+
+struct ion_removed_heap {
+ struct ion_heap heap;
+ struct gen_pool *pool;
+ ion_phys_addr_t base;
+ unsigned long allocated_bytes;
+ unsigned long total_size;
+ int (*request_region)(void *);
+ int (*release_region)(void *);
+ atomic_t map_count;
+ void *bus_id;
+ unsigned int has_outer_cache;
+};
+
+ion_phys_addr_t ion_removed_allocate(struct ion_heap *heap,
+ unsigned long size,
+ unsigned long align)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ unsigned long offset = gen_pool_alloc_aligned(removed_heap->pool,
+ size, ilog2(align));
+
+ if (!offset) {
+ if ((removed_heap->total_size -
+ removed_heap->allocated_bytes) >= size)
+ pr_debug("%s: heap %s has enough memory (%lx) but the allocation of size %lx still failed. Memory is probably fragmented.",
+ __func__, heap->name,
+ removed_heap->total_size -
+ removed_heap->allocated_bytes, size);
+ return ION_CARVEOUT_ALLOCATE_FAIL;
+ }
+
+ removed_heap->allocated_bytes += size;
+ return offset;
+}
+
+void ion_removed_free(struct ion_heap *heap, ion_phys_addr_t addr,
+ unsigned long size)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
+ return;
+ gen_pool_free(removed_heap->pool, addr, size);
+ removed_heap->allocated_bytes -= size;
+}
+
+static int ion_removed_heap_phys(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ *addr = buffer->priv_phys;
+ *len = buffer->size;
+ return 0;
+}
+
+static int ion_removed_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long size, unsigned long align,
+ unsigned long flags)
+{
+ buffer->priv_phys = ion_removed_allocate(heap, size, align);
+ return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
+}
+
+static void ion_removed_heap_free(struct ion_buffer *buffer)
+{
+ struct ion_heap *heap = buffer->heap;
+
+ ion_removed_free(heap, buffer->priv_phys, buffer->size);
+ buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL;
+}
+
+struct sg_table *ion_removed_heap_map_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct sg_table *table;
+ int ret;
+
+ table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ ret = sg_alloc_table(table, 1, GFP_KERNEL);
+ if (ret)
+ goto err0;
+
+ table->sgl->length = buffer->size;
+ table->sgl->offset = 0;
+ table->sgl->dma_address = buffer->priv_phys;
+
+ return table;
+
+err0:
+ kfree(table);
+ return ERR_PTR(ret);
+}
+
+void ion_removed_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ if (buffer->sg_table)
+ sg_free_table(buffer->sg_table);
+ kfree(buffer->sg_table);
+ buffer->sg_table = 0;
+}
+
+static int ion_removed_request_region(struct ion_removed_heap *removed_heap)
+{
+ int ret_value = 0;
+ if (atomic_inc_return(&removed_heap->map_count) == 1) {
+ if (removed_heap->request_region) {
+ ret_value = removed_heap->request_region(
+ removed_heap->bus_id);
+ if (ret_value) {
+ pr_err("Unable to request SMI region");
+ atomic_dec(&removed_heap->map_count);
+ }
+ }
+ }
+ return ret_value;
+}
+
+static int ion_removed_release_region(struct ion_removed_heap *removed_heap)
+{
+ int ret_value = 0;
+ if (atomic_dec_and_test(&removed_heap->map_count)) {
+ if (removed_heap->release_region) {
+ ret_value = removed_heap->release_region(
+ removed_heap->bus_id);
+ if (ret_value)
+ pr_err("Unable to release SMI region");
+ }
+ }
+ return ret_value;
+}
+
+void *ion_removed_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ void *ret_value;
+
+ if (ion_removed_request_region(removed_heap))
+ return NULL;
+
+ if (ION_IS_CACHED(buffer->flags))
+ ret_value = ioremap_cached(buffer->priv_phys, buffer->size);
+ else
+ ret_value = ioremap(buffer->priv_phys, buffer->size);
+
+ if (!ret_value)
+ ion_removed_release_region(removed_heap);
+ return ret_value;
+}
+
+void ion_removed_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ __arm_iounmap(buffer->vaddr);
+ buffer->vaddr = NULL;
+
+ ion_removed_release_region(removed_heap);
+ return;
+}
+
+int ion_removed_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ int ret_value = 0;
+
+ if (ion_removed_request_region(removed_heap))
+ return -EINVAL;
+
+ if (!ION_IS_CACHED(buffer->flags))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ ret_value = remap_pfn_range(vma, vma->vm_start,
+ __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+
+ if (ret_value)
+ ion_removed_release_region(removed_heap);
+ return ret_value;
+}
+
+void ion_removed_heap_unmap_user(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ ion_removed_release_region(removed_heap);
+}
+
+int ion_removed_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
+ void *vaddr, unsigned int offset, unsigned int length,
+ unsigned int cmd)
+{
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ unsigned int size_to_vmap, total_size;
+ int i, j;
+ void *ptr = NULL;
+ ion_phys_addr_t buff_phys = buffer->priv_phys;
+
+ if (!vaddr) {
+ /*
+ * Split the vmalloc space into smaller regions in
+ * order to clean and/or invalidate the cache.
+ */
+ size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8);
+ total_size = buffer->size;
+
+ for (i = 0; i < total_size; i += size_to_vmap) {
+ size_to_vmap = min(size_to_vmap, total_size - i);
+ for (j = 0; j < 10 && size_to_vmap; ++j) {
+ ptr = ioremap(buff_phys, size_to_vmap);
+ if (ptr) {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
+ buff_phys += size_to_vmap;
+ break;
+ } else {
+ size_to_vmap >>= 1;
+ }
+ }
+ if (!ptr) {
+ pr_err("Couldn't io-remap the memory\n");
+ return -EINVAL;
+ }
+ iounmap(ptr);
+ }
+ } else {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (removed_heap->has_outer_cache) {
+ unsigned long pstart = buffer->priv_phys + offset;
+ outer_cache_op(pstart, pstart + length);
+ }
+ return 0;
+}
+
+static int ion_removed_print_debug(struct ion_heap *heap, struct seq_file *s,
+ const struct rb_root *mem_map)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ seq_printf(s, "total bytes currently allocated: %lx\n",
+ removed_heap->allocated_bytes);
+ seq_printf(s, "total heap size: %lx\n", removed_heap->total_size);
+
+ if (mem_map) {
+ unsigned long base = removed_heap->base;
+ unsigned long size = removed_heap->total_size;
+ unsigned long end = base+size;
+ unsigned long last_end = base;
+ struct rb_node *n;
+
+ seq_printf(s, "\nMemory Map\n");
+ seq_printf(s, "%16.s %14.s %14.s %14.s\n",
+ "client", "start address", "end address",
+ "size (hex)");
+
+ for (n = rb_first(mem_map); n; n = rb_next(n)) {
+ struct mem_map_data *data =
+ rb_entry(n, struct mem_map_data, node);
+ const char *client_name = "(null)";
+
+ if (last_end < data->addr) {
+ phys_addr_t da;
+
+ da = data->addr-1;
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ "FREE", &last_end, &da,
+ data->addr-last_end,
+ data->addr-last_end);
+ }
+
+ if (data->client_name)
+ client_name = data->client_name;
+
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
+ data->size, data->size);
+ last_end = data->addr_end+1;
+ }
+ if (last_end < end) {
+ seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n", "FREE",
+ last_end, end-1, end-last_end, end-last_end);
+ }
+ }
+ return 0;
+}
+
+static struct ion_heap_ops removed_heap_ops = {
+ .allocate = ion_removed_heap_allocate,
+ .free = ion_removed_heap_free,
+ .phys = ion_removed_heap_phys,
+ .map_user = ion_removed_heap_map_user,
+ .map_kernel = ion_removed_heap_map_kernel,
+ .unmap_user = ion_removed_heap_unmap_user,
+ .unmap_kernel = ion_removed_heap_unmap_kernel,
+ .map_dma = ion_removed_heap_map_dma,
+ .unmap_dma = ion_removed_heap_unmap_dma,
+ .cache_op = ion_removed_cache_ops,
+ .print_debug = ion_removed_print_debug,
+};
+
+struct ion_heap *ion_removed_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_removed_heap *removed_heap;
+ int ret;
+
+ removed_heap = kzalloc(sizeof(struct ion_removed_heap), GFP_KERNEL);
+ if (!removed_heap)
+ return ERR_PTR(-ENOMEM);
+
+ removed_heap->pool = gen_pool_create(12, -1);
+ if (!removed_heap->pool) {
+ kfree(removed_heap);
+ return ERR_PTR(-ENOMEM);
+ }
+ removed_heap->base = heap_data->base;
+ ret = gen_pool_add(removed_heap->pool, removed_heap->base,
+ heap_data->size, -1);
+ if (ret < 0) {
+ gen_pool_destroy(removed_heap->pool);
+ kfree(removed_heap);
+ return ERR_PTR(-EINVAL);
+ }
+ removed_heap->heap.ops = &removed_heap_ops;
+ removed_heap->heap.type = ION_HEAP_TYPE_REMOVED;
+ removed_heap->allocated_bytes = 0;
+ removed_heap->total_size = heap_data->size;
+ removed_heap->has_outer_cache = heap_data->has_outer_cache;
+
+ if (heap_data->extra_data) {
+ struct ion_co_heap_pdata *extra_data =
+ heap_data->extra_data;
+
+ if (extra_data->setup_region)
+ removed_heap->bus_id = extra_data->setup_region();
+ if (extra_data->request_region)
+ removed_heap->request_region =
+ extra_data->request_region;
+ if (extra_data->release_region)
+ removed_heap->release_region =
+ extra_data->release_region;
+ }
+ return &removed_heap->heap;
+}
+
+void ion_removed_heap_destroy(struct ion_heap *heap)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ gen_pool_destroy(removed_heap->pool);
+ kfree(removed_heap);
+ removed_heap = NULL;
+}
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 4b55875..a7dcd19 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -770,6 +770,10 @@
heap = ion_secure_cma_heap_create(heap_data);
break;
#endif
+ case ION_HEAP_TYPE_REMOVED:
+ heap = ion_removed_heap_create(heap_data);
+ break;
+
default:
heap = ion_heap_create(heap_data);
}
@@ -807,6 +811,9 @@
ion_secure_cma_heap_destroy(heap);
break;
#endif
+ case ION_HEAP_TYPE_REMOVED:
+ ion_removed_heap_destroy(heap);
+ break;
default:
ion_heap_destroy(heap);
}
diff --git a/drivers/gpu/ion/msm_ion_priv.h b/drivers/gpu/ion/msm_ion_priv.h
new file mode 100644
index 0000000..2729ce2
--- /dev/null
+++ b/drivers/gpu/ion/msm_ion_priv.h
@@ -0,0 +1,153 @@
+/*
+ * drivers/gpu/ion/ion_priv.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MSM_ION_PRIV_H
+#define _MSM_ION_PRIV_H
+
+#include <linux/kref.h>
+#include <linux/mm_types.h>
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/ion.h>
+#include <linux/iommu.h>
+#include <linux/seq_file.h>
+
+enum {
+ DI_PARTITION_NUM = 0,
+ DI_DOMAIN_NUM = 1,
+ DI_MAX,
+};
+
+/**
+ * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
+ * @iova_addr - iommu virtual address
+ * @node - rb node to exist in the buffer's tree of iommu mappings
+ * @domain_info - contains the partition number and domain number
+ * domain_info[1] = domain number
+ * domain_info[0] = partition number
+ * @ref - for reference counting this mapping
+ * @mapped_size - size of the iova space mapped
+ * (may not be the same as the buffer size)
+ * @flags - iommu domain/partition specific flags.
+ *
+ * Represents a mapping of one ion buffer to a particular iommu domain
+ * and address range. There may exist other mappings of this buffer in
+ * different domains or address ranges. All mappings will have the same
+ * cacheability and security.
+ */
+struct ion_iommu_map {
+ unsigned long iova_addr;
+ struct rb_node node;
+ union {
+ int domain_info[DI_MAX];
+ uint64_t key;
+ };
+ struct ion_buffer *buffer;
+ struct kref ref;
+ int mapped_size;
+ unsigned long flags;
+};
+
+/**
+ * struct mem_map_data - represents information about the memory map for a heap
+ * @node: rb node used to store in the tree of mem_map_data
+ * @addr: start address of memory region.
+ * @addr: end address of memory region.
+ * @size: size of memory region
+ * @client_name: name of the client who owns this buffer.
+ *
+ */
+struct mem_map_data {
+ struct rb_node node;
+ ion_phys_addr_t addr;
+ ion_phys_addr_t addr_end;
+ unsigned long size;
+ const char *client_name;
+};
+
+#define iommu_map_domain(__m) ((__m)->domain_info[1])
+#define iommu_map_partition(__m) ((__m)->domain_info[0])
+
+struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
+void ion_iommu_heap_destroy(struct ion_heap *);
+
+struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *);
+void ion_cp_heap_destroy(struct ion_heap *);
+
+#ifdef CONFIG_CMA
+struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *);
+void ion_cma_heap_destroy(struct ion_heap *);
+
+struct ion_heap *ion_secure_cma_heap_create(struct ion_platform_heap *);
+void ion_secure_cma_heap_destroy(struct ion_heap *);
+#endif
+
+struct ion_heap *ion_removed_heap_create(struct ion_platform_heap *);
+void ion_removed_heap_destroy(struct ion_heap *);
+
+#define ION_CP_ALLOCATE_FAIL -1
+#define ION_RESERVED_ALLOCATE_FAIL -1
+
+/**
+ * ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @uaddr - virtual address to operate on.
+ * @offset - offset from physical address.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ * ION_IOC_CLEAN_CACHES
+ * ION_IOC_INV_CACHES
+ * ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *uaddr, unsigned long offset, unsigned long len,
+ unsigned int cmd);
+
+void ion_cp_heap_get_base(struct ion_heap *heap, unsigned long *base,
+ unsigned long *size);
+
+void ion_mem_map_show(struct ion_heap *heap);
+
+
+
+int ion_secure_handle(struct ion_client *client, struct ion_handle *handle,
+ int version, void *data, int flags);
+
+int ion_unsecure_handle(struct ion_client *client, struct ion_handle *handle);
+
+int ion_heap_allow_secure_allocation(enum ion_heap_type type);
+
+int ion_heap_allow_heap_secure(enum ion_heap_type type);
+
+int ion_heap_allow_handle_secure(enum ion_heap_type type);
+
+/**
+ * ion_create_chunked_sg_table - helper function to create sg table
+ * with specified chunk size
+ * @buffer_base: The starting address used for the sg dma address
+ * @chunk_size: The size of each entry in the sg table
+ * @total_size: The total size of the sg table (i.e. the sum of the
+ * entries). This will be rounded up to the nearest
+ * multiple of `chunk_size'
+ */
+struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
+ size_t chunk_size, size_t total_size);
+#endif /* _MSM_ION_PRIV_H */
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index a2f0e60..c768bb7 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -396,6 +396,19 @@
#define A3XX_VBIF_OUT_AXI_AMEMTYPE_CONF0 0x3058
#define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
+#define A3XX_VBIF_PERF_CNT_EN 0x3070
+#define A3XX_VBIF_PERF_CNT_CLR 0x3071
+#define A3XX_VBIF_PERF_CNT_SEL 0x3072
+#define A3XX_VBIF_PERF_CNT0_LO 0x3073
+#define A3XX_VBIF_PERF_CNT0_HI 0x3074
+#define A3XX_VBIF_PERF_CNT1_LO 0x3075
+#define A3XX_VBIF_PERF_CNT1_HI 0x3076
+#define A3XX_VBIF_PERF_PWR_CNT0_LO 0x3077
+#define A3XX_VBIF_PERF_PWR_CNT0_HI 0x3078
+#define A3XX_VBIF_PERF_PWR_CNT1_LO 0x3079
+#define A3XX_VBIF_PERF_PWR_CNT1_HI 0x307a
+#define A3XX_VBIF_PERF_PWR_CNT2_LO 0x307b
+#define A3XX_VBIF_PERF_PWR_CNT2_HI 0x307c
/* Bit flags for RBBM_CTL */
#define RBBM_RBBM_CTL_RESET_PWR_CTR0 BIT(0)
@@ -670,11 +683,11 @@
#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
+#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A305B_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A330_RBBM_GPR0_CTL_DEFAULT 0x00000000
-#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x00000000
+#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x05515455
/* COUNTABLE FOR SP PERFCOUNTER */
#define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E
@@ -682,4 +695,20 @@
#define SP0_ICL1_MISSES 0x1A
#define SP_FS_CFLOW_INSTRUCTIONS 0x0C
+/* VBIF PERFCOUNTER ENA/CLR values */
+#define VBIF_PERF_CNT_0 BIT(0)
+#define VBIF_PERF_CNT_1 BIT(1)
+#define VBIF_PERF_PWR_CNT_0 BIT(2)
+#define VBIF_PERF_PWR_CNT_1 BIT(3)
+#define VBIF_PERF_PWR_CNT_2 BIT(4)
+
+/* VBIF PERFCOUNTER SEL values */
+#define VBIF_PERF_CNT_0_SEL 0
+#define VBIF_PERF_CNT_0_SEL_MASK 0x7f
+#define VBIF_PERF_CNT_1_SEL 8
+#define VBIF_PERF_CNT_1_SEL_MASK 0x7f00
+
+/* VBIF countables */
+#define VBIF_DDR_TOTAL_CYCLES 110
+
#endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 62b6a71..5589ff0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1859,7 +1859,8 @@
}
if (status)
KGSL_FT_ERR(rb->device,
- "Failed to find the command sequence after eop timestamp\n");
+ "Failed to find the command sequence after eop timestamp %x\n",
+ global_eop);
return status;
}
@@ -1972,44 +1973,38 @@
/* find the start of bad command sequence in rb */
context = idr_find(&device->context_idr, ft_data->context_id);
- /* Look for the command stream that is right after the global eop */
-
- if (!context) {
- /*
- * If there is no context then fault tolerance does not need to
- * replay anything, just reset GPU and thats it
- */
- return;
- }
ft_data->ft_policy = adreno_dev->ft_policy;
if (!ft_data->ft_policy)
ft_data->ft_policy = KGSL_FT_DEFAULT_POLICY;
+ /* Look for the command stream that is right after the global eop */
ret = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
ft_data->global_eop + 1, false);
if (ret) {
ft_data->ft_policy |= KGSL_FT_TEMP_DISABLE;
return;
- } else
+ } else {
+ ft_data->start_of_replay_cmds = rb_rptr;
ft_data->ft_policy &= ~KGSL_FT_TEMP_DISABLE;
+ }
- ft_data->start_of_replay_cmds = rb_rptr;
-
- adreno_context = context->devctxt;
- if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
- if (ft_data->ib1) {
- ret = _find_hanging_ib_sequence(rb,
- &rb_rptr, ft_data->ib1);
- if (ret) {
- KGSL_FT_ERR(device,
- "Start not found for replay IB sequence\n");
- ret = 0;
- return;
+ if (context) {
+ adreno_context = context->devctxt;
+ if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
+ if (ft_data->ib1) {
+ ret = _find_hanging_ib_sequence(rb,
+ &rb_rptr, ft_data->ib1);
+ if (ret) {
+ KGSL_FT_ERR(device,
+ "Start not found for replay IB seq\n");
+ ret = 0;
+ return;
+ }
+ ft_data->start_of_replay_cmds = rb_rptr;
+ ft_data->replay_for_snapshot = rb_rptr;
}
- ft_data->start_of_replay_cmds = rb_rptr;
- ft_data->replay_for_snapshot = rb_rptr;
}
}
}
@@ -2046,9 +2041,6 @@
_adreno_ft_restart_device(struct kgsl_device *device,
struct kgsl_context *context)
{
-
- struct adreno_context *adreno_context = context->devctxt;
-
/* restart device */
if (adreno_stop(device)) {
KGSL_FT_ERR(device, "Device stop failed\n");
@@ -2065,9 +2057,11 @@
return 1;
}
- if (context)
+ if (context) {
+ struct adreno_context *adreno_context = context->devctxt;
kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
KGSL_MEMSTORE_GLOBAL);
+ }
/* If iommu is used then we need to make sure that the iommu clocks
* are on since there could be commands in pipeline that touch iommu */
@@ -2168,13 +2162,22 @@
struct adreno_context *adreno_context = NULL;
struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
unsigned int long_ib = 0;
+ static int no_context_ft;
context = idr_find(&device->context_idr, ft_data->context_id);
if (context == NULL) {
KGSL_FT_ERR(device, "Last context unknown id:%d\n",
ft_data->context_id);
- goto play_good_cmds;
+ if (no_context_ft) {
+ /*
+ * If 2 consecutive no context ft occurred then
+ * just reset GPU
+ */
+ no_context_ft = 0;
+ goto play_good_cmds;
+ }
} else {
+ no_context_ft = 0;
adreno_context = context->devctxt;
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
/*
@@ -2230,7 +2233,7 @@
}
/* Do not try the reply if hang is due to a pagefault */
- if (adreno_context->pagefault) {
+ if (adreno_context && adreno_context->pagefault) {
if ((ft_data->context_id == adreno_context->id) &&
(ft_data->global_eop == adreno_context->pagefault_ts)) {
ft_data->ft_policy &= ~KGSL_FT_REPLAY;
@@ -2295,7 +2298,7 @@
/* EOF not found in RB, discard till EOF in
next IB submission */
- if (i == ft_data->bad_rb_size) {
+ if (adreno_context && (i == ft_data->bad_rb_size)) {
adreno_context->flags |= CTXT_FLAGS_SKIP_EOF;
KGSL_FT_INFO(device,
"EOF not found in RB, skip next issueib till EOF\n");
@@ -2332,8 +2335,14 @@
ft_data->good_rb_buffer, ft_data->good_rb_size);
if (ret) {
- /* If we fail here we can try to invalidate another
- * context and try fault tolerance again */
+ /*
+ * If we fail here we can try to invalidate another
+ * context and try fault tolerance again, although
+ * we will only try ft with no context once to avoid
+ * going into continuous loop of trying ft with no context
+ */
+ if (!context)
+ no_context_ft = 1;
ret = -EAGAIN;
KGSL_FT_ERR(device, "Playing good commands unsuccessful\n");
goto done;
@@ -3166,6 +3175,31 @@
"Fault tolerance no context found\n");
}
}
+ for (i = 0; i < ft_detect_regs_count; i++) {
+ if (curr_reg_val[i] != prev_reg_val[i]) {
+ fast_hang_detected = 0;
+
+ /* Check for long IB here */
+ if ((i >=
+ LONG_IB_DETECT_REG_INDEX_START)
+ &&
+ (i <=
+ LONG_IB_DETECT_REG_INDEX_END))
+ long_ib_detected = 0;
+ }
+ }
+
+ if (fast_hang_detected) {
+ KGSL_FT_ERR(device,
+ "Proc %s, ctxt_id %d ts %d triggered fault tolerance"
+ " on global ts %d\n",
+ curr_context ? curr_context->pid_name : "",
+ curr_context ? curr_context->id : 0,
+ (kgsl_readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED) + 1),
+ curr_global_ts + 1);
+ return 1;
+ }
if (curr_context != NULL) {
@@ -3175,31 +3209,6 @@
curr_context->pid_name, curr_context->ib_gpu_time_used,
curr_global_ts+1);
- for (i = 0; i < ft_detect_regs_count; i++) {
- if (curr_reg_val[i] != prev_reg_val[i]) {
- fast_hang_detected = 0;
-
- /* Check for long IB here */
- if ((i >=
- LONG_IB_DETECT_REG_INDEX_START)
- &&
- (i <=
- LONG_IB_DETECT_REG_INDEX_END))
- long_ib_detected = 0;
- }
- }
-
- if (fast_hang_detected) {
- KGSL_FT_ERR(device,
- "Proc %s, ctxt_id %d ts %d triggered fault tolerance"
- " on global ts %d\n",
- curr_context->pid_name, curr_context->id
- , (kgsl_readtimestamp(device, context,
- KGSL_TIMESTAMP_RETIRED)+1),
- curr_global_ts+1);
- return 1;
- }
-
if ((long_ib_detected) &&
(!(curr_context->flags &
CTXT_FLAGS_NO_FAULT_TOLERANCE))) {
@@ -3229,10 +3238,6 @@
}
}
}
- } else {
- KGSL_FT_ERR(device,
- "Last context unknown id:%d\n",
- curr_context_id);
}
} else {
/* GPU is moving forward */
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 13c723a..be5c786 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2752,6 +2752,58 @@
return;
}
+static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device,
+ unsigned int counter,
+ unsigned int countable)
+{
+ unsigned int in, out, bit, sel;
+
+ if (countable > 0x7f)
+ return;
+
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
+
+ if (counter == 0) {
+ bit = VBIF_PERF_CNT_0;
+ sel = (sel & ~VBIF_PERF_CNT_0_SEL_MASK) | countable;
+ } else if (counter == 1) {
+ bit = VBIF_PERF_CNT_1;
+ sel = (sel & ~VBIF_PERF_CNT_1_SEL_MASK)
+ | (countable << VBIF_PERF_CNT_1_SEL);
+ }
+
+ out = in | bit;
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+}
+
+static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
+ unsigned int countable)
+{
+ unsigned int in, out, bit;
+
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+ if (countable == 0)
+ bit = VBIF_PERF_PWR_CNT_0;
+ else if (countable == 1)
+ bit = VBIF_PERF_PWR_CNT_1;
+ else
+ bit = VBIF_PERF_PWR_CNT_2;
+
+ out = in | bit;
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+}
+
/*
* a3xx_perfcounter_enable - Configure a performance counter for a countable
* @adreno_dev - Adreno device to configure
@@ -2775,9 +2827,13 @@
if (counter > a3xx_perfcounter_reglist[group].count)
return;
- /* Special case - power */
+ /* Special cases */
if (group == KGSL_PERFCOUNTER_GROUP_PWR)
return a3xx_perfcounter_enable_pwr(device, countable);
+ else if (group == KGSL_PERFCOUNTER_GROUP_VBIF)
+ return a3xx_perfcounter_enable_vbif(device, counter, countable);
+ else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
+ return a3xx_perfcounter_enable_vbif_pwr(device, countable);
reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
@@ -3265,6 +3321,16 @@
{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
};
+static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO },
+};
+static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
+};
+
static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
{ a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) },
{ a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) },
@@ -3279,6 +3345,8 @@
{ a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) },
{ a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) },
{ a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) },
+ { a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) },
+ { a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) },
};
static struct adreno_perfcounters a3xx_perfcounters = {
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 0e3e046..813305a 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -69,6 +69,7 @@
struct kgsl_fence_event_priv {
struct kgsl_context *context;
+ unsigned int timestamp;
};
/**
@@ -85,7 +86,7 @@
void *priv, u32 context_id, u32 timestamp)
{
struct kgsl_fence_event_priv *ev = priv;
- kgsl_sync_timeline_signal(ev->context->timeline, timestamp);
+ kgsl_sync_timeline_signal(ev->context->timeline, ev->timestamp);
kgsl_context_put(ev->context);
kfree(ev);
}
@@ -125,6 +126,7 @@
if (event == NULL)
return -ENOMEM;
event->context = context;
+ event->timestamp = timestamp;
kgsl_context_get(context);
pt = kgsl_sync_pt_create(context->timeline, timestamp);
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index aea3431..df0eeb3 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -222,8 +222,8 @@
struct timespec timeout);
int (*start_filtering) (struct dmx_ts_feed* feed);
int (*stop_filtering) (struct dmx_ts_feed* feed);
- int (*set_indexing_params) (struct dmx_ts_feed *feed,
- struct dmx_indexing_video_params *params);
+ int (*set_video_codec) (struct dmx_ts_feed *feed,
+ enum dmx_video_codec video_codec);
int (*get_decoder_buff_status)(
struct dmx_ts_feed *feed,
struct dmx_buffer_status *dmx_buffer_status);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 219970b..75a11c1 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -2711,10 +2711,9 @@
(para->pes_type == DMX_PES_VIDEO1) ||
(para->pes_type == DMX_PES_VIDEO2) ||
(para->pes_type == DMX_PES_VIDEO3)) {
-
- if (tsfeed->set_indexing_params) {
- ret = tsfeed->set_indexing_params(tsfeed,
- ¶->video_params);
+ if (tsfeed->set_video_codec) {
+ ret = tsfeed->set_video_codec(tsfeed,
+ para->video_codec);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux,
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 3f73c4d..5b286e8 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -122,6 +122,235 @@
* Software filter functions
******************************************************************************/
+/*
+ * Check if two patterns are identical, taking mask into consideration.
+ * @pattern1: the first byte pattern to compare.
+ * @pattern2: the second byte pattern to compare.
+ * @mask: the bit mask to use.
+ * @pattern_size: the length of both patterns and the mask, in bytes.
+ *
+ * Return: 1 if patterns match, 0 otherwise.
+ */
+static inline int dvb_dmx_patterns_match(const u8 *pattern1, const u8 *pattern2,
+ const u8 *mask, size_t pattern_size)
+{
+ int i;
+
+ /*
+ * Assumption: it is OK to access pattern1, pattern2 and mask.
+ * This function performs no sanity checks to keep things fast.
+ */
+
+ for (i = 0; i < pattern_size; i++)
+ if ((pattern1[i] & mask[i]) != (pattern2[i] & mask[i]))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * dvb_dmx_video_pattern_search -
+ * search for framing patterns in a given buffer.
+ *
+ * Optimized version: first search for a common substring, e.g. 0x00 0x00 0x01.
+ * If this string is found, go over all the given patterns (all must start
+ * with this string) and search for their ending in the buffer.
+ *
+ * Assumption: the patterns we look for do not spread over more than two
+ * buffers.
+ *
+ * @paterns: the full patterns information to look for.
+ * @patterns_num: the number of patterns to look for.
+ * @buf: the buffer to search.
+ * @buf_size: the size of the buffer to search. we search the entire buffer.
+ * @prefix_size_masks: a bit mask (per pattern) of possible prefix sizes to use
+ * when searching for a pattern that started at the last buffer.
+ * Updated in this function for use in the next lookup.
+ * @results: lookup results (offset, type, used_prefix_size) per found pattern,
+ * up to DVB_DMX_MAX_FOUND_PATTERNS.
+ *
+ * Return:
+ * Number of patterns found (up to DVB_DMX_MAX_FOUND_PATTERNS).
+ * 0 if pattern was not found.
+ * error value on failure.
+ */
+int dvb_dmx_video_pattern_search(
+ const struct dvb_dmx_video_patterns *patterns,
+ int patterns_num,
+ const u8 *buf,
+ size_t buf_size,
+ struct dvb_dmx_video_prefix_size_masks *prefix_size_masks,
+ struct dvb_dmx_video_patterns_results *results)
+{
+ int i, j;
+ unsigned int current_size;
+ u32 prefix;
+ int found = 0;
+ int start_offset = 0;
+ /* the starting common substring to look for */
+ u8 string[] = {0x00, 0x00, 0x01};
+ /* the mask for the starting string */
+ u8 string_mask[] = {0xFF, 0xFF, 0xFF};
+ /* the size of the starting string (in bytes) */
+ size_t string_size = 3;
+
+ if ((patterns == NULL) || (patterns_num <= 0) || (buf == NULL))
+ return -EINVAL;
+
+ memset(results, 0, sizeof(struct dvb_dmx_video_patterns_results));
+
+ /*
+ * handle prefix - disregard string, simply check all patterns,
+ * looking for a matching suffix at the very beginning of the buffer.
+ */
+ for (j = 0; (j < patterns_num) && !found; j++) {
+ prefix = prefix_size_masks->size_mask[j];
+ current_size = 32;
+ while (prefix) {
+ if (prefix & (0x1 << (current_size - 1))) {
+ /*
+ * check that we don't look further
+ * than buf_size boundary
+ */
+ if ((int)(patterns[j].size - current_size) >
+ buf_size)
+ break;
+
+ if (dvb_dmx_patterns_match(
+ (patterns[j].pattern + current_size),
+ buf, (patterns[j].mask + current_size),
+ (patterns[j].size - current_size))) {
+
+ /*
+ * pattern found using prefix at the
+ * very beginning of the buffer, so
+ * offset is 0, but we already zeroed
+ * everything in the beginning of the
+ * function. that's why the next line
+ * is commented.
+ */
+ /* results->info[found].offset = 0; */
+ results->info[found].type =
+ patterns[j].type;
+ results->info[found].used_prefix_size =
+ current_size;
+ found++;
+ /*
+ * save offset to start looking from
+ * in the buffer, to avoid reusing the
+ * data of a pattern we already found.
+ */
+ start_offset = (patterns[j].size -
+ current_size);
+
+ if (found >= DVB_DMX_MAX_FOUND_PATTERNS)
+ goto next_prefix_lookup;
+ /*
+ * we don't want to search for the same
+ * pattern with several possible prefix
+ * sizes if we have already found it,
+ * so we break from the inner loop.
+ * since we incremented 'found', we
+ * will not search for additional
+ * patterns using a prefix - that would
+ * imply ambiguous patterns where one
+ * pattern can be included in another.
+ * the for loop will exit.
+ */
+ break;
+ }
+ }
+ prefix &= ~(0x1 << (current_size - 1));
+ current_size--;
+ }
+ }
+
+ /*
+ * Search buffer for entire pattern, starting with the string.
+ * Note the external for loop does not execute if buf_size is
+ * smaller than string_size (the cast to int is required, since
+ * size_t is unsigned).
+ */
+ for (i = start_offset; i < (int)(buf_size - string_size + 1); i++) {
+ if (dvb_dmx_patterns_match(string, (buf + i), string_mask,
+ string_size)) {
+ /* now search for patterns: */
+ for (j = 0; j < patterns_num; j++) {
+ /* avoid overflow to next buffer */
+ if ((i + patterns[j].size) > buf_size)
+ continue;
+
+ if (dvb_dmx_patterns_match(
+ (patterns[j].pattern + string_size),
+ (buf + i + string_size),
+ (patterns[j].mask + string_size),
+ (patterns[j].size - string_size))) {
+
+ results->info[found].offset = i;
+ results->info[found].type =
+ patterns[j].type;
+ /*
+ * save offset to start next prefix
+ * lookup, to avoid reusing the data
+ * of any pattern we already found.
+ */
+ if ((i + patterns[j].size) >
+ start_offset)
+ start_offset = (i +
+ patterns[j].size);
+ /*
+ * did not use a prefix to find this
+ * pattern, but we zeroed everything
+ * in the beginning of the function.
+ * So no need to zero used_prefix_size
+ * for results->info[found]
+ */
+
+ found++;
+ if (found >= DVB_DMX_MAX_FOUND_PATTERNS)
+ goto next_prefix_lookup;
+ /*
+ * theoretically we don't have to break
+ * here, but we don't want to search
+ * for the other matching patterns on
+ * the very same same place in the
+ * buffer. That would mean the
+ * (pattern & mask) combinations are
+ * not unique. So we break from inner
+ * loop and move on to the next place
+ * in the buffer.
+ */
+ break;
+ }
+ }
+ }
+ }
+
+next_prefix_lookup:
+ /* check for possible prefix sizes for the next buffer */
+ for (j = 0; j < patterns_num; j++) {
+ prefix_size_masks->size_mask[j] = 0;
+ for (i = 1; i < patterns[j].size; i++) {
+ /*
+ * avoid looking outside of the buffer
+ * or reusing previously used data.
+ */
+ if (i > (buf_size - start_offset))
+ break;
+
+ if (dvb_dmx_patterns_match(patterns[j].pattern,
+ (buf + buf_size - i),
+ patterns[j].mask, i)) {
+ prefix_size_masks->size_mask[j] |=
+ (1 << (i - 1));
+ }
+ }
+ }
+
+ return found;
+}
+EXPORT_SYMBOL(dvb_dmx_video_pattern_search);
+
static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
const u8 *buf)
{
@@ -1242,14 +1471,13 @@
return ret;
}
-static int dmx_ts_set_indexing_params(
+static int dmx_ts_set_video_codec(
struct dmx_ts_feed *ts_feed,
- struct dmx_indexing_video_params *params)
+ enum dmx_video_codec video_codec)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
- memcpy(&feed->indexing_params, params,
- sizeof(struct dmx_indexing_video_params));
+ feed->video_codec = video_codec;
return 0;
}
@@ -1386,8 +1614,6 @@
feed->secure_mode.is_secured = 0;
feed->buffer = NULL;
feed->tsp_out_format = DMX_TSP_FORMAT_188;
- memset(&feed->indexing_params, 0,
- sizeof(struct dmx_indexing_video_params));
/* default behaviour - pass first PES data even if it is
* partial PES data from previous PES that we didn't receive its header.
@@ -1403,7 +1629,7 @@
(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
(*ts_feed)->set = dmx_ts_feed_set;
- (*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
+ (*ts_feed)->set_video_codec = dmx_ts_set_video_codec;
(*ts_feed)->set_tsp_out_format = dmx_ts_set_tsp_out_format;
(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
(*ts_feed)->reuse_decoder_buffer = dmx_ts_feed_reuse_decoder_buffer;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index fc04219..c63ecd4 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -113,7 +113,7 @@
struct list_head list_head;
unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
- struct dmx_indexing_video_params indexing_params;
+ enum dmx_video_codec video_codec;
};
struct dvb_demux {
@@ -189,6 +189,51 @@
u32 total_crc_time;
};
+/*
+ * dvb_dmx_video_patterns - video pattern lookup parameters.
+ *
+ * @pattern: the byte pattern to look for.
+ * @mask: the byte mask to use (same length as pattern).
+ * @size: the length of the pattern, in bytes.
+ * @type: the type of the pattern. One of DMX_IDX_* definitions.
+ */
+#define DVB_DMX_MAX_PATTERN_LEN 6
+struct dvb_dmx_video_patterns {
+ u8 pattern[DVB_DMX_MAX_PATTERN_LEN];
+ u8 mask[DVB_DMX_MAX_PATTERN_LEN];
+ size_t size;
+ u64 type;
+};
+
+/*
+ * dvb_dmx_video_prefix_size_masks - possible prefix sizes.
+ *
+ * @size_mask: a bit mask (per pattern) of possible prefix sizes to use
+ * when searching for a pattern that started in the previous TS packet.
+ * Updated by dvb_dmx_video_pattern_search for use in the next lookup.
+ */
+#define DVB_DMX_MAX_FOUND_PATTERNS 10
+struct dvb_dmx_video_prefix_size_masks {
+ u32 size_mask[DVB_DMX_MAX_FOUND_PATTERNS];
+};
+
+/*
+ * dvb_dmx_video_patterns_results - video patterns results
+ *
+ * @offset: The offset in the buffer where the pattern was found.
+ * If a pattern is found using a prefix (i.e. started on the
+ * previous buffer), offset is zero.
+ * @type: The type of the pattern found. One of DMX_IDX_* definitions.
+ * @used_prefix_size: The prefix size that was used to find this pattern
+ */
+struct dvb_dmx_video_patterns_results {
+ struct {
+ u32 offset;
+ u64 type;
+ u32 used_prefix_size;
+ } info[DVB_DMX_MAX_FOUND_PATTERNS];
+};
+
int dvb_dmx_init(struct dvb_demux *dvbdemux);
void dvb_dmx_release(struct dvb_demux *dvbdemux);
void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf,
@@ -204,6 +249,11 @@
enum dmx_tsp_format_t tsp_format);
void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf,
const u8 timestamp[TIMESTAMP_LEN]);
+int dvb_dmx_video_pattern_search(
+ const struct dvb_dmx_video_patterns *patterns, int patterns_num,
+ const u8 *buf, size_t buf_size,
+ struct dvb_dmx_video_prefix_size_masks *prefix_size_masks,
+ struct dvb_dmx_video_patterns_results *results);
/**
* dvb_dmx_is_video_feed - Returns whether the PES feed
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 1a481ce..6660668 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
@@ -95,12 +95,6 @@
static int mpq_sdmx_debug;
module_param(mpq_sdmx_debug, int, S_IRUGO | S_IWUSR);
-
-/**
- * Maximum allowed framing pattern size
- */
-#define MPQ_MAX_PATTERN_SIZE 6
-
/**
* Number of patterns to look for when doing framing, per video standard
*/
@@ -109,64 +103,49 @@
#define MPQ_VC1_PATTERN_NUM 3
/*
- * mpq_framing_pattern_lookup_params - framing pattern lookup parameters.
- *
- * @pattern: the byte pattern to look for.
- * @mask: the byte mask to use (same length as pattern).
- * @size: the length of the pattern, in bytes.
- * @type: the type of the pattern.
- */
-struct mpq_framing_pattern_lookup_params {
- u8 pattern[MPQ_MAX_PATTERN_SIZE];
- u8 mask[MPQ_MAX_PATTERN_SIZE];
- size_t size;
- enum dmx_framing_pattern_type type;
-};
-
-/*
* Pre-defined video framing lookup pattern information.
* Note: the first pattern in each patterns database must
* be the Sequence Header (or equivalent SPS in H.264).
* The code assumes this is the case when prepending
* Sequence Header data in case it is required.
*/
-static const struct mpq_framing_pattern_lookup_params
+static const struct dvb_dmx_video_patterns
mpeg2_patterns[MPQ_MPEG2_PATTERN_NUM] = {
{{0x00, 0x00, 0x01, 0xB3}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_MPEG2_SEQUENCE_HEADER},
+ DMX_IDX_MPEG_SEQ_HEADER},
{{0x00, 0x00, 0x01, 0xB8}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_MPEG2_GOP_HEADER},
+ DMX_IDX_MPEG_GOP},
{{0x00, 0x00, 0x01, 0x00, 0x00, 0x08},
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_I_PIC},
+ DMX_IDX_MPEG_I_FRAME_START},
{{0x00, 0x00, 0x01, 0x00, 0x00, 0x10},
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_P_PIC},
+ DMX_IDX_MPEG_P_FRAME_START},
{{0x00, 0x00, 0x01, 0x00, 0x00, 0x18},
{0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_B_PIC}
+ DMX_IDX_MPEG_B_FRAME_START}
};
-static const struct mpq_framing_pattern_lookup_params
+static const struct dvb_dmx_video_patterns
h264_patterns[MPQ_H264_PATTERN_NUM] = {
{{0x00, 0x00, 0x01, 0x07}, {0xFF, 0xFF, 0xFF, 0x1F}, 4,
- DMX_FRM_H264_SPS},
+ DMX_IDX_H264_SPS},
{{0x00, 0x00, 0x01, 0x08}, {0xFF, 0xFF, 0xFF, 0x1F}, 4,
- DMX_FRM_H264_PPS},
+ DMX_IDX_H264_PPS},
{{0x00, 0x00, 0x01, 0x05, 0x80}, {0xFF, 0xFF, 0xFF, 0x1F, 0x80}, 5,
- DMX_FRM_H264_IDR_PIC},
+ DMX_IDX_H264_IDR_START},
{{0x00, 0x00, 0x01, 0x01, 0x80}, {0xFF, 0xFF, 0xFF, 0x1F, 0x80}, 5,
- DMX_FRM_H264_NON_IDR_PIC}
+ DMX_IDX_H264_NON_IDR_START}
};
-static const struct mpq_framing_pattern_lookup_params
+static const struct dvb_dmx_video_patterns
vc1_patterns[MPQ_VC1_PATTERN_NUM] = {
{{0x00, 0x00, 0x01, 0x0F}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_SEQUENCE_HEADER},
+ DMX_IDX_VC1_SEQ_HEADER},
{{0x00, 0x00, 0x01, 0x0E}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_ENTRY_POINT_HEADER},
+ DMX_IDX_VC1_ENTRY_POINT},
{{0x00, 0x00, 0x01, 0x0D}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_FRAME_START_CODE}
+ DMX_IDX_VC1_FRAME_START}
};
/* Global data-structure for managing demux devices */
@@ -211,309 +190,64 @@
/* Check if a framing pattern is a video frame pattern or a header pattern */
static inline int mpq_dmx_is_video_frame(
- enum dmx_indexing_video_standard standard,
- enum dmx_framing_pattern_type pattern_type)
+ enum dmx_video_codec codec,
+ u64 pattern_type)
{
- switch (standard) {
- case DMX_INDEXING_MPEG2:
- if ((pattern_type == DMX_FRM_MPEG2_I_PIC) ||
- (pattern_type == DMX_FRM_MPEG2_P_PIC) ||
- (pattern_type == DMX_FRM_MPEG2_B_PIC))
+ switch (codec) {
+ case DMX_VIDEO_CODEC_MPEG2:
+ if ((pattern_type == DMX_IDX_MPEG_I_FRAME_START) ||
+ (pattern_type == DMX_IDX_MPEG_P_FRAME_START) ||
+ (pattern_type == DMX_IDX_MPEG_B_FRAME_START))
return 1;
return 0;
- case DMX_INDEXING_H264:
- if ((pattern_type == DMX_FRM_H264_IDR_PIC) ||
- (pattern_type == DMX_FRM_H264_NON_IDR_PIC))
+
+ case DMX_VIDEO_CODEC_H264:
+ if ((pattern_type == DMX_IDX_H264_IDR_START) ||
+ (pattern_type == DMX_IDX_H264_NON_IDR_START))
return 1;
return 0;
- case DMX_INDEXING_VC1:
- if (pattern_type == DMX_FRM_VC1_FRAME_START_CODE)
+
+ case DMX_VIDEO_CODEC_VC1:
+ if (pattern_type == DMX_IDX_VC1_FRAME_START)
return 1;
return 0;
+
default:
return -EINVAL;
}
}
/*
- * mpq_framing_pattern_lookup_results - framing lookup results
- *
- * @offset: The offset in the buffer where the pattern was found.
- * If a pattern is found using a prefix (i.e. started on the
- * previous buffer), offset is zero.
- * @type: the type of the pattern found.
- * @used_prefix_size: the prefix size that was used to find this pattern
- */
-struct mpq_framing_pattern_lookup_results {
- struct {
- u32 offset;
- enum dmx_framing_pattern_type type;
- u32 used_prefix_size;
- } info[MPQ_MAX_FOUND_PATTERNS];
-};
-
-/*
- * Check if two patterns are identical, taking mask into consideration.
- * @pattern1: the first byte pattern to compare.
- * @pattern2: the second byte pattern to compare.
- * @mask: the bit mask to use.
- * @pattern_size: the length of both patterns and the mask, in bytes.
- *
- * Return: 1 if patterns match, 0 otherwise.
- */
-static inline int mpq_dmx_patterns_match(const u8 *pattern1, const u8 *pattern2,
- const u8 *mask, size_t pattern_size)
-{
- int i;
-
- /*
- * Assumption: it is OK to access pattern1, pattern2 and mask.
- * This function performs no sanity checks to keep things fast.
- */
-
- for (i = 0; i < pattern_size; i++)
- if ((pattern1[i] & mask[i]) != (pattern2[i] & mask[i]))
- return 0;
-
- return 1;
-}
-
-/*
- * mpq_dmx_framing_pattern_search -
- * search for framing patterns in a given buffer.
- *
- * Optimized version: first search for a common substring, e.g. 0x00 0x00 0x01.
- * If this string is found, go over all the given patterns (all must start
- * with this string) and search for their ending in the buffer.
- *
- * Assumption: the patterns we look for do not spread over more than two
- * buffers.
- *
- * @paterns: the full patterns information to look for.
- * @patterns_num: the number of patterns to look for.
- * @buf: the buffer to search.
- * @buf_size: the size of the buffer to search. we search the entire buffer.
- * @prefix_size_masks: a bit mask (per pattern) of possible prefix sizes to use
- * when searching for a pattern that started at the last buffer.
- * Updated in this function for use in the next lookup.
- * @results: lookup results (offset, type, used_prefix_size) per found pattern,
- * up to MPQ_MAX_FOUND_PATTERNS.
- *
- * Return:
- * Number of patterns found (up to MPQ_MAX_FOUND_PATTERNS).
- * 0 if pattern was not found.
- * Negative error value on failure.
- */
-static int mpq_dmx_framing_pattern_search(
- const struct mpq_framing_pattern_lookup_params *patterns,
- int patterns_num,
- const u8 *buf,
- size_t buf_size,
- struct mpq_framing_prefix_size_masks *prefix_size_masks,
- struct mpq_framing_pattern_lookup_results *results)
-{
- int i, j;
- unsigned int current_size;
- u32 prefix;
- int found = 0;
- int start_offset = 0;
- /* the starting common substring to look for */
- u8 string[] = {0x00, 0x00, 0x01};
- /* the mask for the starting string */
- u8 string_mask[] = {0xFF, 0xFF, 0xFF};
- /* the size of the starting string (in bytes) */
- size_t string_size = 3;
-
- /* sanity checks - can be commented out for optimization purposes */
- if ((patterns == NULL) || (patterns_num <= 0) || (buf == NULL)) {
- MPQ_DVB_ERR_PRINT("%s: invalid parameters\n", __func__);
- return -EINVAL;
- }
-
- memset(results, 0, sizeof(struct mpq_framing_pattern_lookup_results));
-
- /*
- * handle prefix - disregard string, simply check all patterns,
- * looking for a matching suffix at the very beginning of the buffer.
- */
- for (j = 0; (j < patterns_num) && !found; j++) {
- prefix = prefix_size_masks->size_mask[j];
- current_size = 32;
- while (prefix) {
- if (prefix & (0x1 << (current_size - 1))) {
- /*
- * check that we don't look further
- * than buf_size boundary
- */
- if ((int)(patterns[j].size - current_size) >
- buf_size)
- break;
-
- if (mpq_dmx_patterns_match(
- (patterns[j].pattern + current_size),
- buf, (patterns[j].mask + current_size),
- (patterns[j].size - current_size))) {
-
- MPQ_DVB_DBG_PRINT(
- "%s: Found matching pattern using prefix of size %d\n",
- __func__, current_size);
- /*
- * pattern found using prefix at the
- * very beginning of the buffer, so
- * offset is 0, but we already zeroed
- * everything in the beginning of the
- * function. that's why the next line
- * is commented.
- */
- /* results->info[found].offset = 0; */
- results->info[found].type =
- patterns[j].type;
- results->info[found].used_prefix_size =
- current_size;
- found++;
- /*
- * save offset to start looking from
- * in the buffer, to avoid reusing the
- * data of a pattern we already found.
- */
- start_offset = (patterns[j].size -
- current_size);
-
- if (found >= MPQ_MAX_FOUND_PATTERNS)
- goto next_prefix_lookup;
- /*
- * we don't want to search for the same
- * pattern with several possible prefix
- * sizes if we have already found it,
- * so we break from the inner loop.
- * since we incremented 'found', we
- * will not search for additional
- * patterns using a prefix - that would
- * imply ambiguous patterns where one
- * pattern can be included in another.
- * the for loop will exit.
- */
- break;
- }
- }
- prefix &= ~(0x1 << (current_size - 1));
- current_size--;
- }
- }
-
- /*
- * Search buffer for entire pattern, starting with the string.
- * Note the external for loop does not execute if buf_size is
- * smaller than string_size (the cast to int is required, since
- * size_t is unsigned).
- */
- for (i = start_offset; i < (int)(buf_size - string_size + 1); i++) {
- if (mpq_dmx_patterns_match(string, (buf + i), string_mask,
- string_size)) {
- /* now search for patterns: */
- for (j = 0; j < patterns_num; j++) {
- /* avoid overflow to next buffer */
- if ((i + patterns[j].size) > buf_size)
- continue;
-
- if (mpq_dmx_patterns_match(
- (patterns[j].pattern + string_size),
- (buf + i + string_size),
- (patterns[j].mask + string_size),
- (patterns[j].size - string_size))) {
-
- results->info[found].offset = i;
- results->info[found].type =
- patterns[j].type;
- /*
- * save offset to start next prefix
- * lookup, to avoid reusing the data
- * of any pattern we already found.
- */
- if ((i + patterns[j].size) >
- start_offset)
- start_offset = (i +
- patterns[j].size);
- /*
- * did not use a prefix to find this
- * pattern, but we zeroed everything
- * in the beginning of the function.
- * So no need to zero used_prefix_size
- * for results->info[found]
- */
-
- found++;
- if (found >= MPQ_MAX_FOUND_PATTERNS)
- goto next_prefix_lookup;
- /*
- * theoretically we don't have to break
- * here, but we don't want to search
- * for the other matching patterns on
- * the very same same place in the
- * buffer. That would mean the
- * (pattern & mask) combinations are
- * not unique. So we break from inner
- * loop and move on to the next place
- * in the buffer.
- */
- break;
- }
- }
- }
- }
-
-next_prefix_lookup:
- /* check for possible prefix sizes for the next buffer */
- for (j = 0; j < patterns_num; j++) {
- prefix_size_masks->size_mask[j] = 0;
- for (i = 1; i < patterns[j].size; i++) {
- /*
- * avoid looking outside of the buffer
- * or reusing previously used data.
- */
- if (i > (buf_size - start_offset))
- break;
-
- if (mpq_dmx_patterns_match(patterns[j].pattern,
- (buf + buf_size - i),
- patterns[j].mask, i)) {
- prefix_size_masks->size_mask[j] |=
- (1 << (i - 1));
- }
- }
- }
-
- return found;
-}
-
-/*
* mpq_dmx_get_pattern_params -
* get a pointer to the relevant pattern parameters structure,
* based on the video parameters.
*
- * @video_params: the video parameters (e.g. video standard).
+ * @video_codec: the video codec.
* @patterns: a pointer to a pointer to the pattern parameters,
* updated by this function.
* @patterns_num: number of patterns, updated by this function.
*/
static inline int mpq_dmx_get_pattern_params(
- struct dmx_indexing_video_params *video_params,
- const struct mpq_framing_pattern_lookup_params **patterns,
+ enum dmx_video_codec video_codec,
+ const struct dvb_dmx_video_patterns **patterns,
int *patterns_num)
{
- switch (video_params->standard) {
- case DMX_INDEXING_MPEG2:
+ switch (video_codec) {
+ case DMX_VIDEO_CODEC_MPEG2:
*patterns = mpeg2_patterns;
*patterns_num = MPQ_MPEG2_PATTERN_NUM;
break;
- case DMX_INDEXING_H264:
+
+ case DMX_VIDEO_CODEC_H264:
*patterns = h264_patterns;
*patterns_num = MPQ_H264_PATTERN_NUM;
break;
- case DMX_INDEXING_VC1:
+
+ case DMX_VIDEO_CODEC_VC1:
*patterns = vc1_patterns;
*patterns_num = MPQ_VC1_PATTERN_NUM;
break;
+
default:
MPQ_DVB_ERR_PRINT("%s: invalid parameters\n", __func__);
*patterns = NULL;
@@ -1648,7 +1382,7 @@
/* get and store framing information if required */
if (!mpq_dmx_info.decoder_framing) {
mpq_dmx_get_pattern_params(
- &mpq_feed->dvb_demux_feed->indexing_params,
+ mpq_feed->dvb_demux_feed->video_codec,
&feed_data->patterns, &feed_data->patterns_num);
if (feed_data->patterns == NULL) {
MPQ_DVB_ERR_PRINT(
@@ -1740,10 +1474,10 @@
&feed_data->frame_offset);
feed_data->last_pattern_offset = 0;
feed_data->pending_pattern_len = 0;
- feed_data->last_framing_match_type = DMX_FRM_UNKNOWN;
+ feed_data->last_framing_match_type = 0;
feed_data->found_sequence_header_pattern = 0;
memset(&feed_data->prefix_size, 0,
- sizeof(struct mpq_framing_prefix_size_masks));
+ sizeof(struct dvb_dmx_video_prefix_size_masks));
feed_data->first_prefix_size = 0;
feed_data->saved_pts_dts_info.pts_exist = 0;
feed_data->saved_pts_dts_info.dts_exist = 0;
@@ -2613,7 +2347,7 @@
/* Report last pattern found */
if ((feed_data->pending_pattern_len) &&
- mpq_dmx_is_video_frame(feed->indexing_params.standard,
+ mpq_dmx_is_video_frame(feed->video_codec,
feed_data->last_framing_match_type)) {
meta_data.packet_type = DMX_FRAMING_INFO_PACKET;
mpq_dmx_write_pts_dts(feed_data,
@@ -2734,7 +2468,7 @@
struct mpq_demux *mpq_demux;
struct mpq_feed *mpq_feed;
- struct mpq_framing_pattern_lookup_results framing_res;
+ struct dvb_dmx_video_patterns_results framing_res;
struct mpq_streambuffer_packet_header packet;
struct mpq_adapter_video_meta_data meta_data;
int bytes_written = 0;
@@ -2864,7 +2598,7 @@
* the decoder requires demux to do framing,
* so search for the patterns now.
*/
- found_patterns = mpq_dmx_framing_pattern_search(
+ found_patterns = dvb_dmx_video_pattern_search(
feed_data->patterns,
feed_data->patterns_num,
(buf + ts_payload_offset),
@@ -2872,17 +2606,17 @@
&feed_data->prefix_size,
&framing_res);
- if (!(feed_data->found_sequence_header_pattern)) {
+ if (!feed_data->found_sequence_header_pattern) {
for (i = 0; i < found_patterns; i++) {
if ((framing_res.info[i].type ==
- DMX_FRM_MPEG2_SEQUENCE_HEADER) ||
+ DMX_IDX_MPEG_SEQ_HEADER) ||
(framing_res.info[i].type ==
- DMX_FRM_H264_SPS) ||
- (framing_res.info[i].type ==
- DMX_FRM_VC1_SEQUENCE_HEADER)) {
+ DMX_IDX_H264_SPS) ||
+ (framing_res.info[i].type ==
+ DMX_IDX_VC1_SEQ_HEADER)) {
MPQ_DVB_DBG_PRINT(
- "%s: Found Sequence Pattern, buf %p, i = %d, offset = %d, type = %d\n",
+ "%s: Found Sequence Pattern, buf %p, i = %d, offset = %d, type = %lld\n",
__func__, buf, i,
framing_res.info[i].offset,
framing_res.info[i].type);
@@ -2925,10 +2659,10 @@
if (feed_data->first_pts_dts_copy) {
for (i = first_pattern; i < found_patterns; i++) {
is_video_frame = mpq_dmx_is_video_frame(
- feed->indexing_params.standard,
+ feed->video_codec,
framing_res.info[i].type);
- if (is_video_frame) {
+ if (is_video_frame == 1) {
mpq_dmx_save_pts_dts(feed_data);
feed_data->first_pts_dts_copy = 0;
break;
@@ -3045,9 +2779,8 @@
}
is_video_frame = mpq_dmx_is_video_frame(
- feed->indexing_params.standard,
+ feed->video_codec,
feed_data->last_framing_match_type);
-
if (is_video_frame == 1) {
mpq_dmx_write_pts_dts(feed_data,
&(meta_data.info.framing.pts_dts_info));
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index 4c2a9f4..349151e 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -31,8 +31,6 @@
*/
#define TSIF_NAME_LENGTH 20
-#define MPQ_MAX_FOUND_PATTERNS 5
-
/**
* struct ts_packet_header - Transport packet header
* as defined in MPEG2 transport stream standard.
@@ -200,17 +198,6 @@
#endif
} __packed;
-/*
- * mpq_framing_prefix_size_masks - possible prefix sizes.
- *
- * @size_mask: a bit mask (per pattern) of possible prefix sizes to use
- * when searching for a pattern that started in the last buffer.
- * Updated in mpq_dmx_framing_pattern_search for use in the next lookup
- */
-struct mpq_framing_prefix_size_masks {
- u32 size_mask[MPQ_MAX_FOUND_PATTERNS];
-};
-
/**
* mpq_decoder_buffers_desc - decoder buffer(s) management information.
*
@@ -295,14 +282,14 @@
u32 pes_header_offset;
int fullness_wait_cancel;
enum mpq_adapter_stream_if stream_interface;
- const struct mpq_framing_pattern_lookup_params *patterns;
+ const struct dvb_dmx_video_patterns *patterns;
int patterns_num;
u32 frame_offset;
u32 last_pattern_offset;
u32 pending_pattern_len;
- enum dmx_framing_pattern_type last_framing_match_type;
+ u64 last_framing_match_type;
int found_sequence_header_pattern;
- struct mpq_framing_prefix_size_masks prefix_size;
+ struct dvb_dmx_video_prefix_size_masks prefix_size;
u32 first_prefix_size;
struct dmx_pts_dts_info saved_pts_dts_info;
struct dmx_pts_dts_info new_pts_dts_info;
diff --git a/drivers/media/platform/msm/dvb/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
index b55f367..19abbbe 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
@@ -14,6 +14,7 @@
#define _MPQ_ADAPTER_H
#include "dvbdev.h"
+#include "dvb_demux.h"
#include "mpq_stream_buffer.h"
@@ -36,31 +37,6 @@
MPQ_ADAPTER_MAX_NUM_OF_INTERFACES,
};
-
-enum dmx_framing_pattern_type {
- /* MPEG-2 */
- DMX_FRM_MPEG2_SEQUENCE_HEADER,
- DMX_FRM_MPEG2_GOP_HEADER,
- DMX_FRM_MPEG2_I_PIC,
- DMX_FRM_MPEG2_P_PIC,
- DMX_FRM_MPEG2_B_PIC,
- /* H.264 */
- DMX_FRM_H264_SPS,
- DMX_FRM_H264_PPS,
- /* H.264 First Coded slice of an IDR Picture */
- DMX_FRM_H264_IDR_PIC,
- /* H.264 First Coded slice of a non-IDR Picture */
- DMX_FRM_H264_NON_IDR_PIC,
- /* VC-1 Sequence Header*/
- DMX_FRM_VC1_SEQUENCE_HEADER,
- /* VC-1 Entry Point Header (Advanced Profile only) */
- DMX_FRM_VC1_ENTRY_POINT_HEADER,
- /* VC-1 Frame Start Code */
- DMX_FRM_VC1_FRAME_START_CODE,
- /* Unknown or invalid framing information */
- DMX_FRM_UNKNOWN
-};
-
enum dmx_packet_type {
DMX_PES_PACKET,
DMX_FRAMING_INFO_PACKET,
@@ -83,8 +59,9 @@
};
struct dmx_framing_packet_info {
- /** framing pattern type */
- enum dmx_framing_pattern_type pattern_type;
+ /** framing pattern type, one of DMX_IDX_* definitions */
+ u64 pattern_type;
+
/** PTS/DTS information */
struct dmx_pts_dts_info pts_dts_info;
};
diff --git a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
index 3f33535..0908a6e 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -131,24 +131,24 @@
switch (meta_data.packet_type) {
case DMX_FRAMING_INFO_PACKET:
switch (meta_data.info.framing.pattern_type) {
- case DMX_FRM_H264_SPS:
- case DMX_FRM_MPEG2_SEQUENCE_HEADER:
- case DMX_FRM_VC1_SEQUENCE_HEADER:
+ case DMX_IDX_H264_SPS:
+ case DMX_IDX_MPEG_SEQ_HEADER:
+ case DMX_IDX_VC1_SEQ_HEADER:
DBG("SPS FOUND\n");
frame_found = false;
break;
- case DMX_FRM_H264_PPS:
- case DMX_FRM_MPEG2_GOP_HEADER:
- case DMX_FRM_VC1_ENTRY_POINT_HEADER:
+ case DMX_IDX_H264_PPS:
+ case DMX_IDX_MPEG_GOP:
+ case DMX_IDX_VC1_ENTRY_POINT:
DBG("PPS FOUND\n");
frame_found = false;
break;
- case DMX_FRM_H264_IDR_PIC:
- case DMX_FRM_H264_NON_IDR_PIC:
- case DMX_FRM_MPEG2_I_PIC:
- case DMX_FRM_MPEG2_P_PIC:
- case DMX_FRM_MPEG2_B_PIC:
- case DMX_FRM_VC1_FRAME_START_CODE:
+ case DMX_IDX_H264_IDR_START:
+ case DMX_IDX_H264_NON_IDR_START:
+ case DMX_IDX_MPEG_I_FRAME_START:
+ case DMX_IDX_MPEG_P_FRAME_START:
+ case DMX_IDX_MPEG_B_FRAME_START:
+ case DMX_IDX_VC1_FRAME_START:
DBG("FRAME FOUND\n");
frame_found = true;
break;
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index f46abcf..ef3e698 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1183,6 +1183,24 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_VENC_H264_VUI_TIMING_INFO:
+ {
+ struct hfi_h264_vui_timing_info *hfi;
+ struct hal_h264_vui_timing_info *timing_info = pdata;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
+
+ hfi = (struct hfi_h264_vui_timing_info *)&pkt->
+ rg_property_data[1];
+ hfi->enable = timing_info->enable;
+ hfi->fixed_frame_rate = timing_info->fixed_frame_rate;
+ hfi->time_scale = timing_info->time_scale;
+
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_h264_vui_timing_info);
+ break;
+ }
case HAL_CONFIG_VPE_DEINTERLACE:
break;
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
@@ -1213,6 +1231,7 @@
case HAL_PARAM_VENC_LOW_LATENCY:
default:
dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x", ptype);
+ rc = -ENOTSUPP;
break;
}
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index eca8091..3c181fe 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1280,7 +1280,7 @@
break;
}
- if (property_id) {
+ if (!rc && property_id) {
dprintk(VIDC_DBG,
"Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
property_id,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 160d450..da97c7a 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -131,7 +131,7 @@
.step = 1,
.menu_skip_mask = 0,
.qmenu = NULL,
- .cluster = 0,
+ .cluster = MSM_VENC_CTRL_CLUSTER_TIMING,
},
{
.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD,
@@ -209,7 +209,8 @@
(1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR)
),
.qmenu = mpeg_video_rate_control,
- .cluster = MSM_VENC_CTRL_CLUSTER_BITRATE,
+ .cluster = MSM_VENC_CTRL_CLUSTER_BITRATE |
+ MSM_VENC_CTRL_CLUSTER_TIMING,
},
{
.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
@@ -630,6 +631,16 @@
.qmenu = mpeg_video_vidc_extradata,
.step = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO,
+ .name = "H264 VUI Timing Info",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED,
+ .default_value =
+ V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+ .cluster = MSM_VENC_CTRL_CLUSTER_TIMING,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -1117,8 +1128,9 @@
struct hal_multi_slice_control multi_slice_control;
struct hal_h264_db_control h264_db_control;
struct hal_enable enable;
+ struct hal_h264_vui_timing_info vui_timing_info;
u32 property_id = 0, property_val = 0;
- void *pdata;
+ void *pdata = NULL;
struct v4l2_ctrl *temp_ctrl = NULL;
struct hfi_device *hdev;
@@ -1625,14 +1637,57 @@
pdata = &extra;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO:
+ {
+ struct v4l2_ctrl *rc_mode, *frame_rate;
+ bool cfr = false;
+
+ property_id = HAL_PARAM_VENC_H264_VUI_TIMING_INFO;
+ rc_mode = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
+ frame_rate = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE);
+
+ switch (rc_mode->val) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
+ cfr = true;
+ break;
+ default:
+ cfr = false;
+ break;
+ }
+
+ switch (ctrl->val) {
+ case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED:
+ vui_timing_info.enable = 0;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED:
+ /* Only support this in CFR mode because we
+ * don't really know how to fill out vui_timing_info.
+ * time_scale in vfr mode. The assumed framerate
+ * might be incorrect. */
+ if (!cfr) {
+ dprintk(VIDC_ERR, "Can't set %x in VFR mode\n",
+ ctrl->id);
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ vui_timing_info.enable = 1;
+ vui_timing_info.fixed_frame_rate = cfr;
+ vui_timing_info.time_scale = frame_rate->val;
+ }
+
+ pdata = &vui_timing_info;
+ break;
+ }
default:
rc = -ENOTSUPP;
break;
}
#undef TRY_GET_CTRL
- if (property_id) {
- dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
+ if (!rc && property_id) {
+ dprintk(VIDC_DBG, "Control: HAL property=%x,ctrl_value=%d\n",
property_id,
ctrl->val);
rc = call_hfi_op(hdev, session_set_property,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 3b82666..3729c3a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -167,6 +167,7 @@
HAL_PARAM_VDEC_SYNC_FRAME_DECODE,
HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
HAL_CONFIG_VENC_MAX_BITRATE,
+ HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
};
enum hal_domain {
@@ -765,6 +766,13 @@
u32 time_stamp_scale;
};
+
+struct hal_h264_vui_timing_info {
+ u32 enable;
+ u32 fixed_frame_rate;
+ u32 time_scale;
+};
+
enum vidc_resource_id {
VIDC_RESOURCE_OCMEM = 0x00000001,
VIDC_UNUSED_RESORUCE = 0x10000000,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index baf7bc4..2d0c3bd 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -294,9 +294,16 @@
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x019)
#define HFI_PROPERTY_PARAM_VENC_HIER_P_NUM_ENH_LAYER \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01A)
-
#define HFI_PROPERTY_PARAM_VENC_H264_NAL_SVC_EXT \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01B)
+#define HFI_PROPERTY_PARAM_VENC_H264_LTRMODE \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01C)
+#define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01D)
+#define HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01E)
+#define HFI_PROPERTY_PARAM_VENC_VC1_PERF_CFG \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01F)
#define HFI_PROPERTY_CONFIG_VENC_COMMON_START \
(HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000)
@@ -500,6 +507,12 @@
u32 height;
};
+struct hfi_h264_vui_timing_info {
+ u32 enable;
+ u32 fixed_frame_rate;
+ u32 time_scale;
+};
+
#define HFI_COLOR_FORMAT_MONOCHROME (HFI_COMMON_BASE + 0x1)
#define HFI_COLOR_FORMAT_NV12 (HFI_COMMON_BASE + 0x2)
#define HFI_COLOR_FORMAT_NV21 (HFI_COMMON_BASE + 0x3)
@@ -883,5 +896,4 @@
u32 packet_type;
u32 trigger_type;
};
-
#endif
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index b719b3f..4f7fb44 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -28,6 +28,7 @@
#define BUF_TYPE_INPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
static struct ion_client *venc_ion_client;
+static long venc_secure(struct v4l2_subdev *sd);
struct index_bitmap {
unsigned long *bitmap;
@@ -321,8 +322,9 @@
goto venc_open_fail;
}
- inst->secure = false;
inst->vmops = *vmops;
+ inst->secure = vmops->secure; /* We need to inform vidc, but defer
+ until after s_fmt() */
INIT_LIST_HEAD(&inst->registered_output_bufs.list);
INIT_LIST_HEAD(&inst->registered_input_bufs.list);
init_completion(&inst->dq_complete);
@@ -903,6 +905,15 @@
WFD_MSG_ERR("Failed to format for input port\n");
goto venc_set_format_fail;
}
+
+ /* If the device was secured previously, we need to inform vidc _now_ */
+ if (inst->secure) {
+ rc = venc_secure(sd);
+ if (rc) {
+ WFD_MSG_ERR("Failed secure vidc\n");
+ goto venc_set_format_fail;
+ }
+ }
venc_set_format_fail:
return rc;
}
@@ -1329,12 +1340,6 @@
rc = -EEXIST;
}
- if (inst->secure) {
- /* Nothing to do! */
- rc = 0;
- goto secure_fail;
- }
-
ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
if (rc) {
@@ -1342,7 +1347,6 @@
goto secure_fail;
}
- inst->secure = true;
secure_fail:
return rc;
}
@@ -1419,9 +1423,6 @@
case SET_FRAMERATE_MODE:
rc = venc_set_framerate_mode(sd, arg);
break;
- case ENC_SECURE:
- rc = venc_secure(sd);
- break;
default:
WFD_MSG_ERR("Unknown ioctl %d to enc-subdev\n", cmd);
rc = -ENOTSUPP;
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 16de0d4..55386b9 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -26,6 +26,8 @@
struct switch_dev sdev;
};
+static int mdp_secure(struct v4l2_subdev *sd, void *arg);
+
int mdp_init(struct v4l2_subdev *sd, u32 val)
{
return 0;
@@ -47,10 +49,6 @@
WFD_MSG_ERR("Invalid arguments\n");
rc = -EINVAL;
goto mdp_open_fail;
- } else if (mops->secure) {
- /* Deprecated API; use MDP_SECURE ioctl */
- WFD_MSG_ERR("Deprecated API for securing subdevice\n");
- return -ENOTSUPP;
}
fbi = msm_fb_get_writeback_fb();
@@ -66,12 +64,25 @@
WFD_MSG_ERR("WFD switch registration failed\n");
goto mdp_open_fail;
}
+
msm_fb_writeback_init(fbi);
+
inst->mdp = fbi;
inst->secure = mops->secure;
+ if (mops->secure) {
+ rc = mdp_secure(sd, inst);
+ if (rc) {
+ WFD_MSG_ERR("Couldn't secure MDP\n");
+ goto mdp_secure_fail;
+ }
+ }
+
mops->cookie = inst;
- return rc;
+ return 0;
+mdp_secure_fail:
+ switch_dev_unregister(&inst->sdev);
+ msm_fb_writeback_terminate(inst->mdp);
mdp_open_fail:
kfree(inst);
return rc;
@@ -118,7 +129,8 @@
}
return 0;
}
-int mdp_close(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_close(struct v4l2_subdev *sd, void *arg)
{
struct mdp_instance *inst = arg;
struct fb_info *fbi = NULL;
@@ -133,7 +145,8 @@
}
return 0;
}
-int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
{
int rc = 0;
struct mdp_buf_info *binfo = arg;
@@ -161,7 +174,8 @@
WFD_MSG_ERR("Failed to queue buffer\n");
return rc;
}
-int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
{
int rc = 0;
struct mdp_buf_info *obuf = arg;
@@ -184,7 +198,8 @@
obuf->cookie = (void *)fbdata.priv;
return rc;
}
-int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
{
struct mdp_prop *prop = (struct mdp_prop *)arg;
struct mdp_instance *inst = prop->inst;
@@ -197,7 +212,7 @@
return 0;
}
-int mdp_mmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_mmap(struct v4l2_subdev *sd, void *arg)
{
int rc = 0, align = 0;
struct mem_region_map *mmap = arg;
@@ -250,7 +265,7 @@
return rc;
}
-int mdp_munmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_munmap(struct v4l2_subdev *sd, void *arg)
{
struct mem_region_map *mmap = arg;
struct mem_region *mregion;
@@ -278,7 +293,7 @@
return 0;
}
-int mdp_secure(struct v4l2_subdev *sd, void *arg)
+static int mdp_secure(struct v4l2_subdev *sd, void *arg)
{
struct mdp_instance *inst = NULL;
int rc = 0;
@@ -331,9 +346,6 @@
case MDP_MUNMAP:
rc = mdp_munmap(sd, arg);
break;
- case MDP_SECURE:
- rc = mdp_secure(sd, arg);
- break;
default:
WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 1d3c9f55..af3cd69 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -1040,30 +1040,9 @@
{
int rc = 0;
struct wfd_device *wfd_dev = video_drvdata(filp);
- struct wfd_inst *inst = file_to_inst(filp);
- switch (a->id) {
- case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
- ioctl, ENC_SECURE, NULL);
- if (rc) {
- WFD_MSG_ERR("Couldn't secure encoder");
- break;
- }
-
- rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
- ioctl, MDP_SECURE, (void *)inst->mdp_inst);
- if (rc) {
- WFD_MSG_ERR("Couldn't secure MDP");
- break;
- }
-
- wfd_dev->secure = true;
- break;
- default:
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
- ioctl, SET_PROP, a);
- }
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
+ ioctl, SET_PROP, a);
if (rc)
WFD_MSG_ERR("Failed to set encoder property\n");
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d339d81..73a1b41 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -167,10 +167,12 @@
static inline void mmc_update_clk_scaling(struct mmc_host *host)
{
- if (host->clk_scaling.enable)
+ if (host->clk_scaling.enable) {
host->clk_scaling.busy_time_us +=
ktime_to_us(ktime_sub(ktime_get(),
host->clk_scaling.start_busy));
+ host->clk_scaling.start_busy = ktime_get();
+ }
}
/**
* mmc_request_done - finish processing an MMC request
@@ -811,6 +813,12 @@
context_info->is_urgent = false;
context_info->is_new_req = false;
if (mmc_should_stop_curr_req(host)) {
+ /*
+ * We are going to stop the ongoing request.
+ * Update stuff that we ought to do when the
+ * request actually completes.
+ */
+ mmc_update_clk_scaling(host);
err = mmc_stop_request(host);
if (err && !context_info->is_done_rcv) {
err = MMC_BLK_ABORT;
@@ -823,14 +831,6 @@
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(
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2038d3d..6b392b9 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2416,6 +2416,9 @@
goto out;
}
+ if (msm_host->msm_bus_vote.client_handle)
+ sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
+
return sdhci_msm_runtime_suspend(dev);
out:
return ret;
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 47108c6..6412fc0 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -886,6 +886,12 @@
(u32) base, status);
bam_output_register_content(base);
*cb_case = SPS_CALLBACK_BAM_HRESP_ERR_IRQ;
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ } else if (status & IRQ_STTS_BAM_TIMER_IRQ) {
+ SPS_DBG1("sps:bam 0x%x(va);receive BAM_TIMER_IRQ\n",
+ (u32) base);
+ *cb_case = SPS_CALLBACK_BAM_TIMER_IRQ;
+#endif
} else
SPS_INFO("sps:bam 0x%x(va);bam irq status="
"0x%x.", (u32) base, status);
@@ -1126,9 +1132,25 @@
void bam_pipe_timer_config(void *base, u32 pipe, enum bam_pipe_timer_mode mode,
u32 timeout_count)
{
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_MODE, mode);
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_TRSHLD,
- timeout_count);
+ u32 for_all_pipes = 0;
+
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ for_all_pipes = bam_read_reg_field(base, REVISION,
+ BAM_NUM_INACTIV_TMRS);
+#endif
+
+ if (for_all_pipes) {
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_MODE, mode);
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_TRSHLD,
+ timeout_count);
+#endif
+ } else {
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_MODE,
+ mode);
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_TRSHLD,
+ timeout_count);
+ }
}
/**
@@ -1137,10 +1159,26 @@
*/
void bam_pipe_timer_reset(void *base, u32 pipe)
{
- /* reset */
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 0);
- /* active */
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 1);
+ u32 for_all_pipes = 0;
+
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ for_all_pipes = bam_read_reg_field(base, REVISION,
+ BAM_NUM_INACTIV_TMRS);
+#endif
+
+ if (for_all_pipes) {
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ /* reset */
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_RST, 0);
+ /* active */
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_RST, 1);
+#endif
+ } else {
+ /* reset */
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 0);
+ /* active */
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 1);
+ }
}
/**
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index cda1717..23c346a 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2232,8 +2232,7 @@
SPS_ERR("sps:%s:timer_ctrl pointer is NULL.\n", __func__);
return SPS_ERROR;
} else if (timer_result == NULL) {
- SPS_ERR("sps:%s:result pointer is NULL.\n", __func__);
- return SPS_ERROR;
+ SPS_DBG("sps:%s:no result to return.\n", __func__);
}
bam = sps_bam_lock(pipe);
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index a84d99e..80056f5 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -24,7 +24,8 @@
#include "spsi.h"
/* All BAM global IRQ sources */
-#define BAM_IRQ_ALL (BAM_DEV_IRQ_HRESP_ERROR | BAM_DEV_IRQ_ERROR)
+#define BAM_IRQ_ALL (BAM_DEV_IRQ_HRESP_ERROR | BAM_DEV_IRQ_ERROR | \
+ BAM_DEV_IRQ_TIMER)
/* BAM device state flags */
#define BAM_STATE_INIT (1UL << 1)
@@ -145,7 +146,7 @@
BAM_ID(dev), source, mask);
if ((source & (1UL << 31)) && (dev->props.callback)) {
- SPS_INFO("sps:bam_isr:bam=0x%x;callback for case %d.\n",
+ SPS_DBG1("sps:bam_isr:bam=0x%x;callback for case %d.\n",
BAM_ID(dev), cb_case);
dev->props.callback(cb_case, dev->props.user);
}
@@ -2027,7 +2028,7 @@
BAM_PIPE_TIMER_ONESHOT :
BAM_PIPE_TIMER_PERIODIC;
bam_pipe_timer_config(dev->base, pipe_index, mode,
- timer_ctrl->timeout_msec * 10);
+ timer_ctrl->timeout_msec * 8);
break;
case SPS_TIMER_OP_RESET:
bam_pipe_timer_reset(dev->base, pipe_index);
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index bbc0373..dede487 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -32,6 +32,7 @@
BAM_DEV_IRQ_RDY_TO_SLEEP = 0x00000001,
BAM_DEV_IRQ_HRESP_ERROR = 0x00000002,
BAM_DEV_IRQ_ERROR = 0x00000004,
+ BAM_DEV_IRQ_TIMER = 0x00000010,
};
/* Pipe interrupt mask */
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index ee80975..9ba954a 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -1504,11 +1504,10 @@
},
};
-static int __init tsens_tm_init_driver(void)
+int __init tsens_tm_init_driver(void)
{
return platform_driver_register(&tsens_tm_driver);
}
-arch_initcall(tsens_tm_init_driver);
static int __init tsens_thermal_register(void)
{
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f83794c..7a6765b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1254,50 +1254,11 @@
return ret;
}
-/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+/* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
{
u32 data = 0;
- /* SSPHY Initialization: Use ref_clk from pads and set its parameters */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
- msleep(30);
- /* Assert SSPHY reset */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
- usleep_range(2000, 2200);
- /* De-assert SSPHY reset - power and ref_clock must be ON */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
- usleep_range(2000, 2200);
- /* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
- usleep_range(2000, 2200);
- /*
- * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
- * and disable RETENTION (power-on default is ENABLED)
- */
- dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
- usleep_range(2000, 2200);
- /* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
- /*
- * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
- * VBUS valid threshold, disconnect valid threshold, DC voltage level,
- * preempasis and rise/fall time.
- */
- if (override_phy_init)
- msm->hsphy_init_seq = override_phy_init;
- if (msm->hsphy_init_seq)
- dwc3_msm_write_readback(msm->base,
- PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
- msm->hsphy_init_seq & 0x03FFFFFF);
-
- /* Enable master clock for RAMs to allow BAM to access RAMs when
- * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
- * are seen where RAM clocks get turned OFF in SS mode
- */
- dwc3_msm_write_reg(msm->base, CGCTL_REG,
- dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
-
/*
* WORKAROUND: There is SSPHY suspend bug due to which USB enumerates
* in HS mode instead of SS mode. Workaround it by asserting
@@ -1344,6 +1305,51 @@
dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1, 0x07, 0x5);
}
+/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+{
+ /* SSPHY Initialization: Use ref_clk from pads and set its parameters */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ msleep(30);
+ /* Assert SSPHY reset */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ usleep_range(2000, 2200);
+ /* De-assert SSPHY reset - power and ref_clock must be ON */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ usleep_range(2000, 2200);
+ /* Ref clock must be stable now, enable ref clock for HS mode */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ usleep_range(2000, 2200);
+ /*
+ * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
+ * and disable RETENTION (power-on default is ENABLED)
+ */
+ dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ usleep_range(2000, 2200);
+ /* Disable (bypass) VBUS and ID filters */
+ dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ /*
+ * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
+ * VBUS valid threshold, disconnect valid threshold, DC voltage level,
+ * preempasis and rise/fall time.
+ */
+ if (override_phy_init)
+ msm->hsphy_init_seq = override_phy_init;
+ if (msm->hsphy_init_seq)
+ dwc3_msm_write_readback(msm->base,
+ PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
+ msm->hsphy_init_seq & 0x03FFFFFF);
+
+ /* Enable master clock for RAMs to allow BAM to access RAMs when
+ * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
+ * are seen where RAM clocks get turned OFF in SS mode
+ */
+ dwc3_msm_write_reg(msm->base, CGCTL_REG,
+ dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+
+ dwc3_msm_ss_phy_reg_init(msm);
+}
+
static void dwc3_msm_block_reset(bool core_reset)
{
@@ -1791,6 +1797,11 @@
udelay(10);
dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7), 0x0);
+ /*
+ * Reinitilize SSPHY parameters as SS_PHY RESET will reset
+ * the internal registers to default values.
+ */
+ dwc3_msm_ss_phy_reg_init(mdwc);
atomic_set(&mdwc->in_lpm, 0);
/* match disable_irq call from isr */
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index fa53656..4e51100 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -294,6 +294,8 @@
ctl->stop_fnc = NULL;
ctl->prepare_fnc = NULL;
ctl->display_fnc = NULL;
+ ctl->wait_fnc = NULL;
+ ctl->set_vsync_handler = NULL;
mutex_unlock(&mdss_mdp_ctl_lock);
return 0;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 19face8..1523700 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -120,25 +120,39 @@
};
-/* Indexing: supported video standards */
-enum dmx_indexing_video_standard {
- DMX_INDEXING_MPEG2,
- DMX_INDEXING_H264,
- DMX_INDEXING_VC1
+enum dmx_video_codec {
+ DMX_VIDEO_CODEC_MPEG2,
+ DMX_VIDEO_CODEC_H264,
+ DMX_VIDEO_CODEC_VC1
};
-/* Indexing: Supported video profiles */
-enum dmx_indexing_video_profile {
- DMX_INDEXING_MPEG2_ANY,
- DMX_INDEXING_H264_ANY,
- DMX_INDEXING_VC1_ANY
-};
-
-/* Indexing: video configuration parameters */
-struct dmx_indexing_video_params {
- enum dmx_indexing_video_standard standard;
- enum dmx_indexing_video_profile profile;
-};
+/* Index entries types */
+#define DMX_IDX_RAI 0x00000001
+#define DMX_IDX_PUSI 0x00000002
+#define DMX_IDX_MPEG_SEQ_HEADER 0x00000004
+#define DMX_IDX_MPEG_GOP 0x00000008
+#define DMX_IDX_MPEG_FIRST_SEQ_FRAME_START 0x00000010
+#define DMX_IDX_MPEG_FIRST_SEQ_FRAME_END 0x00000020
+#define DMX_IDX_MPEG_I_FRAME_START 0x00000040
+#define DMX_IDX_MPEG_I_FRAME_END 0x00000080
+#define DMX_IDX_MPEG_P_FRAME_START 0x00000100
+#define DMX_IDX_MPEG_P_FRAME_END 0x00000200
+#define DMX_IDX_MPEG_B_FRAME_START 0x00000400
+#define DMX_IDX_MPEG_B_FRAME_END 0x00000800
+#define DMX_IDX_H264_SPS 0x00001000
+#define DMX_IDX_H264_PPS 0x00002000
+#define DMX_IDX_H264_FIRST_SPS_FRAME_START 0x00004000
+#define DMX_IDX_H264_FIRST_SPS_FRAME_END 0x00008000
+#define DMX_IDX_H264_IDR_START 0x00010000
+#define DMX_IDX_H264_IDR_END 0x00020000
+#define DMX_IDX_H264_NON_IDR_START 0x00040000
+#define DMX_IDX_H264_NON_IDR_END 0x00080000
+#define DMX_IDX_VC1_SEQ_HEADER 0x00100000
+#define DMX_IDX_VC1_ENTRY_POINT 0x00200000
+#define DMX_IDX_VC1_FIRST_SEQ_FRAME_START 0x00400000
+#define DMX_IDX_VC1_FIRST_SEQ_FRAME_END 0x00800000
+#define DMX_IDX_VC1_FRAME_START 0x01000000
+#define DMX_IDX_VC1_FRAME_END 0x02000000
struct dmx_pes_filter_params
{
@@ -160,7 +174,7 @@
*/
__u32 rec_chunk_size;
- struct dmx_indexing_video_params video_params;
+ enum dmx_video_codec video_codec;
};
struct dmx_buffer_status {
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 67b5e6c..88ad9a0 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -29,10 +29,6 @@
* @ION_HEAP_TYPE_CARVEOUT: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous
- * @ION_HEAP_TYPE_IOMMU: IOMMU memory
- * @ION_HEAP_TYPE_CP: memory allocated from a prereserved
- * carveout heap, allocations are physically
- * contiguous. Used for content protection.
* @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
@@ -104,11 +100,6 @@
* struct ion_platform_data - array of platform heaps passed from board file
* @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
* @nr: number of structures in the array
- * @request_region: function to be called when the number of allocations goes
- * from 0 -> 1
- * @release_region: function to be called when the number of allocations goes
- * from 1 -> 0
- * @setup_region: function to be called upon ion registration
* @heaps: array of platform_heap structions
*
* Provided by the board file in the form of platform data to a platform device.
@@ -116,9 +107,6 @@
struct ion_platform_data {
unsigned int has_outer_cache;
int nr;
- int (*request_region)(void *);
- int (*release_region)(void *);
- void *(*setup_region)(void);
struct ion_platform_heap *heaps;
};
@@ -145,17 +133,6 @@
unsigned int heap_mask, const char *name);
/**
- * msm_ion_client_create - allocate a client using the ion_device specified in
- * drivers/gpu/ion/msm/msm_ion.c
- *
- * heap_mask and name are the same as ion_client_create, return values
- * are the same as ion_client_create.
- */
-
-struct ion_client *msm_ion_client_create(unsigned int heap_mask,
- const char *name);
-
-/**
* ion_client_destroy() - free's a client and all it's handles
* @client: the client
*
@@ -257,124 +234,6 @@
*/
struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd);
-/**
- * ion_handle_get_flags - get the flags for a given handle
- *
- * @client - client who allocated the handle
- * @handle - handle to get the flags
- * @flags - pointer to store the flags
- *
- * Gets the current flags for a handle. These flags indicate various options
- * of the buffer (caching, security, etc.)
- */
-int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
- unsigned long *flags);
-
-
-/**
- * ion_map_iommu - map the given handle into an iommu
- *
- * @client - client who allocated the handle
- * @handle - handle to map
- * @domain_num - domain number to map to
- * @partition_num - partition number to allocate iova from
- * @align - alignment for the iova
- * @iova_length - length of iova to map. If the iova length is
- * greater than the handle length, the remaining
- * address space will be mapped to a dummy buffer.
- * @iova - pointer to store the iova address
- * @buffer_size - pointer to store the size of the buffer
- * @flags - flags for options to map
- * @iommu_flags - flags specific to the iommu.
- *
- * Maps the handle into the iova space specified via domain number. Iova
- * will be allocated from the partition specified via partition_num.
- * Returns 0 on success, negative value on error.
- */
-int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
- int domain_num, int partition_num, unsigned long align,
- unsigned long iova_length, unsigned long *iova,
- unsigned long *buffer_size,
- unsigned long flags, unsigned long iommu_flags);
-
-
-/**
- * ion_handle_get_size - get the allocated size of a given handle
- *
- * @client - client who allocated the handle
- * @handle - handle to get the size
- * @size - pointer to store the size
- *
- * gives the allocated size of a handle. returns 0 on success, negative
- * value on error
- *
- * NOTE: This is intended to be used only to get a size to pass to map_iommu.
- * You should *NOT* rely on this for any other usage.
- */
-
-int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
- unsigned long *size);
-
-/**
- * ion_unmap_iommu - unmap the handle from an iommu
- *
- * @client - client who allocated the handle
- * @handle - handle to unmap
- * @domain_num - domain to unmap from
- * @partition_num - partition to unmap from
- *
- * Decrement the reference count on the iommu mapping. If the count is
- * 0, the mapping will be removed from the iommu.
- */
-void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
- int domain_num, int partition_num);
-
-
-/**
- * ion_secure_heap - secure a heap
- *
- * @client - a client that has allocated from the heap heap_id
- * @heap_id - heap id to secure.
- * @version - version of content protection
- * @data - extra data needed for protection
- *
- * Secure a heap
- * Returns 0 on success
- */
-int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
- void *data);
-
-/**
- * ion_unsecure_heap - un-secure a heap
- *
- * @client - a client that has allocated from the heap heap_id
- * @heap_id - heap id to un-secure.
- * @version - version of content protection
- * @data - extra data needed for protection
- *
- * Un-secure a heap
- * Returns 0 on success
- */
-int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
- void *data);
-
-/**
- * msm_ion_do_cache_op - do cache operations.
- *
- * @client - pointer to ION client.
- * @handle - pointer to buffer handle.
- * @vaddr - virtual address to operate on.
- * @len - Length of data to do cache operation on.
- * @cmd - Cache operation to perform:
- * ION_IOC_CLEAN_CACHES
- * ION_IOC_INV_CACHES
- * ION_IOC_CLEAN_INV_CACHES
- *
- * Returns 0 on success
- */
-int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
- void *vaddr, unsigned long len, unsigned int cmd);
-
#else
static inline void ion_reserve(struct ion_platform_data *data)
{
@@ -387,12 +246,6 @@
return ERR_PTR(-ENODEV);
}
-static inline struct ion_client *msm_ion_client_create(unsigned int heap_mask,
- const char *name)
-{
- return ERR_PTR(-ENODEV);
-}
-
static inline void ion_client_destroy(struct ion_client *client) { }
static inline struct ion_handle *ion_alloc(struct ion_client *client,
@@ -444,54 +297,6 @@
return -ENODEV;
}
-static inline int ion_map_iommu(struct ion_client *client,
- struct ion_handle *handle, int domain_num,
- int partition_num, unsigned long align,
- unsigned long iova_length, unsigned long *iova,
- unsigned long *buffer_size,
- unsigned long flags,
- unsigned long iommu_flags)
-{
- return -ENODEV;
-}
-
-static inline int ion_handle_get_size(struct ion_client *client,
- struct ion_handle *handle, unsigned long *size)
-{
- return -ENODEV;
-}
-
-static inline void ion_unmap_iommu(struct ion_client *client,
- struct ion_handle *handle, int domain_num,
- int partition_num)
-{
- return;
-}
-
-static inline int ion_secure_heap(struct ion_device *dev, int heap_id,
- int version, void *data)
-{
- return -ENODEV;
-
-}
-
-static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id,
- int version, void *data)
-{
- return -ENODEV;
-}
-
-static inline void ion_mark_dangling_buffers_locked(struct ion_device *dev)
-{
-}
-
-static inline int msm_ion_do_cache_op(struct ion_client *client,
- struct ion_handle *handle, void *vaddr,
- unsigned long len, unsigned int cmd)
-{
- return -ENODEV;
-}
-
#endif /* CONFIG_ION */
#endif /* __KERNEL__ */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 3b5742e..9eef3a0 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -454,6 +454,12 @@
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
+ if (!host->sdio_irqs) {
+ pr_err("%s: SDIO interrupt recieved without function driver claiming an irq\n",
+ mmc_hostname(host));
+ return;
+ }
+
host->ops->enable_sdio_irq(host, 0);
host->sdio_irq_pending = true;
wake_up_process(host->sdio_irq_thread);
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 3c3c7a9..20b7317 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -9,6 +9,7 @@
ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CP,
ION_HEAP_TYPE_SECURE_DMA,
+ ION_HEAP_TYPE_REMOVED,
};
/**
@@ -194,9 +195,138 @@
#ifdef CONFIG_ION
/**
+ * msm_ion_client_create - allocate a client using the ion_device specified in
+ * drivers/gpu/ion/msm/msm_ion.c
+ *
+ * heap_mask and name are the same as ion_client_create, return values
+ * are the same as ion_client_create.
+ */
+
+struct ion_client *msm_ion_client_create(unsigned int heap_mask,
+ const char *name);
+
+/**
+ * ion_handle_get_flags - get the flags for a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the flags
+ * @flags - pointer to store the flags
+ *
+ * Gets the current flags for a handle. These flags indicate various options
+ * of the buffer (caching, security, etc.)
+ */
+int ion_handle_get_flags(struct ion_client *client, struct ion_handle *handle,
+ unsigned long *flags);
+
+
+/**
+ * ion_map_iommu - map the given handle into an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to map
+ * @domain_num - domain number to map to
+ * @partition_num - partition number to allocate iova from
+ * @align - alignment for the iova
+ * @iova_length - length of iova to map. If the iova length is
+ * greater than the handle length, the remaining
+ * address space will be mapped to a dummy buffer.
+ * @iova - pointer to store the iova address
+ * @buffer_size - pointer to store the size of the buffer
+ * @flags - flags for options to map
+ * @iommu_flags - flags specific to the iommu.
+ *
+ * Maps the handle into the iova space specified via domain number. Iova
+ * will be allocated from the partition specified via partition_num.
+ * Returns 0 on success, negative value on error.
+ */
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags, unsigned long iommu_flags);
+
+
+/**
+ * ion_handle_get_size - get the allocated size of a given handle
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to get the size
+ * @size - pointer to store the size
+ *
+ * gives the allocated size of a handle. returns 0 on success, negative
+ * value on error
+ *
+ * NOTE: This is intended to be used only to get a size to pass to map_iommu.
+ * You should *NOT* rely on this for any other usage.
+ */
+
+int ion_handle_get_size(struct ion_client *client, struct ion_handle *handle,
+ unsigned long *size);
+
+/**
+ * ion_unmap_iommu - unmap the handle from an iommu
+ *
+ * @client - client who allocated the handle
+ * @handle - handle to unmap
+ * @domain_num - domain to unmap from
+ * @partition_num - partition to unmap from
+ *
+ * Decrement the reference count on the iommu mapping. If the count is
+ * 0, the mapping will be removed from the iommu.
+ */
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num);
+
+
+/**
+ * ion_secure_heap - secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
+ *
+ * Secure a heap
+ * Returns 0 on success
+ */
+int ion_secure_heap(struct ion_device *dev, int heap_id, int version,
+ void *data);
+
+/**
+ * ion_unsecure_heap - un-secure a heap
+ *
+ * @client - a client that has allocated from the heap heap_id
+ * @heap_id - heap id to un-secure.
+ * @version - version of content protection
+ * @data - extra data needed for protection
+ *
+ * Un-secure a heap
+ * Returns 0 on success
+ */
+int ion_unsecure_heap(struct ion_device *dev, int heap_id, int version,
+ void *data);
+
+/**
+ * msm_ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @vaddr - virtual address to operate on.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ * ION_IOC_CLEAN_CACHES
+ * ION_IOC_INV_CACHES
+ * ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *vaddr, unsigned long len, unsigned int cmd);
+
+/**
* msm_ion_secure_heap - secure a heap. Wrapper around ion_secure_heap.
*
- * @heap_id - heap id to secure.
+ * @heap_id - heap id to secure.
*
* Secure a heap
* Returns 0 on success
@@ -257,6 +387,60 @@
int msm_ion_unsecure_buffer(struct ion_client *client,
struct ion_handle *handle);
#else
+static inline struct ion_client *msm_ion_client_create(unsigned int heap_mask,
+ const char *name)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline int ion_map_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags,
+ unsigned long iommu_flags)
+{
+ return -ENODEV;
+}
+
+static inline int ion_handle_get_size(struct ion_client *client,
+ struct ion_handle *handle, unsigned long *size)
+{
+ return -ENODEV;
+}
+
+static inline void ion_unmap_iommu(struct ion_client *client,
+ struct ion_handle *handle, int domain_num,
+ int partition_num)
+{
+ return;
+}
+
+static inline int ion_secure_heap(struct ion_device *dev, int heap_id,
+ int version, void *data)
+{
+ return -ENODEV;
+
+}
+
+static inline int ion_unsecure_heap(struct ion_device *dev, int heap_id,
+ int version, void *data)
+{
+ return -ENODEV;
+}
+
+static inline void ion_mark_dangling_buffers_locked(struct ion_device *dev)
+{
+}
+
+static inline int msm_ion_do_cache_op(struct ion_client *client,
+ struct ion_handle *handle, void *vaddr,
+ unsigned long len, unsigned int cmd)
+{
+ return -ENODEV;
+}
+
static inline int msm_ion_secure_heap(int heap_id)
{
return -ENODEV;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 7e1a709..f932494 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -552,6 +552,65 @@
uint32_t data;
};
+#define MDSS_AD_MODE_AUTO_BL 0x0
+#define MDSS_AD_MODE_AUTO_STR 0x1
+#define MDSS_AD_MODE_TARG_STR 0x3
+#define MDSS_AD_MODE_MAN_STR 0x7
+
+#define MDP_PP_AD_INIT 0x10
+#define MDP_PP_AD_CFG 0x20
+
+struct mdss_ad_init {
+ uint32_t asym_lut[33];
+ uint32_t color_corr_lut[33];
+ uint8_t i_control[2];
+ uint16_t black_lvl;
+ uint16_t white_lvl;
+ uint8_t var;
+ uint8_t limit_ampl;
+ uint8_t i_dither;
+ uint8_t slope_max;
+ uint8_t slope_min;
+ uint8_t dither_ctl;
+ uint8_t format;
+ uint8_t auto_size;
+ uint16_t frame_w;
+ uint16_t frame_h;
+ uint8_t logo_v;
+ uint8_t logo_h;
+};
+
+struct mdss_ad_cfg {
+ uint32_t mode;
+ uint32_t al_calib_lut[33];
+ uint16_t backlight_min;
+ uint16_t backlight_max;
+ uint16_t backlight_scale;
+ uint16_t amb_light_min;
+ uint16_t filter[2];
+ uint16_t calib[4];
+ uint8_t strength_limit;
+ uint8_t t_filter_recursion;
+};
+
+/* ops uses standard MDP_PP_* flags */
+struct mdss_ad_init_cfg {
+ uint32_t ops;
+ union {
+ struct mdss_ad_init init;
+ struct mdss_ad_cfg cfg;
+ } params;
+};
+
+/* mode uses MDSS_AD_MODE_* flags */
+struct mdss_ad_input {
+ uint32_t mode;
+ union {
+ uint32_t amb_light;
+ uint32_t strength;
+ } in;
+};
+
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
@@ -562,6 +621,8 @@
mdp_op_dither_cfg,
mdp_op_gamut_cfg,
mdp_op_calib_cfg,
+ mdp_op_ad_cfg,
+ mdp_op_ad_input,
mdp_op_max,
};
@@ -586,6 +647,8 @@
struct mdp_dither_cfg_data dither_cfg_data;
struct mdp_gamut_cfg_data gamut_cfg_data;
struct mdp_calib_config_data calib_cfg;
+ struct mdss_ad_init_cfg ad_init_cfg;
+ struct mdss_ad_input ad_input;
} data;
};
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 8aa7c17..757f1dc 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -41,6 +41,14 @@
int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
int msm_tsens_early_init(struct tsens_platform_data *pdata);
+
+#if defined(CONFIG_THERMAL_TSENS8974)
+int __init tsens_tm_init_driver(void);
+#else
+static inline int __init tsens_tm_init_driver(void)
+{ return -ENXIO; }
+#endif
+
#if defined(CONFIG_THERMAL_TSENS8974) || defined(CONFIG_THERMAL_TSENS8960)
int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
#else
diff --git a/mm/dmapool.c b/mm/dmapool.c
index c5ab33b..da1b0f0 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -50,7 +50,6 @@
size_t allocation;
size_t boundary;
char name[32];
- wait_queue_head_t waitq;
struct list_head pools;
};
@@ -62,8 +61,6 @@
unsigned int offset;
};
-#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
-
static DEFINE_MUTEX(pools_lock);
static ssize_t
@@ -172,7 +169,6 @@
retval->size = size;
retval->boundary = boundary;
retval->allocation = allocation;
- init_waitqueue_head(&retval->waitq);
if (dev) {
int ret;
@@ -227,7 +223,6 @@
memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
#endif
pool_initialise_page(pool, page);
- list_add(&page->page_list, &pool->page_list);
page->in_use = 0;
page->offset = 0;
} else {
@@ -315,30 +310,21 @@
might_sleep_if(mem_flags & __GFP_WAIT);
spin_lock_irqsave(&pool->lock, flags);
- restart:
list_for_each_entry(page, &pool->page_list, page_list) {
if (page->offset < pool->allocation)
goto ready;
}
- page = pool_alloc_page(pool, GFP_ATOMIC);
- if (!page) {
- if (mem_flags & __GFP_WAIT) {
- DECLARE_WAITQUEUE(wait, current);
- __set_current_state(TASK_UNINTERRUPTIBLE);
- __add_wait_queue(&pool->waitq, &wait);
- spin_unlock_irqrestore(&pool->lock, flags);
+ /* pool_alloc_page() might sleep, so temporarily drop &pool->lock */
+ spin_unlock_irqrestore(&pool->lock, flags);
- schedule_timeout(POOL_TIMEOUT_JIFFIES);
+ page = pool_alloc_page(pool, mem_flags);
+ if (!page)
+ return NULL;
- spin_lock_irqsave(&pool->lock, flags);
- __remove_wait_queue(&pool->waitq, &wait);
- goto restart;
- }
- retval = NULL;
- goto done;
- }
+ spin_lock_irqsave(&pool->lock, flags);
+ list_add(&page->page_list, &pool->page_list);
ready:
page->in_use++;
offset = page->offset;
@@ -348,7 +334,6 @@
#ifdef DMAPOOL_DEBUG
memset(retval, POOL_POISON_ALLOCATED, pool->size);
#endif
- done:
spin_unlock_irqrestore(&pool->lock, flags);
return retval;
}
@@ -435,8 +420,6 @@
page->in_use--;
*(int *)vaddr = page->offset;
page->offset = offset;
- if (waitqueue_active(&pool->waitq))
- wake_up_locked(&pool->waitq);
/*
* Resist a temptation to do
* if (!is_page_busy(page)) pool_free_page(pool, page);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 866f524..f5f4e23 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -102,6 +102,12 @@
#define SITAR_MBHC_STATUS_REL_DETECTION 0x0C
#define SITAR_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 200
+#define CUT_OF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x01
+#define CF_MIN_3DB_150HZ 0x02
+
+
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -194,6 +200,15 @@
0, /* AIF1_CAP */
};
+struct hpf_work {
+ struct sitar_priv *sitar;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
struct sitar_priv {
struct snd_soc_codec *codec;
u32 mclk_freq;
@@ -1755,6 +1770,8 @@
snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
break;
case SND_SOC_DAPM_POST_PMU:
+
+ usleep_range(20000, 20000);
if (sitar->mbhc_polling_active &&
sitar->mbhc_cfg.micbias == micb_line) {
SITAR_ACQUIRE_LOCK(sitar->codec_resource_lock);
@@ -1780,36 +1797,141 @@
return 0;
}
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct sitar_priv *sitar;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ sitar = hpf_work->sitar;
+ codec = hpf_work->sitar->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 8;
+
+ pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+ hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg,
+ CUT_OF_FREQ_MASK, hpf_cut_of_freq << 4);
+}
+
static int sitar_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u16 dec_reset_reg, gain_reg;
- u8 current_gain;
+ u16 dec_reset_reg, gain_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ unsigned int decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0;
+ u8 dec_hpf_cut_of_freq, current_gain;
pr_debug("%s %d\n", __func__, event);
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "1234"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
else {
pr_err("%s: Error, incorrect dec\n", __func__);
- return -EINVAL;
+ ret = EINVAL;
+ goto out;
}
+ tx_vol_ctl_reg = SITAR_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
+ tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ /* Enable TX Digital Mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1 << w->shift);
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+ dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq &
+ CUT_OF_FREQ_MASK) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+ /* Set cut off freq to CF_MIN_3DB_150HZ (0x01) */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg,
+ CUT_OF_FREQ_MASK, CF_MIN_3DB_150HZ << 4);
+ }
+
+ /* enable HPF */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x00);
+
break;
+
case SND_SOC_DAPM_POST_PMU:
+ /* Disable TX Digital Mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+
/* Reprogram the digital gain after power up of Decimator */
gain_reg = SITAR_A_CDC_TX1_VOL_CTL_GAIN + (8 * w->shift);
current_gain = snd_soc_read(codec, gain_reg);
snd_soc_write(codec, gain_reg, current_gain);
break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Enable Digital Mute, Cancel possibly scheduled work */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, CUT_OF_FREQ_MASK,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+ break;
+
}
- return 0;
+
+out:
+ kfree(widget_name);
+ return ret;
+
}
static int sitar_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
@@ -2278,16 +2400,23 @@
SND_SOC_DAPM_MUX_E("DEC1 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
&dec1_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
&dec2_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
&dec3_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
&dec4_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
@@ -5316,6 +5445,14 @@
return -ENOMEM;
}
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].sitar = sitar;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
+
+
/* Make sure mbhc micbias register addresses are zeroed out */
memset(&sitar->mbhc_bias_regs, 0,
sizeof(struct mbhc_micbias_regs));
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index c5cb560..e74a0dd 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -93,6 +93,7 @@
static const DECLARE_TLV_DB_LINEAR(compressed3_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
static int msm_route_ec_ref_rx;
+static int msm_route_ext_ec_ref;
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
#define MAX_EQ_SESSIONS MSM_FRONTEND_DAI_CS_VOICE
@@ -1425,6 +1426,57 @@
msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put),
};
+static int msm_routing_ext_ec_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: ext_ec_ref_rx = %x\n", __func__, msm_route_ext_ec_ref);
+
+ mutex_lock(&routing_lock);
+ ucontrol->value.integer.value[0] = msm_route_ext_ec_ref;
+ mutex_unlock(&routing_lock);
+ return 0;
+}
+
+static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ int mux = ucontrol->value.enumerated.item[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int ret = 0;
+
+ pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n",
+ __func__, msm_route_ext_ec_ref,
+ ucontrol->value.integer.value[0]);
+
+ mutex_lock(&routing_lock);
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ msm_route_ext_ec_ref = MI2S_TX;
+ ret = voc_set_ext_ec_ref(msm_route_ext_ec_ref, true);
+ break;
+ default:
+ msm_route_ext_ec_ref = AFE_PORT_INVALID;
+ ret = voc_set_ext_ec_ref(msm_route_ext_ec_ref, false);
+ break;
+ }
+ snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+ mutex_unlock(&routing_lock);
+ return ret;
+}
+
+static const char * const ext_ec_ref_rx[] = {"NONE", "MI2S_TX"};
+
+static const struct soc_enum msm_route_ext_ec_ref_rx_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, ext_ec_ref_rx),
+};
+
+static const struct snd_kcontrol_new voc_ext_ec_mux =
+ SOC_DAPM_ENUM_EXT("VOC_EXT_EC MUX Mux", msm_route_ext_ec_ref_rx_enum[0],
+ msm_routing_ext_ec_get, msm_routing_ext_ec_put);
+
+
static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -2887,6 +2939,7 @@
/* Virtual Pins to force backends ON atm */
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_INPUT("BE_IN"),
+ SND_SOC_DAPM_MUX("VOC_EXT_EC MUX", SND_SOC_NOPM, 0, 0, &voc_ext_ec_mux),
};
@@ -3071,6 +3124,8 @@
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
{"HDMI", NULL, "HDMI_DL_HL"},
+ {"VOC_EXT_EC MUX", "MI2S_TX" , "MI2S_TX"},
+ {"CS-VOICE_UL1", NULL, "VOC_EXT_EC MUX"},
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "SEC_TX_Voice", "SEC_I2S_TX"},
{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 17f2d03..bb13695 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -73,6 +73,7 @@
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv);
static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv);
static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv);
+static int voice_send_set_device_cmd_v2(struct voice_data *v);
static u16 voice_get_mvm_handle(struct voice_data *v)
{
@@ -1380,6 +1381,80 @@
return -EINVAL;
}
+static int voice_send_set_device_cmd_v2(struct voice_data *v)
+{
+ struct cvp_set_device_cmd_v2 cvp_setdev_cmd_v2;
+ int ret = 0;
+ void *apr_cvp;
+ u16 cvp_handle;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvp = common.apr_q6_cvp;
+
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ cvp_handle = voice_get_cvp_handle(v);
+
+ /* set device and wait for response */
+ cvp_setdev_cmd_v2.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_setdev_cmd_v2.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_setdev_cmd_v2) - APR_HDR_SIZE);
+ cvp_setdev_cmd_v2.hdr.src_port = v->session_id;
+ cvp_setdev_cmd_v2.hdr.dest_port = cvp_handle;
+ cvp_setdev_cmd_v2.hdr.token = 0;
+ cvp_setdev_cmd_v2.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE_V2;
+
+ voc_get_tx_rx_topology(v,
+ &cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id,
+ &cvp_setdev_cmd_v2.cvp_set_device_v2.rx_topology_id);
+
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
+ if (common.ec_ref_ext == true) {
+ cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id =
+ common.ec_port_id;
+ } else {
+ cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id =
+ VSS_IVOCPROC_PORT_ID_NONE;
+ }
+ pr_debug("%s:topology=%d , tx_port_id=%d, rx_port_id=%d\n"
+ "ec_ref_port_id = %x\n", __func__,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id);
+
+ v->cvp_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd_v2);
+ if (ret < 0) {
+ pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n");
+ goto fail;
+ }
+ pr_debug("wait for cvp create session event\n");
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
static int voice_send_stop_voice_cmd(struct voice_data *v)
{
struct apr_hdr mvm_stop_voice_cmd;
@@ -2277,7 +2352,13 @@
pr_err("%s: wait_event timeout\n", __func__);
goto fail;
}
-
+ if (common.ec_ref_ext == true) {
+ ret = voice_send_set_device_cmd_v2(v);
+ if (ret < 0)
+ pr_err("%s: set device V2 failed rc =%x\n",
+ __func__, ret);
+ goto fail;
+ }
/* send cvs cal */
ret = voice_send_cvs_map_memory_cmd(v);
if (!ret)
@@ -3242,7 +3323,8 @@
voice_send_cvp_deregister_cal_cmd(v);
voice_get_cal_paddr_size(v, &paddr, NULL);
voice_send_cvp_unmap_memory_cmd(v, paddr);
-
+ if (common.ec_ref_ext == true)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
v->voc_state = VOC_CHANGE;
}
@@ -3268,10 +3350,19 @@
mutex_lock(&v->lock);
if (v->voc_state == VOC_CHANGE) {
- ret = voice_send_set_device_cmd(v);
- if (ret < 0) {
- pr_err("%s: set device failed\n", __func__);
- goto fail;
+ if (common.ec_ref_ext == true) {
+ ret = voice_send_set_device_cmd_v2(v);
+ if (ret < 0)
+ pr_err("%s: set device V2 failed\n"
+ "rc =%x\n", __func__, ret);
+ goto fail;
+ } else {
+ ret = voice_send_set_device_cmd(v);
+ if (ret < 0) {
+ pr_err("%s: set device failed rc=%x\n",
+ __func__, ret);
+ goto fail;
+ }
}
/* send cvp and vol cal */
if (!voice_get_cal_paddr_size(v, &cal_paddr, &cal_size) &&
@@ -3675,7 +3766,8 @@
if (ret < 0)
pr_err("%s: destroy voice failed\n", __func__);
voice_destroy_mvm_cvs_session(v);
-
+ if (common.ec_ref_ext == true)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
v->voc_state = VOC_RELEASE;
}
mutex_unlock(&v->lock);
@@ -3845,6 +3937,28 @@
return ret;
}
+int voc_set_ext_ec_ref(uint16_t port_id, bool state)
+{
+ int ret = 0;
+
+ mutex_lock(&common.common_lock);
+ if (state == true) {
+ if (port_id == AFE_PORT_INVALID) {
+ pr_err("%s: Invalid port id", __func__);
+ ret = -EINVAL;
+ goto fail;
+ }
+ common.ec_port_id = port_id;
+ common.ec_ref_ext = true;
+ } else {
+ common.ec_ref_ext = false;
+ common.ec_port_id = port_id;
+ }
+fail:
+ mutex_unlock(&common.common_lock);
+ return ret;
+}
+
void voc_register_mvs_cb(ul_cb_fn ul_cb,
dl_cb_fn dl_cb,
void *private_data)
@@ -4201,6 +4315,7 @@
v->cvp_state = CMD_STATUS_SUCCESS;
wake_up(&v->cvp_wait);
break;
+ case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
case VSS_IVOCPROC_CMD_SET_DEVICE:
case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX:
case VSS_IVOCPROC_CMD_ENABLE:
@@ -4517,6 +4632,7 @@
common.default_mute_val = 0; /* default is un-mute */
common.default_vol_val = 0;
common.default_sample_val = 8000;
+ common.ec_ref_ext = false;
/* Initialize MVS info. */
common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 0bae384..7463a5f 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -903,6 +903,8 @@
#define VSS_IVOCPROC_CMD_SET_DEVICE 0x000100C4
+#define VSS_IVOCPROC_CMD_SET_DEVICE_V2 0x000112C6
+
#define VSS_IVOCPROC_CMD_SET_VP3_DATA 0x000110EB
#define VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX 0x000110EE
@@ -958,6 +960,9 @@
#define VOICE_CMD_GET_PARAM 0x00011007
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
+/* Default AFE port ID. Applicable to Tx and Rx. */
+#define VSS_IVOCPROC_PORT_ID_NONE 0xFFFF
+
struct vss_ivocproc_cmd_create_full_control_session_t {
uint16_t direction;
/*
@@ -1027,6 +1032,32 @@
*/
} __packed;
+/* Internal EC */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING 0x00010F7C
+
+/* External EC */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING 0x00010F7D
+
+struct vss_ivocproc_cmd_set_device_v2_t {
+ uint16_t tx_port_id;
+ /* Tx device port ID to which the vocproc connects. */
+ uint32_t tx_topology_id;
+ /* Tx path topology ID. */
+ uint16_t rx_port_id;
+ /* Rx device port ID to which the vocproc connects. */
+ uint32_t rx_topology_id;
+ /* Rx path topology ID. */
+ uint32_t vocproc_mode;
+ /* Vocproc mode. The supported values:
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING - 0x00010F7C
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING - 0x00010F7D
+ */
+ uint16_t ec_ref_port_id;
+ /* Port ID to which the vocproc connects for receiving
+ * echo cancellation reference signal.
+ */
+} __packed;
+
struct vss_ivocproc_cmd_register_calibration_data_t {
uint32_t phys_addr;
/* Phsical address to be registered with vocproc. Calibration data
@@ -1076,6 +1107,11 @@
struct vss_ivocproc_cmd_set_device_t cvp_set_device;
} __packed;
+struct cvp_set_device_cmd_v2 {
+ struct apr_hdr hdr;
+ struct vss_ivocproc_cmd_set_device_v2_t cvp_set_device_v2;
+} __packed;
+
struct cvp_set_vp3_data_cmd {
struct apr_hdr hdr;
} __packed;
@@ -1227,6 +1263,8 @@
uint32_t default_mute_val;
uint32_t default_vol_val;
uint32_t default_sample_val;
+ bool ec_ref_ext;
+ uint16_t ec_port_id;
/* APR to MVM in the Q6 */
void *apr_q6_mvm;
@@ -1325,4 +1363,5 @@
int voc_start_playback(uint32_t set);
int voc_start_record(uint32_t port_id, uint32_t set);
+int voc_set_ext_ec_ref(uint16_t port_id, bool state);
#endif
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 09d6a0f..9d6896e 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -944,7 +944,7 @@
i = port_id - SLIMBUS_0_RX;
if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
- pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
+ pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
return MAD_HW_NONE;
}
return (enum afe_mad_type) atomic_read(&afe_ports_mad_type[i]);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2b824f..59d4de2 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -866,7 +866,6 @@
data->reset_proc,
this_mmap.apr);
apr_reset(this_mmap.apr);
- atomic_set(&this_mmap.ref_cnt, 0);
this_mmap.apr = NULL;
reset_custom_topology_flags();
set_custom_topology = 1;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index a417b26..80bc4f9 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -4116,6 +4116,11 @@
if (v != NULL)
v->voc_state = VOC_ERROR;
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
+
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
v = voice_get_session(session_id);
if (v != NULL)
@@ -4250,6 +4255,11 @@
if (v != NULL)
v->voc_state = VOC_ERROR;
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
+
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
v = voice_get_session(session_id);
if (v != NULL)
@@ -4515,6 +4525,11 @@
if (v != NULL)
v->voc_state = VOC_ERROR;
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ v = voice_get_session(session_id);
+ if (v != NULL)
+ v->voc_state = VOC_ERROR;
+
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
v = voice_get_session(session_id);
if (v != NULL)