Merge "input: misc: stk3x1x: turn off device power when sensor is not enabled"
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 3d7e5a2..e564cd5 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -3,6 +3,9 @@
MDSS EDP is a edp driver which supports panels that are compatable with
VESA EDP display interface specification.
+When configuring the optional properties for external backlight, one should also
+configure the gpio that drives the pwm to it.
+
Required properties
- compatible : Must be "qcom,mdss-edp".
- reg : Offset and length of the register set for the
@@ -12,8 +15,6 @@
- vdda-supply : Phandle for vdd regulator device node.
- gpio-panel-en : GPIO for supplying power to panel and backlight
driver.
-- qcom,panel-lpg-channel : LPG channel for backlight.
-- qcom,panel-pwm-period : PWM period in microseconds.
- status : A string that has to be set to "okay/ok" to enable
the driver. By default this property will be set to
"disable". Will be set to "ok/okay" status for
@@ -37,4 +38,8 @@
gpio-panel-hpd = <&msmgpio 102 0>;
};
+Optional properties
+- qcom,panel-lpg-channel : LPG channel for backlight.
+- qcom,panel-pwm-period : PWM period in microseconds.
+
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 8f17a90..a4e61e8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -141,6 +141,11 @@
restricted for a source surface pipe. If this
property is not specified, no such restriction
would be applied.
+- qcom,mdss-pipe-rgb-fixed-mmb: Array of indexes describing fixed Memory Macro
+ Blocks (MMBs) for rgb pipes. First value denotes
+ total numbers of MMBs per pipe while values, if
+ any, following first one denotes indexes of MMBs
+ to that RGB pipe.
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -194,6 +199,10 @@
qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
qcom,mdss-pipe-dma-fetch-id = <10 13>;
+ qcom,mdss-pipe-rgb-fixed-mmb = <2 0 1>,
+ <2 2 3>,
+ <2 4 5>,
+ <2 6 7>;
qcom,mdss-smp-data = <22 4096>;
qcom,mdss-rot-block-size = <64>;
qcom,mdss-smp-mb-per-pipe = <2>;
diff --git a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
new file mode 100755
index 0000000..7e63014
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
@@ -0,0 +1,135 @@
+/* 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.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_hx8389b_qhd_vid: qcom,mdss_dsi_hx8389b_qhd_video {
+ qcom,mdss-dsi-panel-name = "HX8389b qhd video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <540>;
+ qcom,mdss-dsi-panel-height = <960>;
+ qcom,mdss-dsi-h-front-porch = <48>;
+ qcom,mdss-dsi-h-back-porch = <96>;
+ qcom,mdss-dsi-h-pulse-width = <96>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-front-porch = <9>;
+ qcom,mdss-dsi-v-pulse-width = <3>;
+ qcom,mdss-dsi-v-back-porch = <13>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 39 01 00 00 00 00 04
+ B9 FF 83 89
+ 39 01 00 00 00 00 08
+ BA 41 93 00
+ 16 A4 10 18
+ 23 01 00 00 00 00 02
+ C6 08
+ 39 01 00 00 00 00 03
+ BC 02 00
+ 23 01 00 00 00 00 02
+ CC 02
+ 39 01 00 00 00 00 14
+ B1 00 00 07
+ E8 50 10 11
+ 98 f8 21 29
+ 27 27 43 01
+ 58 F0 00 E6
+ 39 01 00 00 00 00 08
+ B2 00 00 78
+ 0C 07 3F 80
+ 39 01 00 00 00 00 18
+ b4 82 08 00
+ 32 10 04 32
+ 10 00 32 10
+ 00 37 0a 40
+ 08 37 0a 40
+ 14 46 50 0a
+ 39 01 00 00 00 00 39
+ d5 00 00 00
+ 00 01 00 00
+ 00 60 00 99
+ 88 AA BB 88
+ 23 88 01 88
+ 67 88 45 01
+ 23 88 88 88
+ 88 88 88 99
+ BB AA 88 54
+ 88 76 88 10
+ 88 32 32 10
+ 88 88 88 88
+ 88 00 04 00
+ 00 00 00 00
+ 00
+ 39 01 00 00 00 00 03
+ CB 07 07
+ 39 01 00 00 00 00 05
+ BB 00 00 FF
+ 80
+ 39 01 00 00 00 00 04
+ DE 05 58 10
+ 39 01 00 00 00 00 05
+ B6 00 8A 00
+ 8A
+ 39 01 00 00 00 00 23
+ E0 01 08 0C
+ 1F 25 36 12
+ 35 05 09 0D
+ 10 11 0F 0F
+ 1C 1D 01 08
+ 0C 1F 25 36
+ 12 35 05 09
+ 0D 10 11 0F
+ 0F 1C 1D
+ 05 01 00 00 96 00 02
+ 11 00
+ 05 01 00 00 96 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-panel-timings = [97 23 17 00 4B 53 1C 27 27 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index ec3f248..feef9d5 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -215,12 +215,56 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <2>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -232,7 +276,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -242,7 +286,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -252,7 +296,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -262,7 +306,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -272,7 +316,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -282,7 +326,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -292,7 +336,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -302,7 +346,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -312,7 +356,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -322,7 +366,7 @@
reg = <0xfc340000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-l2";
coresight-nr-inports = <0>;
};
@@ -332,7 +376,7 @@
reg = <0xfc341000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -342,7 +386,7 @@
reg = <0xfc342000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -352,7 +396,7 @@
reg = <0xfc343000 0x1000>;
reg-names = "cti-base";
- coresight-id = <27>;
+ coresight-id = <31>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -362,11 +406,61 @@
reg = <0xfc344000 0x1000>;
reg-names = "cti-base";
- coresight-id = <28>;
+ coresight-id = <32>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_video_cpu0: cti@fc348000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc348000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-video-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_wcn_cpu0: cti@fc34d000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc34d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <35>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <36>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <37>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fd828018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfd828018 0x80>,
@@ -375,7 +469,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <29>;
+ coresight-id = <38>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -387,7 +481,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <30>;
+ coresight-id = <39>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index dbd2031..a4bd8fd 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -497,6 +497,7 @@
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8226_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index c31c612..eac0bb6 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -494,6 +494,7 @@
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8226_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dtsi b/arch/arm/boot/dts/msm8610-cdp.dtsi
index 452cc2f..1fe7d2f 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -245,7 +245,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <200 60000>;
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 78a4b5a..ca4f721 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -205,12 +205,56 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <13>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <0>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc301000 {
compatible = "qcom,coresight-csr";
reg = <0xfc301000 0x1000>;
reg-names = "csr-base";
- coresight-id = <13>;
+ coresight-id = <17>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -222,7 +266,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -232,7 +276,7 @@
reg = <0xfc311000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -242,7 +286,7 @@
reg = <0xfc312000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -252,7 +296,7 @@
reg = <0xfc313000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -262,7 +306,7 @@
reg = <0xfc314000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -272,7 +316,7 @@
reg = <0xfc315000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -282,7 +326,7 @@
reg = <0xfc316000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -292,7 +336,7 @@
reg = <0xfc317000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -302,7 +346,7 @@
reg = <0xfc318000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -312,7 +356,7 @@
reg = <0xfc351000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -322,7 +366,7 @@
reg = <0xfc352000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -332,7 +376,7 @@
reg = <0xfc353000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -342,11 +386,51 @@
reg = <0xfc354000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_wcn_cpu0: cti@fc335000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc335000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <31>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc338000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc338000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <32>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc33c000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc33c000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc360000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc360000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fd820018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfd820018 0x80>,
@@ -355,7 +439,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <27>;
+ coresight-id = <35>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -367,7 +451,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <28>;
+ coresight-id = <36>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
index 243d7e8..afc5459 100644
--- a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
@@ -15,3 +15,4 @@
/include/ "dsi-panel-nt35590-720p-video.dtsi"
/include/ "dsi-panel-otm8018b-fwvga-video.dtsi"
/include/ "dsi-panel-hx8379a-wvga-video.dtsi"
+/include/ "dsi-panel-hx8389b-qhd-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 8d0e201..cad636c 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -312,7 +312,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <200 60000>;
@@ -445,6 +444,7 @@
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8110_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 83d84c0..7e191e1 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -367,3 +367,7 @@
qcom,android-usb-cdrom;
qcom,android-usb-internal-ums;
};
+
+&mdss_mdp {
+ batfet-supply = <&pm8110_chg_batif>;
+};
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index e560447..6296692 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -180,7 +180,6 @@
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
- <0xff 63>, /* wcd9xxx_irq */
<0xff 65>, /* o_gc_sys_irq[0] */
<0xff 74>, /* venus0_mmu_cirpt[1] */
<0xff 75>, /* venus0_mmu_cirpt[0] */
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
index f250c4a..4a08f3f 100644
--- a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
@@ -21,3 +21,15 @@
compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
qcom,board-id = <0x2000b 3>;
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8389b_qhd_vid>;
+};
+
+&dsi_hx8389b_qhd_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 72509c1..6c7f2f6 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -177,7 +177,6 @@
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
- <0xff 63>, /* wcd9xxx_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
index e32afba..4735554 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
@@ -44,3 +44,15 @@
qcom,led-flash-src = <&led_flash0>;
};
};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8389b_qhd_vid>;
+};
+
+&dsi_hx8389b_qhd_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b0f9d62..f6ced20 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -271,7 +271,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <9000 60000>;
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index a809c2b..b7e64c3 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -219,12 +219,57 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <2>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -236,7 +281,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -246,7 +291,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -256,7 +301,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -266,7 +311,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -276,7 +321,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -286,7 +331,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -296,7 +341,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -306,7 +351,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -316,7 +361,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -326,7 +371,7 @@
reg = <0xfc340000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-l2";
coresight-nr-inports = <0>;
};
@@ -336,7 +381,7 @@
reg = <0xfc341000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -346,7 +391,7 @@
reg = <0xfc342000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -356,7 +401,7 @@
reg = <0xfc343000 0x1000>;
reg-names = "cti-base";
- coresight-id = <27>;
+ coresight-id = <31>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -366,11 +411,61 @@
reg = <0xfc344000 0x1000>;
reg-names = "cti-base";
- coresight-id = <28>;
+ coresight-id = <32>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_video_cpu0: cti@fc348000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc348000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-video-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_wcn_cpu0: cti@fc34d000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc34d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <35>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <36>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <37>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fdf30018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfdf30018 0x80>,
@@ -379,7 +474,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <29>;
+ coresight-id = <38>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -391,7 +486,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <30>;
+ coresight-id = <39>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index c112bea..d0ca01d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -30,6 +30,7 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8941_chg_batif>;
};
qcom,hdmi_tx@fd922100 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 67e1802..16672fd 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -26,6 +26,8 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "edp";
+ qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
+ qcom,panel-pwm-period = <53>;
};
i2c@f9967000 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 6d5000f..c866de7 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -187,9 +187,6 @@
reg-names = "edp_base", "mmss_cc_base";
vdda-supply = <&pm8941_l12>;
gpio-panel-en = <&msmgpio 58 0>;
- gpio-panel-pwm = <&pm8941_gpios 36 0>;
- qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
- qcom,panel-pwm-period = <53>;
qcom,mdss-fb-map = <&mdss_fb0>;
gpio-panel-hpd = <&msmgpio 102 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index b88fbdc..f73bcdc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -30,6 +30,7 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8941_chg_batif>;
};
qcom,hdmi_tx@fd922100 {
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi
index 746702b..dc438bb 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi
@@ -106,6 +106,7 @@
interrupt-map = <0x0 0 &intc 0 133 0
0x0 1 &spmi_bus 0x0 0x2 0x9 0x0>;
interrupt-names = "hs_phy_irq", "pmic_id_irq";
+ qcom,dwc-ssphy-deemphasis-value = <26>;
};
/* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 4880f96..05d5238 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -135,12 +135,45 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <9>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <10>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <11>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <9>;
+ coresight-id = <12>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -152,7 +185,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <10>;
+ coresight-id = <13>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -162,7 +195,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <11>;
+ coresight-id = <14>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -172,7 +205,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <12>;
+ coresight-id = <15>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -182,7 +215,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <13>;
+ coresight-id = <16>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -192,7 +225,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <14>;
+ coresight-id = <17>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -202,7 +235,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <18>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -212,7 +245,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <19>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -222,7 +255,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <20>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -232,18 +265,48 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <21>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
- cti_cpu: cti@fc333000 {
+ cti_cpu0: cti@fc333000 {
compatible = "arm,coresight-cti";
reg = <0xfc333000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
- coresight-name = "coresight-cti-cpu";
+ coresight-id = <22>;
+ coresight-name = "coresight-cti-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <23>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <24>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <25>;
+ coresight-name = "coresight-cti-rpm-cpu0";
coresight-nr-inports = <0>;
};
@@ -254,7 +317,7 @@
<0xfc401600 0x80>;
reg-names = "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <20>;
+ coresight-id = <26>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
};
@@ -264,7 +327,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <21>;
+ coresight-id = <27>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index f953a70..8d116f1 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -443,6 +443,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 325aba1..20c6362 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -81,6 +81,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 2c5363d..0a7faae 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -82,6 +82,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -401,6 +402,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index b26a028..8f6f52f 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -475,6 +475,10 @@
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_BIF=y
CONFIG_BIF_QPNP=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 3f34690..d6811df 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -295,6 +295,9 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 66534eb..60be20a 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -55,7 +55,7 @@
.hfpll_phys_base = 0xF908A000,
.l2cpmr_iaddr = 0x4501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait0", 1100000 },
+ .vreg[VREG_CORE] = { "krait0", 1120000 },
.vreg[VREG_MEM] = { "krait0_mem", 1050000 },
.vreg[VREG_DIG] = { "krait0_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
@@ -64,7 +64,7 @@
.hfpll_phys_base = 0xF909A000,
.l2cpmr_iaddr = 0x5501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait1", 1100000 },
+ .vreg[VREG_CORE] = { "krait1", 1120000 },
.vreg[VREG_MEM] = { "krait1_mem", 1050000 },
.vreg[VREG_DIG] = { "krait1_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
@@ -73,7 +73,7 @@
.hfpll_phys_base = 0xF90AA000,
.l2cpmr_iaddr = 0x6501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait2", 1100000 },
+ .vreg[VREG_CORE] = { "krait2", 1120000 },
.vreg[VREG_MEM] = { "krait2_mem", 1050000 },
.vreg[VREG_DIG] = { "krait2_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
@@ -82,7 +82,7 @@
.hfpll_phys_base = 0xF90BA000,
.l2cpmr_iaddr = 0x7501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait3", 1100000 },
+ .vreg[VREG_CORE] = { "krait3", 1120000 },
.vreg[VREG_MEM] = { "krait3_mem", 1050000 },
.vreg[VREG_DIG] = { "krait3_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 993ce58..5b057a8e 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3217,6 +3217,11 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fd828018.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -3251,6 +3256,11 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fd828018.hwevent"),
CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fd828018.hwevent"),
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 85a9f45..45a6b89 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -1351,8 +1351,6 @@
.cbcr_reg = LPASS_Q6_AXI_CBCR,
.has_sibling = 1,
.base = &virt_bases[GCC_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.dbg_name = "gcc_lpass_q6_axi_clk",
.ops = &clk_ops_branch,
@@ -1893,14 +1891,10 @@
.cbcr_reg = BIMC_GFX_CBCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.dbg_name = "bimc_gfx_clk",
.ops = &clk_ops_branch,
CLK_INIT(bimc_gfx_clk.c),
- /* FIXME: Remove once kgsl votes on the depends clock. */
- .depends = &gcc_bimc_smmu_clk.c,
},
};
@@ -2267,8 +2261,6 @@
static struct branch_clk mdp_axi_clk = {
.cbcr_reg = MDP_AXI_CBCR,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.parent = &mdp_axi_clk_src.c,
.dbg_name = "mdp_axi_clk",
@@ -2416,8 +2408,6 @@
.bcr_reg = VFE_AXI_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.parent = &axi_clk_src.c,
.dbg_name = "vfe_axi_clk",
@@ -2831,6 +2821,10 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc352000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc353000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc335000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc338000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc33c000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc360000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34c000.jtagmm"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.jtagmm"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34e000.jtagmm"),
@@ -2865,6 +2859,10 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc352000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc353000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc335000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc338000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33c000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc360000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34c000.jtagmm"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.jtagmm"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34e000.jtagmm"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index b0adfa0..ca7302a 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5461,6 +5461,11 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fdf30018.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -5491,6 +5496,11 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fdf30018.hwevent"),
CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fdf30018.hwevent"),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 3b07069..0b73ac9 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1887,6 +1887,9 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc333000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "f9011038.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -1909,6 +1912,9 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc333000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "f9011038.hwevent"),
};
diff --git a/arch/arm/mach-msm/qdsp6v2/aac_in.c b/arch/arm/mach-msm/qdsp6v2/aac_in.c
index 0741538..865f6f2 100644
--- a/arch/arm/mach-msm/qdsp6v2/aac_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/aac_in.c
@@ -58,11 +58,33 @@
break;
}
- rc = audio_in_buf_alloc(audio);
- if (rc < 0) {
- pr_err("%s:session id %d: buffer allocation failed\n",
- __func__, audio->ac->session);
- break;
+ if (audio->opened) {
+ rc = audio_in_buf_alloc(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: buffer allocation failed\n",
+ __func__, audio->ac->session);
+ break;
+ }
+ } else {
+ if(audio->feedback == NON_TUNNEL_MODE){
+ pr_debug("%s: starting in non_tunnel mode",__func__);
+ rc = q6asm_open_read_write(audio->ac, FORMAT_MPEG4_AAC,
+ FORMAT_LINEAR_PCM);
+ if (rc < 0) {
+ pr_err("%s:open read write failed\n", __func__);
+ break;
+ }
+ }
+ if(audio->feedback == TUNNEL_MODE){
+ pr_debug("%s: starting in tunnel mode",__func__);
+ rc = q6asm_open_read(audio->ac,FORMAT_MPEG4_AAC);
+
+ if (rc < 0) {
+ pr_err("%s:open read failed\n", __func__);
+ break;
+ }
+ }
+ audio->stopped = 0;
}
pr_debug("%s:sbr_ps_flag = %d, sbr_flag = %d\n", __func__,
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 5355de1..85af4a7 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -260,14 +260,16 @@
}
audio->str_cfg.buffer_size = cfg.buffer_size;
audio->str_cfg.buffer_count = cfg.buffer_count;
- rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+ if(audio->opened){
+ rc = q6asm_audio_client_buf_alloc(OUT,audio->ac,
ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
audio->str_cfg.buffer_count);
- if (rc < 0) {
+ if (rc < 0) {
pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n",
- __func__, audio->ac->session, rc);
+ __func__, audio->ac->session, rc);
rc = -ENOMEM;
break;
+ }
}
audio->buf_alloc |= BUF_ALLOC_OUT;
rc = 0;
@@ -349,14 +351,16 @@
audio->pcm_cfg.buffer_size = cfg.buffer_size;
audio->pcm_cfg.channel_count = cfg.channel_count;
audio->pcm_cfg.sample_rate = cfg.sample_rate;
- rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
- ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
- audio->pcm_cfg.buffer_count);
- if (rc < 0) {
- pr_err("%s:session id %d: Buffer Alloc failed\n",
- __func__, audio->ac->session);
- rc = -ENOMEM;
- break;
+ if(audio->opened && audio->feedback == NON_TUNNEL_MODE){
+ rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
+ ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
+ audio->pcm_cfg.buffer_count);
+ if(rc < 0){
+ pr_err("%s:session id %d: Buffer Alloc failed\n",
+ __func__,audio->ac->session);
+ rc = -ENOMEM;
+ break;
+ }
}
audio->buf_alloc |= BUF_ALLOC_IN;
rc = 0;
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 266b759..601c42c 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -114,6 +114,7 @@
static int scm_remap_error(int err)
{
+ pr_err("scm_call failed with error code %d\n", err);
switch (err) {
case SCM_ERROR:
return -EIO;
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 249c768..8af3890 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -41,6 +41,7 @@
#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75
#define SMEM_IMAGE_VERSION_OEM_SIZE 32
#define SMEM_IMAGE_VERSION_OEM_OFFSET 96
+#define SMEM_IMAGE_VERSION_PARTITION_APPS 10
enum {
HW_PLATFORM_UNKNOWN = 0,
@@ -859,23 +860,28 @@
}
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
string_address += SMEM_IMAGE_VERSION_NAME_OFFSET;
- return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s",
+ return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.72s\n",
string_address);
}
static ssize_t
-msm_store_image_type(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
+msm_set_image_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
{
- int ret, digit;
+ char *store_address;
- ret = kstrtoint(buf, 10, &digit);
- if (ret)
- return ret;
- if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT)
- current_image = digit;
- else
- current_image = 0;
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf);
return count;
}
@@ -895,11 +901,33 @@
}
string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
- return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s",
+ return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n",
string_address);
}
static ssize_t
+msm_set_image_variant(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf);
+ return count;
+}
+
+static ssize_t
msm_get_image_crm_version(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -955,6 +983,54 @@
socinfo_show_pmic_die_revision, NULL),
};
+static ssize_t
+msm_set_image_crm_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_number(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ current_image);
+}
+
+static ssize_t
+msm_select_image(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, digit;
+
+ ret = kstrtoint(buf, 10, &digit);
+ if (ret)
+ return ret;
+ if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT)
+ current_image = digit;
+ else
+ current_image = 0;
+ return count;
+}
+
+
static struct device_attribute msm_soc_attr_raw_version =
__ATTR(raw_version, S_IRUGO, msm_get_raw_version, NULL);
@@ -993,15 +1069,19 @@
static struct device_attribute image_version =
__ATTR(image_version, S_IRUGO | S_IWUSR,
- msm_get_image_version, msm_store_image_type);
+ msm_get_image_version, msm_set_image_version);
static struct device_attribute image_variant =
- __ATTR(image_variant, S_IRUGO,
- msm_get_image_variant, NULL);
+ __ATTR(image_variant, S_IRUGO | S_IWUSR,
+ msm_get_image_variant, msm_set_image_variant);
static struct device_attribute image_crm_version =
- __ATTR(image_crm_version, S_IRUGO,
- msm_get_image_crm_version, NULL);
+ __ATTR(image_crm_version, S_IRUGO | S_IWUSR,
+ msm_get_image_crm_version, msm_set_image_crm_version);
+
+static struct device_attribute select_image =
+ __ATTR(select_image, S_IRUGO | S_IWUGO,
+ msm_get_image_number, msm_select_image);
static struct sysdev_class soc_sysdev_class = {
.name = "soc",
@@ -1060,6 +1140,7 @@
device_create_file(msm_soc_device, &image_version);
device_create_file(msm_soc_device, &image_variant);
device_create_file(msm_soc_device, &image_crm_version);
+ device_create_file(msm_soc_device, &select_image);
switch (legacy_format) {
case 8:
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e6b2a3c..af494c6 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -144,6 +144,7 @@
unsigned int sampling_down_factor;
int powersave_bias;
unsigned int io_is_busy;
+ unsigned int input_boost;
} dbs_tuners_ins = {
.up_threshold_multi_core = DEF_FREQUENCY_UP_THRESHOLD,
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
@@ -155,6 +156,7 @@
.powersave_bias = 0,
.sync_freq = 0,
.optimal_freq = 0,
+ .input_boost = 0,
};
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
@@ -319,6 +321,7 @@
show_one(optimal_freq, optimal_freq);
show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load);
show_one(sync_freq, sync_freq);
+show_one(input_boost, input_boost);
static ssize_t show_powersave_bias
(struct kobject *kobj, struct attribute *attr, char *buf)
@@ -396,6 +399,18 @@
return count;
}
+static ssize_t store_input_boost(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
+ return -EINVAL;
+ dbs_tuners_ins.input_boost = input;
+ return count;
+}
+
static ssize_t store_sync_freq(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -680,6 +695,7 @@
define_one_global_rw(optimal_freq);
define_one_global_rw(up_threshold_any_cpu_load);
define_one_global_rw(sync_freq);
+define_one_global_rw(input_boost);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -694,6 +710,7 @@
&optimal_freq.attr,
&up_threshold_any_cpu_load.attr,
&sync_freq.attr,
+ &input_boost.attr,
NULL
};
@@ -1006,6 +1023,7 @@
struct cpu_dbs_info_s *this_dbs_info;
struct dbs_work_struct *dbs_work;
unsigned int cpu;
+ unsigned int target_freq;
dbs_work = container_of(work, struct dbs_work_struct, work);
cpu = dbs_work->cpu;
@@ -1022,14 +1040,19 @@
goto bail_incorrect_governor;
}
- if (policy->cur < policy->max) {
+ if (dbs_tuners_ins.input_boost)
+ target_freq = dbs_tuners_ins.input_boost;
+ else
+ target_freq = policy->max;
+
+ if (policy->cur < target_freq) {
/*
* Arch specific cpufreq driver may fail.
* Don't update governor frequency upon failure.
*/
- if (__cpufreq_driver_target(policy, policy->max,
+ if (__cpufreq_driver_target(policy, target_freq,
CPUFREQ_RELATION_L) >= 0)
- policy->cur = policy->max;
+ policy->cur = target_freq;
this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
&this_dbs_info->prev_cpu_wall);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4dbe5c1..3731561 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1727,7 +1727,7 @@
}
ret = request_firmware(&fw, fn, dev);
- if (ret < 0) {
+ if (ret < 0 || !fw) {
dev_err(dev, "Unable to open firmware %s\n", fn);
goto free_frame;
}
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 4e75971..cf43a9c 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -79,9 +79,12 @@
STATUS_DEVICE_FAILURE = 0x03,
STATUS_CONFIG_CRC_FAILURE = 0x04,
STATUS_FIRMWARE_CRC_FAILURE = 0x05,
- STATUS_CRC_IN_PROGRESS = 0x06
+ STATUS_CRC_IN_PROGRESS = 0x06,
+ STATUS_UNCONFIGURED = 0x80
};
+#define DEVICE_CONFIGURED 0x1
+
#define RMI4_VTG_MIN_UV 2700000
#define RMI4_VTG_MAX_UV 3300000
#define RMI4_ACTIVE_LOAD_UA 15000
@@ -172,6 +175,20 @@
};
};
+struct synaptics_rmi4_f01_device_control_0 {
+ union {
+ struct {
+ unsigned char sleep_mode:2;
+ unsigned char nosleep:1;
+ unsigned char reserved:2;
+ unsigned char charger_input:1;
+ unsigned char report_rate:1;
+ unsigned char configured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
struct synaptics_rmi4_f12_query_5 {
union {
struct {
@@ -2654,8 +2671,6 @@
goto err_reset_gpio_dir;
}
- gpio_set_value(rmi4_data->board->reset_gpio, 0);
- usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(rmi4_data->board->reset_gpio, 1);
msleep(rmi4_data->board->reset_delay);
} else
@@ -3088,12 +3103,12 @@
static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned char device_ctrl;
+ struct synaptics_rmi4_f01_device_control_0 device_ctrl;
retval = synaptics_rmi4_i2c_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to enter sleep mode\n",
@@ -3102,13 +3117,13 @@
return;
}
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP);
+ device_ctrl.sleep_mode = SENSOR_SLEEP;
+ device_ctrl.nosleep = NO_SLEEP_OFF;
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to enter sleep mode\n",
@@ -3132,12 +3147,12 @@
static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned char device_ctrl;
+ struct synaptics_rmi4_f01_device_control_0 device_ctrl;
retval = synaptics_rmi4_i2c_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to wake from sleep mode\n",
@@ -3146,13 +3161,13 @@
return;
}
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | NORMAL_OPERATION);
+ device_ctrl.sleep_mode = NORMAL_OPERATION;
+ device_ctrl.nosleep = NO_SLEEP_OFF;
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to wake from sleep mode\n",
@@ -3365,6 +3380,51 @@
return retval;
}
+static int synaptics_rmi4_check_configuration(struct synaptics_rmi4_data
+ *rmi4_data)
+{
+ int retval;
+ struct synaptics_rmi4_f01_device_control_0 device_control;
+ struct synaptics_rmi4_f01_device_status device_status;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ device_status.data,
+ sizeof(device_status.data));
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Failed to read device status, rc=%d\n", retval);
+ return retval;
+ }
+
+ if (device_status.unconfigured) {
+ retval = synaptics_rmi4_query_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Failed to query device, rc=%d\n", retval);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ device_control.data,
+ sizeof(device_control.data));
+ if (retval < 0)
+ return retval;
+
+ device_control.configured = DEVICE_CONFIGURED;
+
+ retval = synaptics_rmi4_i2c_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ device_control.data,
+ sizeof(device_control.data));
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
/**
* synaptics_rmi4_suspend()
*
@@ -3447,24 +3507,29 @@
return 0;
}
+ retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "Failed to enter active power mode\n");
+ return retval;
+ }
+
if (rmi4_data->board->disable_gpios) {
retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
if (retval < 0) {
- dev_err(dev, "failed to put gpios in active state\n");
+ dev_err(dev, "Failed to put gpios in active state\n");
return retval;
}
}
- retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
- if (retval < 0) {
- dev_err(dev, "failed to enter active power mode\n");
- return retval;
- }
-
synaptics_rmi4_sensor_wake(rmi4_data);
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
+ retval = synaptics_rmi4_check_configuration(rmi4_data);
+ if (retval < 0) {
+ dev_err(dev, "Failed to check configuration\n");
+ return retval;
+ }
rmi4_data->suspended = false;
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 16a1616..bb2b074 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -79,6 +79,11 @@
struct msm_camera_i2c_reg_array *i2c_tbl = a_ctrl->i2c_reg_tbl;
CDBG("Enter\n");
for (i = 0; i < size; i++) {
+ /* check that the index into i2c_tbl cannot grow larger that
+ the allocated size of i2c_tbl */
+ if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index)) {
+ break;
+ }
if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
value = (next_lens_position <<
write_arr[i].data_shift) |
@@ -196,11 +201,19 @@
struct msm_actuator_move_params_t *move_params)
{
int32_t dest_step_position = move_params->dest_step_pos;
+ struct damping_params_t ringing_params_kernel;
int32_t rc = 0;
int32_t num_steps = move_params->num_steps;
struct msm_camera_i2c_reg_setting reg_setting;
CDBG("Enter\n");
+ if (copy_from_user(&ringing_params_kernel,
+ &(move_params->ringing_params[0]),
+ sizeof(struct damping_params_t))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
if (num_steps == 0)
return rc;
@@ -208,7 +221,7 @@
a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
(num_steps *
a_ctrl->region_params[0].code_per_step),
- move_params->ringing_params[0].hw_params, 0);
+ ringing_params_kernel.hw_params, 0);
reg_setting.reg_setting = a_ctrl->i2c_reg_tbl;
reg_setting.data_type = a_ctrl->i2c_data_type;
@@ -230,6 +243,7 @@
struct msm_actuator_move_params_t *move_params)
{
int32_t rc = 0;
+ struct damping_params_t ringing_params_kernel;
int8_t sign_dir = move_params->sign_dir;
uint16_t step_boundary = 0;
uint16_t target_step_pos = 0;
@@ -240,6 +254,14 @@
int32_t num_steps = move_params->num_steps;
struct msm_camera_i2c_reg_setting reg_setting;
+ if (copy_from_user(&ringing_params_kernel,
+ &(move_params->ringing_params[a_ctrl->curr_region_index]),
+ sizeof(struct damping_params_t))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
+
CDBG("called, dir %d, num_steps %d\n", dir, num_steps);
if (dest_step_pos == a_ctrl->curr_step_pos)
@@ -262,9 +284,7 @@
a_ctrl->step_position_table[target_step_pos];
a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
curr_lens_pos,
- &(move_params->
- ringing_params[a_ctrl->
- curr_region_index]),
+ &ringing_params_kernel,
sign_dir,
target_lens_pos);
curr_lens_pos = target_lens_pos;
@@ -275,8 +295,7 @@
a_ctrl->step_position_table[target_step_pos];
a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
curr_lens_pos,
- &(move_params->ringing_params[a_ctrl->
- curr_region_index]),
+ &ringing_params_kernel,
sign_dir,
target_lens_pos);
curr_lens_pos = target_lens_pos;
@@ -437,8 +456,11 @@
a_ctrl->i2c_data_type = set_info->actuator_params.i2c_data_type;
a_ctrl->i2c_client.addr_type = set_info->actuator_params.i2c_addr_type;
- a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
- if (a_ctrl->reg_tbl_size > MAX_ACTUATOR_REG_TBL_SIZE) {
+ if (set_info->actuator_params.reg_tbl_size <=
+ MAX_ACTUATOR_REG_TBL_SIZE) {
+ a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
+ } else {
+ a_ctrl->reg_tbl_size = 0;
pr_err("MAX_ACTUATOR_REG_TBL_SIZE is exceeded.\n");
return -EFAULT;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index 7f13568..45db19c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -48,10 +48,12 @@
e_ctrl->num_bytes;
break;
case CFG_EEPROM_READ_CAL_DATA:
- CDBG("%s E CFG_EEPROM_READ_CAL_DATA\n", __func__);
- rc = copy_to_user(cdata->cfg.read_data.dbuffer,
+ if (cdata->cfg.read_data.num_bytes <= e_ctrl->num_bytes) {
+ CDBG("%s E CFG_EEPROM_READ_CAL_DATA\n", __func__);
+ rc = copy_to_user(cdata->cfg.read_data.dbuffer,
e_ctrl->memory_data,
cdata->cfg.read_data.num_bytes);
+ }
break;
default:
break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 20905c9..01d2c13 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -29,6 +29,7 @@
extern int32_t msm_led_torch_create_classdev(
struct platform_device *pdev, void *data);
+static enum flash_type flashtype;
static struct msm_led_flash_ctrl_t fctrl;
static int32_t msm_led_trigger_get_subdev_id(struct msm_led_flash_ctrl_t *fctrl,
@@ -119,6 +120,7 @@
struct device_node *of_node = pdev->dev.of_node;
struct device_node *flash_src_node = NULL;
uint32_t count = 0;
+ struct led_trigger *temp = NULL;
CDBG("called\n");
@@ -137,11 +139,18 @@
}
CDBG("pdev id %d\n", pdev->id);
+ rc = of_property_read_u32(of_node,
+ "qcom,flash-type", &flashtype);
+ if (rc < 0) {
+ pr_err("flash-type: read failed\n");
+ return -EINVAL;
+ }
+
if (of_get_property(of_node, "qcom,flash-source", &count)) {
count /= sizeof(uint32_t);
CDBG("count %d\n", count);
if (count > MAX_LED_TRIGGERS) {
- pr_err("failed\n");
+ pr_err("invalid count\n");
return -EINVAL;
}
fctrl.num_sources = count;
@@ -157,7 +166,7 @@
"linux,default-trigger",
&fctrl.flash_trigger_name[i]);
if (rc < 0) {
- pr_err("failed\n");
+ pr_err("default-trigger: read failed\n");
of_node_put(flash_src_node);
continue;
}
@@ -165,12 +174,18 @@
CDBG("default trigger %s\n",
fctrl.flash_trigger_name[i]);
- rc = of_property_read_u32(flash_src_node,
- "qcom,current", &fctrl.flash_op_current[i]);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- of_node_put(flash_src_node);
- continue;
+ if (flashtype == GPIO_FLASH) {
+ /* use fake current */
+ fctrl.flash_op_current[i] = LED_FULL;
+ } else {
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,current",
+ &fctrl.flash_op_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(flash_src_node);
+ continue;
+ }
}
of_node_put(flash_src_node);
@@ -180,6 +195,10 @@
led_trigger_register_simple(fctrl.flash_trigger_name[i],
&fctrl.flash_trigger[i]);
+
+ if (flashtype == GPIO_FLASH)
+ if (fctrl.flash_trigger[i])
+ temp = fctrl.flash_trigger[i];
}
/* Torch source */
@@ -190,25 +209,39 @@
"linux,default-trigger",
&fctrl.torch_trigger_name);
if (rc < 0) {
- pr_err("failed\n");
- } else {
- CDBG("default trigger %s\n",
- fctrl.torch_trigger_name);
+ pr_err("default-trigger: read failed\n");
+ goto torch_failed;
+ }
+ CDBG("default trigger %s\n",
+ fctrl.torch_trigger_name);
+
+ if (flashtype == GPIO_FLASH) {
+ /* use fake current */
+ fctrl.torch_op_current = LED_FULL;
+ if (temp)
+ fctrl.torch_trigger = temp;
+ else
+ led_trigger_register_simple(
+ fctrl.torch_trigger_name,
+ &fctrl.torch_trigger);
+ } else {
rc = of_property_read_u32(flash_src_node,
"qcom,current",
&fctrl.torch_op_current);
if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- } else {
- CDBG("torch max_current %d\n",
- fctrl.torch_op_current);
-
- led_trigger_register_simple(
- fctrl.torch_trigger_name,
- &fctrl.torch_trigger);
+ pr_err("current: read failed\n");
+ goto torch_failed;
}
+
+ CDBG("torch max_current %d\n",
+ fctrl.torch_op_current);
+
+ led_trigger_register_simple(
+ fctrl.torch_trigger_name,
+ &fctrl.torch_trigger);
}
+torch_failed:
of_node_put(flash_src_node);
}
}
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 5e056be..31d03b6 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -49,11 +49,15 @@
static char utf_8_flag;
static char rt_ert_flag;
static char formatting_dir;
+static unsigned char sig_blend = CTRL_ON;
static DEFINE_MUTEX(iris_fm);
module_param(rds_buf, uint, 0);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
+module_param(sig_blend, byte, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(sig_blend, "signal blending switch: 0:OFF 1:ON");
+
static void radio_hci_cmd_task(unsigned long arg);
static void radio_hci_rx_task(unsigned long arg);
static struct video_device *video_get_dev(void);
@@ -4141,7 +4145,7 @@
}
radio->stereo_mode.stereo_mode = CTRL_OFF;
- radio->stereo_mode.sig_blend = CTRL_ON;
+ radio->stereo_mode.sig_blend = sig_blend;
radio->stereo_mode.intf_blend = CTRL_ON;
radio->stereo_mode.most_switch = CTRL_ON;
retval = hci_set_fm_stereo_mode(&radio->stereo_mode,
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index dc32efd..9209f0b 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -150,13 +150,15 @@
msm_cpuidle_get_deep_idle_latency());
}
mutex_unlock(&wcd9xxx_res->pm_lock);
- os = wcd9xxx_pm_cmpxchg(wcd9xxx_res,
- WCD9XXX_PM_SLEEPABLE,
- WCD9XXX_PM_AWAKE);
+
if (!wait_event_timeout(wcd9xxx_res->pm_wq,
- (os == WCD9XXX_PM_SLEEPABLE ||
- os == WCD9XXX_PM_AWAKE),
- msecs_to_jiffies(WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
+ ((os = wcd9xxx_pm_cmpxchg(wcd9xxx_res,
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE)) ==
+ WCD9XXX_PM_SLEEPABLE ||
+ (os == WCD9XXX_PM_AWAKE)),
+ msecs_to_jiffies(
+ WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
__func__,
WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state,
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 89e3472..5786190 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -516,8 +516,6 @@
if (mrq->data)
mrq->data->bytes_xfered = host->curr.data_xfered;
- if (mrq->cmd->error == -ETIMEDOUT)
- mdelay(5);
msmsdcc_reset_dpsm(host);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 4512d02..45400cb 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -652,8 +652,6 @@
if (dd->qup_ver == SPI_QUP_VERSION_NONE)
/* flags removed from SPI_CONFIG in QUP version-2 */
msm_spi_set_bpw_and_no_io_flags(dd, &spi_config, bpw-1);
- else if (dd->mode == SPI_BAM_MODE)
- spi_config |= SPI_CFG_INPUT_FIRST;
/*
* HS_MODE improves signal stability for spi-clk high rates
diff --git a/drivers/spmi/spmi-dbgfs.h b/drivers/spmi/spmi-dbgfs.h
index 10e98b9..a419002 100644
--- a/drivers/spmi/spmi-dbgfs.h
+++ b/drivers/spmi/spmi-dbgfs.h
@@ -18,8 +18,14 @@
int spmi_dfs_add_controller(struct spmi_controller *ctrl);
int spmi_dfs_del_controller(struct spmi_controller *ctrl);
#else
-static int spmi_dfs_add_controller(struct spmi_controller *ctrl) { return 0; }
-static int spmi_dfs_del_controller(struct spmi_controller *ctrl) { return 0; }
+static inline int spmi_dfs_add_controller(struct spmi_controller *ctrl)
+{
+ return 0;
+}
+static inline int spmi_dfs_del_controller(struct spmi_controller *ctrl)
+{
+ return 0;
+}
#endif
struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e4fb26a..7d63bf9 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1356,6 +1356,14 @@
if (c && c->setup)
value = c->setup(c, ctrl);
}
+ if (value == USB_GADGET_DELAYED_STATUS) {
+ DBG(cdev,
+ "%s: interface %d (%s) requested delayed status\n",
+ __func__, intf, f->name);
+ cdev->delayed_status++;
+ DBG(cdev, "delayed_status count %d\n",
+ cdev->delayed_status);
+ }
goto done;
}
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 2f35315..4410e99 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -637,7 +637,10 @@
*/
DBG(fsg, "bulk reset request\n");
raise_exception(fsg->common, FSG_STATE_RESET);
- return DELAYED_STATUS;
+ if (fsg->common->cdev)
+ return USB_GADGET_DELAYED_STATUS;
+ else
+ return DELAYED_STATUS;
case US_BULK_GET_MAX_LUN:
if (ctrl->bRequestType !=
@@ -2698,8 +2701,13 @@
&common->fsg->atomic_bitflags))
usb_ep_clear_halt(common->fsg->bulk_in);
- if (common->ep0_req_tag == exception_req_tag)
- ep0_queue(common); /* Complete the status stage */
+ if (common->ep0_req_tag == exception_req_tag) {
+ /* Complete the status stage */
+ if (common->cdev)
+ usb_composite_setup_continue(common->cdev);
+ else
+ ep0_queue(common);
+ }
/*
* Technically this should go here, but it would only be
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 5264005..05cc9cc 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -591,6 +591,17 @@
{
int cnt, len, diff, pkt_size, rc = 0;
char cmd;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ u32 dsi_ctrl, data;
+ int video_mode;
+
+ /* turn on cmd mode for video mode */
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(ctrl_base + DSI_CTRL, data);
+ }
if (pdata->panel_info.mipi.no_max_pkt_size)
rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
@@ -699,6 +710,9 @@
break;
}
+ if (video_mode)
+ MIPI_OUTP(ctrl_base + DSI_CTRL,
+ dsi_ctrl); /* restore */
end:
return rp->len;
}
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 5857606..b70fe28 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -28,6 +28,8 @@
#define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_res->mdp_base + addr)
#define MDSS_REG_READ(addr) readl_relaxed(mdss_res->mdp_base + addr)
+#define MAX_DRV_SUP_MMB_BLKS 44
+
enum mdss_mdp_clk_type {
MDSS_CLK_AHB,
MDSS_CLK_AXI,
@@ -113,6 +115,9 @@
u32 nvig_pipes;
u32 nrgb_pipes;
u32 ndma_pipes;
+
+ DECLARE_BITMAP(mmb_alloc_map, MAX_DRV_SUP_MMB_BLKS);
+
struct mdss_mdp_mixer *mixer_intf;
struct mdss_mdp_mixer *mixer_wb;
u32 nmixers_intf;
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 64caaf5..042491d 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -164,46 +164,33 @@
ret = of_property_read_u32(edp_drv->pdev->dev.of_node,
"qcom,panel-pwm-period", &edp_drv->pwm_period);
if (ret) {
- pr_err("%s: panel pwm period is not specified, %d", __func__,
+ pr_warn("%s: panel pwm period is not specified, %d", __func__,
edp_drv->pwm_period);
- return -EINVAL;
+ edp_drv->pwm_period = -EINVAL;
}
ret = of_property_read_u32(edp_drv->pdev->dev.of_node,
"qcom,panel-lpg-channel", &edp_drv->lpg_channel);
if (ret) {
- pr_err("%s: panel lpg channel is not specified, %d", __func__,
+ pr_warn("%s: panel lpg channel is not specified, %d", __func__,
edp_drv->lpg_channel);
- return -EINVAL;
+ edp_drv->lpg_channel = -EINVAL;
}
- edp_drv->bl_pwm = pwm_request(edp_drv->lpg_channel, "lcd-backlight");
- if (edp_drv->bl_pwm == NULL || IS_ERR(edp_drv->bl_pwm)) {
- pr_err("%s: pwm request failed", __func__);
+ if (edp_drv->pwm_period != -EINVAL &&
+ edp_drv->lpg_channel != -EINVAL) {
+ edp_drv->bl_pwm = pwm_request(edp_drv->lpg_channel,
+ "lcd-backlight");
+ if (edp_drv->bl_pwm == NULL || IS_ERR(edp_drv->bl_pwm)) {
+ pr_err("%s: pwm request failed", __func__);
+ edp_drv->bl_pwm = NULL;
+ return -EIO;
+ }
+ } else {
edp_drv->bl_pwm = NULL;
- return -EIO;
- }
-
- edp_drv->gpio_panel_pwm = of_get_named_gpio(edp_drv->pdev->dev.of_node,
- "gpio-panel-pwm", 0);
- if (!gpio_is_valid(edp_drv->gpio_panel_pwm)) {
- pr_err("%s: gpio_panel_pwm=%d not specified\n", __func__,
- edp_drv->gpio_panel_pwm);
- goto edp_free_pwm;
- }
-
- ret = gpio_request(edp_drv->gpio_panel_pwm, "disp_pwm");
- if (ret) {
- pr_err("%s: Request reset gpio_panel_pwm failed, ret=%d\n",
- __func__, ret);
- goto edp_free_pwm;
}
return 0;
-
-edp_free_pwm:
- pwm_free(edp_drv->bl_pwm);
- return -ENODEV;
}
void mdss_edp_set_backlight(struct mdss_panel_data *pdata, u32 bl_level)
@@ -218,27 +205,26 @@
return;
}
- bl_max = edp_drv->panel_data.panel_info.bl_max;
- if (bl_level > bl_max)
- bl_level = bl_max;
+ if (edp_drv->bl_pwm != NULL) {
+ bl_max = edp_drv->panel_data.panel_info.bl_max;
+ if (bl_level > bl_max)
+ bl_level = bl_max;
- if (edp_drv->bl_pwm == NULL) {
- pr_err("%s: edp_drv->bl_pwm=NULL.\n", __func__);
- return;
- }
+ ret = pwm_config(edp_drv->bl_pwm,
+ bl_level * edp_drv->pwm_period / bl_max,
+ edp_drv->pwm_period);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__,
+ ret);
+ return;
+ }
- ret = pwm_config(edp_drv->bl_pwm,
- bl_level * edp_drv->pwm_period / bl_max,
- edp_drv->pwm_period);
- if (ret) {
- pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
- return;
- }
-
- ret = pwm_enable(edp_drv->bl_pwm);
- if (ret) {
- pr_err("%s: pwm_enable() failed err=%d\n", __func__, ret);
- return;
+ ret = pwm_enable(edp_drv->bl_pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable() failed err=%d\n", __func__,
+ ret);
+ return;
+ }
}
}
@@ -378,7 +364,8 @@
mdss_edp_irq_disable(edp_drv);
gpio_set_value(edp_drv->gpio_panel_en, 0);
- pwm_disable(edp_drv->bl_pwm);
+ if (edp_drv->bl_pwm != NULL)
+ pwm_disable(edp_drv->bl_pwm);
mdss_edp_enable(edp_drv->base, 0);
mdss_edp_unconfig_clk(edp_drv->base, edp_drv->mmss_cc_base);
mdss_edp_enable_mainlink(edp_drv->base, 0);
diff --git a/drivers/video/msm/mdss/mdss_edp.h b/drivers/video/msm/mdss/mdss_edp.h
index c3f7d0d..33b899f 100644
--- a/drivers/video/msm/mdss/mdss_edp.h
+++ b/drivers/video/msm/mdss/mdss_edp.h
@@ -261,7 +261,6 @@
/* gpios */
int gpio_panel_en;
- int gpio_panel_pwm;
/* backlight */
struct pwm_device *bl_pwm;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 4ca0a3f..631853a 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -43,6 +43,7 @@
#include <linux/sw_sync.h>
#include <linux/file.h>
#include <linux/memory_alloc.h>
+#include <linux/kthread.h>
#include <mach/board.h>
#include <mach/memory.h>
@@ -86,8 +87,10 @@
unsigned long arg);
static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
+static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
+ unsigned long val, void *data);
-static void mdss_fb_commit_wq_handler(struct work_struct *work);
+static int __mdss_fb_display_thread(void *data);
static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
int event, void *arg);
@@ -386,11 +389,12 @@
if (mfd->mdp_sync_pt_data.timeline == NULL) {
pr_err("%s: cannot create time line", __func__);
return -ENOMEM;
- } else {
- mfd->mdp_sync_pt_data.timeline_value = 0;
}
+ mfd->mdp_sync_pt_data.notifier.notifier_call =
+ __mdss_fb_sync_buf_done_callback;
}
- if (mfd->panel.type == WRITEBACK_PANEL)
+ if ((mfd->panel.type == WRITEBACK_PANEL) ||
+ (mfd->panel.type == MIPI_CMD_PANEL))
mfd->mdp_sync_pt_data.threshold = 1;
else
mfd->mdp_sync_pt_data.threshold = 2;
@@ -1086,6 +1090,8 @@
mutex_init(&mfd->update.lock);
mutex_init(&mfd->no_update.lock);
mutex_init(&mfd->mdp_sync_pt_data.sync_mutex);
+ atomic_set(&mfd->mdp_sync_pt_data.commit_cnt, 0);
+ atomic_set(&mfd->commits_pending, 0);
init_timer(&mfd->no_update.timer);
mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb;
@@ -1093,15 +1099,9 @@
init_completion(&mfd->update.comp);
init_completion(&mfd->no_update.comp);
init_completion(&mfd->power_off_comp);
- init_completion(&mfd->commit_comp);
init_completion(&mfd->power_set_comp);
- INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler);
- mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
- GFP_KERNEL);
- if (mfd->msm_fb_backup == 0) {
- pr_err("error: not enough memory!\n");
- return -ENOMEM;
- }
+ init_waitqueue_head(&mfd->commit_wait_q);
+ init_waitqueue_head(&mfd->idle_wait_q);
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret)
@@ -1118,9 +1118,9 @@
mfd->index, fbi->var.xres, fbi->var.yres,
fbi->fix.smem_len);
- ret = 0;
+ kthread_run(__mdss_fb_display_thread, mfd, "mdss_fb%d", mfd->index);
- return ret;
+ return 0;
}
static int mdss_fb_open(struct fb_info *info, int user)
@@ -1249,85 +1249,155 @@
void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data)
{
+ struct sync_fence *fences[MDP_MAX_FENCE_FD];
+ int fence_cnt;
int i, ret = 0;
+
+ pr_debug("%s: wait for fences\n", sync_pt_data->fence_name);
+
+ mutex_lock(&sync_pt_data->sync_mutex);
+ /*
+ * Assuming that acq_fen_cnt is sanitized in bufsync ioctl
+ * to check for sync_pt_data->acq_fen_cnt) <= MDP_MAX_FENCE_FD
+ */
+ fence_cnt = sync_pt_data->acq_fen_cnt;
+ sync_pt_data->acq_fen_cnt = 0;
+ if (fence_cnt)
+ memcpy(fences, sync_pt_data->acq_fen,
+ fence_cnt * sizeof(struct sync_fence *));
+ mutex_unlock(&sync_pt_data->sync_mutex);
+
/* buf sync */
- for (i = 0; i < sync_pt_data->acq_fen_cnt; i++) {
- ret = sync_fence_wait(sync_pt_data->acq_fen[i],
+ for (i = 0; i < fence_cnt && !ret; i++) {
+ ret = sync_fence_wait(fences[i],
WAIT_FENCE_FIRST_TIMEOUT);
if (ret == -ETIME) {
- pr_warn("sync_fence_wait timed out! ");
+ pr_warn("%s: sync_fence_wait timed out! ",
+ sync_pt_data->fence_name);
pr_cont("Waiting %ld more seconds\n",
WAIT_FENCE_FINAL_TIMEOUT/MSEC_PER_SEC);
- ret = sync_fence_wait(sync_pt_data->acq_fen[i],
+ ret = sync_fence_wait(fences[i],
WAIT_FENCE_FINAL_TIMEOUT);
}
- if (ret < 0) {
- pr_err("%s: sync_fence_wait failed! ret = %x\n",
- __func__, ret);
- break;
- }
- sync_fence_put(sync_pt_data->acq_fen[i]);
+ sync_fence_put(fences[i]);
}
if (ret < 0) {
- while (i < sync_pt_data->acq_fen_cnt) {
- sync_fence_put(sync_pt_data->acq_fen[i]);
- i++;
- }
+ pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ sync_pt_data->fence_name, ret);
+ for (; i < fence_cnt; i++)
+ sync_fence_put(fences[i]);
}
- sync_pt_data->acq_fen_cnt = 0;
}
-static void mdss_fb_signal_timeline_locked(
- struct msm_sync_pt_data *sync_pt_data)
-{
- if (sync_pt_data->timeline && !list_empty((const struct list_head *)
- (&(sync_pt_data->timeline->obj.active_list_head)))) {
- sw_sync_timeline_inc(sync_pt_data->timeline, 1);
- sync_pt_data->timeline_value++;
- }
- sync_pt_data->cur_rel_fence = 0;
-}
-
+/**
+ * mdss_fb_signal_timeline() - signal a single release fence
+ * @sync_pt_data: Sync point data structure for the timeline which
+ * should be signaled.
+ *
+ * This is called after a frame has been pushed to display. This signals the
+ * timeline to release the fences associated with this frame.
+ */
void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data)
{
mutex_lock(&sync_pt_data->sync_mutex);
- mdss_fb_signal_timeline_locked(sync_pt_data);
+ if (atomic_add_unless(&sync_pt_data->commit_cnt, -1, 0) &&
+ sync_pt_data->timeline) {
+ sw_sync_timeline_inc(sync_pt_data->timeline, 1);
+ sync_pt_data->timeline_value++;
+
+ pr_debug("%s: buffer signaled! timeline val=%d remaining=%d\n",
+ sync_pt_data->fence_name, sync_pt_data->timeline_value,
+ atomic_read(&sync_pt_data->commit_cnt));
+ } else {
+ pr_debug("%s timeline signaled without commits val=%d\n",
+ sync_pt_data->fence_name, sync_pt_data->timeline_value);
+ }
mutex_unlock(&sync_pt_data->sync_mutex);
}
+/**
+ * mdss_fb_release_fences() - signal all pending release fences
+ * @mfd: Framebuffer data structure for display
+ *
+ * Release all currently pending release fences, including those that are in
+ * the process to be commited.
+ *
+ * Note: this should only be called during close or suspend sequence.
+ */
static void mdss_fb_release_fences(struct msm_fb_data_type *mfd)
{
+ struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
+ int val;
- mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
- if (mfd->mdp_sync_pt_data.timeline) {
- sw_sync_timeline_inc(mfd->mdp_sync_pt_data.timeline, 2);
- mfd->mdp_sync_pt_data.timeline_value += 2;
+ mutex_lock(&sync_pt_data->sync_mutex);
+ if (sync_pt_data->timeline) {
+ val = sync_pt_data->threshold +
+ atomic_read(&sync_pt_data->commit_cnt);
+ sw_sync_timeline_inc(sync_pt_data->timeline, val);
+ sync_pt_data->timeline_value += val;
+ atomic_set(&sync_pt_data->commit_cnt, 0);
}
- mfd->mdp_sync_pt_data.cur_rel_fence = 0;
- mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
+ mutex_unlock(&sync_pt_data->sync_mutex);
}
+/**
+ * __mdss_fb_sync_buf_done_callback() - process async display events
+ * @p: Notifier block registered for async events.
+ * @event: Event enum to identify the event.
+ * @data: Optional argument provided with the event.
+ *
+ * See enum mdp_notify_event for events handled.
+ */
+static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
+ unsigned long event, void *data)
+{
+ struct msm_sync_pt_data *sync_pt_data;
+
+ sync_pt_data = container_of(p, struct msm_sync_pt_data, notifier);
+
+ switch (event) {
+ case MDP_NOTIFY_FRAME_READY:
+ if (sync_pt_data->async_wait_fences)
+ mdss_fb_wait_for_fence(sync_pt_data);
+ break;
+ case MDP_NOTIFY_FRAME_FLUSHED:
+ pr_debug("%s: frame flushed\n", sync_pt_data->fence_name);
+ sync_pt_data->flushed = true;
+ break;
+ case MDP_NOTIFY_FRAME_TIMEOUT:
+ pr_err("%s: frame timeout\n", sync_pt_data->fence_name);
+ mdss_fb_signal_timeline(sync_pt_data);
+ break;
+ case MDP_NOTIFY_FRAME_DONE:
+ pr_debug("%s: frame done\n", sync_pt_data->fence_name);
+ mdss_fb_signal_timeline(sync_pt_data);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+/**
+ * mdss_fb_pan_idle() - wait for panel programming to be idle
+ * @mfd: Framebuffer data structure for display
+ *
+ * Wait for any pending programming to be done if in the process of programming
+ * hardware configuration. After this function returns it is safe to perform
+ * software updates for next frame.
+ */
static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
{
int ret;
- if (mfd->is_committing) {
- ret = wait_for_completion_timeout(
- &mfd->commit_comp,
+ ret = wait_event_timeout(mfd->idle_wait_q,
+ !atomic_read(&mfd->commits_pending),
msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
- if (ret < 0)
- ret = -ERESTARTSYS;
- else if (!ret)
- pr_err("%s wait for commit_comp timeout %d %d",
- __func__, ret, mfd->is_committing);
- if (ret <= 0) {
- mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
- mdss_fb_signal_timeline_locked(&mfd->mdp_sync_pt_data);
- mfd->is_committing = 0;
- complete_all(&mfd->commit_comp);
- mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
- }
+ if (!ret) {
+ pr_err("wait for idle timeout %d pending=%d\n",
+ ret, atomic_read(&mfd->commits_pending));
+
+ mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data);
}
}
@@ -1335,7 +1405,6 @@
struct mdp_display_commit *disp_commit)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- struct msm_fb_backup_type *fb_backup;
struct fb_var_screeninfo *var = &disp_commit->var;
u32 wait_for_finish = disp_commit->wait_for_finish;
int ret = 0;
@@ -1360,13 +1429,12 @@
info->var.yoffset =
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
- fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
- memcpy(&fb_backup->info, info, sizeof(struct fb_info));
- memcpy(&fb_backup->disp_commit, disp_commit,
- sizeof(struct mdp_display_commit));
- INIT_COMPLETION(mfd->commit_comp);
- mfd->is_committing = 1;
- schedule_work(&mfd->commit_work);
+ mfd->msm_fb_backup.info = *info;
+ mfd->msm_fb_backup.disp_commit = *disp_commit;
+
+ atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+ atomic_inc(&mfd->commits_pending);
+ wake_up_all(&mfd->commit_wait_q);
mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
if (wait_for_finish)
mdss_fb_pan_idle(mfd);
@@ -1405,14 +1473,12 @@
info->var.yoffset =
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
- mdss_fb_wait_for_fence(&mfd->mdp_sync_pt_data);
if (mfd->mdp.dma_fnc)
mfd->mdp.dma_fnc(mfd);
else
pr_warn("dma function not set for panel type=%d\n",
mfd->panel.type);
- mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data);
- mdss_fb_update_backlight(mfd);
+
return 0;
}
@@ -1430,35 +1496,69 @@
pinfo->clk_rate = var->pixclock;
}
-static void mdss_fb_commit_wq_handler(struct work_struct *work)
+/**
+ * __mdss_fb_perform_commit() - process a frame to display
+ * @mfd: Framebuffer data structure for display
+ *
+ * Processes all layers and buffers programmed and ensures all pending release
+ * fences are signaled once the buffer is transfered to display.
+ */
+static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd)
{
- struct msm_fb_data_type *mfd;
- struct fb_var_screeninfo *var;
- struct fb_info *info;
- struct msm_fb_backup_type *fb_backup;
- int ret = 0;
+ struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
+ struct msm_fb_backup_type *fb_backup = &mfd->msm_fb_backup;
+ int ret = -ENOSYS;
- mfd = container_of(work, struct msm_fb_data_type, commit_work);
- fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
- info = &fb_backup->info;
- if (fb_backup->disp_commit.flags &
- MDP_DISPLAY_COMMIT_OVERLAY) {
- mdss_fb_wait_for_fence(&mfd->mdp_sync_pt_data);
+ if (!sync_pt_data->async_wait_fences)
+ mdss_fb_wait_for_fence(sync_pt_data);
+ sync_pt_data->flushed = false;
+
+ if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) {
if (mfd->mdp.kickoff_fnc)
- ret = mfd->mdp.kickoff_fnc(mfd, &fb_backup->disp_commit);
- if (!ret)
- mdss_fb_update_backlight(mfd);
- mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data);
+ ret = mfd->mdp.kickoff_fnc(mfd,
+ &fb_backup->disp_commit);
+ else
+ pr_warn("no kickoff function setup for fb%d\n",
+ mfd->index);
} else {
- var = &fb_backup->disp_commit.var;
- ret = mdss_fb_pan_display_sub(var, info);
+ ret = mdss_fb_pan_display_sub(&fb_backup->disp_commit.var,
+ &fb_backup->info);
if (ret)
- pr_err("%s fails: ret = %x", __func__, ret);
+ pr_err("pan display failed %x on fb%d\n", ret,
+ mfd->index);
}
- mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
- mfd->is_committing = 0;
- complete_all(&mfd->commit_comp);
- mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
+ if (!ret)
+ mdss_fb_update_backlight(mfd);
+
+ if (IS_ERR_VALUE(ret) || !sync_pt_data->flushed)
+ mdss_fb_signal_timeline(sync_pt_data);
+
+ return ret;
+}
+
+static int __mdss_fb_display_thread(void *data)
+{
+ struct msm_fb_data_type *mfd = data;
+ int ret;
+ struct sched_param param;
+
+ param.sched_priority = 16;
+ ret = sched_setscheduler(current, SCHED_FIFO, ¶m);
+ if (ret)
+ pr_warn("set priority failed for fb%d display thread\n",
+ mfd->index);
+
+ while (1) {
+ wait_event(mfd->commit_wait_q,
+ atomic_read(&mfd->commits_pending));
+
+ ret = __mdss_fb_perform_commit(mfd);
+
+ atomic_dec(&mfd->commits_pending);
+ wake_up_all(&mfd->idle_wait_q);
+ }
+
+ return ret;
}
static int mdss_fb_check_var(struct fb_var_screeninfo *var,
@@ -1716,12 +1816,52 @@
return 0;
}
+/**
+ * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline
+ * @sync_pt_data: Sync pt structure holding timeline and fence info.
+ *
+ * Function returns a release fence on the timeline associated with the
+ * sync pt struct given and it's associated information. The release fence
+ * created can be used to signal when buffers provided will be released.
+ */
+static struct sync_fence *__mdss_fb_sync_get_rel_fence(
+ struct msm_sync_pt_data *sync_pt_data)
+{
+ struct sync_pt *rel_sync_pt;
+ struct sync_fence *rel_fence;
+ int val;
+
+ val = sync_pt_data->timeline_value + sync_pt_data->threshold +
+ atomic_read(&sync_pt_data->commit_cnt);
+
+ pr_debug("%s: buf sync rel fence timeline=%d\n",
+ sync_pt_data->fence_name, val);
+
+ rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val);
+ if (rel_sync_pt == NULL) {
+ pr_err("%s: cannot create sync point\n",
+ sync_pt_data->fence_name);
+ return NULL;
+ }
+
+ /* create fence */
+ rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt);
+ if (rel_fence == NULL) {
+ sync_pt_free(rel_sync_pt);
+ pr_err("%s: cannot create fence\n", sync_pt_data->fence_name);
+ return NULL;
+ }
+
+ return rel_fence;
+}
+
static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
struct mdp_buf_sync *buf_sync)
{
int i, ret = 0;
int acq_fen_fd[MDP_MAX_FENCE_FD];
- struct sync_fence *fence;
+ struct sync_fence *fence, *rel_fence;
+ int rel_fen_fd;
if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
(sync_pt_data->timeline == NULL))
@@ -1731,16 +1871,24 @@
ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
buf_sync->acq_fen_fd_cnt * sizeof(int));
if (ret) {
- pr_err("%s:copy_from_user failed", __func__);
+ pr_err("%s: copy_from_user failed", sync_pt_data->fence_name);
return ret;
}
+ if (sync_pt_data->acq_fen_cnt) {
+ pr_warn("%s: currently %d fences active. waiting...\n",
+ sync_pt_data->fence_name,
+ sync_pt_data->acq_fen_cnt);
+ mdss_fb_wait_for_fence(sync_pt_data);
+ }
+
mutex_lock(&sync_pt_data->sync_mutex);
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
fence = sync_fence_fdget(acq_fen_fd[i]);
if (fence == NULL) {
- pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
- acq_fen_fd[i]);
+ pr_err("%s: null fence! i=%d fd=%d\n",
+ sync_pt_data->fence_name, i,
+ acq_fen_fd[i]);
ret = -EINVAL;
break;
}
@@ -1750,54 +1898,40 @@
if (ret)
goto buf_sync_err_1;
- if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
- mdss_fb_wait_for_fence(sync_pt_data);
-
- sync_pt_data->cur_rel_sync_pt = sw_sync_pt_create(
- sync_pt_data->timeline, sync_pt_data->timeline_value +
- sync_pt_data->threshold);
-
- if (sync_pt_data->cur_rel_sync_pt == NULL) {
- pr_err("%s: cannot create sync point", __func__);
- ret = -ENOMEM;
+ rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data);
+ if (IS_ERR_OR_NULL(rel_fence)) {
+ pr_err("%s: unable to retrieve release fence\n",
+ sync_pt_data->fence_name);
+ ret = rel_fence ? PTR_ERR(rel_fence) : -ENOMEM;
goto buf_sync_err_1;
}
- /* create fence */
- sync_pt_data->cur_rel_fence = sync_fence_create(
- sync_pt_data->fence_name, sync_pt_data->cur_rel_sync_pt);
- if (sync_pt_data->cur_rel_fence == NULL) {
- sync_pt_free(sync_pt_data->cur_rel_sync_pt);
- sync_pt_data->cur_rel_sync_pt = NULL;
- pr_err("%s: cannot create fence", __func__);
- ret = -ENOMEM;
- goto buf_sync_err_1;
- }
/* create fd */
- sync_pt_data->cur_rel_fen_fd = get_unused_fd_flags(0);
- if (sync_pt_data->cur_rel_fen_fd < 0) {
- pr_err("%s: get_unused_fd_flags failed", __func__);
- ret = -EIO;
+ rel_fen_fd = get_unused_fd_flags(0);
+ if (rel_fen_fd < 0) {
+ pr_err("%s: get_unused_fd_flags failed\n",
+ sync_pt_data->fence_name);
+ ret = -EIO;
goto buf_sync_err_2;
}
- sync_fence_install(sync_pt_data->cur_rel_fence,
- sync_pt_data->cur_rel_fen_fd);
- ret = copy_to_user(buf_sync->rel_fen_fd,
- &sync_pt_data->cur_rel_fen_fd, sizeof(int));
+ sync_fence_install(rel_fence, rel_fen_fd);
+ ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int));
if (ret) {
- pr_err("%s:copy_to_user failed", __func__);
+ pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name);
goto buf_sync_err_3;
}
mutex_unlock(&sync_pt_data->sync_mutex);
+
+ if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+ mdss_fb_wait_for_fence(sync_pt_data);
+
return ret;
buf_sync_err_3:
- put_unused_fd(sync_pt_data->cur_rel_fen_fd);
+ put_unused_fd(rel_fen_fd);
buf_sync_err_2:
- sync_fence_put(sync_pt_data->cur_rel_fence);
- sync_pt_data->cur_rel_fence = NULL;
- sync_pt_data->cur_rel_fen_fd = 0;
+ sync_fence_put(rel_fence);
buf_sync_err_1:
for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
sync_fence_put(sync_pt_data->acq_fen[i]);
@@ -1834,8 +1968,8 @@
return -EINVAL;
mfd = (struct msm_fb_data_type *)info->par;
mdss_fb_power_setting_idle(mfd);
-
- mdss_fb_pan_idle(mfd);
+ if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL))
+ mdss_fb_pan_idle(mfd);
switch (cmd) {
case MSMFB_CURSOR:
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 256789d..8213dbe 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -18,6 +18,7 @@
#include <linux/list.h>
#include <linux/msm_mdp.h>
#include <linux/types.h>
+#include <linux/notifier.h>
#include "mdss_panel.h"
@@ -40,6 +41,32 @@
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
+/**
+ * enum mdp_notify_event - Different frame events to indicate frame update state
+ *
+ * @MDP_NOTIFY_FRAME_BEGIN: Frame update has started, the frame is about to
+ * be programmed into hardware.
+ * @MDP_NOTIFY_FRAME_READY: Frame ready to be kicked off, this can be used
+ * as the last point in time to synchronized with
+ * source buffers before kickoff.
+ * @MDP_NOTIFY_FRAME_FLUSHED: Configuration of frame has been flushed and
+ * DMA transfer has started.
+ * @MDP_NOTIFY_FRAME_DONE: Frame DMA transfer has completed.
+ * - For video mode panels this will indicate that
+ * previous frame has been replaced by new one.
+ * - For command mode/writeback frame done happens
+ * as soon as the DMA of the frame is done.
+ * @MDP_NOTIFY_FRAME_TIMEOUT: Frame DMA transfer has failed to complete within
+ * a fair amount of time.
+ */
+enum mdp_notify_event {
+ MDP_NOTIFY_FRAME_BEGIN = 1,
+ MDP_NOTIFY_FRAME_READY,
+ MDP_NOTIFY_FRAME_FLUSHED,
+ MDP_NOTIFY_FRAME_DONE,
+ MDP_NOTIFY_FRAME_TIMEOUT,
+};
+
struct disp_info_type_suspend {
int op_enable;
int panel_power_on;
@@ -57,13 +84,17 @@
char *fence_name;
u32 acq_fen_cnt;
struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
- int cur_rel_fen_fd;
- struct sync_pt *cur_rel_sync_pt;
- struct sync_fence *cur_rel_fence;
+
struct sw_sync_timeline *timeline;
int timeline_value;
u32 threshold;
+
+ atomic_t commit_cnt;
+ bool flushed;
+ bool async_wait_fences;
+
struct mutex sync_mutex;
+ struct notifier_block notifier;
};
struct msm_fb_data_type;
@@ -105,6 +136,11 @@
struct list_head list;
};
+struct msm_fb_backup_type {
+ struct fb_info info;
+ struct mdp_display_commit disp_commit;
+};
+
struct msm_fb_data_type {
u32 key;
u32 index;
@@ -159,10 +195,11 @@
struct msm_sync_pt_data mdp_sync_pt_data;
/* for non-blocking */
- struct completion commit_comp;
- u32 is_committing;
- struct work_struct commit_work;
- void *msm_fb_backup;
+ atomic_t commits_pending;
+ wait_queue_head_t commit_wait_q;
+ wait_queue_head_t idle_wait_q;
+
+ struct msm_fb_backup_type msm_fb_backup;
struct completion power_set_comp;
u32 is_power_setting;
@@ -170,11 +207,6 @@
struct list_head proc_list;
};
-struct msm_fb_backup_type {
- struct fb_info info;
- struct mdp_display_commit disp_commit;
-};
-
static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd)
{
int needs_complete = 0;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 0074873..cf0c287 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -469,13 +469,17 @@
return status;
} /* hdmi_edid_read_block */
+#define EDID_BLK_LEN 128
+#define EDID_DTD_LEN 18
static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
u8 type, u8 *len)
{
/* the start of data block collection, start of Video Data Block */
u32 offset = start_offset;
- u32 end_dbc_offset = in_buf[2];
+ u32 dbc_offset = in_buf[2];
+ if (dbc_offset >= EDID_BLK_LEN - EDID_DTD_LEN)
+ return NULL;
*len = 0;
/*
@@ -484,14 +488,15 @@
* * edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block
* collection present and no DTD data present.
*/
- if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
+ if ((dbc_offset == 0) || (dbc_offset == 4)) {
DEV_WARN("EDID: no DTD or non-DTD data present\n");
return NULL;
}
- while (offset < end_dbc_offset) {
+ while (offset < dbc_offset) {
u8 block_len = in_buf[offset] & 0x1F;
- if ((in_buf[offset] >> 5) == type) {
+ if ((offset + block_len <= dbc_offset) &&
+ (in_buf[offset] >> 5) == type) {
*len = block_len;
DEV_DBG("%s: EDID: block=%d found @ 0x%x w/ len=%d\n",
__func__, type, offset, block_len);
@@ -695,7 +700,7 @@
}
vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
- if (vsd == NULL)
+ if (vsd == NULL || len < 8)
return 0;
DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
@@ -885,7 +890,7 @@
}
} /* hdmi_edid_add_sink_video_format */
-static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
+static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
{
u8 len, offset, present_multi_3d, hdmi_vic_len;
@@ -896,22 +901,34 @@
3, &len) : NULL;
int i;
+ if (!vsd)
+ return -ENXIO;
+
offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
present_multi_3d = (vsd[offset] & 0x60) >> 5;
offset += 1;
+
hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
hdmi_3d_len = vsd[offset] & 0x1F;
DEV_DBG("%s: EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n", __func__,
hdmi_vic_len, hdmi_3d_len);
offset += (hdmi_vic_len + 1);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
if (present_multi_3d == 1 || present_multi_3d == 2) {
DEV_DBG("%s: EDID[3D]: multi 3D present (%d)\n", __func__,
present_multi_3d);
/* 3d_structure_all */
structure_all = (vsd[offset] << 8) | vsd[offset + 1];
offset += 2;
+ if (offset >= len - 1)
+ return -ETOOSMALL;
hdmi_3d_len -= 2;
if (present_multi_3d == 2) {
/* 3d_structure_mask */
@@ -958,16 +975,18 @@
i = 0;
while (hdmi_3d_len > 0) {
+ if (offset >= len - 1)
+ return -ETOOSMALL;
DEV_DBG("%s: EDID: 3D_Structure_%d @ 0x%x: %02x\n",
__func__, i + 1, offset, vsd[offset]);
-
if ((vsd[offset] >> 4) >=
sink_data->disp_multi_3d_mode_list_cnt) {
if ((vsd[offset] & 0x0F) >= 8) {
offset += 1;
hdmi_3d_len -= 1;
DEV_DBG("%s:EDID:3D_Detail_%d @ 0x%x: %02x\n",
- __func__, i + 1, offset, vsd[offset]);
+ __func__, i + 1, offset,
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
@@ -1003,12 +1022,13 @@
hdmi_3d_len -= 1;
DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ 0x%x: %02x\n",
__func__, i + 1, offset,
- vsd[offset]);
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
hdmi_3d_len -= 1;
}
+ return 0;
} /* hdmi_edid_get_display_vsd_3d_mode */
static void hdmi_edid_get_extended_video_formats(
@@ -1061,6 +1081,7 @@
u32 video_format = HDMI_VFRMT_640x480p60_4_3;
u32 has480p = false;
u8 len;
+ int rc;
const u8 *edid_blk0 = NULL;
const u8 *edid_blk1 = NULL;
const u8 *svd = NULL;
@@ -1311,8 +1332,10 @@
}
/* 3d format described in Vendor Specific Data */
- hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
+ rc = hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
num_of_cea_blocks);
+ if (!rc)
+ pr_debug("%s: 3D formats in VSD\n", __func__);
}
/*
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index bf28e8c..80b27ed 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1185,9 +1185,6 @@
DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
- /* Wait to be clean on DDC HW engine */
- hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
-
/* Disable encryption and disable the HDCP block */
DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 0b64bbb..e46e361 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -46,6 +46,14 @@
#define HPD_DISCONNECT_POLARITY 0
#define HPD_CONNECT_POLARITY 1
+/*
+ * Audio engine may take 1 to 3 sec to shutdown
+ * in normal cases. To handle worst cases, making
+ * timeout for audio engine shutdown as 5 sec.
+ */
+#define AUDIO_POLL_SLEEP_US (5 * 1000)
+#define AUDIO_POLL_TIMEOUT_US (AUDIO_POLL_SLEEP_US * 1000)
+
#define IFRAME_CHECKSUM_32(d) \
((d & 0xff) + ((d >> 8) & 0xff) + \
((d >> 16) & 0xff) + ((d >> 24) & 0xff))
@@ -87,8 +95,8 @@
static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable);
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool wait_audio_tx);
+static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
+ int val, bool force);
static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
struct mdss_hw hdmi_tx_hw = {
@@ -343,6 +351,52 @@
return new_vic;
} /* hdmi_tx_get_vic_from_panel_info */
+static inline void hdmi_tx_send_cable_notification(
+ struct hdmi_tx_ctrl *hdmi_ctrl, int val)
+{
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
+ switch_set_state(&hdmi_ctrl->sdev, val);
+} /* hdmi_tx_send_cable_notification */
+
+static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ return hdmi_edid_get_sink_mode(
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
+} /* hdmi_tx_is_dvi_mode */
+
+static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ u32 status = 0;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return;
+ }
+
+ if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status,
+ (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
+ AUDIO_POLL_TIMEOUT_US))
+ DEV_ERR("%s: Error turning off audio packet transmission.\n",
+ __func__);
+
+ if (readl_poll_timeout(io->base + HDMI_AUDIO_CFG, status,
+ (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
+ AUDIO_POLL_TIMEOUT_US))
+ DEV_ERR("%s: Error turning off audio engine.\n", __func__);
+}
+
static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data(
struct mdss_panel_data *mpd)
{
@@ -461,6 +515,15 @@
if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+
+ if (hdmi_ctrl->panel_power_on && hdmi_ctrl->hpd_state) {
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
+ hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
+ }
+
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
+ DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+ hdmi_ctrl->sdev.state);
} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
} else {
@@ -708,24 +771,6 @@
hdmi_ctrl->kobj = NULL;
} /* hdmi_tx_sysfs_remove */
-static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
-{
- return hdmi_edid_get_sink_mode(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
-} /* hdmi_tx_is_dvi_mode */
-
-static inline void hdmi_tx_send_cable_notification(
- struct hdmi_tx_ctrl *hdmi_ctrl, int val)
-{
- if (!hdmi_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
- return;
- }
-
- if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
- switch_set_state(&hdmi_ctrl->sdev, val);
-} /* hdmi_tx_send_cable_notification */
-
static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
int val, bool force)
{
@@ -1012,8 +1057,8 @@
DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
__func__, hdmi_ctrl->sdev.state);
} else {
- if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
- DEV_WARN("%s: Failed to disable ddc power\n", __func__);
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
+ hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
@@ -2245,10 +2290,8 @@
return 0;
} /* hdmi_tx_audio_setup */
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool wait_audio_tx)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2262,34 +2305,6 @@
return;
}
- if (wait_audio_tx) {
- /* Check if audio engine is turned off by QDSP or not */
- /* send off notification after every 1 sec for 15 seconds */
- for (i = 0; i < timeout_sec; i++) {
- /* Maximum time to sleep between two reads */
- sleep_us = 5000;
- /* Total time for condition to meet */
- timeout_us = 1000 * 1000;
-
- if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
- status, ((status & BIT(0)) == 0),
- sleep_us, timeout_us)) {
-
- DEV_ERR(
- "%s: audio still on after %d sec. try again\n",
- __func__, i+1);
-
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
- true);
- continue;
- }
- break;
- }
- }
-
- if (i == timeout_sec)
- DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
-
if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
@@ -2413,10 +2428,11 @@
hdmi_hdcp_off(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
}
- if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
- hdmi_tx_audio_off(hdmi_ctrl, true);
- }
+ if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
+ DEV_WARN("%s: Failed to disable ddc power\n", __func__);
+
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
+ hdmi_tx_audio_off(hdmi_ctrl);
hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2667,10 +2683,6 @@
hdmi_tx_hpd_off(hdmi_ctrl);
else
hdmi_ctrl->hpd_off_pending = true;
-
- hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
- DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
- hdmi_ctrl->sdev.state);
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index db8a098..9cb76c2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1771,7 +1771,8 @@
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
u32 num;
u32 data[2];
- int rc;
+ int rc, len;
+ const u32 *arr;
num = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-smp-data");
@@ -1793,7 +1794,49 @@
"qcom,mdss-smp-mb-per-pipe", data);
mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
- return 0;
+ rc = 0;
+ arr = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pipe-rgb-fixed-mmb", &len);
+ if (arr) {
+ int i, j, k;
+ u32 cnt, mmb;
+
+ len /= sizeof(u32);
+ for (i = 0, k = 0; i < len; k++) {
+ struct mdss_mdp_pipe *pipe = NULL;
+
+ if (k >= mdata->nrgb_pipes) {
+ pr_err("invalid fixed mmbs for rgb pipes\n");
+ return -EINVAL;
+ }
+
+ pipe = &mdata->rgb_pipes[k];
+
+ cnt = be32_to_cpu(arr[i++]);
+ if (cnt == 0)
+ continue;
+
+ for (j = 0; j < cnt; j++) {
+ mmb = be32_to_cpu(arr[i++]);
+ if (mmb > mdata->smp_mb_cnt) {
+ pr_err("overflow mmb%d: rgb%d: max%d\n",
+ mmb, k, mdata->smp_mb_cnt);
+ return -EINVAL;
+ }
+ /* rgb pipes fetches only single plane */
+ set_bit(mmb, pipe->smp_map[0].fixed);
+ }
+ if (bitmap_intersects(pipe->smp_map[0].fixed,
+ mdata->mmb_alloc_map, mdata->smp_mb_cnt)) {
+ pr_err("overlapping fixed mmb map\n");
+ return -EINVAL;
+ }
+ bitmap_or(mdata->mmb_alloc_map, pipe->smp_map[0].fixed,
+ mdata->mmb_alloc_map, mdata->smp_mb_cnt);
+ }
+ }
+
+ return rc;
}
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 3ce61a0..d8dc6ca 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -18,9 +18,11 @@
#include <linux/io.h>
#include <linux/msm_mdp.h>
#include <linux/platform_device.h>
+#include <linux/notifier.h>
#include "mdss.h"
#include "mdss_mdp_hwio.h"
+#include "mdss_fb.h"
#define MDSS_MDP_DEFAULT_INTR_MASK 0
#define MDSS_MDP_CURSOR_WIDTH 64
@@ -187,6 +189,9 @@
int (*remove_vsync_handler) (struct mdss_mdp_ctl *,
struct mdss_mdp_vsync_handler *);
int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, int new_fps);
+
+ struct blocking_notifier_head notifier_head;
+
void *priv_data;
u32 wb_type;
};
@@ -311,8 +316,9 @@
};
struct mdss_mdp_pipe_smp_map {
- DECLARE_BITMAP(reserved, MDSS_MDP_SMP_MMB_BLOCKS);
- DECLARE_BITMAP(allocated, MDSS_MDP_SMP_MMB_BLOCKS);
+ DECLARE_BITMAP(reserved, MAX_DRV_SUP_MMB_BLKS);
+ DECLARE_BITMAP(allocated, MAX_DRV_SUP_MMB_BLKS);
+ DECLARE_BITMAP(fixed, MAX_DRV_SUP_MMB_BLKS);
};
struct mdss_mdp_pipe {
@@ -324,6 +330,7 @@
atomic_t ref_cnt;
u32 play_cnt;
int pid;
+ bool is_handed_off;
u32 flags;
u32 bwc_mode;
@@ -393,6 +400,7 @@
int free_list_size;
int ad_state;
+ bool handoff;
u32 splash_mem_addr;
u32 splash_mem_size;
u32 sd_enabled;
@@ -479,9 +487,11 @@
struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
struct msm_fb_data_type *mfd);
-int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff);
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff);
+int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff);
int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
struct mdss_panel_data *pdata);
@@ -491,7 +501,14 @@
int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_perf_params *perf);
+int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event);
+void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier);
+void mdss_mdp_ctl_notifier_unregister(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier);
+int mdss_mdp_mixer_handoff(struct mdss_mdp_ctl *ctl, u32 num,
+ struct mdss_mdp_pipe *pipe);
struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer);
struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux);
@@ -545,6 +562,8 @@
int mdss_mdp_calib_mode(struct msm_fb_data_type *mfd,
struct mdss_calib_cfg *cfg);
+int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_smp_handoff(struct mdss_data_type *mdata);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
u32 type);
struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e50598f..82937e3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -385,6 +385,7 @@
ctl->ref_cnt++;
ctl->mdata = mdata;
mutex_init(&ctl->lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&ctl->notifier_head);
pr_debug("alloc ctl_num=%d\n", ctl->num);
break;
}
@@ -610,13 +611,13 @@
return 0;
}
-int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff)
{
switch (ctl->panel_data->panel_info.type) {
case MIPI_VIDEO_PANEL:
- return mdss_mdp_video_reconfigure_splash_done(ctl);
+ return mdss_mdp_video_reconfigure_splash_done(ctl, handoff);
case MIPI_CMD_PANEL:
- return mdss_mdp_cmd_reconfigure_splash_done(ctl);
+ return mdss_mdp_cmd_reconfigure_splash_done(ctl, handoff);
default:
return 0;
}
@@ -1078,9 +1079,12 @@
pr_debug("ctl_num=%d\n", ctl->num);
- nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER + MDSS_MDP_WB_MAX_LAYERMIXER;
- for (i = 0; i < nmixers; i++)
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
+ if (!ctl->panel_data->panel_info.cont_splash_enabled) {
+ nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER +
+ MDSS_MDP_WB_MAX_LAYERMIXER;
+ for (i = 0; i < nmixers; i++)
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
+ }
mixer = ctl->mixer_left;
mdss_mdp_pp_resume(ctl, mixer->num);
@@ -1870,6 +1874,11 @@
}
}
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_READY);
+
+ if (ctl->wait_pingpong)
+ ctl->wait_pingpong(ctl, NULL);
+
/* postprocessing setup, including dspp */
mdss_mdp_pp_setup_locked(ctl);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
@@ -1895,6 +1904,23 @@
return ret;
}
+void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_register(&ctl->notifier_head, notifier);
+}
+
+void mdss_mdp_ctl_notifier_unregister(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_unregister(&ctl->notifier_head, notifier);
+}
+
+int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event)
+{
+ return blocking_notifier_call_chain(&ctl->notifier_head, event, ctl);
+}
+
int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id)
{
int i;
@@ -1965,3 +1991,66 @@
MDSS_MDP_INTF_LAYERMIXER3);
}
}
+
+static int __mdss_mdp_mixer_handoff_helper(struct mdss_mdp_mixer *mixer,
+ struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+
+ if (!mixer) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (mixer->stage_pipe[MDSS_MDP_STAGE_UNUSED] != NULL) {
+ pr_err("More than one pipe staged on mixer num %d\n",
+ mixer->num);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ pr_debug("Staging pipe num %d on mixer num %d\n",
+ pipe->num, mixer->num);
+ mixer->stage_pipe[MDSS_MDP_STAGE_UNUSED] = pipe;
+ pipe->mixer = mixer;
+ pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
+
+error:
+ return rc;
+}
+
+/**
+ * mdss_mdp_mixer_handoff() - Stages a given pipe on the appropriate mixer
+ * @ctl: pointer to the control structure associated with the overlay device.
+ * @num: the mixer number on which the pipe needs to be staged.
+ * @pipe: pointer to the pipe to be staged.
+ *
+ * Function stages a given pipe on either the left mixer or the right mixer
+ * for the control structre based on the mixer number. If the input mixer
+ * number does not match either of the mixers then an error is returned.
+ * This function is called during overlay handoff when certain pipes are
+ * already staged by the bootloader.
+ */
+int mdss_mdp_mixer_handoff(struct mdss_mdp_ctl *ctl, u32 num,
+ struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+ struct mdss_mdp_mixer *mx_left = ctl->mixer_left;
+ struct mdss_mdp_mixer *mx_right = ctl->mixer_right;
+
+ /*
+ * For performance calculations, stage the handed off pipe
+ * as MDSS_MDP_STAGE_UNUSED
+ */
+ if (mx_left && (mx_left->num == num)) {
+ rc = __mdss_mdp_mixer_handoff_helper(mx_left, pipe);
+ } else if (mx_right && (mx_right->num == num)) {
+ rc = __mdss_mdp_mixer_handoff_helper(mx_right, pipe);
+ } else {
+ pr_err("pipe num %d staged on unallocated mixer num %d\n",
+ pipe->num, num);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 940d6c9..c8af903 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -419,8 +419,6 @@
MDSS_MDP_MAX_INTF
};
-#define MDSS_MDP_REG_INTF_OFFSET(intf) (0x20F00 + ((intf) * 0x200))
-
#define MDSS_MDP_REG_INTF_TIMING_ENGINE_EN 0x000
#define MDSS_MDP_REG_INTF_CONFIG 0x004
#define MDSS_MDP_REG_INTF_HSYNC_CTL 0x008
@@ -499,8 +497,6 @@
#define MDSS_MDP_REG_SMP_ALLOC_W0 0x00180
#define MDSS_MDP_REG_SMP_ALLOC_R0 0x00230
-#define MDSS_MDP_SMP_MMB_BLOCKS 44
-
#define MDSS_MDP_LP_MISR_SEL 0x450
#define MDSS_MDP_LP_MISR_CTRL_MDP 0x454
#define MDSS_MDP_LP_MISR_CTRL_HDMI 0x458
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index e0717ad..6056f21 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -12,9 +12,9 @@
*/
#include <linux/kernel.h>
-#include "mdss_panel.h"
+
#include "mdss_mdp.h"
-#include "mdss_dsi.h"
+#include "mdss_panel.h"
#define VSYNC_EXPIRE_TICK 4
@@ -43,6 +43,9 @@
struct mutex clk_mtx;
spinlock_t clk_lock;
struct work_struct clk_work;
+ struct work_struct pp_done_work;
+ atomic_t pp_done_cnt;
+
/* te config */
u8 tear_check;
u16 height; /* panel height */
@@ -311,6 +314,8 @@
complete_all(&ctx->pp_comp);
if (ctx->koff_cnt) {
+ atomic_inc(&ctx->pp_done_cnt);
+ schedule_work(&ctx->pp_done_work);
ctx->koff_cnt--;
if (ctx->koff_cnt) {
pr_err("%s: too many kickoffs=%d!\n", __func__,
@@ -326,6 +331,16 @@
spin_unlock(&ctx->clk_lock);
}
+static void pingpong_done_work(struct work_struct *work)
+{
+ struct mdss_mdp_cmd_ctx *ctx =
+ container_of(work, typeof(*ctx), pp_done_work);
+
+ if (ctx->ctl)
+ while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
+ mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);
+}
+
static void clk_ctrl_work(struct work_struct *work)
{
struct mdss_mdp_cmd_ctx *ctx =
@@ -399,7 +414,7 @@
return 0;
}
-int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl, bool handoff)
{
struct mdss_panel_data *pdata;
int ret = 0;
@@ -446,8 +461,10 @@
WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
rc, ctl->num);
rc = -EPERM;
- } else
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
+ } else {
rc = 0;
+ }
}
return rc;
@@ -525,6 +542,10 @@
pr_err("invalid ctx\n");
return -ENODEV;
}
+
+ list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
+ mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
+
spin_lock_irqsave(&ctx->clk_lock, flags);
if (ctx->rdptr_enabled) {
INIT_COMPLETION(ctx->stop_comp);
@@ -542,10 +563,9 @@
mdss_mdp_cmd_clk_off(ctx);
- ctx->panel_on = 0;
+ flush_work(&ctx->pp_done_work);
- list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
- mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
+ ctx->panel_on = 0;
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
NULL, NULL);
@@ -611,6 +631,8 @@
spin_lock_init(&ctx->clk_lock);
mutex_init(&ctx->clk_mtx);
INIT_WORK(&ctx->clk_work, clk_ctrl_work);
+ INIT_WORK(&ctx->pp_done_work, pingpong_done_work);
+ atomic_set(&ctx->pp_done_cnt, 0);
INIT_LIST_HEAD(&ctx->vsync_handlers);
ctx->recovery.fxn = mdss_mdp_cmd_underflow_recovery;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index a040785..7c79ceb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -21,6 +21,7 @@
#include "mdss_fb.h"
#include "mdss_mdp.h"
+#include "mdss_panel.h"
/* wait for at least 2 vsyncs for lowest refresh rate (24hz) */
#define VSYNC_TIMEOUT_US 100000
@@ -428,6 +429,9 @@
} else {
rc = 0;
}
+
+ mdss_mdp_ctl_notify(ctl,
+ rc ? MDP_NOTIFY_FRAME_TIMEOUT : MDP_NOTIFY_FRAME_DONE);
}
if (ctx->wait_pending) {
@@ -583,46 +587,52 @@
return 0;
}
-int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff)
{
- struct mdss_panel_data *pdata;
- int ret = 0, off;
- int mdss_mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
- int mdss_v2_intf_off = 0;
+ struct mdss_panel_data *pdata = ctl->panel_data;
+ int i, ret = 0;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(ctl->mfd);
+ struct mdss_mdp_video_ctx *ctx;
+ struct mdss_data_type *mdata = ctl->mdata;
- off = 0;
-
- pdata = ctl->panel_data;
-
- pdata->panel_info.cont_splash_enabled = 0;
-
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
- NULL);
- if (ret) {
- pr_err("%s: Failed to handle 'CONT_SPLASH_BEGIN' event\n",
- __func__);
- return ret;
+ i = ctl->intf_num - MDSS_MDP_INTF0;
+ if (i < mdata->nintf) {
+ ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + i;
+ pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
+ } else {
+ pr_err("Invalid intf number: %d\n", ctl->intf_num);
+ ret = -EINVAL;
+ goto error;
}
- mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
- off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
+ if (!handoff) {
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
+ NULL);
+ if (ret) {
+ pr_err("%s: Failed to handle 'CONT_SPLASH_BEGIN' event\n"
+ , __func__);
+ return ret;
+ }
- if (mdss_mdp_rev >= MDSS_MDP_HW_REV_102)
- mdss_v2_intf_off = 0xEC00;
+ mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
+ mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
- MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN -
- mdss_v2_intf_off, 0);
- /* wait for 1 VSYNC for the pipe to be unstaged */
- msleep(20);
+ /* wait for 1 VSYNC for the pipe to be unstaged */
+ msleep(20);
+
+ ret = mdss_mdp_ctl_intf_event(ctl,
+ MDSS_EVENT_CONT_SPLASH_FINISH, NULL);
+ }
+
+error:
+ pdata->panel_info.cont_splash_enabled = 0;
/* Give back the reserved memory to the system */
memblock_free(mdp5_data->splash_mem_addr, mdp5_data->splash_mem_size);
free_bootmem_late(mdp5_data->splash_mem_addr,
mdp5_data->splash_mem_size);
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
- NULL);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 7f872b4..3929501 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -13,9 +13,9 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
-#include "mdss_fb.h"
#include "mdss_mdp.h"
#include "mdss_mdp_rotator.h"
+#include "mdss_panel.h"
enum mdss_mdp_writeback_type {
MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
@@ -421,10 +421,12 @@
NULL, NULL);
if (rc == 0) {
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
rc = -ENODEV;
WARN(1, "writeback kickoff timed out (%d) ctl=%d\n",
rc, ctl->num);
} else {
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_DONE);
rc = 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index cccec93..c565d98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -720,12 +720,60 @@
mdss_mdp_pipe_destroy(pipe);
}
+static void __mdss_mdp_handoff_cleanup_pipes(struct msm_fb_data_type *mfd,
+ u32 type)
+{
+ u32 i, npipes;
+ struct mdss_mdp_pipe *pipes;
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+
+ switch (type) {
+ case MDSS_MDP_PIPE_TYPE_VIG:
+ pipes = mdata->vig_pipes;
+ npipes = mdata->nvig_pipes;
+ break;
+ case MDSS_MDP_PIPE_TYPE_RGB:
+ pipes = mdata->rgb_pipes;
+ npipes = mdata->nrgb_pipes;
+ break;
+ case MDSS_MDP_PIPE_TYPE_DMA:
+ pipes = mdata->dma_pipes;
+ npipes = mdata->ndma_pipes;
+ break;
+ default:
+ return;
+ }
+
+ for (i = 0; i < npipes; i++) {
+ pipe = &pipes[i];
+ if (pipe->is_handed_off) {
+ pr_debug("Unmapping handed off pipe %d\n", pipe->num);
+ list_add(&pipe->cleanup_list,
+ &mdp5_data->pipes_cleanup);
+ mdss_mdp_mixer_pipe_unstage(pipe);
+ pipe->is_handed_off = false;
+ }
+ }
+}
+
+/**
+ * mdss_mdp_overlay_start() - Programs the MDP control data path to hardware
+ * @mfd: Msm frame buffer structure associated with fb device.
+ *
+ * Program the MDP hardware with the control settings for the framebuffer
+ * device. In addition to this, this function also handles the transition
+ * from the the splash screen to the android boot animation when the
+ * continuous splash screen feature is enabled.
+ */
static int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd)
{
int rc;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
- if (mdp5_data->ctl->power_on) {
+ if (ctl->power_on) {
if (!mdp5_data->mdata->batfet)
mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
return 0;
@@ -739,24 +787,84 @@
return rc;
}
- if (mfd->panel_info->cont_splash_enabled) {
- mdss_mdp_ctl_splash_finish(mdp5_data->ctl);
- mdss_mdp_footswitch_ctrl_splash(0);
- }
-
+ /*
+ * We need to do hw init before any hw programming.
+ * Also, hw init involves programming the VBIF registers which
+ * should be done only after attaching IOMMU which in turn would call
+ * in to TZ to restore security configs on the VBIF registers.
+ * This is not needed when continuous splash screen is enabled since
+ * we would have called in to TZ to restore security configs from LK.
+ */
if (!is_mdss_iommu_attached()) {
- mdss_iommu_attach(mdss_res);
+ if (!mfd->panel_info->cont_splash_enabled)
+ mdss_iommu_attach(mdss_res);
mdss_hw_init(mdss_res);
}
- rc = mdss_mdp_ctl_start(mdp5_data->ctl);
+ rc = mdss_mdp_ctl_start(ctl);
if (rc == 0) {
atomic_inc(&ov_active_panels);
- } else {
- pr_err("overlay start failed.\n");
- mdss_mdp_ctl_destroy(mdp5_data->ctl);
- mdp5_data->ctl = NULL;
+ mdss_mdp_ctl_notifier_register(mdp5_data->ctl,
+ &mfd->mdp_sync_pt_data.notifier);
+ } else {
+ pr_err("mdp ctl start failed.\n");
+ goto error;
+ }
+
+ if (mfd->panel_info->cont_splash_enabled) {
+ if (mdp5_data->handoff) {
+ /*
+ * Set up border-fill on the handed off pipes.
+ * This is needed to ensure that there are no memory
+ * accesses prior to attaching iommu during continuous
+ * splash screen case. However, for command mode
+ * displays, this is not necessary since the panels can
+ * refresh from their internal memory if no data is sent
+ * out on the dsi lanes.
+ */
+ if (ctl && ctl->is_video_mode) {
+ rc = mdss_mdp_display_commit(ctl, NULL);
+ if (!IS_ERR_VALUE(rc)) {
+ mdss_mdp_display_wait4comp(ctl);
+ } else {
+ /*
+ * Since border-fill setup failed, we
+ * need to ensure that we turn off the
+ * MDP timing generator before attaching
+ * iommu
+ */
+ pr_err("failed to set BF at handoff\n");
+ mdp5_data->handoff = false;
+ rc = 0;
+ }
+ }
+
+ /* Add all the handed off pipes to the cleanup list */
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_RGB);
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_VIG);
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_DMA);
+ }
+ rc = mdss_mdp_ctl_splash_finish(ctl, mdp5_data->handoff);
+ /*
+ * Remove the vote for footswitch even if above function
+ * returned error
+ */
+ mdss_mdp_footswitch_ctrl_splash(0);
+ if (rc)
+ goto error;
+
+ if (!is_mdss_iommu_attached())
+ mdss_iommu_attach(mdss_res);
+ }
+
+error:
+ if (rc) {
+ mdss_mdp_ctl_destroy(ctl);
+ mdp5_data->ctl = NULL;
pm_runtime_put(&mfd->pdev->dev);
}
@@ -783,7 +891,7 @@
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_ctl *tmp;
- int ret;
+ int ret = 0;
int sd_in_pipe = 0;
if (ctl->shared_lock)
@@ -792,14 +900,6 @@
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
- ret = mdss_mdp_display_wait4pingpong(mdp5_data->ctl);
- if (ret) {
- mutex_unlock(&mfd->lock);
- mutex_unlock(&mdp5_data->ov_lock);
- if (ctl->shared_lock)
- mutex_unlock(ctl->shared_lock);
- return ret;
- }
/*
* check if there is a secure display session
*/
@@ -819,6 +919,9 @@
mdp5_data->sd_enabled = 0;
}
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
if (data)
mdss_mdp_set_roi(ctl, data);
@@ -913,6 +1016,8 @@
mdss_fb_update_notify_update(mfd);
commit_fail:
mdss_mdp_overlay_cleanup(mfd);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_FLUSHED);
mutex_unlock(&mdp5_data->ov_lock);
if (ctl->shared_lock)
@@ -2098,7 +2203,6 @@
case MSMFB_OVERLAY_COMMIT:
mdss_fb_wait_for_fence(&(mfd->mdp_sync_pt_data));
ret = mfd->mdp.kickoff_fnc(mfd, NULL);
- mdss_fb_signal_timeline(&(mfd->mdp_sync_pt_data));
break;
case MSMFB_METADATA_SET:
ret = copy_from_user(&metadata, argp, sizeof(metadata));
@@ -2123,10 +2227,66 @@
return ret;
}
+/**
+ * __mdss_mdp_overlay_ctl_init - Helper function to intialize control structure
+ * @mfd: msm frame buffer data structure associated with the fb device.
+ *
+ * Helper function that allocates and initializes the mdp control structure
+ * for a frame buffer device. Whenver applicable, this function will also setup
+ * the control for the split display path as well.
+ *
+ * Return: pointer to the newly allocated control structure.
+ */
+static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
+ struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdss_mdp_ctl *ctl;
+ struct mdss_panel_data *pdata;
+
+ if (!mfd)
+ return ERR_PTR(-EINVAL);
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected for fb%d\n", mfd->index);
+ rc = -ENODEV;
+ goto error;
+ }
+
+ ctl = mdss_mdp_ctl_init(pdata, mfd);
+ if (IS_ERR_OR_NULL(ctl)) {
+ pr_err("Unable to initialize ctl for fb%d\n",
+ mfd->index);
+ rc = PTR_ERR(ctl);
+ goto error;
+ }
+ ctl->vsync_handler.vsync_handler =
+ mdss_mdp_overlay_handle_vsync;
+ ctl->vsync_handler.cmd_post_flush = false;
+
+ if (mfd->split_display && pdata->next) {
+ /* enable split display */
+ rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
+ if (rc) {
+ mdss_mdp_ctl_destroy(ctl);
+ goto error;
+ }
+ }
+
+error:
+ if (rc)
+ return ERR_PTR(rc);
+ else
+ return ctl;
+}
+
static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
{
int rc;
struct mdss_overlay_private *mdp5_data;
+ struct mdss_mdp_ctl *ctl = NULL;
+
if (!mfd)
return -ENODEV;
@@ -2138,33 +2298,9 @@
return -EINVAL;
if (!mdp5_data->ctl) {
- struct mdss_mdp_ctl *ctl;
- struct mdss_panel_data *pdata;
-
- pdata = dev_get_platdata(&mfd->pdev->dev);
- if (!pdata) {
- pr_err("no panel connected for fb%d\n", mfd->index);
- return -ENODEV;
- }
-
- ctl = mdss_mdp_ctl_init(pdata, mfd);
- if (IS_ERR_OR_NULL(ctl)) {
- pr_err("Unable to initialize ctl for fb%d\n",
- mfd->index);
+ ctl = __mdss_mdp_overlay_ctl_init(mfd);
+ if (IS_ERR_OR_NULL(ctl))
return PTR_ERR(ctl);
- }
- ctl->vsync_handler.vsync_handler =
- mdss_mdp_overlay_handle_vsync;
- ctl->vsync_handler.cmd_post_flush = false;
-
- if (mfd->split_display && pdata->next) {
- /* enable split display */
- rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
- if (rc) {
- mdss_mdp_ctl_destroy(ctl);
- return rc;
- }
- }
mdp5_data->ctl = ctl;
}
@@ -2232,6 +2368,8 @@
rc = mdss_mdp_ctl_stop(mdp5_data->ctl);
if (rc == 0) {
__mdss_mdp_overlay_free_list_purge(mfd);
+ mdss_mdp_ctl_notifier_unregister(mdp5_data->ctl,
+ &mfd->mdp_sync_pt_data.notifier);
if (!mfd->ref_cnt) {
mdp5_data->borderfill_enable = false;
@@ -2263,6 +2401,96 @@
return 0;
}
+/**
+ * mdss_mdp_overlay_handoff() - Read MDP registers to handoff an active ctl path
+ * @mfd: Msm frame buffer structure associated with the fb device.
+ *
+ * This function populates the MDP software structures with the current state of
+ * the MDP hardware to handoff any active control path for the framebuffer
+ * device. This is needed to identify any ctl, mixers and pipes being set up by
+ * the bootloader to display the splash screen when the continuous splash screen
+ * feature is enabled in kernel.
+ */
+static int mdss_mdp_overlay_handoff(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int i, j;
+ u32 reg;
+ struct mdss_mdp_pipe *pipe = NULL;
+ struct mdss_mdp_ctl *ctl = NULL;
+
+ if (!mdp5_data->ctl) {
+ ctl = __mdss_mdp_overlay_ctl_init(mfd);
+ if (IS_ERR_OR_NULL(ctl)) {
+ rc = PTR_ERR(ctl);
+ goto error;
+ }
+ mdp5_data->ctl = ctl;
+ }
+
+ rc = mdss_mdp_ctl_setup(ctl);
+ if (rc)
+ goto error;
+
+ ctl->clk_rate = mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC);
+ pr_debug("Set the ctl clock rate to %d Hz\n", ctl->clk_rate);
+
+ for (i = 0; i < mdata->nmixers_intf; i++) {
+ reg = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_LAYER(i));
+ pr_debug("for lm%d reg = 0x%09x\n", i, reg);
+ for (j = MDSS_MDP_SSPP_VIG0; j < MDSS_MDP_MAX_SSPP; j++) {
+ u32 cfg = j * 3;
+ if ((j == MDSS_MDP_SSPP_VIG3) ||
+ (j == MDSS_MDP_SSPP_RGB3)) {
+ /* Add 2 to account for Cursor & Border bits */
+ cfg += 2;
+ }
+ if (reg & (0x7 << cfg)) {
+ pr_debug("Pipe %d staged\n", j);
+ pipe = mdss_mdp_pipe_search(mdata, BIT(j));
+ if (!pipe) {
+ pr_warn("Invalid pipe %d staged\n", j);
+ continue;
+ }
+
+ rc = mdss_mdp_pipe_handoff(pipe);
+ if (rc) {
+ pr_err("Failed to handoff pipe num %d\n"
+ , pipe->num);
+ goto error;
+ }
+
+ rc = mdss_mdp_mixer_handoff(ctl, i, pipe);
+ if (rc) {
+ pr_err("failed to handoff mixer num %d\n"
+ , i);
+ goto error;
+ }
+ }
+ }
+ }
+
+ rc = mdss_mdp_smp_handoff(mdata);
+ if (rc)
+ pr_err("Failed to handoff smps\n");
+
+ mdp5_data->handoff = true;
+
+error:
+ if (rc && ctl) {
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_RGB);
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_VIG);
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_DMA);
+ mdss_mdp_ctl_destroy(ctl);
+ mdp5_data->ctl = NULL;
+ mdp5_data->handoff = false;
+ }
+
+ return rc;
+}
+
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
{
struct device *dev = mfd->fbi->dev;
@@ -2329,6 +2557,7 @@
goto init_fail;
}
}
+ mfd->mdp_sync_pt_data.async_wait_fences = true;
pm_runtime_set_suspended(&mfd->pdev->dev);
pm_runtime_enable(&mfd->pdev->dev);
@@ -2340,6 +2569,21 @@
if (!mdp5_data->cpu_pm_hdl)
pr_warn("%s: unable to add event timer\n", __func__);
+ if (mfd->panel_info->cont_splash_enabled) {
+ rc = mdss_mdp_overlay_handoff(mfd);
+ if (rc) {
+ /*
+ * Even though handoff failed, it is not fatal.
+ * MDP can continue, just that we would have a longer
+ * delay in transitioning from splash screen to boot
+ * animation
+ */
+ pr_warn("Overlay handoff failed for fb%d. rc=%d\n",
+ mfd->index, rc);
+ rc = 0;
+ }
+ }
+
return rc;
init_fail:
kfree(mdp5_data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index c18fd9b..779f74c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -27,10 +27,10 @@
static DEFINE_MUTEX(mdss_mdp_sspp_lock);
static DEFINE_MUTEX(mdss_mdp_smp_lock);
-static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
-static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
+ struct mdss_data_type *mdata, int client_id);
static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
u32 reg, u32 val)
@@ -43,21 +43,29 @@
return readl_relaxed(pipe->base + reg);
}
-static u32 mdss_mdp_smp_mmb_reserve(unsigned long *existing,
- unsigned long *reserve, size_t n)
+static u32 mdss_mdp_smp_mmb_reserve(struct mdss_mdp_pipe_smp_map *smp_map,
+ size_t n)
{
u32 i, mmb;
+ u32 fixed_cnt = bitmap_weight(smp_map->fixed, SMP_MB_CNT);
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ if (n <= fixed_cnt)
+ return fixed_cnt;
+ else
+ n -= fixed_cnt;
/* reserve more blocks if needed, but can't free mmb at this point */
- for (i = bitmap_weight(existing, SMP_MB_CNT); i < n; i++) {
- if (bitmap_full(mdss_mdp_smp_mmb_pool, SMP_MB_CNT))
+ for (i = bitmap_weight(smp_map->allocated, SMP_MB_CNT); i < n; i++) {
+ if (bitmap_full(mdata->mmb_alloc_map, SMP_MB_CNT))
break;
- mmb = find_first_zero_bit(mdss_mdp_smp_mmb_pool, SMP_MB_CNT);
- set_bit(mmb, reserve);
- set_bit(mmb, mdss_mdp_smp_mmb_pool);
+ mmb = find_first_zero_bit(mdata->mmb_alloc_map, SMP_MB_CNT);
+ set_bit(mmb, smp_map->reserved);
+ set_bit(mmb, mdata->mmb_alloc_map);
}
- return i;
+
+ return i + fixed_cnt;
}
static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
@@ -86,20 +94,17 @@
static void mdss_mdp_smp_mmb_free(unsigned long *smp, bool write)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
if (!bitmap_empty(smp, SMP_MB_CNT)) {
if (write)
mdss_mdp_smp_mmb_set(0, smp);
- bitmap_andnot(mdss_mdp_smp_mmb_pool, mdss_mdp_smp_mmb_pool,
+ bitmap_andnot(mdata->mmb_alloc_map, mdata->mmb_alloc_map,
smp, SMP_MB_CNT);
bitmap_zero(smp, SMP_MB_CNT);
}
}
-static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
-{
- return bitmap_weight(smp, SMP_MB_CNT) == 0;
-}
-
static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
{
u32 fetch_size, val, wm[3];
@@ -229,8 +234,8 @@
pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
num_blks, pipe->num, i);
- reserved = mdss_mdp_smp_mmb_reserve(pipe->smp_map[i].allocated,
- pipe->smp_map[i].reserved, num_blks);
+ reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp_map[i],
+ num_blks);
if (reserved < num_blks)
break;
}
@@ -246,7 +251,21 @@
return rc;
}
-
+/*
+ * mdss_mdp_smp_alloc() -- set smp mmb and and wm levels for a staged pipe
+ * @pipe: pointer to a pipe
+ *
+ * Function amends reserved smp mmbs to allocated bitmap and ties respective
+ * mmbs to their pipe fetch_ids. Based on the number of total allocated mmbs
+ * for a staged pipe, it also sets the watermark levels (wm).
+ *
+ * This function will be called on every commit where pipe params might not
+ * have changed. In such cases, we need to ensure that wm levels are not
+ * wiped out. Also in some rare situations hw might have reset and wiped out
+ * smp mmb programming but new smp reservation is not done. In such cases we
+ * need to ensure that for a staged pipes, mmbs are set properly based on
+ * allocated bitmap.
+ */
static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
{
int i;
@@ -254,8 +273,14 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++) {
- if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+ cnt += bitmap_weight(pipe->smp_map[i].fixed, SMP_MB_CNT);
+
+ if (bitmap_empty(pipe->smp_map[i].reserved, SMP_MB_CNT)) {
+ cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
+ pipe->smp_map[i].allocated);
continue;
+ }
+
mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
pipe->smp_map[i].reserved);
cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -284,6 +309,80 @@
return 0;
}
+/**
+ * mdss_mdp_smp_handoff() - Handoff SMP MMBs in use by staged pipes
+ * @mdata: pointer to the global mdss data structure.
+ *
+ * Iterate through the list of all SMP MMBs and check to see if any
+ * of them are assigned to a pipe being marked as being handed-off.
+ * If so, update the corresponding software allocation map to reflect
+ * this.
+ *
+ * This function would typically be called during MDP probe for the case
+ * when certain pipes might be programmed in the bootloader to display
+ * the splash screen.
+ */
+int mdss_mdp_smp_handoff(struct mdss_data_type *mdata)
+{
+ int rc = 0;
+ int i, client_id, prev_id = 0;
+ u32 off, s, data;
+ struct mdss_mdp_pipe *pipe = NULL;
+
+ /*
+ * figure out what SMP MMBs are allocated for each of the pipes
+ * that need to be handed off.
+ */
+ for (i = 0; i < SMP_MB_CNT; i++) {
+ off = (i / 3) * 4;
+ s = (i % 3) * 8;
+ data = MDSS_MDP_REG_READ(MDSS_MDP_REG_SMP_ALLOC_W0 + off);
+ client_id = (data >> s) & 0xFF;
+ if (test_bit(i, mdata->mmb_alloc_map)) {
+ /*
+ * Certain pipes may have a dedicated set of
+ * SMP MMBs statically allocated to them. In
+ * such cases, we do not need to do anything
+ * here.
+ */
+ pr_debug("smp mmb %d already assigned to pipe %d (client_id %d)"
+ , i, pipe->num, client_id);
+ continue;
+ }
+
+ if (client_id) {
+ if (client_id != prev_id) {
+ pipe = mdss_mdp_pipe_search_by_client_id(mdata,
+ client_id);
+ prev_id = client_id;
+ }
+
+ if (!pipe) {
+ pr_warn("Invalid client id %d for SMP MMB %d\n",
+ client_id, i);
+ continue;
+ }
+
+ if (!pipe->is_handed_off) {
+ pr_warn("SMP MMB %d assigned to a pipe not marked for handoff (client id %d)"
+ , i, client_id);
+ continue;
+ }
+
+ /*
+ * Assume that the source format only has
+ * one plane
+ */
+ pr_debug("Assigning smp mmb %d to pipe %d (client_id %d)\n"
+ , i, pipe->num, client_id);
+ set_bit(i, pipe->smp_map[0].allocated);
+ set_bit(i, mdata->mmb_alloc_map);
+ }
+ }
+
+ return rc;
+}
+
void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe)
{
int tmp;
@@ -427,6 +526,29 @@
return pipe;
}
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
+ struct mdss_data_type *mdata, int client_id)
+{
+ u32 i;
+
+ for (i = 0; i < mdata->nrgb_pipes; i++) {
+ if (mdata->rgb_pipes[i].ftch_id == client_id)
+ return &mdata->rgb_pipes[i];
+ }
+
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ if (mdata->vig_pipes[i].ftch_id == client_id)
+ return &mdata->vig_pipes[i];
+ }
+
+ for (i = 0; i < mdata->ndma_pipes; i++) {
+ if (mdata->dma_pipes[i].ftch_id == client_id)
+ return &mdata->dma_pipes[i];
+ }
+
+ return NULL;
+}
+
struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
u32 ndx)
{
@@ -481,6 +603,67 @@
}
+/**
+ * mdss_mdp_pipe_handoff() - Handoff staged pipes during bootup
+ * @pipe: pointer to the pipe to be handed-off
+ *
+ * Populate the software structures for the pipe based on the current
+ * configuration of the hardware pipe by the reading the appropriate MDP
+ * registers.
+ *
+ * This function would typically be called during MDP probe for the case
+ * when certain pipes might be programmed in the bootloader to display
+ * the splash screen.
+ */
+int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+ u32 src_fmt, reg = 0, bpp = 0;
+
+ /*
+ * todo: for now, only reading pipe src and dest size details
+ * from the registers. This is needed for appropriately
+ * calculating perf metrics for the handed off pipes.
+ * We may need to parse some more details at a later date.
+ */
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_SRC_SIZE);
+ pipe->src.h = reg >> 16;
+ pipe->src.w = reg & 0xFFFF;
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_OUT_SIZE);
+ pipe->dst.h = reg >> 16;
+ pipe->dst.w = reg & 0xFFFF;
+
+ /* Assume that the source format is RGB */
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT);
+ bpp = ((reg >> 9) & 0x3) + 1;
+ switch (bpp) {
+ case 4:
+ src_fmt = MDP_RGBA_8888;
+ break;
+ case 3:
+ src_fmt = MDP_RGB_888;
+ break;
+ case 2:
+ src_fmt = MDP_RGB_565;
+ break;
+ default:
+ pr_err("Invalid bpp=%d found\n", bpp);
+ rc = -EINVAL;
+ goto error;
+ }
+ pipe->src_fmt = mdss_mdp_get_format_params(src_fmt);
+
+ pr_debug("Pipe settings: src.h=%d src.w=%d dst.h=%d dst.w=%d bpp=%d\n"
+ , pipe->src.h, pipe->src.w, pipe->dst.h, pipe->dst.w,
+ pipe->src_fmt->bpp);
+
+ pipe->is_handed_off = true;
+ atomic_inc(&pipe->ref_cnt);
+
+error:
+ return rc;
+}
+
void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
struct mdss_mdp_img_rect *dst_rect,
const struct mdss_mdp_img_rect *sci_rect)
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index e48e749..b31f6c1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -711,7 +711,7 @@
if (src_h <= pipe->dst.h) {
scale_config |= /* G/Y, A */
(filter_mode << 10) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+ (MDSS_MDP_SCALE_FILTER_BIL << 18);
} else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
@@ -730,7 +730,7 @@
if (src_h <= pipe->dst.h)
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_BIL << 10) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+ (MDSS_MDP_SCALE_FILTER_BIL << 18);
else
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
@@ -764,7 +764,7 @@
if (src_w <= pipe->dst.w) {
scale_config |= /* G/Y, A */
(filter_mode << 8) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+ (MDSS_MDP_SCALE_FILTER_BIL << 16);
} else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
@@ -783,7 +783,7 @@
if (src_w <= pipe->dst.w)
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_BIL << 8) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+ (MDSS_MDP_SCALE_FILTER_BIL << 16);
else
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 261679f..1d172f3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -276,17 +276,15 @@
mutex_lock(&rotator_lock);
ret = mdss_mdp_rotator_queue_helper(rot);
-
- if (ret) {
+ if (ret)
pr_err("rotator queue failed\n");
- mutex_unlock(&rotator_lock);
- return;
- }
- if (rot->rot_sync_pt_data)
+ if (rot->rot_sync_pt_data) {
+ atomic_inc(&rot->rot_sync_pt_data->commit_cnt);
mdss_fb_signal_timeline(rot->rot_sync_pt_data);
- else
+ } else {
pr_err("rot_sync_pt_data is NULL\n");
+ }
mutex_unlock(&rotator_lock);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index a9f3e35..58acb8e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -524,6 +524,7 @@
pr_err("unable to get writeback buf ctl=%d\n", ctl->num);
/* drop buffer but don't return error */
ret = 0;
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_DONE);
goto kickoff_fail;
}
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 326e8bf..cccf851 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -48,6 +48,12 @@
#define MAX_AF_ITERATIONS 3
+enum flash_type {
+ LED_FLASH = 1,
+ STROBE_FLASH,
+ GPIO_FLASH
+};
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
diff --git a/include/media/msm_media_info.h b/include/media/msm_media_info.h
index 65831db..ddf9c8e 100644
--- a/include/media/msm_media_info.h
+++ b/include/media/msm_media_info.h
@@ -6,7 +6,76 @@
#endif
enum color_fmts {
+ /* Venus NV12:
+ * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+ * by an interleaved U/V plane containing 8 bit 2x2 subsampled
+ * colour difference samples.
+ *
+ * <-------- Y/UV_Stride -------->
+ * <------- Width ------->
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X ^ ^
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X Height |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | Y_Scanlines
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X V |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * U V U V U V U V U V U V X X X X ^
+ * U V U V U V U V U V U V X X X X |
+ * U V U V U V U V U V U V X X X X |
+ * U V U V U V U V U V U V X X X X UV_Scanlines
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * X X X X X X X X X X X X X X X X --> Buffer size alignment
+ *
+ * Y_Stride : Width aligned to 128
+ * UV_Stride : Width aligned to 128
+ * Y_Scanlines: Height aligned to 32
+ * UV_Scanlines: Height/2 aligned to 16
+ * Total size = align((Y_Stride * Y_Scanlines
+ * + UV_Stride * UV_Scanlines + 4096), 4096)
+ */
COLOR_FMT_NV12,
+
+ /* Venus NV21:
+ * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+ * by an interleaved V/U plane containing 8 bit 2x2 subsampled
+ * colour difference samples.
+ *
+ * <-------- Y/UV_Stride -------->
+ * <------- Width ------->
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X ^ ^
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X Height |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | Y_Scanlines
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X V |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * V U V U V U V U V U V U X X X X ^
+ * V U V U V U V U V U V U X X X X |
+ * V U V U V U V U V U V U X X X X |
+ * V U V U V U V U V U V U X X X X UV_Scanlines
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * X X X X X X X X X X X X X X X X --> Padding & Buffer size alignment
+ *
+ * Y_Stride : Width aligned to 128
+ * UV_Stride : Width aligned to 128
+ * Y_Scanlines: Height aligned to 32
+ * UV_Scanlines: Height/2 aligned to 16
+ * Total size = align((Y_Stride * Y_Scanlines
+ * + UV_Stride * UV_Scanlines + 4096), 4096)
+ */
COLOR_FMT_NV21,
};
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 942d095..7707aa0 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -3311,12 +3311,61 @@
{ },
};
+#ifdef CONFIG_PM
+static int msm8x10_wcd_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct msm8x10_wcd_priv *priv = i2c_get_clientdata(client);
+ struct msm8x10_wcd *msm8x10;
+ int ret = 0;
+
+ if (client->addr == HELICON_CORE_0_I2C_ADDR) {
+ if (!priv || !priv->codec || !priv->codec->control_data) {
+ ret = -EINVAL;
+ dev_err(dev, "%s: Invalid client data\n", __func__);
+ goto rtn;
+ }
+ msm8x10 = priv->codec->control_data;
+ return wcd9xxx_core_res_resume(&msm8x10->wcd9xxx_res);
+ }
+rtn:
+ return 0;
+}
+
+static int msm8x10_wcd_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct msm8x10_wcd_priv *priv = i2c_get_clientdata(client);
+ struct msm8x10_wcd *msm8x10;
+ int ret = 0;
+
+ if (client->addr == HELICON_CORE_0_I2C_ADDR) {
+ if (!priv || !priv->codec || !priv->codec->control_data) {
+ ret = -EINVAL;
+ dev_err(dev, "%s: Invalid client data\n", __func__);
+ goto rtn;
+ }
+ msm8x10 = priv->codec->control_data;
+ return wcd9xxx_core_res_suspend(&msm8x10->wcd9xxx_res,
+ PMSG_SUSPEND);
+ }
+
+rtn:
+ return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(msm8x1_wcd_pm_ops, msm8x10_wcd_i2c_suspend,
+ msm8x10_wcd_i2c_resume);
+#endif
static struct i2c_driver msm8x10_wcd_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "msm8x10-wcd-i2c-core",
- .of_match_table = msm8x10_wcd_of_match
+ .of_match_table = msm8x10_wcd_of_match,
+#ifdef CONFIG_PM
+ .pm = &msm8x1_wcd_pm_ops,
+#endif
},
.id_table = msm8x10_wcd_id_table,
.probe = msm8x10_wcd_i2c_probe,