Merge "msm: camera: support simple led flash controlled by one gpio for SKUAB"
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/media/video/msm-camera-flash.txt b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
index d848baf..3b2c44c 100644
--- a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
@@ -10,6 +10,10 @@
- qcom,flash-type : Should contain type flash device
- 1 for LED flash
- 2 for strobe flash
+ - 3 for simple led flash controlled by one gpio
+ This is a low cost led used for camera flash, the led is driven by
+ system power, and use a transistor controlled by external pin to
+ gate its on/off state.
- qcom,flash-source : Should contain array of phandles to flash source nodes.
- pm8941_flash0 pm8941_flash1
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index adcf168..9468df5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1853,13 +1853,36 @@
config ENABLE_DMM
def_bool n
+choice
+ prompt "Virtual Memory Reclaim"
+ default NO_VM_RECLAIM
+ help
+ Select the method of reclaiming virtual memory
+
config DONT_MAP_HOLE_AFTER_MEMBANK0
- def_bool n
- depends on ENABLE_VMALLOC_SAVING=n
+ bool "Map around the largest hole"
+ help
+ Do not map the memory belonging to the largest hole
+ into the virtual space. This results in more lowmem.
+ If multiple holes are present, only the largest hole
+ in the first 256MB of memory is not mapped.
config ENABLE_VMALLOC_SAVING
- def_bool n
- depends on DONT_MAP_HOLE_AFTER_MEMBANK0=n
+ bool "Reclaim memory for each subsystem"
+ help
+ Enable this config to reclaim the virtual space belonging
+ to any subsystem which is expected to have a lifetime of
+ the entire system. This feature allows lowmem to be non-
+ contiguous.
+
+config NO_VM_RECLAIM
+ bool "Do not reclaim memory"
+ help
+ Do not reclaim any memory. This might result in less lowmem
+ and wasting virtual memory space which could otherwise be
+ reclaimed by using any of the other two config options.
+
+endchoice
config HOLES_IN_ZONE
def_bool n
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-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-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index 2fe6a34..08e9be5 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -13,6 +13,16 @@
/include/ "msm8610-qrd.dtsi"
&soc {
+ gpio-leds {
+ compatible = "gpio-leds";
+ status = "disabled";
+
+ gpio_flash: gpio-flash {
+ gpios = <&pm8110_gpios 1 0>;
+ label = "gpio-flash";
+ linux,default-trigger = "gpio_flash_trigger";
+ };
+ };
sound {
qcom,model = "msm8x10-skuab-snd-card";
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-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 9867ca6..e32afba 100644
--- a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
@@ -21,3 +21,26 @@
compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
qcom,board-id = <0x2000b 3>;
};
+
+&soc {
+ gpio-leds {
+ status = "ok";
+ };
+};
+
+&pm8110_gpios {
+ gpio@c000 { /* GPIO 1 */
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ };
+};
+
+&led_flash0 {
+ status = "ok";
+};
+
+&i2c {
+ qcom,camera@20 {
+ qcom,led-flash-src = <&led_flash0>;
+ };
+};
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/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
index b060abe..fc14455 100644
--- a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -11,6 +11,17 @@
* GNU General Public License for more details.
*/
+&soc {
+
+ led_flash0: qcom,camera-led-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-led-flash";
+ qcom,flash-type = <3>;
+ qcom,flash-source = <&gpio_flash>;
+ qcom,torch-source = <&gpio_flash>;
+ status = "disabled";
+ };
+};
&i2c {
qcom,camera@20 {
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/msm8974pro-pma8084-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
index 26fdebb..d5c1143 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
@@ -92,7 +92,7 @@
vdd-supply = <&pma8084_l20>;
vdd-io-supply = <&pma8084_s4>;
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000 384000000>;
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 384000000>;
qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
qcom,pad-pull-on = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
index c38c9e1..df00f8a 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
@@ -480,6 +480,7 @@
#size-cells = <1>;
ranges;
qcom,pfm-threshold = <76>;
+ qcom,use-phase-scaling-factor;
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
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..17c6ef9 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2831,6 +2831,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 +2869,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/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index c4f762d..beaf75d 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -105,6 +105,9 @@
"RIVA CNTL in_buf_1_size: %d\n"
"Modem DCI in_buf_1_size: %d\n"
"Modem DCI CMD in_buf_1_size: %d\n"
+ "Received Feature mask from Modem: %d\n"
+ "Received Feature mask from LPASS: %d\n"
+ "Received Feature mask from WCNSS: %d\n"
"logging_mode: %d\n"
"real_time_mode: %d\n",
(unsigned int)driver->smd_data[MODEM_DATA].ch,
@@ -171,6 +174,9 @@
(unsigned int)driver->smd_cntl[WCNSS_DATA].buf_in_1_size,
(unsigned int)driver->smd_dci[MODEM_DATA].buf_in_1_size,
(unsigned int)driver->smd_dci_cmd[MODEM_DATA].buf_in_1_size,
+ driver->rcvd_feature_mask[MODEM_DATA],
+ driver->rcvd_feature_mask[LPASS_DATA],
+ driver->rcvd_feature_mask[WCNSS_DATA],
driver->logging_mode,
driver->real_time_mode);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index e0a428d..9d9d89b 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -340,6 +340,7 @@
struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
struct diag_smd_info smd_cmd[NUM_SMD_CMD_CHANNELS];
struct diag_smd_info smd_dci_cmd[NUM_SMD_DCI_CMD_CHANNELS];
+ int rcvd_feature_mask[NUM_SMD_CONTROL_CHANNELS];
int separate_cmdrsp[NUM_SMD_CONTROL_CHANNELS];
unsigned char *usb_buf_out;
unsigned char *apps_rsp_buf;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c74ab99..1a7b2f8 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -203,11 +203,12 @@
* has registered to respond for polling
*/
return 1;
- else if (!(driver->smd_data[MODEM_DATA].ch) &&
- !(chk_apps_master()))
+ else if (!((driver->smd_data[MODEM_DATA].ch) &&
+ (driver->rcvd_feature_mask[MODEM_DATA])) &&
+ (chk_apps_master()))
/*
* If the apps processor is not the master and the modem
- * is not up
+ * is not up or we did not receive the feature masks from Modem
*/
return 1;
else
@@ -1170,6 +1171,18 @@
return 0;
}
+int diag_apps_responds()
+{
+ if (chk_apps_only()) {
+ if (driver->smd_data[MODEM_DATA].ch &&
+ driver->rcvd_feature_mask[MODEM_DATA]) {
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
int diag_process_apps_pkt(unsigned char *buf, int len)
{
uint16_t subsys_cmd_code;
@@ -1204,7 +1217,8 @@
pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
for (i = 0; i < diag_max_reg; i++) {
entry = driver->table[i];
- if (entry.process_id != NO_PROCESS) {
+ if (entry.process_id != NO_PROCESS &&
+ driver->rcvd_feature_mask[entry.client_id]) {
if (entry.cmd_code == cmd_code && entry.subsys_id ==
subsys_id && entry.cmd_code_lo <=
subsys_cmd_code &&
@@ -1250,8 +1264,7 @@
return diag_process_stm_cmd(buf);
}
/* Check for Apps Only & get event mask request */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only() &&
- *buf == 0x81) {
+ else if (diag_apps_responds() && *buf == 0x81) {
driver->apps_rsp_buf[0] = 0x81;
driver->apps_rsp_buf[1] = 0x0;
*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
@@ -1262,8 +1275,8 @@
return 0;
}
/* Get log ID range & Check for Apps Only */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x73) && *(int *)(buf+4) == 1) {
+ else if (diag_apps_responds() && (*buf == 0x73) &&
+ *(int *)(buf+4) == 1) {
driver->apps_rsp_buf[0] = 0x73;
*(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
@@ -1287,8 +1300,8 @@
return 0;
}
/* Respond to Get SSID Range request message */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
+ else if (diag_apps_responds() && (*buf == 0x7d) &&
+ (*(buf+1) == 0x1)) {
driver->apps_rsp_buf[0] = 0x7d;
driver->apps_rsp_buf[1] = 0x1;
driver->apps_rsp_buf[2] = 0x1;
@@ -1345,8 +1358,8 @@
return 0;
}
/* Check for Apps Only Respond to Get Subsys Build mask */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
+ else if (diag_apps_responds() && (*buf == 0x7d) &&
+ (*(buf+1) == 0x2)) {
ssid_first = *(uint16_t *)(buf + 2);
ssid_last = *(uint16_t *)(buf + 4);
ssid_range = 4 * (ssid_last - ssid_first + 1);
@@ -2444,6 +2457,7 @@
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
driver->separate_cmdrsp[i] = 0;
driver->peripheral_supports_stm[i] = DISABLE_STM;
+ driver->rcvd_feature_mask[i] = 0;
}
for (i = 0; i < NUM_STM_PROCESSORS; i++) {
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index c6e1273..1a4601a 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -53,6 +53,7 @@
void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
int diag_process_apps_pkt(unsigned char *buf, int len);
void diag_reset_smd_data(int queue);
+int diag_apps_responds(void);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index e0deef3..d784678 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -37,6 +37,9 @@
diag_clear_reg(smd_info->peripheral);
reg_dirty ^= smd_info->peripheral_mask;
+ /* Reset the feature mask flag */
+ driver->rcvd_feature_mask[smd_info->peripheral] = 0;
+
smd_info->notify_context = 0;
}
@@ -158,14 +161,21 @@
msg = buf+HDR_SIZ;
range = buf+HDR_SIZ+
sizeof(struct diag_ctrl_msg);
+ if (msg->count_entries == 0) {
+ pr_debug("diag: In %s, received reg tbl with no entries\n",
+ __func__);
+ buf = buf + HDR_SIZ + data_len;
+ continue;
+ }
pkt_params->count = msg->count_entries;
pkt_params->params = kzalloc(pkt_params->count *
sizeof(struct bindpkt_params), GFP_KERNEL);
- if (ZERO_OR_NULL_PTR(pkt_params->params)) {
- pr_alert("diag: In %s, Memory alloc fail\n",
- __func__);
- kfree(pkt_params);
- return flag;
+ if (!pkt_params->params) {
+ pr_alert("diag: In %s, Memory alloc fail for cmd_code: %d, subsys: %d\n",
+ __func__, msg->cmd_code,
+ msg->subsysid);
+ buf = buf + HDR_SIZ + data_len;
+ continue;
}
temp = pkt_params->params;
for (j = 0; j < pkt_params->count; j++) {
@@ -195,6 +205,8 @@
int feature_mask_len = *(int *)(buf+8);
if (feature_mask_len > 0) {
int periph = smd_info->peripheral;
+ driver->rcvd_feature_mask[smd_info->peripheral]
+ = 1;
feature_mask = *(uint8_t *)(buf+12);
if (periph == MODEM_DATA)
driver->log_on_demand_support =
@@ -262,31 +274,39 @@
{
int temp_real_time = MODE_REALTIME, i;
- /* If any of the process is voting for Real time, then Diag
- should be in real time mode irrespective of other clauses. If
- USB is connected, check what the memory device process is
- voting for. If it is voting for Non real time, the final mode
- should be Non real time, real time otherwise. If USB is
- disconncted and no process is voting for real time, the
- resultant mode should be Non Real Time.
- */
- if ((driver->proc_rt_vote_mask & driver->proc_active_mask) &&
- (driver->proc_active_mask != 0))
- temp_real_time = MODE_REALTIME;
- else if (driver->usb_connected)
+ if (driver->proc_active_mask == 0) {
+ /* There are no DCI or Memory Device processes. Diag should
+ * be in Real Time mode irrespective of USB connection
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (driver->proc_rt_vote_mask & driver->proc_active_mask) {
+ /* Atleast one process is alive and is voting for Real Time
+ * data - Diag should be in real time mode irrespective of USB
+ * connection.
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (driver->usb_connected) {
+ /* If USB is connected, check individual process. If Memory
+ * Device Mode is active, set the mode requested by Memory
+ * Device process. Set to realtime mode otherwise.
+ */
if ((driver->proc_rt_vote_mask & DIAG_PROC_MEMORY_DEVICE) == 0)
temp_real_time = MODE_NONREALTIME;
else
temp_real_time = MODE_REALTIME;
- else
+ } else {
+ /* We come here if USB is not connected and the active
+ * processes are voting for Non realtime mode.
+ */
temp_real_time = MODE_NONREALTIME;
+ }
if (temp_real_time != driver->real_time_mode) {
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
temp_real_time);
} else {
- pr_info("diag: did not update real time mode, already in the req mode %d",
+ pr_debug("diag: did not update real time mode, already in the req mode %d",
temp_real_time);
}
if (driver->real_time_update_busy > 0)
@@ -297,9 +317,15 @@
{
int temp_real_time = MODE_REALTIME, i;
- if (!(driver->proc_rt_vote_mask & driver->proc_active_mask) &&
- (driver->proc_active_mask != 0))
+ if (driver->proc_active_mask == 0) {
+ /* There are no DCI or Memory Device processes. Diag should
+ * be in Real Time mode.
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (!(driver->proc_rt_vote_mask & driver->proc_active_mask)) {
+ /* No active process is voting for real time mode */
temp_real_time = MODE_NONREALTIME;
+ }
if (temp_real_time != driver->real_time_mode) {
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 374170d..975a42f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1114,10 +1114,10 @@
#ifdef CONFIG_HOTPLUG_CPU
strncpy(per_cpu(cpufreq_policy_save, cpu).gov, data->governor->name,
CPUFREQ_NAME_LEN);
- per_cpu(cpufreq_policy_save, cpu).min = data->min;
- per_cpu(cpufreq_policy_save, cpu).max = data->max;
- pr_debug("Saving CPU%d policy min %d and max %d\n",
- cpu, data->min, data->max);
+ per_cpu(cpufreq_policy_save, cpu).min = data->user_policy.min;
+ per_cpu(cpufreq_policy_save, cpu).max = data->user_policy.max;
+ pr_debug("Saving CPU%d user policy min %d and max %d\n",
+ cpu, data->user_policy.min, data->user_policy.max);
#endif
/* if we have other CPUs still registered, we need to unlink them,
@@ -1143,9 +1143,11 @@
#ifdef CONFIG_HOTPLUG_CPU
strncpy(per_cpu(cpufreq_policy_save, j).gov,
data->governor->name, CPUFREQ_NAME_LEN);
- per_cpu(cpufreq_policy_save, j).min = data->min;
- per_cpu(cpufreq_policy_save, j).max = data->max;
- pr_debug("Saving CPU%d policy min %d and max %d\n",
+ per_cpu(cpufreq_policy_save, j).min
+ = data->user_policy.min;
+ per_cpu(cpufreq_policy_save, j).max
+ = data->user_policy.max;
+ pr_debug("Saving CPU%d user policy min %d and max %d\n",
j, data->min, data->max);
#endif
cpu_dev = get_cpu_device(j);
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/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index bf59d03..cf6c6e2 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -25,6 +25,7 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
#define WLED_IDAC_DLY_REG(base, n) (WLED_MOD_EN_REG(base, n) + 0x01)
@@ -103,6 +104,7 @@
#define FLASH_LED_TORCH(base) (base + 0xE4)
#define FLASH_FAULT_DETECT(base) (base + 0x51)
#define FLASH_PERIPHERAL_SUBTYPE(base) (base + 0x05)
+#define FLASH_CURRENT_RAMP(base) (base + 0x54)
#define FLASH_MAX_LEVEL 0x4F
#define TORCH_MAX_LEVEL 0x0F
@@ -121,6 +123,7 @@
#define FLASH_HW_VREG_OK 0x40
#define FLASH_VREG_MASK 0xC0
#define FLASH_STARTUP_DLY_MASK 0x02
+#define FLASH_CURRENT_RAMP_MASK 0xBF
#define FLASH_ENABLE_ALL 0xE0
#define FLASH_ENABLE_MODULE 0x80
@@ -131,6 +134,7 @@
#define FLASH_ENABLE_LED_1 0xA0
#define FLASH_INIT_MASK 0xE0
#define FLASH_SELFCHECK_ENABLE 0x80
+#define FLASH_RAMP_STEP_27US 0xBF
#define FLASH_STROBE_SW 0xC0
#define FLASH_STROBE_HW 0x04
@@ -155,6 +159,9 @@
#define FLASH_SUBTYPE_DUAL 0x01
#define FLASH_SUBTYPE_SINGLE 0x02
+#define FLASH_RAMP_UP_DELAY_US 1000
+#define FLASH_RAMP_DN_DELAY_US 2160
+
#define LED_TRIGGER_DEFAULT "none"
#define RGB_LED_SRC_SEL(base) (base + 0x45)
@@ -932,22 +939,6 @@
rc);
goto error_flash_set;
}
-
- /*
- * Write 0x80 to MODULE_ENABLE before writing
- * 0xE0 in order to avoid a hardware bug caused
- * by register value going from 0x00 to 0xE0.
- */
- rc = qpnp_led_masked_write(led,
- FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK,
- FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n",
- rc);
- return rc;
- }
}
rc = qpnp_led_masked_write(led,
@@ -1064,22 +1055,6 @@
goto error_flash_set;
}
- /*
- * Write 0x80 to MODULE_ENABLE before writing
- * 0xE0 in order to avoid a hardware bug caused
- * by register value going from 0x00 to 0xE0.
- */
- rc = qpnp_led_masked_write(led,
- FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK,
- FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n",
- rc);
- goto error_flash_set;
- }
-
rc = qpnp_led_masked_write(led,
led->flash_cfg->current_addr,
FLASH_CURRENT_MASK,
@@ -1100,6 +1075,11 @@
goto error_flash_set;
}
+ /*
+ * Add 1ms delay for bharger enter stable state
+ */
+ usleep(FLASH_RAMP_UP_DELAY_US);
+
if (!led->flash_cfg->strobe_type) {
rc = qpnp_led_masked_write(led,
FLASH_LED_STROBE_CTRL(led->base),
@@ -1180,6 +1160,12 @@
}
}
} else {
+ /*
+ * Disable module after ramp down complete for stable
+ * behavior
+ */
+ usleep(FLASH_RAMP_DN_DELAY_US);
+
rc = qpnp_led_masked_write(led,
FLASH_ENABLE_CONTROL(led->base),
led->flash_cfg->enable_module &
@@ -2260,7 +2246,7 @@
/* Disable flash LED module */
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK, FLASH_DISABLE_ALL);
+ FLASH_ENABLE_MASK, FLASH_DISABLE_ALL);
if (rc) {
dev_err(&led->spmi_dev->dev,
"Enable reg write failed(%d)\n", rc);
@@ -2329,6 +2315,15 @@
return rc;
}
+ /* Set current ramp */
+ rc = qpnp_led_masked_write(led, FLASH_CURRENT_RAMP(led->base),
+ FLASH_CURRENT_RAMP_MASK, FLASH_RAMP_STEP_27US);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current ramp reg write failed(%d)\n", rc);
+ return rc;
+ }
+
led->flash_cfg->strobe_type = 0;
/* dump flash registers */
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/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 81afd5c..468ba74 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -35,7 +35,7 @@
struct msm_vidc_drv *vidc_driver;
-uint32_t msm_vidc_pwr_collapse_delay = 2000;
+uint32_t msm_vidc_pwr_collapse_delay = 10000;
static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
{
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/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_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.h b/drivers/video/msm/mdss/mdss_mdp.h
index 7bf14e6..5d0ae43 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;
};
@@ -460,7 +465,15 @@
struct mdss_data_type *mdss_mdp_get_mdata(void);
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
+int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req,
+ struct mdss_mdp_format_params *fmt);
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
+int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
+ struct mdss_mdp_data *data,
+ struct msmfb_data *planes,
+ int num_planes,
+ u32 flags);
int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
u32 *offsets, u32 count);
int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
@@ -483,6 +496,11 @@
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);
struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer);
@@ -573,6 +591,7 @@
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
+int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);
void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index e50598f..8569311 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;
}
@@ -1870,6 +1871,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 +1901,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;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index e0717ad..1f2bb52 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 =
@@ -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..501220d 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) {
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 1584925..b18b68c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -92,9 +92,9 @@
return 0;
}
-static int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
- struct mdp_overlay *req,
- struct mdss_mdp_format_params *fmt)
+int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req,
+ struct mdss_mdp_format_params *fmt)
{
u32 xres, yres;
u32 min_src_size, min_dst_size;
@@ -250,84 +250,6 @@
return 0;
}
-static int mdss_mdp_overlay_rotator_setup(struct msm_fb_data_type *mfd,
- struct mdp_overlay *req)
-{
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdss_mdp_rotator_session *rot;
- struct mdss_mdp_format_params *fmt;
- int ret = 0;
- u32 bwc_enabled;
-
- pr_debug("rot ctl=%u req id=%x\n", mdp5_data->ctl->num, req->id);
-
- fmt = mdss_mdp_get_format_params(req->src.format);
- if (!fmt) {
- pr_err("invalid rot format %d\n", req->src.format);
- return -EINVAL;
- }
-
- ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
- if (ret)
- return ret;
-
- if (req->id == MSMFB_NEW_REQUEST) {
- rot = mdss_mdp_rotator_session_alloc();
- rot->pid = current->tgid;
- list_add(&rot->list, &mdp5_data->rot_proc_list);
-
- if (!rot) {
- pr_err("unable to allocate rotator session\n");
- return -ENOMEM;
- }
- } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
- rot = mdss_mdp_rotator_session_get(req->id);
-
- if (!rot) {
- pr_err("rotator session=%x not found\n", req->id);
- return -ENODEV;
- }
- } else {
- pr_err("invalid rotator session id=%x\n", req->id);
- return -EINVAL;
- }
-
- /* keep only flags of interest to rotator */
- rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
- MDP_SECURE_OVERLAY_SESSION);
-
- bwc_enabled = req->flags & MDP_BWC_EN;
- if (bwc_enabled && !mdp5_data->mdata->has_bwc) {
- pr_err("BWC is not supported in MDP version %x\n",
- mdp5_data->mdata->mdp_rev);
- rot->bwc_mode = 0;
- } else {
- rot->bwc_mode = bwc_enabled ? 1 : 0;
- }
- rot->format = fmt->format;
- rot->img_width = req->src.width;
- rot->img_height = req->src.height;
- rot->src_rect.x = req->src_rect.x;
- rot->src_rect.y = req->src_rect.y;
- rot->src_rect.w = req->src_rect.w;
- rot->src_rect.h = req->src_rect.h;
-
- if (req->flags & MDP_DEINTERLACE) {
- rot->flags |= MDP_DEINTERLACE;
- rot->src_rect.h /= 2;
- }
-
- ret = mdss_mdp_rotator_setup(rot);
- if (ret == 0) {
- req->id = rot->session_id;
- } else {
- pr_err("Unable to setup rotator session\n");
- mdss_mdp_rotator_release(rot);
- }
-
- return ret;
-}
-
static int __mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe)
{
struct mdss_data_type *mdata = pipe->mixer->ctl->mdata;
@@ -670,7 +592,7 @@
}
if (req->flags & MDSS_MDP_ROT_ONLY) {
- ret = mdss_mdp_overlay_rotator_setup(mfd, req);
+ ret = mdss_mdp_rotator_setup(mfd, req);
} else if (req->src.format == MDP_RGB_BORDERFILL) {
req->id = BORDERFILL_NDX;
} else {
@@ -689,7 +611,7 @@
return ret;
}
-static inline int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
+int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
struct mdss_mdp_data *data,
struct msmfb_data *planes,
int num_planes,
@@ -719,7 +641,7 @@
return rc;
}
-static inline int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
+int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
{
int i;
for (i = 0; i < data->num_planes && data->p[i].len; i++)
@@ -830,6 +752,9 @@
rc = mdss_mdp_ctl_start(mdp5_data->ctl);
if (rc == 0) {
atomic_inc(&ov_active_panels);
+
+ mdss_mdp_ctl_notifier_register(mdp5_data->ctl,
+ &mfd->mdp_sync_pt_data.notifier);
} else {
pr_err("overlay start failed.\n");
mdss_mdp_ctl_destroy(mdp5_data->ctl);
@@ -861,7 +786,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)
@@ -870,14 +795,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
*/
@@ -897,6 +814,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);
@@ -991,6 +911,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)
@@ -1062,17 +984,7 @@
pr_debug("unset ndx=%x\n", ndx);
if (ndx & MDSS_MDP_ROT_SESSION_MASK) {
- struct mdss_mdp_rotator_session *rot;
- rot = mdss_mdp_rotator_session_get(ndx);
- if (rot) {
- mdss_mdp_overlay_free_buf(&rot->src_buf);
- mdss_mdp_overlay_free_buf(&rot->dst_buf);
-
- rot->pid = 0;
- if (!list_empty(&rot->list))
- list_del_init(&rot->list);
- ret = mdss_mdp_rotator_release(rot);
- }
+ ret = mdss_mdp_rotator_unset(ndx);
} else {
ret = mdss_mdp_overlay_release(mfd, ndx);
}
@@ -1153,50 +1065,6 @@
return ret;
}
-static int mdss_mdp_overlay_rotate(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_data *req)
-{
- struct mdss_mdp_rotator_session *rot;
- int ret;
- u32 flgs;
-
- rot = mdss_mdp_rotator_session_get(req->id);
- if (!rot) {
- pr_err("invalid session id=%x\n", req->id);
- return -ENOENT;
- }
-
- flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;
-
- ret = mdss_mdp_rotator_busy_wait_ex(rot);
- if (ret) {
- pr_err("rotator busy wait error\n");
- return ret;
- }
-
- mdss_mdp_overlay_free_buf(&rot->src_buf);
- ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
- if (ret) {
- pr_err("src_data pmem error\n");
- return ret;
- }
-
- mdss_mdp_overlay_free_buf(&rot->dst_buf);
- ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
- &req->dst_data, 1, flgs);
- if (ret) {
- pr_err("dst_data pmem error\n");
- goto dst_buf_fail;
- }
-
- ret = mdss_mdp_rotator_queue(rot);
- if (ret)
- pr_err("rotator queue error session id=%x\n", req->id);
-
-dst_buf_fail:
- return ret;
-}
-
static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
@@ -1292,7 +1160,7 @@
if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
mdss_mdp_overlay_force_dma_cleanup(mfd_to_mdata(mfd));
- ret = mdss_mdp_overlay_rotate(mfd, req);
+ ret = mdss_mdp_rotator_play(mfd, req);
} else if (req->id == BORDERFILL_NDX) {
pr_debug("borderfill enable\n");
mdp5_data->borderfill_enable = true;
@@ -2230,7 +2098,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));
@@ -2364,6 +2231,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;
@@ -2461,6 +2330,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);
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 44734f8..1d172f3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -37,12 +37,11 @@
static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
struct mdss_mdp_rotator_session *rot);
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
+static struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
{
struct mdss_mdp_rotator_session *rot;
int i;
- mutex_lock(&rotator_lock);
for (i = 0; i < MAX_ROTATOR_SESSIONS; i++) {
rot = &rotator_session[i];
if (rot->ref_cnt == 0) {
@@ -52,16 +51,15 @@
break;
}
}
- mutex_unlock(&rotator_lock);
if (i == MAX_ROTATOR_SESSIONS) {
pr_err("max rotator sessions reached\n");
return NULL;
}
-
return rot;
}
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id)
+static inline struct mdss_mdp_rotator_session
+*mdss_mdp_rotator_session_get(u32 session_id)
{
struct mdss_mdp_rotator_session *rot;
u32 ndx;
@@ -113,16 +111,15 @@
static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot)
{
- struct mdss_mdp_pipe *rot_pipe = NULL;
- struct mdss_mdp_ctl *ctl = NULL;
- rot_pipe = rot->pipe;
- if (!rot_pipe)
- return -ENODEV;
-
- ctl = rot_pipe->mixer->ctl;
mutex_lock(&rot->lock);
+ if (!rot->pipe || !rot->pipe->mixer || !rot->pipe->mixer->ctl) {
+ mutex_unlock(&rot->lock);
+ return -ENODEV;
+ }
+
if (rot->busy) {
+ struct mdss_mdp_ctl *ctl = rot->pipe->mixer->ctl;
mdss_mdp_display_wait4comp(ctl);
rot->busy = false;
if (ctl->shared_lock)
@@ -276,17 +273,20 @@
int ret;
rot = container_of(work, struct mdss_mdp_rotator_session, commit_work);
- ret = mdss_mdp_rotator_queue_helper(rot);
- if (ret) {
+ mutex_lock(&rotator_lock);
+ ret = mdss_mdp_rotator_queue_helper(rot);
+ if (ret)
pr_err("rotator queue failed\n");
- return;
+
+ 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 {
+ pr_err("rot_sync_pt_data is NULL\n");
}
- if (rot->rot_sync_pt_data)
- mdss_fb_signal_timeline(rot->rot_sync_pt_data);
- else
- pr_err("rot_sync_pt_data is NULL\n");
+ mutex_unlock(&rotator_lock);
}
static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
@@ -318,7 +318,7 @@
return sync_pt_data;
}
-int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot)
+static int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot)
{
struct mdss_mdp_rotator_session *tmp;
@@ -337,20 +337,12 @@
int ret;
struct mdss_mdp_rotator_session *tmp;
- ret = mutex_lock_interruptible(&rotator_lock);
- if (ret) {
- pr_err("mutex lock on rotator_lock failed\n");
- return ret;
- }
-
pr_debug("rotator session=%x start\n", rot->session_id);
for (ret = 0, tmp = rot; ret == 0 && tmp; tmp = tmp->next)
ret = mdss_mdp_rotator_queue_sub(tmp,
&rot->src_buf, &rot->dst_buf);
- mutex_unlock(&rotator_lock);
-
if (ret) {
pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id);
return ret;
@@ -362,7 +354,7 @@
return ret;
}
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
+static int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
{
int ret = 0;
@@ -376,10 +368,80 @@
return ret;
}
-int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)
+int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_rotator_session *rot = NULL;
+ struct mdss_mdp_format_params *fmt;
+ u32 bwc_enabled;
+ int ret = 0;
+
+ mutex_lock(&rotator_lock);
+
+ fmt = mdss_mdp_get_format_params(req->src.format);
+ if (!fmt) {
+ pr_err("invalid rot format %d\n", req->src.format);
+ ret = -EINVAL;
+ goto rot_err;
+ }
+
+ ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
+ if (ret)
+ goto rot_err;
+
+ if (req->id == MSMFB_NEW_REQUEST) {
+ rot = mdss_mdp_rotator_session_alloc();
+ rot->pid = current->tgid;
+ list_add(&rot->list, &mdp5_data->rot_proc_list);
+
+ if (!rot) {
+ pr_err("unable to allocate rotator session\n");
+ ret = -ENOMEM;
+ goto rot_err;
+ }
+ } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
+ rot = mdss_mdp_rotator_session_get(req->id);
+
+ if (!rot) {
+ pr_err("rotator session=%x not found\n", req->id);
+ ret = -ENODEV;
+ goto rot_err;
+ }
+ } else {
+ pr_err("invalid rotator session id=%x\n", req->id);
+ ret = -EINVAL;
+ goto rot_err;
+ }
+
+ /* keep only flags of interest to rotator */
+ rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
+ MDP_SECURE_OVERLAY_SESSION);
+
+ bwc_enabled = req->flags & MDP_BWC_EN;
+ if (bwc_enabled && !mdp5_data->mdata->has_bwc) {
+ pr_err("BWC is not supported in MDP version %x\n",
+ mdp5_data->mdata->mdp_rev);
+ rot->bwc_mode = 0;
+ } else {
+ rot->bwc_mode = bwc_enabled ? 1 : 0;
+ }
+ rot->format = fmt->format;
+ rot->img_width = req->src.width;
+ rot->img_height = req->src.height;
+ rot->src_rect.x = req->src_rect.x;
+ rot->src_rect.y = req->src_rect.y;
+ rot->src_rect.w = req->src_rect.w;
+ rot->src_rect.h = req->src_rect.h;
+
+ if (req->flags & MDP_DEINTERLACE) {
+ rot->flags |= MDP_DEINTERLACE;
+ rot->src_rect.h /= 2;
+ rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2);
+ }
rot->dst = rot->src_rect;
+
/*
* by default, rotator output should be placed directly on
* output buffer address without any offset.
@@ -396,7 +458,8 @@
if (rot->bwc_mode) {
pr_err("Unable to do split rotation with bwc set\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto rot_err;
}
width = rot->src_rect.w;
@@ -406,14 +469,16 @@
if (width > (MAX_MIXER_WIDTH * 2)) {
pr_err("unsupported source width %d\n", width);
- return -EOVERFLOW;
+ ret = -EOVERFLOW;
+ goto rot_err;
}
if (!rot->next) {
tmp = mdss_mdp_rotator_session_alloc();
if (!tmp) {
pr_err("unable to allocate rot dual session\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto rot_err;
}
rot->next = tmp;
}
@@ -461,7 +526,16 @@
rot->params_changed++;
- return 0;
+ req->id = rot->session_id;
+
+ rot_err:
+ mutex_unlock(&rotator_lock);
+ if (ret) {
+ pr_err("Unable to setup rotator session\n");
+ if (rot)
+ mdss_mdp_rotator_release(rot);
+ }
+ return ret;
}
static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
@@ -537,3 +611,70 @@
return 0;
}
+
+int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req)
+{
+ struct mdss_mdp_rotator_session *rot;
+ int ret;
+ u32 flgs;
+
+ mutex_lock(&rotator_lock);
+ rot = mdss_mdp_rotator_session_get(req->id);
+ if (!rot) {
+ pr_err("invalid session id=%x\n", req->id);
+ ret = -ENOENT;
+ goto dst_buf_fail;
+ }
+
+ flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;
+
+ ret = mdss_mdp_rotator_busy_wait_ex(rot);
+ if (ret) {
+ pr_err("rotator busy wait error\n");
+ goto dst_buf_fail;
+ }
+
+ mdss_mdp_overlay_free_buf(&rot->src_buf);
+ ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
+ if (ret) {
+ pr_err("src_data pmem error\n");
+ goto dst_buf_fail;
+ }
+
+ mdss_mdp_overlay_free_buf(&rot->dst_buf);
+ ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
+ &req->dst_data, 1, flgs);
+ if (ret) {
+ pr_err("dst_data pmem error\n");
+ goto dst_buf_fail;
+ }
+
+ ret = mdss_mdp_rotator_queue(rot);
+
+ if (ret)
+ pr_err("rotator queue error session id=%x\n", req->id);
+
+dst_buf_fail:
+ mutex_unlock(&rotator_lock);
+ return ret;
+}
+
+int mdss_mdp_rotator_unset(int ndx)
+{
+ struct mdss_mdp_rotator_session *rot;
+ int ret = 0;
+ mutex_lock(&rotator_lock);
+ rot = mdss_mdp_rotator_session_get(ndx);
+ if (rot) {
+ mdss_mdp_overlay_free_buf(&rot->src_buf);
+ mdss_mdp_overlay_free_buf(&rot->dst_buf);
+
+ rot->pid = 0;
+ if (!list_empty(&rot->list))
+ list_del_init(&rot->list);
+ ret = mdss_mdp_rotator_finish(rot);
+ }
+ mutex_unlock(&rotator_lock);
+ return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index ab7cce1..7229995 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -75,14 +75,13 @@
}
}
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
-
-int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot);
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot);
+int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req);
int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_release_all(void);
-int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot);
struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get(
struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync);
+int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req);
+int mdss_mdp_rotator_unset(int ndx);
#endif /* MDSS_MDP_ROTATOR_H */
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_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/lib/klist.c b/lib/klist.c
index 0874e41..358a368 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -193,10 +193,10 @@
if (waiter->node != n)
continue;
+ list_del(&waiter->list);
waiter->woken = 1;
mb();
wake_up_process(waiter->process);
- list_del(&waiter->list);
}
spin_unlock(&klist_remove_lock);
knode_set_klist(n, NULL);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
old mode 100644
new mode 100755
index e9a0ac8..b96094c
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2187,10 +2187,15 @@
* However if a driver requested this specific regulatory
* domain we keep it for its private use
*/
- if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
+ const struct ieee80211_regdomain *tmp;
+
+ tmp = request_wiphy->regd;
request_wiphy->regd = rd;
- else
+ kfree(tmp);
+ } else {
kfree(rd);
+ }
rd = NULL;
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,