Merge "mdss: display: add dynamic mdp clock control for smart panel"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 4f31f07..a221433 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -68,8 +68,30 @@
- qcom,default-state: default state of the led, should be "on" or "off"
- qcom,turn-off-delay-ms: delay in millisecond for turning off the led when its default-state is "on". Value is being ignored in case default-state is "off".
+MPP LED is an LED controled through a Multi Purpose Pin.
+
+Optional properties for MPP LED:
+- linux,default-trigger: trigger the led from external modules such as display
+- qcom,default-state: default state of the led, should be "on" or "off"
+- qcom,source-sel: select power source, default 1 (enabled)
+- qcom,mode-ctrl: select operation mode, default 0x60 = Mode Sink
+
Example:
+ qcom,leds@a200 {
+ status = "okay";
+ qcom,led_mpp_3 {
+ label = "mpp";
+ linux,name = "wled-backlight";
+ linux-default-trigger = "none";
+ qcom,default-state = "on";
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x10>;
+ };
+ };
+
qcom,leds@d000 {
status = "okay";
qcom,rgb_pwm {
@@ -151,3 +173,4 @@
linux,name = "led:wled_backlight";
};
};
+
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
index 2116888..041928d 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
@@ -16,12 +16,17 @@
the spmi-slave-container property
Optional properties:
+- interrupts: List of interrupts used by the regulator.
+- interrupt-names: List of strings defining the names of the
+ interrupts in the 'interrupts' property 1-to-1.
+ Supported values are "ocp" for voltage switch
+ type regulators. If an OCP interrupt is
+ specified, then the voltage switch will be
+ toggled off and back on when OCP triggers in
+ order to handle high in-rush current.
- qcom,system-load: Load in uA present on regulator that is not
captured by any consumer request
- qcom,enable-time: Time in us to delay after enabling the regulator
-- qcom,ocp-enable-time: Time to delay in us between enabling a switch and
- subsequently enabling over current protection
- (OCP) for the switch
- qcom,auto-mode-enable: 1 = Enable automatic hardware selection of
regulator mode (HPM vs LPM); not available on
boost type regulators
@@ -30,11 +35,18 @@
so that it acts like a switch and simply outputs
its input voltage
0 = Do not enable bypass mode
-- qcom,ocp-enable: 1 = Enable over current protection (OCP) for
- voltage switch type regulators so that they
- latch off automatically when over current is
- detected
+- qcom,ocp-enable: 1 = Allow over current protection (OCP) to be
+ enabled for voltage switch type regulators so
+ that they latch off automatically when over
+ current is detected. OCP is enabled when in
+ HPM or auto mode.
0 = Disable OCP
+- qcom,ocp-max-retries: Maximum number of times to try toggling a voltage
+ switch off and back on as a result of
+ consecutive over current events.
+- qcom,ocp-retry-delay: Time to delay in milliseconds between each
+ voltage switch toggle after an over current
+ event takes place.
- qcom,pull-down-enable: 1 = Enable output pull down resistor when the
regulator is disabled
0 = Disable pull down resistor
@@ -76,6 +88,16 @@
1 = 0.25 uA
2 = 0.55 uA
3 = 0.75 uA
+- qcom,hpm-enable: 1 = Enable high power mode (HPM), also referred
+ to as NPM. HPM consumes more ground current
+ than LPM, but it can source significantly higher
+ load current. HPM is not available on boost
+ type regulators. For voltage switch type
+ regulators, HPM implies that over current
+ protection and soft start are active all the
+ time. This configuration can be overwritten
+ by changing the regulator's mode dynamically.
+ 0 = Do not enable HPM
- qcom,force-type: Override the type and subtype register values. Useful for some
regulators that have invalid types advertised by the hardware.
The format is two unsigned integers of the form <type subtype>.
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 9ebfb56..fe4cada 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -197,6 +197,12 @@
interrupts = <0x0 0x61 0x1>;
};
};
+
+ qcom,leds@a200 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa200 0x100>;
+ label = "mpp";
+ };
};
qcom,pm8110@1 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index e4700a1..19d451b 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -33,7 +33,7 @@
compatible = "synaptics,rmi4";
reg = <0x20>;
interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2>;
+ interrupts = <17 0x2008>;
vdd-supply = <&pm8226_l19>;
vcc_i2c-supply = <&pm8226_lvs1>;
synaptics,reset-gpio = <&msmgpio 16 0x00>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 478d064..156c72d 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -33,7 +33,7 @@
compatible = "synaptics,rmi4";
reg = <0x20>;
interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2>;
+ interrupts = <17 0x2008>;
vdd-supply = <&pm8226_l19>;
vcc_i2c-supply = <&pm8226_lvs1>;
synaptics,reset-gpio = <&msmgpio 16 0x00>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index ecb3b5a..64cc869 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -33,7 +33,7 @@
compatible = "synaptics,rmi4";
reg = <0x20>;
interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2>;
+ interrupts = <17 0x2008>;
vdd-supply = <&pm8226_l19>;
vcc_i2c-supply = <&pm8226_lvs1>;
synaptics,reset-gpio = <&msmgpio 16 0x00>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 533ad53..a8a2446 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -24,6 +24,24 @@
};
};
+&spmi_bus {
+ qcom,pm8110@0 {
+ qcom,leds@a200 {
+ status = "okay";
+ qcom,led_mpp_3 {
+ label = "mpp";
+ linux,name = "wled-backlight";
+ linux-default-trigger = "none";
+ qcom,default-state = "on";
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x10>;
+ };
+ };
+ };
+};
+
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
qcom,vdd-always-on;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index c906e89..b1511ff 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -24,6 +24,24 @@
};
};
+&spmi_bus {
+ qcom,pm8110@0 {
+ qcom,leds@a200 {
+ status = "okay";
+ qcom,led_mpp_3 {
+ label = "mpp";
+ linux,name = "wled-backlight";
+ linux-default-trigger = "none";
+ qcom,default-state = "on";
+ qcom,max-current = <40>;
+ qcom,id = <6>;
+ qcom,source-sel = <1>;
+ qcom,mode-ctrl = <0x10>;
+ };
+ };
+ };
+};
+
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
qcom,vdd-always-on;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index ad8b24b..b6a4315 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -700,6 +700,12 @@
<55 512 3936000 393600>;
};
+ qcom,msm-rng@f9bff000 {
+ compatible = "qcom,msm-rng";
+ reg = <0xf9bff000 0x200>;
+ qcom,msm-rng-iface-clk;
+ };
+
jtag_mm0: jtagmm@fc34c000 {
compatible = "qcom,jtag-mm";
reg = <0xfc34c000 0x1000>,
@@ -727,6 +733,11 @@
<0xfc346000 0x1000>;
reg-names = "etm-base","debug-base";
};
+
+ qcom,tz-log@fe805720 {
+ compatible = "qcom,tz-log";
+ reg = <0x0fe805720 0x1000>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index bb4b48e..3e0ef04 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -1349,30 +1349,18 @@
qcom,hw-sel = "NoC";
};
- mas-video-p0-ocmem {
+ mas-video-ocmem {
cell-id = <68>;
- label = "mas-video-p0-ocmem";
- qcom,masterp = <3>;
+ label = "mas-video-ocmem";
+ qcom,masterp = <3 4>;
qcom,tier = <2>;
qcom,perm-mode = "Fixed";
qcom,mode = "Fixed";
- qcom,qport = <2>;
+ qcom,qport = <2 3>;
qcom,mas-hw-id = <15>;
qcom,hw-sel = "NoC";
};
- mas-video-p1-ocmem {
- cell-id = <69>;
- label = "mas-video-p1-ocmem";
- qcom,masterp = <4>;
- qcom,tier = <2>;
- qcom,perm-mode = "Fixed";
- qcom,mode = "Fixed";
- qcom,qport = <3>;
- qcom,mas-hw-id = <16>;
- qcom,hw-sel = "NoC";
- };
-
mas-vfe-ocmem {
cell-id = <70>;
label = "mas-vfe-ocmem";
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 05451671..0be3756 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -26,15 +26,33 @@
pm8941_mvs1: regulator@8300 {
parent-supply = <&pm8941_boost>;
- qcom,enable-time = <200>;
+ qcom,enable-time = <1000>;
qcom,pull-down-enable = <1>;
+ interrupts = <0x1 0x83 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
status = "okay";
};
pm8941_mvs2: regulator@8400 {
parent-supply = <&pm8941_boost>;
- qcom,enable-time = <200>;
+ qcom,enable-time = <1000>;
qcom,pull-down-enable = <1>;
+ interrupts = <0x1 0x84 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index ec6b14a..f9c0920 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -142,7 +142,7 @@
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <5>; /* Super Turbo */
+ qcom,init-value = <6>; /* Super Turbo */
};
qcom,lpm-resources@1 {
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 41837c1..5a1c047 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -142,7 +142,7 @@
qcom,type = <0x62706d73>; /* "smpb" */
qcom,id = <0x02>;
qcom,key = <0x6e726f63>; /* "corn" */
- qcom,init-value = <5>; /* Super Turbo */
+ qcom,init-value = <6>; /* Super Turbo */
};
qcom,lpm-resources@1 {
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-cdp.dtsi
similarity index 79%
rename from arch/arm/boot/dts/msm9625-v2-1-cdp.dts
rename to arch/arm/boot/dts/msm9625-cdp.dtsi
index da07100..1f9cbb0 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-cdp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,17 +10,10 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm9625-v2-1.dtsi"
+/include/ "msm9625-display.dtsi"
+/include/ "qpic-panel-ili-qvga.dtsi"
/ {
- model = "Qualcomm MSM 9625V2.1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
- qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
- <150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
- <173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
-
i2c@f9925000 {
charger@57 {
compatible = "summit,smb137c";
@@ -42,10 +35,18 @@
wlan0: qca,wlan {
cell-index = <0>;
- compatible = "qca,ar6004-sdio";
+ compatible = "qca,ar6004-hsic";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-mtp.dtsi
similarity index 73%
copy from arch/arm/boot/dts/msm9625-v2-1-cdp.dts
copy to arch/arm/boot/dts/msm9625-mtp.dtsi
index da07100..cc0bf5e 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,17 +10,7 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm9625-v2-1.dtsi"
-
/ {
- model = "Qualcomm MSM 9625V2.1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
- qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
- <150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
- <173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
-
i2c@f9925000 {
charger@57 {
compatible = "summit,smb137c";
@@ -42,10 +32,18 @@
wlan0: qca,wlan {
cell-index = <0>;
- compatible = "qca,ar6004-sdio";
+ compatible = "qca,ar6004-hsic";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
@@ -89,11 +87,23 @@
};
mpp@a300 { /* MPP 4 */
+ /* VADC channel 19 */
+ qcom,mode = <4>;
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
mpp@a400 { /* MPP 5 */
};
mpp@a500 { /* MPP 6 */
+ /* channel 21 */
+ qcom,mode = <4>;
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index cf17c69..d7537eb 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm9625-v1.dtsi"
+/include/ "msm9625-cdp.dtsi"
/ {
model = "Qualcomm MSM 9625V1 CDP";
@@ -20,88 +21,4 @@
qcom,msm-id = <134 1 0>, <152 1 0>, <149 1 0>, <150 1 0>,
<151 1 0>, <148 1 0>, <173 1 0>, <174 1 0>,
<175 1 0>;
-
- i2c@f9925000 {
- charger@57 {
- compatible = "summit,smb137c";
- reg = <0x57>;
- summit,chg-current-ma = <1500>;
- summit,term-current-ma = <50>;
- summit,pre-chg-current-ma = <100>;
- summit,float-voltage-mv = <4200>;
- summit,thresh-voltage-mv = <3000>;
- summit,recharge-thresh-mv = <75>;
- summit,system-voltage-mv = <4250>;
- summit,charging-timeout = <382>;
- summit,pre-charge-timeout = <48>;
- summit,therm-current-ua = <10>;
- summit,temperature-min = <4>; /* 0 C */
- summit,temperature-max = <3>; /* 45 C */
- };
- };
-
- wlan0: qca,wlan {
- cell-index = <0>;
- compatible = "qca,ar6004-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-
- qca,wlan_ar6003 {
- cell-index = <0>;
- compatible = "qca,ar6003-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-};
-
-/* PM8019 GPIO and MPP configuration */
-&pm8019_gpios {
- gpio@c000 { /* GPIO 1 */
- };
-
- gpio@c100 { /* GPIO 2 */
- };
-
- gpio@c200 { /* GPIO 3 */
- };
-
- gpio@c300 { /* GPIO 4 */
- /* ext_2p95v regulator enable config */
- qcom,mode = <1>; /* Digital output */
- qcom,output-type = <0>; /* CMOS */
- qcom,invert = <0>; /* Output low */
- qcom,out-strength = <1>; /* Low */
- qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-sel = <0>; /* Constant */
- qcom,master-en = <1>; /* Enable GPIO */
- };
-
- gpio@c400 { /* GPIO 5 */
- };
-
- gpio@c500 { /* GPIO 6 */
- };
-};
-
-&pm8019_mpps {
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- };
-
- mpp@a200 { /* MPP 3 */
- };
-
- mpp@a300 { /* MPP 4 */
- };
-
- mpp@a400 { /* MPP 5 */
- };
-
- mpp@a500 { /* MPP 6 */
- };
};
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index 24aa3af..a70ec1a 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm9625-v1.dtsi"
+/include/ "msm9625-mtp.dtsi"
/ {
model = "Qualcomm MSM 9625V1 MTP";
@@ -20,100 +21,4 @@
qcom,msm-id = <134 7 0>, <152 7 0>, <149 7 0>, <150 7 0>,
<151 7 0>, <148 7 0>, <173 7 0>, <174 7 0>,
<175 7 0>;
-
- i2c@f9925000 {
- charger@57 {
- compatible = "summit,smb137c";
- reg = <0x57>;
- summit,chg-current-ma = <1500>;
- summit,term-current-ma = <50>;
- summit,pre-chg-current-ma = <100>;
- summit,float-voltage-mv = <4200>;
- summit,thresh-voltage-mv = <3000>;
- summit,recharge-thresh-mv = <75>;
- summit,system-voltage-mv = <4250>;
- summit,charging-timeout = <382>;
- summit,pre-charge-timeout = <48>;
- summit,therm-current-ua = <10>;
- summit,temperature-min = <4>; /* 0 C */
- summit,temperature-max = <3>; /* 45 C */
- };
- };
-
- wlan0: qca,wlan {
- cell-index = <0>;
- compatible = "qca,ar6004-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-
- qca,wlan_ar6003 {
- cell-index = <0>;
- compatible = "qca,ar6003-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-};
-
-/* PM8019 GPIO and MPP configuration */
-&pm8019_gpios {
- gpio@c000 { /* GPIO 1 */
- };
-
- gpio@c100 { /* GPIO 2 */
- };
-
- gpio@c200 { /* GPIO 3 */
- };
-
- gpio@c300 { /* GPIO 4 */
- /* ext_2p95v regulator enable config */
- qcom,mode = <1>; /* Digital output */
- qcom,output-type = <0>; /* CMOS */
- qcom,invert = <0>; /* Output low */
- qcom,out-strength = <1>; /* Low */
- qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-sel = <0>; /* Constant */
- qcom,master-en = <1>; /* Enable GPIO */
- };
-
- gpio@c400 { /* GPIO 5 */
- };
-
- gpio@c500 { /* GPIO 6 */
- };
-};
-
-&pm8019_mpps {
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- };
-
- mpp@a200 { /* MPP 3 */
- };
-
- mpp@a300 { /* MPP 4 */
- /* VADC channel 19 */
- qcom,mode = <4>;
- qcom,ain-route = <3>; /* AMUX 8 */
- qcom,master-en = <1>;
- qcom,src-sel = <0>; /* Function constant */
- qcom,invert = <1>;
- };
-
- mpp@a400 { /* MPP 5 */
- };
-
- mpp@a500 { /* MPP 6 */
- /* VADC channel 21 */
- qcom,mode = <4>;
- qcom,ain-route = <1>; /* AMUX 6 */
- qcom,master-en = <1>;
- qcom,src-sel = <0>; /* Function constant */
- qcom,invert = <1>;
- };
};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
deleted file mode 100644
index 1e0f3c0..0000000
--- a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/dts-v1/;
-
-/include/ "msm9625-v2-1.dtsi"
-
-/ {
- model = "Qualcomm MSM 9625V2.1 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
- qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
- <150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
- <173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
-
- i2c@f9925000 {
- charger@57 {
- compatible = "summit,smb137c";
- reg = <0x57>;
- summit,chg-current-ma = <1500>;
- summit,term-current-ma = <50>;
- summit,pre-chg-current-ma = <100>;
- summit,float-voltage-mv = <4200>;
- summit,thresh-voltage-mv = <3000>;
- summit,recharge-thresh-mv = <75>;
- summit,system-voltage-mv = <4250>;
- summit,charging-timeout = <382>;
- summit,pre-charge-timeout = <48>;
- summit,therm-current-ua = <10>;
- summit,temperature-min = <4>; /* 0 C */
- summit,temperature-max = <3>; /* 45 C */
- };
- };
-
- wlan0: qca,wlan {
- cell-index = <0>;
- compatible = "qca,ar6004-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
- };
-};
-
-/* PM8019 GPIO and MPP configuration */
-&pm8019_gpios {
- gpio@c000 { /* GPIO 1 */
- };
-
- gpio@c100 { /* GPIO 2 */
- };
-
- gpio@c200 { /* GPIO 3 */
- };
-
- gpio@c300 { /* GPIO 4 */
- /* ext_2p95v regulator enable config */
- qcom,mode = <1>; /* Digital output */
- qcom,output-type = <0>; /* CMOS */
- qcom,invert = <0>; /* Output low */
- qcom,out-strength = <1>; /* Low */
- qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-sel = <0>; /* Constant */
- qcom,master-en = <1>; /* Enable GPIO */
- };
-
- gpio@c400 { /* GPIO 5 */
- };
-
- gpio@c500 { /* GPIO 6 */
- };
-};
-
-&pm8019_mpps {
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- };
-
- mpp@a200 { /* MPP 3 */
- };
-
- mpp@a300 { /* MPP 4 */
- };
-
- mpp@a400 { /* MPP 5 */
- };
-
- mpp@a500 { /* MPP 6 */
- };
-};
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 660bdbd..9fbe5ec 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -13,8 +13,7 @@
/dts-v1/;
/include/ "msm9625-v2.dtsi"
-/include/ "msm9625-display.dtsi"
-/include/ "qpic-panel-ili-qvga.dtsi"
+/include/ "msm9625-cdp.dtsi"
/ {
model = "Qualcomm MSM 9625V2 CDP";
@@ -22,88 +21,4 @@
qcom,msm-id = <134 1 0x20000>, <152 1 0x20000>, <149 1 0x20000>,
<150 1 0x20000>, <151 1 0x20000>, <148 1 0x20000>,
<173 1 0x20000>, <174 1 0x20000>, <175 1 0x20000>;
-
- i2c@f9925000 {
- charger@57 {
- compatible = "summit,smb137c";
- reg = <0x57>;
- summit,chg-current-ma = <1500>;
- summit,term-current-ma = <50>;
- summit,pre-chg-current-ma = <100>;
- summit,float-voltage-mv = <4200>;
- summit,thresh-voltage-mv = <3000>;
- summit,recharge-thresh-mv = <75>;
- summit,system-voltage-mv = <4250>;
- summit,charging-timeout = <382>;
- summit,pre-charge-timeout = <48>;
- summit,therm-current-ua = <10>;
- summit,temperature-min = <4>; /* 0 C */
- summit,temperature-max = <3>; /* 45 C */
- };
- };
-
- wlan0: qca,wlan {
- cell-index = <0>;
- compatible = "qca,ar6004-hsic";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-
- qca,wlan_ar6003 {
- cell-index = <0>;
- compatible = "qca,ar6003-sdio";
- qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
- qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,vdd-io-supply = <&pm8019_l11>;
- };
-};
-
-/* PM8019 GPIO and MPP configuration */
-&pm8019_gpios {
- gpio@c000 { /* GPIO 1 */
- };
-
- gpio@c100 { /* GPIO 2 */
- };
-
- gpio@c200 { /* GPIO 3 */
- };
-
- gpio@c300 { /* GPIO 4 */
- /* ext_2p95v regulator enable config */
- qcom,mode = <1>; /* Digital output */
- qcom,output-type = <0>; /* CMOS */
- qcom,invert = <0>; /* Output low */
- qcom,out-strength = <1>; /* Low */
- qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
- qcom,src-sel = <0>; /* Constant */
- qcom,master-en = <1>; /* Enable GPIO */
- };
-
- gpio@c400 { /* GPIO 5 */
- };
-
- gpio@c500 { /* GPIO 6 */
- };
-};
-
-&pm8019_mpps {
- mpp@a000 { /* MPP 1 */
- };
-
- mpp@a100 { /* MPP 2 */
- };
-
- mpp@a200 { /* MPP 3 */
- };
-
- mpp@a300 { /* MPP 4 */
- };
-
- mpp@a400 { /* MPP 5 */
- };
-
- mpp@a500 { /* MPP 6 */
- };
};
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index c9e54be..5324e2c 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm9625-v2.dtsi"
+/include/ "msm9625-mtp.dtsi"
/ {
model = "Qualcomm MSM 9625V2 MTP";
diff --git a/arch/arm/boot/dts/msm9625-v2.1-cdp.dts b/arch/arm/boot/dts/msm9625-v2.1-cdp.dts
new file mode 100644
index 0000000..b643593
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-v2.1-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625-v2.1.dtsi"
+/include/ "msm9625-cdp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 9625V2.1 CDP";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
+ qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
+ <150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
+ <173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
+};
diff --git a/arch/arm/boot/dts/msm9625-v2.1-mtp.dts b/arch/arm/boot/dts/msm9625-v2.1-mtp.dts
new file mode 100644
index 0000000..8bbcc0d
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-v2.1-mtp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625-v2.1.dtsi"
+/include/ "msm9625-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 9625V2.1 MTP";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
+ qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
+ <150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
+ <173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1.dtsi b/arch/arm/boot/dts/msm9625-v2.1.dtsi
similarity index 100%
rename from arch/arm/boot/dts/msm9625-v2-1.dtsi
rename to arch/arm/boot/dts/msm9625-v2.1.dtsi
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 348e8c9..faec7af 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -761,9 +761,9 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
- qcom,smem@fa00000 {
+ qcom,smem@0 {
compatible = "qcom,smem";
- reg = <0xfa00000 0x200000>,
+ reg = <0x0 0x100000>,
<0xf9011000 0x1000>,
<0xfc428000 0x4000>;
reg-names = "smem", "irq-reg-base", "aux-mem1";
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index f67cb0d..aa2c028 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -98,6 +98,7 @@
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index b5e67fd..c9f068a 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -102,6 +102,7 @@
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 42acd99..ae73bad 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -230,9 +230,6 @@
CONFIG_REGULATOR_QPNP=y
CONFIG_ION=y
CONFIG_ION_MSM=y
-CONFIG_FB=y
-CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 041e89a..f7c3bff 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -231,9 +231,6 @@
CONFIG_REGULATOR_QPNP=y
CONFIG_ION=y
CONFIG_ION_MSM=y
-CONFIG_FB=y
-CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index f20f6ae..8c366da 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -76,8 +76,8 @@
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v1-rumi.dtb
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-cdp.dtb
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-mtp.dtb
- dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-1-mtp.dtb
- dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-1-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2.1-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2.1-cdp.dtb
# MSM8226
zreladdr-$(CONFIG_ARCH_MSM8226) := 0x00008000
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 799d629..25bebd1 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -26,12 +26,13 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/rpm-regulator-smd.h>
+#include <mach/socinfo.h>
#include "acpuclock-cortex.h"
#define RCG_CONFIG_UPDATE_BIT BIT(0)
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl_8226[] = {
[0] = BW_MBPS(152), /* At least 19 MHz on bus. */
[1] = BW_MBPS(300), /* At least 37.5 MHz on bus. */
[2] = BW_MBPS(400), /* At least 50 MHz on bus. */
@@ -42,9 +43,18 @@
[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
};
+static struct msm_bus_paths bw_level_tbl_8610[] = {
+ [0] = BW_MBPS(152), /* At least 19 MHz on bus. */
+ [1] = BW_MBPS(300), /* At least 37.5 MHz on bus. */
+ [2] = BW_MBPS(400), /* At least 50 MHz on bus. */
+ [3] = BW_MBPS(800), /* At least 100 MHz on bus. */
+ [4] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [5] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+};
+
static struct msm_bus_scale_pdata bus_client_pdata = {
- .usecase = bw_level_tbl,
- .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .usecase = bw_level_tbl_8226,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl_8226),
.active_only = 1,
.name = "acpuclock",
};
@@ -54,7 +64,7 @@
* 2) Update bus bandwidth
* 3) Depending on Frodo version, may need minimum of LVL_NOM
*/
-static struct clkctl_acpu_speed acpu_freq_tbl[] = {
+static struct clkctl_acpu_speed acpu_freq_tbl_8226[] = {
{ 0, 19200, CXO, 0, 0, CPR_CORNER_SVS, 1150000, 0 },
{ 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 1150000, 4 },
{ 1, 384000, ACPUPLL, 5, 0, CPR_CORNER_SVS, 1150000, 4 },
@@ -65,8 +75,19 @@
{ 0 }
};
+static struct clkctl_acpu_speed acpu_freq_tbl_8610[] = {
+ { 0, 19200, CXO, 0, 0, CPR_CORNER_SVS, 1150000, 0 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 1150000, 3 },
+ { 1, 384000, ACPUPLL, 5, 0, CPR_CORNER_SVS, 1150000, 3 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 1150000, 4 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 1150000, 4 },
+ { 0, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 1275000, 5 },
+ { 0, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 1275000, 5 },
+ { 0 }
+};
+
static struct acpuclk_drv_data drv_data = {
- .freq_tbl = acpu_freq_tbl,
+ .freq_tbl = acpu_freq_tbl_8226,
.current_speed = &(struct clkctl_acpu_speed){ 0 },
.bus_scale = &bus_client_pdata,
.vdd_max_cpu = CPR_CORNER_TURBO,
@@ -146,8 +167,18 @@
},
};
+void msm8610_acpu_init(void)
+{
+ drv_data.bus_scale->usecase = bw_level_tbl_8610;
+ drv_data.bus_scale->num_usecases = ARRAY_SIZE(bw_level_tbl_8610);
+ drv_data.freq_tbl = acpu_freq_tbl_8610;
+}
+
static int __init acpuclk_a7_init(void)
{
+ if (cpu_is_msm8610())
+ msm8610_acpu_init();
+
return platform_driver_probe(&acpuclk_a7_driver, acpuclk_a7_probe);
}
device_initcall(acpuclk_a7_init);
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 38658a2..0fa2cde 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -109,12 +109,12 @@
static struct acpu_level freq_tbl_PVS0[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 950000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 975000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 1000000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 1025000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 1050000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 1075000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 950000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 975000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 1000000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 1025000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 1050000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 1075000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 1100000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1125000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1150000, AVS(0x0) },
@@ -127,12 +127,12 @@
static struct acpu_level freq_tbl_PVS1[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 925000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 950000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 975000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 1000000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 1025000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 1050000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 925000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 950000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 975000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 1000000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 1025000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 1050000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 1075000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1100000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1125000, AVS(0x0) },
@@ -145,12 +145,12 @@
static struct acpu_level freq_tbl_PVS2[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 900000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 925000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 950000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 975000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 1000000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 1025000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 900000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 925000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 950000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 975000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 1000000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 1025000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 1050000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1075000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1100000, AVS(0x0) },
@@ -163,12 +163,12 @@
static struct acpu_level freq_tbl_PVS3[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 900000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 900000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 925000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 950000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 975000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 1000000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 900000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 900000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 925000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 950000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 975000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 1000000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 1025000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1050000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1075000, AVS(0x0) },
@@ -181,12 +181,12 @@
static struct acpu_level freq_tbl_PVS4[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 875000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 875000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 900000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 925000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 950000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 975000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 875000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 900000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 925000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 950000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 975000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 1000000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1025000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1050000, AVS(0x0) },
@@ -199,12 +199,12 @@
static struct acpu_level freq_tbl_PVS5[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 875000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 875000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 875000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 900000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 925000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 950000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 875000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 875000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 900000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 925000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 950000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 975000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 1000000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1025000, AVS(0x0) },
@@ -217,12 +217,12 @@
static struct acpu_level freq_tbl_PVS6[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 850000, AVS(0x70001F) },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(3), 850000, AVS(0x0) },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(3), 850000, AVS(0x0) },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(3), 850000, AVS(0x0) },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(3), 875000, AVS(0x0) },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(3), 900000, AVS(0x0) },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(3), 925000, AVS(0x0) },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 850000, AVS(0x0) },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(4), 850000, AVS(0x0) },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(4), 850000, AVS(0x0) },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(4), 875000, AVS(0x0) },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(4), 900000, AVS(0x0) },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(4), 925000, AVS(0x0) },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(9), 950000, AVS(0x70000D) },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(9), 975000, AVS(0x0) },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(9), 1000000, AVS(0x0) },
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 2f09162..bed794b 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1386,12 +1386,11 @@
struct list_head *temp;
struct outside_notify_func *func;
+ BAM_DMUX_LOG("%s: event=%d, data=%lu\n", __func__, event, data);
+
for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
- if (bam_ch_is_open(i)) {
+ if (bam_ch_is_open(i))
bam_ch[i].notify(bam_ch[i].priv, event, data);
- BAM_DMUX_LOG("%s: cid=%d, event=%d, data=%lu\n",
- __func__, i, event, data);
- }
}
__list_for_each(temp, &bam_other_notify_funcs) {
@@ -1758,10 +1757,13 @@
/* in_ssr documentation/assumptions found in restart_notifier_cb */
if (!power_management_only_mode) {
if (likely(!in_ssr)) {
+ BAM_DMUX_LOG("%s: disconnect tx\n", __func__);
sps_disconnect(bam_tx_pipe);
+ BAM_DMUX_LOG("%s: disconnect rx\n", __func__);
sps_disconnect(bam_rx_pipe);
__memzero(rx_desc_mem_buf.base, rx_desc_mem_buf.size);
__memzero(tx_desc_mem_buf.base, tx_desc_mem_buf.size);
+ BAM_DMUX_LOG("%s: device reset\n", __func__);
sps_device_reset(a2_device_handle);
} else {
ssr_skipped_disconnect = 1;
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 75aaaec..a6ac986 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -276,6 +276,7 @@
},
};
+#ifdef CONFIG_FB_MSM_QPIC
static struct gpiomux_setting qpic_lcdc_a_d = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_10MA,
@@ -327,6 +328,17 @@
},
};
+static void msm9625_disp_init_gpiomux(void)
+{
+ msm_gpiomux_install(msm9625_qpic_lcdc_configs,
+ ARRAY_SIZE(msm9625_qpic_lcdc_configs));
+}
+#else
+static void msm9625_disp_init_gpiomux(void)
+{
+}
+#endif /* CONFIG_FB_MSM_QPIC */
+
void __init msm9625_init_gpiomux(void)
{
int rc;
@@ -347,7 +359,5 @@
ARRAY_SIZE(mdm9625_cdc_reset_config));
msm_gpiomux_install(sdc2_card_det_config,
ARRAY_SIZE(sdc2_card_det_config));
- msm_gpiomux_install(msm9625_qpic_lcdc_configs,
- ARRAY_SIZE(msm9625_qpic_lcdc_configs));
-
+ msm9625_disp_init_gpiomux();
}
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 4eb3d29..18c922d 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3328,6 +3328,8 @@
CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c, "fda08400.qcom,csid"),
/* ISPIF clocks */
+ CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
"fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 8880661..fae09d0 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2714,7 +2714,7 @@
CLK_LOOKUP("core_clk", gcc_mss_q6_bimc_axi_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, "f9bff000.qcom,msm-rng"),
CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
@@ -2830,6 +2830,11 @@
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "qseecom"),
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
+
+ CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "scm"),
+ CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "scm"),
+ CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "scm"),
+ CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "scm"),
};
static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 509443d..be6d965 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5419,11 +5419,6 @@
CLK_LOOKUP("csi_phy_clk", csi0_phy_clk.c, "msm_csid.0"),
CLK_LOOKUP("csi_phy_clk", csi1_phy_clk.c, "msm_csid.1"),
CLK_LOOKUP("csi_phy_clk", csi2_phy_clk.c, "msm_csid.2"),
- CLK_LOOKUP("csi_pix_clk", csi_pix_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_pix1_clk", csi_pix1_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_rdi_clk", csi_rdi_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_rdi1_clk", csi_rdi1_clk.c, "msm_ispif.0"),
- CLK_LOOKUP("csi_rdi2_clk", csi_rdi2_clk.c, "msm_ispif.0"),
CLK_LOOKUP("csiphy_timer_src_clk",
csiphy_timer_src_clk.c, "msm_csiphy.0"),
CLK_LOOKUP("csiphy_timer_src_clk",
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 1d7af9b..2de8799 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5013,14 +5013,6 @@
/* ISPIF clocks */
CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
"fda0a000.qcom,ispif"),
- CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
- "fda0a000.qcom,ispif"),
- CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
- "fda0a000.qcom,ispif"),
- CLK_LOOKUP("camss_vfe_vfe_clk1", camss_vfe_vfe1_clk.c,
- "fda0a000.qcom,ispif"),
- CLK_LOOKUP("camss_csi_vfe_clk1", camss_csi_vfe1_clk.c,
- "fda0a000.qcom,ispif"),
/*VFE clocks*/
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 8c2121f..0d1104e 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -596,6 +596,13 @@
ret = -EINVAL;
}
writel_relaxed(cbcr_val, CBCR_REG(branch));
+ /*
+ * 8974v2.2 has a requirement that writes to set bits 13 and 14 are
+ * separated by at least 2 bus cycles. Cover one of these cycles by
+ * performing an extra write here. The other cycle is covered by the
+ * read-modify-write design of this function.
+ */
+ writel_relaxed(cbcr_val, CBCR_REG(branch));
spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
/* Make sure write is issued before returning. */
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index a8c7bb7..d155c6f 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -279,6 +279,17 @@
*/
int smd_write_end(smd_channel_t *ch);
+/**
+ * smd_write_segment_avail() - available write space for packet transactions
+ * @ch: channel to write packet to
+ * @returns: number of bytes available to write to, or -ENODEV for invalid ch
+ *
+ * This is a version of smd_write_avail() intended for use with packet
+ * transactions. This version correctly accounts for any internal reserved
+ * space at all stages of the transaction.
+ */
+int smd_write_segment_avail(smd_channel_t *ch);
+
/*
* Returns a pointer to the subsystem name or NULL if no
* subsystem name is available.
@@ -441,6 +452,11 @@
return -ENODEV;
}
+static inline int smd_write_segment_avail(smd_channel_t *ch)
+{
+ return -ENODEV;
+}
+
static inline const char *smd_edge_to_subsystem(uint32_t type)
{
return NULL;
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
index 91e4ef1..ea345fb 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
@@ -53,19 +53,10 @@
uint8_t model_ID[128];
};
-#define ADSP_CMD_SET_DOLBY_MANUFACTURER_ID 0x00012918
-
-struct adsp_dolby_manufacturer_id {
- struct apr_hdr hdr;
- int manufacturer_id;
-};
-
int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps);
uint32_t core_get_adsp_version(void);
uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id);
-uint32_t core_set_dolby_manufacturer_id(int manufacturer_id);
-
#endif /* __Q6CORE_H__ */
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 88ab8e0..b2ec816 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -146,11 +146,11 @@
skb_queue_walk(pkt->pkt_fragment_q, ipc_rtr_pkt) {
offset = 0;
while (offset < ipc_rtr_pkt->len) {
- if (!smd_write_avail(smd_xprtp->channel))
+ if (!smd_write_segment_avail(smd_xprtp->channel))
smd_enable_read_intr(smd_xprtp->channel);
wait_event(smd_xprtp->write_avail_wait_q,
- (smd_write_avail(smd_xprtp->channel) ||
+ (smd_write_segment_avail(smd_xprtp->channel) ||
smd_xprtp->ss_reset));
smd_disable_read_intr(smd_xprtp->channel);
spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
@@ -175,11 +175,11 @@
}
if (align_sz) {
- if (smd_write_avail(smd_xprtp->channel) < align_sz)
+ if (smd_write_segment_avail(smd_xprtp->channel) < align_sz)
smd_enable_read_intr(smd_xprtp->channel);
wait_event(smd_xprtp->write_avail_wait_q,
- ((smd_write_avail(smd_xprtp->channel) >=
+ ((smd_write_segment_avail(smd_xprtp->channel) >=
align_sz) || smd_xprtp->ss_reset));
smd_disable_read_intr(smd_xprtp->channel);
spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
@@ -357,7 +357,7 @@
if (smd_read_avail(smd_xprtp->channel))
queue_delayed_work(smd_xprtp->smd_xprt_wq,
&smd_xprtp->read_work, 0);
- if (smd_write_avail(smd_xprtp->channel))
+ if (smd_write_segment_avail(smd_xprtp->channel))
wake_up(&smd_xprtp->write_avail_wait_q);
break;
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 3b2bbf3..608c5e0 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -22,6 +22,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
+#include <linux/of_gpio.h>
#include <mach/clk.h>
#include <mach/subsystem_restart.h>
@@ -50,6 +51,8 @@
void *wcnss_notif_hdle;
void *modem_notif_hdle;
int crash_shutdown;
+ unsigned int err_fatal_irq;
+ int force_stop_gpio;
};
#define subsys_to_drv(d) container_of(d, struct lpass_data, subsys_desc)
@@ -259,20 +262,19 @@
restart_adsp(drv);
}
-static void adsp_smsm_state_cb(void *data, uint32_t old_state,
- uint32_t new_state)
+static irqreturn_t adsp_err_fatal_intr_handler (int irq, void *dev_id)
{
- struct lpass_data *drv = data;
+ struct lpass_data *drv = dev_id;
- /* Ignore if we're the one that set SMSM_RESET */
+ /* Ignore if we're the one that set the force stop bit in the outbound
+ * entry
+ */
if (drv->crash_shutdown)
- return;
+ return IRQ_HANDLED;
- if (new_state & SMSM_RESET) {
- pr_err("%s: ADSP SMSM state changed to SMSM_RESET, new_state = %#x, old_state = %#x\n",
- __func__, new_state, old_state);
- restart_adsp(drv);
- }
+ pr_err("Fatal error on the ADSP!\n");
+ restart_adsp(drv);
+ return IRQ_HANDLED;
}
#define SCM_Q6_NMI_CMD 0x1
@@ -356,6 +358,7 @@
struct lpass_data *drv = subsys_to_lpass(subsys);
drv->crash_shutdown = 1;
+ gpio_set_value(drv->force_stop_gpio, 1);
send_q6_nmi();
}
@@ -399,6 +402,17 @@
if (drv->wdog_irq < 0)
return drv->wdog_irq;
+ ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-err-fatal", 0));
+ if (ret < 0)
+ return ret;
+ drv->err_fatal_irq = ret;
+
+ drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-force-stop", 0);
+ if (drv->force_stop_gpio < 0)
+ return drv->force_stop_gpio;
+
q6 = pil_q6v5_init(pdev);
if (IS_ERR(q6))
return PTR_ERR(q6);
@@ -470,10 +484,12 @@
if (ret)
goto err_irq;
- ret = smsm_state_cb_register(SMSM_Q6_STATE, SMSM_RESET,
- adsp_smsm_state_cb, drv);
- if (ret < 0)
- goto err_smsm;
+ ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
+ adsp_err_fatal_intr_handler,
+ IRQF_TRIGGER_RISING,
+ dev_name(&pdev->dev), drv);
+ if (ret)
+ goto err_irq;
drv->wcnss_notif_hdle = subsys_notif_register_notifier("wcnss", &wnb);
if (IS_ERR(drv->wcnss_notif_hdle)) {
@@ -507,9 +523,6 @@
err_notif_modem:
subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
err_notif_wcnss:
- smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
- adsp_smsm_state_cb, drv);
-err_smsm:
err_irq:
subsys_unregister(drv->subsys);
err_subsys:
@@ -524,8 +537,6 @@
struct lpass_data *drv = platform_get_drvdata(pdev);
subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
subsys_notif_unregister_notifier(drv->modem_notif_hdle, &mnb);
- smsm_state_cb_deregister(SMSM_Q6_STATE, SMSM_RESET,
- adsp_smsm_state_cb, drv);
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->ramdump_dev);
pil_desc_release(&drv->q6->desc);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 8f7d262..c3a0d32 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -608,8 +608,15 @@
if (ret)
return ret;
ret = pil_boot(&drv->desc);
- if (ret)
+ if (ret) {
pil_shutdown(&drv->q6->desc);
+ /*
+ * We know now that the unvote interrupt is not coming.
+ * Remove the proxy votes immediately.
+ */
+ if (drv->q6->desc.proxy_unvote_irq)
+ pil_q6v5_mss_remove_proxy_votes(&drv->q6->desc);
+ }
return ret;
}
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 0263faf..c6add8f 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -46,7 +46,9 @@
#define Q6SS_CLK_ENA BIT(1)
/* QDSP6SS_PWR_CTL */
-#define Q6SS_L2DATA_SLP_NRET_N (BIT(0)|BIT(1)|BIT(2))
+#define Q6SS_L2DATA_SLP_NRET_N_0 BIT(0)
+#define Q6SS_L2DATA_SLP_NRET_N_1 BIT(1)
+#define Q6SS_L2DATA_SLP_NRET_N_2 BIT(2)
#define Q6SS_L2TAG_SLP_NRET_N BIT(16)
#define Q6SS_ETB_SLP_NRET_N BIT(17)
#define Q6SS_L2DATA_STBY_N BIT(18)
@@ -160,7 +162,8 @@
writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
/* Turn off Q6 memories */
- val &= ~(Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
+ val &= ~(Q6SS_L2DATA_SLP_NRET_N_0 | Q6SS_L2DATA_SLP_NRET_N_1 |
+ Q6SS_L2DATA_SLP_NRET_N_2 | Q6SS_SLP_RET_N |
Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
Q6SS_L2DATA_STBY_N);
writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
@@ -194,11 +197,19 @@
mb();
udelay(1);
- /* Turn on memories */
+ /*
+ * Turn on memories. L2 banks should be done individually
+ * to minimize inrush current.
+ */
val = readl_relaxed(drv->reg_base + QDSP6SS_PWR_CTL);
- val |= Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
- Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
- Q6SS_L2DATA_STBY_N;
+ val |= Q6SS_SLP_RET_N | Q6SS_L2TAG_SLP_NRET_N |
+ Q6SS_ETB_SLP_NRET_N | Q6SS_L2DATA_STBY_N;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= Q6SS_L2DATA_SLP_NRET_N_2;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= Q6SS_L2DATA_SLP_NRET_N_1;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
+ val |= Q6SS_L2DATA_SLP_NRET_N_0;
writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
/* Remove IO clamp */
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 88e2894..6bd3efb 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -12,7 +12,7 @@
obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += lpa_if_hdmi.o
endif
obj-$(CONFIG_MSM_QDSP6_APR) += apr.o apr_v1.o apr_tal.o q6core.o dsp_debug.o
-obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o q6core.o dsp_debug.o
+obj-$(CONFIG_MSM_QDSP6_APRV2) += apr.o apr_v2.o apr_tal.o dsp_debug.o
ifdef CONFIG_ARCH_MSM9615
obj-y += audio_acdb.o
obj-y += rtac.o
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index 6594b08..fd699df 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -69,12 +69,12 @@
switch (payload1[0]) {
case ADSP_CMD_SET_POWER_COLLAPSE_STATE:
- pr_info("Cmd = ADSP_CMD_SET_POWER_COLLAPSE_STATE"
- " status[0x%x]\n", payload1[1]);
+ pr_info("Cmd = ADSP_CMD_SET_POWER_COLLAPSE_STATE status[0x%x]\n",
+ payload1[1]);
break;
case ADSP_CMD_REMOTE_BUS_BW_REQUEST:
- pr_info("%s: cmd = ADSP_CMD_REMOTE_BUS_BW_REQUEST"
- " status = 0x%x\n", __func__, payload1[1]);
+ pr_info("%s: cmd = ADSP_CMD_REMOTE_BUS_BW_REQUEST status = 0x%x\n",
+ __func__, payload1[1]);
bus_bw_resp_received = 1;
wake_up(&bus_bw_req_wait);
@@ -160,10 +160,9 @@
core_handle_q = apr_register("ADSP", "CORE",
aprv2_core_fn_q, 0xFFFFFFFF, NULL);
}
- pr_info("Open_q %p\n", core_handle_q);
- if (core_handle_q == NULL) {
+ pr_debug("Open_q %p\n", core_handle_q);
+ if (core_handle_q == NULL)
pr_err("%s: Unable to register CORE\n", __func__);
- }
}
int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps)
@@ -352,7 +351,7 @@
pc.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
pc.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(uint32_t));;
+ sizeof(uint32_t));
pc.hdr.src_port = 0;
pc.hdr.dest_port = 0;
pc.hdr.token = 0;
@@ -413,32 +412,6 @@
return rc;
}
-uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
-{
- struct adsp_dolby_manufacturer_id payload;
- int rc = 0;
- pr_debug("%s manufacturer_id :%d\n", __func__, manufacturer_id);
- core_open();
- if (core_handle_q) {
- payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- payload.hdr.pkt_size =
- sizeof(struct adsp_dolby_manufacturer_id);
- payload.hdr.src_port = 0;
- payload.hdr.dest_port = 0;
- payload.hdr.token = 0;
- payload.hdr.opcode = ADSP_CMD_SET_DOLBY_MANUFACTURER_ID;
- payload.manufacturer_id = manufacturer_id;
- pr_debug("Send Dolby security opcode=%x manufacturer ID = %d\n",
- payload.hdr.opcode, payload.manufacturer_id);
- rc = apr_send_pkt(core_handle_q, (uint32_t *)&payload);
- if (rc < 0)
- pr_err("%s: SET_DOLBY_MANUFACTURER_ID failed op[0x%x]rc[%d]\n",
- __func__, payload.hdr.opcode, rc);
- }
- return rc;
-}
-
static const struct file_operations apr_debug_fops = {
.write = apr_debug_write,
.open = apr_debug_open,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 07ac930..a213112 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -76,6 +76,7 @@
#define SMSM_SNAPSHOT_CNT 64
#define SMSM_SNAPSHOT_SIZE ((SMSM_NUM_ENTRIES + 1) * 4)
#define RSPIN_INIT_WAIT_MS 1000
+#define SMD_FIFO_FULL_RESERVE 4
uint32_t SMSM_NUM_ENTRIES = 8;
uint32_t SMSM_NUM_HOSTS = 3;
@@ -1053,8 +1054,16 @@
/* how many bytes we are free to write */
static int smd_stream_write_avail(struct smd_channel *ch)
{
- return ch->fifo_mask - ((ch->half_ch->get_head(ch->send) -
- ch->half_ch->get_tail(ch->send)) & ch->fifo_mask);
+ int bytes_avail;
+
+ bytes_avail = ch->fifo_mask - ((ch->half_ch->get_head(ch->send) -
+ ch->half_ch->get_tail(ch->send)) & ch->fifo_mask) + 1;
+
+ if (bytes_avail < SMD_FIFO_FULL_RESERVE)
+ bytes_avail = 0;
+ else
+ bytes_avail -= SMD_FIFO_FULL_RESERVE;
+ return bytes_avail;
}
static int smd_packet_read_avail(struct smd_channel *ch)
@@ -1176,7 +1185,18 @@
}
}
-/* provide a pointer and length to next free space in the fifo */
+/**
+ * ch_write_buffer() - Provide a pointer and length for the next segment of
+ * free space in the FIFO.
+ * @ch: channel
+ * @ptr: Address to pointer for the next segment write
+ * @returns: Maximum size that can be written until the FIFO is either full
+ * or the end of the FIFO has been reached.
+ *
+ * The returned pointer and length are passed to memcpy, so the next segment is
+ * defined as either the space available between the read index (tail) and the
+ * write index (head) or the space available to the end of the FIFO.
+ */
static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
{
unsigned head = ch->half_ch->get_head(ch->send);
@@ -1184,10 +1204,11 @@
*ptr = (void *) (ch->send_data + head);
if (head < tail) {
- return tail - head - 1;
+ return tail - head - SMD_FIFO_FULL_RESERVE;
} else {
- if (tail == 0)
- return ch->fifo_size - head - 1;
+ if (tail < SMD_FIFO_FULL_RESERVE)
+ return ch->fifo_size + tail - head
+ - SMD_FIFO_FULL_RESERVE;
else
return ch->fifo_size - head;
}
@@ -2111,6 +2132,29 @@
}
EXPORT_SYMBOL(smd_write_end);
+int smd_write_segment_avail(smd_channel_t *ch)
+{
+ int n;
+
+ if (!ch) {
+ pr_err("%s: Invalid channel specified\n", __func__);
+ return -ENODEV;
+ }
+ if (!ch->is_pkt_ch) {
+ pr_err("%s: non-packet channel specified\n", __func__);
+ return -ENODEV;
+ }
+
+ n = smd_stream_write_avail(ch);
+
+ /* pkt hdr already written, no need to reserve space for it */
+ if (ch->pending_pkt_sz)
+ return n;
+
+ return n > SMD_HEADER_SIZE ? n - SMD_HEADER_SIZE : 0;
+}
+EXPORT_SYMBOL(smd_write_segment_avail);
+
int smd_read(smd_channel_t *ch, void *data, int len)
{
if (!ch) {
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 7eb9ead..424d310 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -509,7 +509,7 @@
do {
prepare_to_wait(&smd_pkt_devp->ch_write_wait_queue,
&write_wait, TASK_UNINTERRUPTIBLE);
- if (!smd_write_avail(smd_pkt_devp->ch) &&
+ if (!smd_write_segment_avail(smd_pkt_devp->ch) &&
!smd_pkt_devp->has_reset) {
smd_enable_read_intr(smd_pkt_devp->ch);
schedule();
@@ -631,7 +631,7 @@
return;
}
- sz = smd_write_avail(smd_pkt_devp->ch);
+ sz = smd_write_segment_avail(smd_pkt_devp->ch);
if (sz) {
D_WRITE("%s: %d bytes write space in smd_pkt_dev id:%d\n",
__func__, sz, smd_pkt_devp->i);
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 2777769..5a5c0cf 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -276,23 +276,32 @@
}
/*
- * Memory mapped writes to clear os lock are not supported on Krait v1, v2
- * and OS lock must be unlocked before any memory mapped access, otherwise
- * memory mapped reads/writes will be invalid.
+ * Unlock OS lock to allow memory mapped access on Krait and in general
+ * so that ETMSR[1] can be polled while clearing the ETMCR[10] prog bit
+ * since ETMSR[1] is set when prog bit is set or OS lock is set.
*/
static void etm_os_unlock(void *info)
{
struct etm_drvdata *drvdata = (struct etm_drvdata *) info;
- ETM_UNLOCK(drvdata);
+ /*
+ * Memory mapped writes to clear os lock are not supported on Krait v1,
+ * v2 and OS lock must be unlocked before any memory mapped access,
+ * otherwise memory mapped reads/writes will be invalid.
+ */
if (cpu_is_krait()) {
etm_writel_cp14(0x0, ETMOSLAR);
+ /* ensure os lock is unlocked before we return */
isb();
- } else if (etm_os_lock_present(drvdata)) {
- etm_writel(drvdata, 0x0, ETMOSLAR);
- mb();
+ } else {
+ ETM_UNLOCK(drvdata);
+ if (etm_os_lock_present(drvdata)) {
+ etm_writel(drvdata, 0x0, ETMOSLAR);
+ /* ensure os lock is unlocked before we return */
+ mb();
+ }
+ ETM_LOCK(drvdata);
}
- ETM_LOCK(drvdata);
}
/*
@@ -1876,11 +1885,26 @@
void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
+ static bool clk_disable[NR_CPUS];
+ int ret;
if (!etmdrvdata[cpu])
goto out;
switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_UP_PREPARE:
+ if (!etmdrvdata[cpu]->os_unlock) {
+ ret = clk_prepare_enable(etmdrvdata[cpu]->clk);
+ if (ret) {
+ dev_err(etmdrvdata[cpu]->dev,
+ "ETM clk enable during hotplug failed"
+ "for cpu: %d, ret: %d\n", cpu, ret);
+ return notifier_from_errno(ret);
+ }
+ clk_disable[cpu] = true;
+ }
+ break;
+
case CPU_STARTING:
spin_lock(&etmdrvdata[cpu]->spinlock);
if (!etmdrvdata[cpu]->os_unlock) {
@@ -1894,6 +1918,11 @@
break;
case CPU_ONLINE:
+ if (clk_disable[cpu]) {
+ clk_disable_unprepare(etmdrvdata[cpu]->clk);
+ clk_disable[cpu] = false;
+ }
+
if (etmdrvdata[cpu]->boot_enable &&
!etmdrvdata[cpu]->sticky_enable)
coresight_enable(etmdrvdata[cpu]->csdev);
@@ -1903,6 +1932,13 @@
__etm_store_pcsave(etmdrvdata[cpu], 1);
break;
+ case CPU_UP_CANCELED:
+ if (clk_disable[cpu]) {
+ clk_disable_unprepare(etmdrvdata[cpu]->clk);
+ clk_disable[cpu] = false;
+ }
+ break;
+
case CPU_DYING:
spin_lock(&etmdrvdata[cpu]->spinlock);
if (etmdrvdata[cpu]->enable && etmdrvdata[cpu]->round_robin)
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 2b1ad80..245272b 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -1337,19 +1337,6 @@
}
};
-static void _aead_sps_consumer_callback(struct sps_event_notify *notify)
-{
- struct qce_device *pce_dev = (struct qce_device *)
- ((struct sps_event_notify *)notify)->user;
-
- pce_dev->ce_sps.notify = *notify;
- pr_debug("sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
- notify->event_id,
- notify->data.transfer.iovec.addr,
- notify->data.transfer.iovec.size,
- notify->data.transfer.iovec.flags);
-};
-
static void _sha_sps_producer_callback(struct sps_event_notify *notify)
{
struct qce_device *pce_dev = (struct qce_device *)
@@ -1365,19 +1352,6 @@
_sha_complete(pce_dev);
};
-static void _sha_sps_consumer_callback(struct sps_event_notify *notify)
-{
- struct qce_device *pce_dev = (struct qce_device *)
- ((struct sps_event_notify *)notify)->user;
-
- pce_dev->ce_sps.notify = *notify;
- pr_debug("sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
- notify->event_id,
- notify->data.transfer.iovec.addr,
- notify->data.transfer.iovec.size,
- notify->data.transfer.iovec.flags);
-};
-
static void _ablk_cipher_sps_producer_callback(struct sps_event_notify *notify)
{
struct qce_device *pce_dev = (struct qce_device *)
@@ -1412,19 +1386,6 @@
}
};
-static void _ablk_cipher_sps_consumer_callback(struct sps_event_notify *notify)
-{
- struct qce_device *pce_dev = (struct qce_device *)
- ((struct sps_event_notify *)notify)->user;
-
- pce_dev->ce_sps.notify = *notify;
- pr_debug("sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
- notify->event_id,
- notify->data.transfer.iovec.addr,
- notify->data.transfer.iovec.size,
- notify->data.transfer.iovec.flags);
-};
-
static void qce_add_cmd_element(struct qce_device *pdev,
struct sps_command_element **cmd_ptr, u32 addr,
u32 data, struct sps_command_element **populate)
@@ -2371,16 +2332,6 @@
pr_err("Producer callback registration failed rc = %d\n", rc);
goto bad;
}
- /* Register callback event for EOT (End of transfer) event. */
- pce_dev->ce_sps.consumer.event.callback = _aead_sps_consumer_callback;
- pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
- rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
- &pce_dev->ce_sps.consumer.event);
- if (rc) {
- pr_err("Consumer callback registration failed rc = %d\n", rc);
- goto bad;
- }
-
_qce_sps_iovec_count_init(pce_dev);
_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
@@ -2539,17 +2490,6 @@
pr_err("Producer callback registration failed rc = %d\n", rc);
goto bad;
}
- /* Register callback event for EOT (End of transfer) event. */
- pce_dev->ce_sps.consumer.event.callback =
- _ablk_cipher_sps_consumer_callback;
- pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
- rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
- &pce_dev->ce_sps.consumer.event);
- if (rc) {
- pr_err("Consumer callback registration failed rc = %d\n", rc);
- goto bad;
- }
-
_qce_sps_iovec_count_init(pce_dev);
_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
@@ -2626,17 +2566,6 @@
pr_err("Producer callback registration failed rc = %d\n", rc);
goto bad;
}
-
- /* Register callback event for EOT (End of transfer) event. */
- pce_dev->ce_sps.consumer.event.callback = _sha_sps_consumer_callback;
- pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
- rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
- &pce_dev->ce_sps.consumer.event);
- if (rc) {
- pr_err("Consumer callback registration failed rc = %d\n", rc);
- goto bad;
- }
-
_qce_sps_iovec_count_init(pce_dev);
_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index f3ee02b..d5904b9 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -30,7 +30,6 @@
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
#include "kgsl_iommu.h"
-#include "kgsl_trace.h"
#include "adreno.h"
#include "adreno_pm4types.h"
@@ -2782,7 +2781,7 @@
if (device->state == KGSL_STATE_ACTIVE) {
/* Is the ring buffer is empty? */
GSL_RB_GET_READPTR(rb, &rb->rptr);
- if (!device->active_cnt && (rb->rptr == rb->wptr)) {
+ if (rb->rptr == rb->wptr) {
/*
* Are there interrupts pending? If so then pretend we
* are not idle - this avoids the possiblity that we go
@@ -2952,7 +2951,7 @@
if (!in_interrupt())
kgsl_pre_hwaccess(device);
- trace_kgsl_regwrite(device, offsetwords, value);
+ kgsl_trace_regwrite(device, offsetwords, value);
kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
@@ -3596,15 +3595,20 @@
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- unsigned int cycles;
+ unsigned int cycles = 0;
- /* Get the busy cycles counted since the counter was last reset */
- /* Calling this function also resets and restarts the counter */
+ /*
+ * Get the busy cycles counted since the counter was last reset.
+ * If we're not currently active, there shouldn't have been
+ * any cycles since the last time this function was called.
+ */
+ if (device->state == KGSL_STATE_ACTIVE)
+ cycles = adreno_dev->gpudev->busy_cycles(adreno_dev);
- cycles = adreno_dev->gpudev->busy_cycles(adreno_dev);
-
- /* In order to calculate idle you have to have run the algorithm *
- * at least once to get a start time. */
+ /*
+ * In order to calculate idle you have to have run the algorithm
+ * at least once to get a start time.
+ */
if (pwr->time != 0) {
s64 tmp = ktime_to_us(ktime_get());
stats->total_time = tmp - pwr->time;
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index ef599e9..980ff13 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -93,4 +93,7 @@
adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
&adreno_dev->ft_pf_policy);
+
+ debugfs_create_u32("active_cnt", 0444, device->d_debugfs,
+ &device->active_cnt);
}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 628d38c..8c96884 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -18,7 +18,6 @@
#include "kgsl.h"
#include "kgsl_sharedmem.h"
#include "kgsl_cffdump.h"
-#include "kgsl_trace.h"
#include "adreno.h"
#include "adreno_pm4types.h"
@@ -1123,7 +1122,7 @@
ret = 0;
done:
- trace_kgsl_issueibcmds(device, context->id, ibdesc, numibs,
+ kgsl_trace_issueibcmds(device, context->id, ibdesc, numibs,
*timestamp, flags, ret, drawctxt->type);
kfree(link);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 53ef392..5275267 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -53,6 +53,46 @@
static struct ion_client *kgsl_ion_client;
+/**
+ * kgsl_trace_issueibcmds() - Call trace_issueibcmds by proxy
+ * device: KGSL device
+ * id: ID of the context submitting the command
+ * ibdesc: Pointer to the list of IB descriptors
+ * numib: Number of IBs in the list
+ * timestamp: Timestamp assigned to the command batch
+ * flags: Flags sent by the user
+ * result: Result of the submission attempt
+ * type: Type of context issuing the command
+ *
+ * Wrap the issueibcmds ftrace hook into a function that can be called from the
+ * GPU specific modules.
+ */
+void kgsl_trace_issueibcmds(struct kgsl_device *device, int id,
+ struct kgsl_ibdesc *ibdesc, int numibs,
+ unsigned int timestamp, unsigned int flags,
+ int result, unsigned int type)
+{
+ trace_kgsl_issueibcmds(device, id, ibdesc, numibs,
+ timestamp, flags, result, type);
+}
+EXPORT_SYMBOL(kgsl_trace_issueibcmds);
+
+/**
+ * kgsl_trace_regwrite - call regwrite ftrace function by proxy
+ * device: KGSL device
+ * offset: dword offset of the register being written
+ * value: Value of the register being written
+ *
+ * Wrap the regwrite ftrace hook into a function that can be called from the
+ * GPU specific modules.
+ */
+void kgsl_trace_regwrite(struct kgsl_device *device, unsigned int offset,
+ unsigned int value)
+{
+ trace_kgsl_regwrite(device, offset, value);
+}
+EXPORT_SYMBOL(kgsl_trace_regwrite);
+
int kgsl_memfree_hist_init(void)
{
void *base;
@@ -413,27 +453,6 @@
kfree(context);
}
-static void kgsl_check_idle_locked(struct kgsl_device *device)
-{
- if (device->pwrctrl.nap_allowed == true &&
- device->state == KGSL_STATE_ACTIVE &&
- device->requested_state == KGSL_STATE_NONE) {
- kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
- kgsl_pwrscale_idle(device);
- if (kgsl_pwrctrl_sleep(device) != 0)
- mod_timer(&device->idle_timer,
- jiffies +
- device->pwrctrl.interval_timeout);
- }
-}
-
-static void kgsl_check_idle(struct kgsl_device *device)
-{
- mutex_lock(&device->mutex);
- kgsl_check_idle_locked(device);
- mutex_unlock(&device->mutex);
-}
-
struct kgsl_device *kgsl_get_device(int dev_idx)
{
int i;
@@ -496,13 +515,12 @@
policy_saved = device->pwrscale.policy;
device->pwrscale.policy = NULL;
kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND);
- /* Make sure no user process is waiting for a timestamp *
- * before supending */
- if (device->active_cnt != 0) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->suspend_gate);
- mutex_lock(&device->mutex);
- }
+ /*
+ * Make sure no user process is waiting for a timestamp
+ * before supending.
+ */
+ kgsl_active_count_wait(device);
+
/* Don't let the timer wake us during suspended sleep. */
del_timer_sync(&device->idle_timer);
switch (device->state) {
@@ -513,6 +531,8 @@
device->ftbl->idle(device);
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
+ /* make sure power is on to stop the device */
+ kgsl_pwrctrl_enable(device);
/* Get the completion ready to be waited upon. */
INIT_COMPLETION(device->hwaccess_gate);
device->ftbl->suspend_context(device);
@@ -632,9 +652,16 @@
device->pwrctrl.restore_slumber = false;
if (device->pwrscale.policy == NULL)
kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
- kgsl_pwrctrl_wake(device);
+ if (kgsl_pwrctrl_wake(device) != 0)
+ return;
+ /*
+ * We don't have a way to go directly from
+ * a deeper sleep state to NAP, which is
+ * the desired state here.
+ */
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
+ kgsl_pwrctrl_sleep(device);
mutex_unlock(&device->mutex);
- kgsl_check_idle(device);
KGSL_PWR_WARN(device, "late resume end\n");
}
EXPORT_SYMBOL(kgsl_late_resume_driver);
@@ -745,7 +772,7 @@
filep->private_data = NULL;
mutex_lock(&device->mutex);
- kgsl_check_suspended(device);
+ kgsl_active_count_get(device);
while (1) {
context = idr_get_next(&device->context_idr, &next);
@@ -767,10 +794,17 @@
device->open_count--;
if (device->open_count == 0) {
+ BUG_ON(device->active_cnt > 1);
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ /*
+ * active_cnt special case: we just stopped the device,
+ * so no need to use kgsl_active_count_put()
+ */
+ device->active_cnt--;
+ } else {
+ kgsl_active_count_put(device);
}
-
mutex_unlock(&device->mutex);
kfree(dev_priv);
@@ -816,9 +850,14 @@
filep->private_data = dev_priv;
mutex_lock(&device->mutex);
- kgsl_check_suspended(device);
if (device->open_count == 0) {
+ /*
+ * active_cnt special case: we are starting up for the first
+ * time, so use this sequence instead of the kgsl_pwrctrl_wake()
+ * which will be called by kgsl_active_count_get().
+ */
+ device->active_cnt++;
kgsl_sharedmem_set(&device->memstore, 0, 0,
device->memstore.size);
@@ -831,6 +870,7 @@
goto err_freedevpriv;
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
+ kgsl_active_count_put(device);
}
device->open_count++;
mutex_unlock(&device->mutex);
@@ -856,10 +896,15 @@
mutex_lock(&device->mutex);
device->open_count--;
if (device->open_count == 0) {
+ /* make sure power is on to stop the device */
+ kgsl_pwrctrl_enable(device);
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
}
err_freedevpriv:
+ /* only the first open takes an active count */
+ if (device->open_count == 0)
+ device->active_cnt--;
mutex_unlock(&device->mutex);
filep->private_data = NULL;
kfree(dev_priv);
@@ -1073,10 +1118,6 @@
struct kgsl_device *device = dev_priv->device;
unsigned int context_id = context ? context->id : KGSL_MEMSTORE_GLOBAL;
- /* Set the active count so that suspend doesn't do the wrong thing */
-
- device->active_cnt++;
-
trace_kgsl_waittimestamp_entry(device, context_id,
kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED),
@@ -1090,9 +1131,6 @@
KGSL_TIMESTAMP_RETIRED),
result);
- /* Fire off any pending suspend operations that are in flight */
- kgsl_active_count_put(dev_priv->device);
-
return result;
}
@@ -1887,7 +1925,6 @@
trace_kgsl_mem_map(entry, param->fd);
- kgsl_check_idle(dev_priv->device);
return result;
error_unmap:
@@ -1907,7 +1944,6 @@
}
error:
kfree(entry);
- kgsl_check_idle(dev_priv->device);
return result;
}
@@ -2035,7 +2071,6 @@
entry->memtype = KGSL_MEM_ENTRY_KERNEL;
- kgsl_check_idle(dev_priv->device);
*ret_entry = entry;
return result;
err:
@@ -2370,7 +2405,7 @@
kgsl_ioctl_cff_user_event, 0),
KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
kgsl_ioctl_timestamp_event,
- KGSL_IOCTL_LOCK),
+ KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
kgsl_ioctl_device_setproperty,
KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE),
@@ -2462,14 +2497,19 @@
if (lock) {
mutex_lock(&dev_priv->device->mutex);
- if (use_hw)
- kgsl_check_suspended(dev_priv->device);
+ if (use_hw) {
+ ret = kgsl_active_count_get(dev_priv->device);
+ if (ret < 0)
+ goto unlock;
+ }
}
ret = func(dev_priv, cmd, uptr);
+unlock:
if (lock) {
- kgsl_check_idle_locked(dev_priv->device);
+ if (use_hw)
+ kgsl_active_count_put(dev_priv->device);
mutex_unlock(&dev_priv->device->mutex);
}
@@ -2600,12 +2640,18 @@
return ret;
}
+static inline bool
+mmap_range_valid(unsigned long addr, unsigned long len)
+{
+ return (addr + len) > addr && (addr + len) < TASK_SIZE;
+}
+
static unsigned long
kgsl_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
- unsigned long ret = 0;
+ unsigned long ret = 0, orig_len = len;
unsigned long vma_offset = pgoff << PAGE_SHIFT;
struct kgsl_device_private *dev_priv = file->private_data;
struct kgsl_process_private *private = dev_priv->process_priv;
@@ -2650,10 +2696,26 @@
if (align)
len += 1 << align;
+
+ if (!mmap_range_valid(addr, len))
+ addr = 0;
do {
ret = get_unmapped_area(NULL, addr, len, pgoff, flags);
- if (IS_ERR_VALUE(ret))
+ if (IS_ERR_VALUE(ret)) {
+ /*
+ * If we are really fragmented, there may not be room
+ * for the alignment padding, so try again without it.
+ */
+ if (!retry && (ret == (unsigned long)-ENOMEM)
+ && (align > PAGE_SHIFT)) {
+ align = PAGE_SHIFT;
+ addr = 0;
+ len = orig_len;
+ retry = 1;
+ continue;
+ }
break;
+ }
if (align)
ret = ALIGN(ret, (1 << align));
@@ -2675,13 +2737,13 @@
* the whole address space at least once by wrapping
* back around once.
*/
- if (!retry && (addr + len >= TASK_SIZE)) {
+ if (!retry && !mmap_range_valid(addr, len)) {
addr = 0;
retry = 1;
} else {
ret = -EBUSY;
}
- } while (addr + len < TASK_SIZE);
+ } while (mmap_range_valid(addr, len));
if (IS_ERR_VALUE(ret))
KGSL_MEM_INFO(device,
@@ -3032,11 +3094,7 @@
/* For a manual dump, make sure that the system is idle */
if (manual) {
- if (device->active_cnt != 0) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->suspend_gate);
- mutex_lock(&device->mutex);
- }
+ kgsl_active_count_wait(device);
if (device->state == KGSL_STATE_ACTIVE)
kgsl_idle(device);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index c568db5..abe9100 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -226,6 +226,14 @@
void kgsl_early_suspend_driver(struct early_suspend *h);
void kgsl_late_resume_driver(struct early_suspend *h);
+void kgsl_trace_regwrite(struct kgsl_device *device, unsigned int offset,
+ unsigned int value);
+
+void kgsl_trace_issueibcmds(struct kgsl_device *device, int id,
+ struct kgsl_ibdesc *ibdesc, int numibs,
+ unsigned int timestamp, unsigned int flags,
+ int result, unsigned int type);
+
#ifdef CONFIG_MSM_KGSL_DRM
extern int kgsl_drm_init(struct platform_device *dev);
extern void kgsl_drm_exit(void);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 0d11660..ac82820 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -454,23 +454,4 @@
kref_put(&context->refcount, kgsl_context_destroy);
}
-/**
- * kgsl_active_count_put - Decrease the device active count
- * @device: Pointer to a KGSL device
- *
- * Decrease the active count for the KGSL device and trigger the suspend_gate
- * completion if it hits zero
- */
-static inline void
-kgsl_active_count_put(struct kgsl_device *device)
-{
- if (device->active_cnt == 1)
- INIT_COMPLETION(device->suspend_gate);
-
- device->active_cnt--;
-
- if (device->active_cnt == 0)
- complete(&device->suspend_gate);
-}
-
#endif /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 9e9c0da..d872783 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -51,6 +51,7 @@
void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
void *owner)
{
+ int ret;
struct kgsl_event *event;
unsigned int cur_ts;
struct kgsl_context *context = NULL;
@@ -82,6 +83,16 @@
if (event == NULL)
return -ENOMEM;
+ /*
+ * Increase the active count on the device to avoid going into power
+ * saving modes while events are pending
+ */
+ ret = kgsl_active_count_get_light(device);
+ if (ret < 0) {
+ kfree(event);
+ return ret;
+ }
+
event->context = context;
event->timestamp = ts;
event->priv = priv;
@@ -112,13 +123,6 @@
} else
_add_event_to_list(&device->events, event);
- /*
- * Increase the active count on the device to avoid going into power
- * saving modes while events are pending
- */
-
- device->active_cnt++;
-
queue_work(device->work_queue, &device->ts_expired_ws);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 4e95373..6e41707 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -610,6 +610,7 @@
* kgsl_pwrctrl_irq() is called
*/
}
+EXPORT_SYMBOL(kgsl_mh_start);
int
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2f8d93e..5909153 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1055,6 +1055,14 @@
pwr->power_flags = 0;
}
+/**
+ * kgsl_idle_check() - Work function for GPU interrupts and idle timeouts.
+ * @device: The device
+ *
+ * This function is called for work that is queued by the interrupt
+ * handler or the idle timer. It attempts to transition to a clocks
+ * off state if the active_cnt is 0 and the hardware is idle.
+ */
void kgsl_idle_check(struct work_struct *work)
{
struct kgsl_device *device = container_of(work, struct kgsl_device,
@@ -1064,15 +1072,22 @@
return;
mutex_lock(&device->mutex);
- if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
- kgsl_pwrscale_idle(device);
- if (kgsl_pwrctrl_sleep(device) != 0) {
+ kgsl_pwrscale_idle(device);
+
+ if (device->state == KGSL_STATE_ACTIVE
+ || device->state == KGSL_STATE_NAP) {
+ if (device->active_cnt > 0 || kgsl_pwrctrl_sleep(device) != 0) {
+
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
+
mod_timer(&device->idle_timer,
jiffies +
device->pwrctrl.interval_timeout);
- /* If the GPU has been too busy to sleep, make sure *
- * that is acurately reflected in the % busy numbers. */
+ /*
+ * If the GPU has been too busy to sleep, make sure
+ * that is acurately reflected in the % busy numbers.
+ */
device->pwrctrl.clk_stats.no_nap_cnt++;
if (device->pwrctrl.clk_stats.no_nap_cnt >
UPDATE_BUSY) {
@@ -1087,6 +1102,7 @@
mutex_unlock(&device->mutex);
}
+EXPORT_SYMBOL(kgsl_idle_check);
void kgsl_timer(unsigned long data)
{
@@ -1104,54 +1120,26 @@
}
}
+
+/**
+ * kgsl_pre_hwaccess - Enforce preconditions for touching registers
+ * @device: The device
+ *
+ * This function ensures that the correct lock is held and that the GPU
+ * clock is on immediately before a register is read or written. Note
+ * that this function does not check active_cnt because the registers
+ * must be accessed during device start and stop, when the active_cnt
+ * may legitimately be 0.
+ */
void kgsl_pre_hwaccess(struct kgsl_device *device)
{
+ /* In order to touch a register you must hold the device mutex...*/
BUG_ON(!mutex_is_locked(&device->mutex));
- switch (device->state) {
- case KGSL_STATE_ACTIVE:
- return;
- case KGSL_STATE_NAP:
- case KGSL_STATE_SLEEP:
- case KGSL_STATE_SLUMBER:
- kgsl_pwrctrl_wake(device);
- break;
- case KGSL_STATE_SUSPEND:
- kgsl_check_suspended(device);
- break;
- case KGSL_STATE_INIT:
- case KGSL_STATE_HUNG:
- case KGSL_STATE_DUMP_AND_FT:
- if (test_bit(KGSL_PWRFLAGS_CLK_ON,
- &device->pwrctrl.power_flags))
- break;
- else
- KGSL_PWR_ERR(device,
- "hw access while clocks off from state %d\n",
- device->state);
- break;
- default:
- KGSL_PWR_ERR(device, "hw access while in unknown state %d\n",
- device->state);
- break;
- }
+ /* and have the clock on! */
+ BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
}
EXPORT_SYMBOL(kgsl_pre_hwaccess);
-void kgsl_check_suspended(struct kgsl_device *device)
-{
- if (device->requested_state == KGSL_STATE_SUSPEND ||
- device->state == KGSL_STATE_SUSPEND) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->hwaccess_gate);
- mutex_lock(&device->mutex);
- } else if (device->state == KGSL_STATE_DUMP_AND_FT) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->ft_gate);
- mutex_lock(&device->mutex);
- } else if (device->state == KGSL_STATE_SLUMBER)
- kgsl_pwrctrl_wake(device);
-}
-
static int
_nap(struct kgsl_device *device)
{
@@ -1230,6 +1218,8 @@
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
del_timer_sync(&device->idle_timer);
+ /* make sure power is on to stop the device*/
+ kgsl_pwrctrl_enable(device);
device->ftbl->suspend_context(device);
device->ftbl->stop(device);
_sleep_accounting(device);
@@ -1278,9 +1268,9 @@
/******************************************************************/
/* Caller must hold the device mutex. */
-void kgsl_pwrctrl_wake(struct kgsl_device *device)
+int kgsl_pwrctrl_wake(struct kgsl_device *device)
{
- int status;
+ int status = 0;
unsigned int context_id;
unsigned int state = device->state;
unsigned int ts_processed = 0xdeaddead;
@@ -1329,8 +1319,10 @@
KGSL_PWR_WARN(device, "unhandled state %s\n",
kgsl_pwrstate_to_str(device->state));
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
+ status = -EINVAL;
break;
}
+ return status;
}
EXPORT_SYMBOL(kgsl_pwrctrl_wake);
@@ -1396,3 +1388,124 @@
}
EXPORT_SYMBOL(kgsl_pwrstate_to_str);
+
+/**
+ * kgsl_active_count_get() - Increase the device active count
+ * @device: Pointer to a KGSL device
+ *
+ * Increase the active count for the KGSL device and turn on
+ * clocks if this is the first reference. Code paths that need
+ * to touch the hardware or wait for the hardware to complete
+ * an operation must hold an active count reference until they
+ * are finished. An error code will be returned if waking the
+ * device fails. The device mutex must be held while *calling
+ * this function.
+ */
+int kgsl_active_count_get(struct kgsl_device *device)
+{
+ int ret = 0;
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ if (device->active_cnt == 0) {
+ if (device->requested_state == KGSL_STATE_SUSPEND ||
+ device->state == KGSL_STATE_SUSPEND) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->hwaccess_gate);
+ mutex_lock(&device->mutex);
+ } else if (device->state == KGSL_STATE_DUMP_AND_FT) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->ft_gate);
+ mutex_lock(&device->mutex);
+ }
+ ret = kgsl_pwrctrl_wake(device);
+ }
+ if (ret == 0)
+ device->active_cnt++;
+ return ret;
+}
+EXPORT_SYMBOL(kgsl_active_count_get);
+
+/**
+ * kgsl_active_count_get_light() - Increase the device active count
+ * @device: Pointer to a KGSL device
+ *
+ * Increase the active count for the KGSL device WITHOUT
+ * turning on the clocks. Currently this is only used for creating
+ * kgsl_events. The device mutex must be held while calling this function.
+ */
+int kgsl_active_count_get_light(struct kgsl_device *device)
+{
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ if (device->state != KGSL_STATE_ACTIVE) {
+ dev_WARN_ONCE(device->dev, 1, "device in unexpected state %s\n",
+ kgsl_pwrstate_to_str(device->state));
+ return -EINVAL;
+ }
+
+ if (device->active_cnt == 0) {
+ dev_WARN_ONCE(device->dev, 1, "active count is 0!\n");
+ return -EINVAL;
+ }
+
+ device->active_cnt++;
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_active_count_get_light);
+
+/**
+ * kgsl_active_count_put() - Decrease the device active count
+ * @device: Pointer to a KGSL device
+ *
+ * Decrease the active count for the KGSL device and turn off
+ * clocks if there are no remaining references. This function will
+ * transition the device to NAP if there are no other pending state
+ * changes. It also completes the suspend gate. The device mutex must
+ * be held while calling this function.
+ */
+void kgsl_active_count_put(struct kgsl_device *device)
+{
+ BUG_ON(!mutex_is_locked(&device->mutex));
+ BUG_ON(device->active_cnt == 0);
+
+ kgsl_pwrscale_idle(device);
+ if (device->active_cnt > 1) {
+ device->active_cnt--;
+ return;
+ }
+
+ INIT_COMPLETION(device->suspend_gate);
+
+ if (device->pwrctrl.nap_allowed == true &&
+ (device->state == KGSL_STATE_ACTIVE &&
+ device->requested_state == KGSL_STATE_NONE)) {
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
+ if (kgsl_pwrctrl_sleep(device) != 0)
+ mod_timer(&device->idle_timer,
+ jiffies
+ + device->pwrctrl.interval_timeout);
+ }
+ device->active_cnt--;
+
+ if (device->active_cnt == 0)
+ complete(&device->suspend_gate);
+}
+EXPORT_SYMBOL(kgsl_active_count_put);
+
+/**
+ * kgsl_active_count_wait() - Wait for activity to finish.
+ * @device: Pointer to a KGSL device
+ *
+ * Block until all active_cnt users put() their reference.
+ */
+void kgsl_active_count_wait(struct kgsl_device *device)
+{
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ if (device->active_cnt != 0) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->suspend_gate);
+ mutex_lock(&device->mutex);
+ }
+}
+EXPORT_SYMBOL(kgsl_active_count_wait);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index ced52e1..0fd64c3 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -99,9 +99,8 @@
void kgsl_timer(unsigned long data);
void kgsl_idle_check(struct work_struct *work);
void kgsl_pre_hwaccess(struct kgsl_device *device);
-void kgsl_check_suspended(struct kgsl_device *device);
int kgsl_pwrctrl_sleep(struct kgsl_device *device);
-void kgsl_pwrctrl_wake(struct kgsl_device *device);
+int kgsl_pwrctrl_wake(struct kgsl_device *device);
void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
unsigned int level);
int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device);
@@ -115,4 +114,10 @@
void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state);
void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state);
+
+int kgsl_active_count_get(struct kgsl_device *device);
+int kgsl_active_count_get_light(struct kgsl_device *device);
+void kgsl_active_count_put(struct kgsl_device *device);
+void kgsl_active_count_wait(struct kgsl_device *device);
+
#endif /* __KGSL_PWRCTRL_H */
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 02ada38..afef62e 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -240,6 +240,7 @@
device->pwrscale.policy->busy(device,
&device->pwrscale);
}
+EXPORT_SYMBOL(kgsl_pwrscale_busy);
void kgsl_pwrscale_idle(struct kgsl_device *device)
{
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 595f78f..62db513 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -607,16 +607,22 @@
while (len > 0) {
struct page *page;
- unsigned int gfp_mask = GFP_KERNEL | __GFP_HIGHMEM |
- __GFP_NOWARN | __GFP_NORETRY;
+ unsigned int gfp_mask = __GFP_HIGHMEM;
int j;
/* don't waste space at the end of the allocation*/
if (len < page_size)
page_size = PAGE_SIZE;
+ /*
+ * Don't do some of the more aggressive memory recovery
+ * techniques for large order allocations
+ */
if (page_size != PAGE_SIZE)
- gfp_mask |= __GFP_COMP;
+ gfp_mask |= __GFP_COMP | __GFP_NORETRY |
+ __GFP_NO_KSWAPD | __GFP_NOWARN;
+ else
+ gfp_mask |= GFP_KERNEL | __GFP_NORETRY;
page = alloc_pages(gfp_mask, get_order(page_size));
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 4c9c744..abcebfb 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -325,6 +325,7 @@
return 0;
}
+EXPORT_SYMBOL(kgsl_snapshot_have_object);
/* kgsl_snapshot_get_object - Mark a GPU buffer to be frozen
* @device - the device that is being snapshotted
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index a07959b..49265fc 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -17,7 +17,6 @@
#include "kgsl.h"
#include "kgsl_cffdump.h"
#include "kgsl_sharedmem.h"
-#include "kgsl_trace.h"
#include "z180.h"
#include "z180_reg.h"
@@ -485,7 +484,7 @@
z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, 0);
error:
- trace_kgsl_issueibcmds(device, context->id, ibdesc, numibs,
+ kgsl_trace_issueibcmds(device, context->id, ibdesc, numibs,
*timestamp, ctrl, result, 0);
return (int)result;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index deda0c8..29b269a 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -397,6 +397,7 @@
atomic_t st_enabled;
atomic_t st_pending_irqs;
struct completion st_completion;
+ struct completion st_powerdown;
#endif
};
@@ -1001,8 +1002,8 @@
static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
{
if (atomic_read(&data->st_enabled)) {
- atomic_cmpxchg(&data->st_pending_irqs, 0, 1);
- complete(&data->st_completion);
+ if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0)
+ complete(&data->st_completion);
return IRQ_HANDLED;
}
return IRQ_NONE;
@@ -1996,6 +1997,7 @@
atomic_set(&data->st_enabled, 0);
complete(&data->st_completion);
mxt_interrupt(data->client->irq, data);
+ complete(&data->st_powerdown);
break;
case 1:
if (atomic_read(&data->st_enabled)) {
@@ -2008,6 +2010,8 @@
err = -EIO;
break;
}
+ INIT_COMPLETION(data->st_completion);
+ INIT_COMPLETION(data->st_powerdown);
atomic_set(&data->st_pending_irqs, 0);
atomic_set(&data->st_enabled, 1);
break;
@@ -2035,7 +2039,7 @@
return err;
if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) != 1)
- return -EBADF;
+ return -EINVAL;
return scnprintf(buf, PAGE_SIZE, "%u", 1);
}
@@ -2064,9 +2068,25 @@
.attrs = mxt_attrs,
};
+
+#if defined(CONFIG_SECURE_TOUCH)
+static void mxt_secure_touch_stop(struct mxt_data *data)
+{
+ if (atomic_read(&data->st_enabled)) {
+ complete(&data->st_completion);
+ wait_for_completion_interruptible(&data->st_powerdown);
+ }
+}
+#else
+static void mxt_secure_touch_stop(struct mxt_data *data)
+{
+}
+#endif
+
static int mxt_start(struct mxt_data *data)
{
int error;
+ mxt_secure_touch_stop(data);
/* restore the old power state values and reenable touch */
error = __mxt_write_reg(data->client, data->t7_start_addr,
@@ -2084,6 +2104,7 @@
{
int error;
u8 t7_data[T7_DATA_SIZE] = {0};
+ mxt_secure_touch_stop(data);
error = __mxt_write_reg(data->client, data->t7_start_addr,
T7_DATA_SIZE, t7_data);
@@ -2465,6 +2486,7 @@
/* calibrate */
if (data->pdata->need_calibration) {
+ mxt_secure_touch_stop(data);
error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
MXT_COMMAND_CALIBRATE, 1);
if (error < 0)
@@ -2800,12 +2822,13 @@
#endif
#if defined(CONFIG_SECURE_TOUCH)
-static void __devinit secure_touch_init(struct mxt_data *data)
+static void __devinit mxt_secure_touch_init(struct mxt_data *data)
{
init_completion(&data->st_completion);
+ init_completion(&data->st_powerdown);
}
#else
-static void __devinit secure_touch_init(struct mxt_data *data)
+static void __devinit mxt_secure_touch_init(struct mxt_data *data)
{
}
#endif
@@ -3002,7 +3025,7 @@
mxt_debugfs_init(data);
- secure_touch_init(data);
+ mxt_secure_touch_init(data);
return 0;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 1d34b06..3667296 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -159,6 +159,27 @@
#define PWM_LUT_MAX_SIZE 63
#define RGB_LED_DISABLE 0x00
+#define MPP_MAX_LEVEL LED_FULL
+#define LED_MPP_MODE_CTRL(base) (base + 0x40)
+#define LED_MPP_VIN_CTRL(base) (base + 0x41)
+#define LED_MPP_EN_CTRL(base) (base + 0x46)
+#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
+
+#define LED_MPP_CURRENT_DEFAULT 10
+#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
+
+#define LED_MPP_SINK_MASK 0x07
+#define LED_MPP_MODE_MASK 0x7F
+#define LED_MPP_EN_MASK 0x80
+
+#define LED_MPP_MODE_SINK (0x06 << 4)
+#define LED_MPP_MODE_ENABLE 0x01
+#define LED_MPP_MODE_OUTPUT 0x10
+#define LED_MPP_MODE_DISABLE 0x00
+#define LED_MPP_EN_ENABLE 0x80
+#define LED_MPP_EN_DISABLE 0x00
+
+#define MPP_SOURCE_DTEST1 0x08
/**
* enum qpnp_leds - QPNP supported led ids
* @QPNP_ID_WLED - White led backlight
@@ -170,6 +191,7 @@
QPNP_ID_RGB_RED,
QPNP_ID_RGB_GREEN,
QPNP_ID_RGB_BLUE,
+ QPNP_ID_LED_MPP,
QPNP_ID_MAX,
};
@@ -240,6 +262,11 @@
static u8 rgb_pwm_debug_regs[] = {
0x45, 0x46, 0x47,
};
+
+static u8 mpp_debug_regs[] = {
+ 0x40, 0x41, 0x42, 0x45, 0x46, 0x4c,
+};
+
/**
* wled_config_data - wled configuration data
* @num_strings - number of wled strings supported
@@ -264,6 +291,16 @@
};
/**
+ * mpp_config_data - mpp configuration data
+ * @current_setting - current setting, 5ma-40ma in 5ma increments
+ */
+struct mpp_config_data {
+ u8 current_setting;
+ u8 source_sel;
+ u8 mode_ctrl;
+};
+
+/**
* flash_config_data - flash configuration data
* @current_prgm - current to be programmed, scaled by max level
* @clamp_curr - clamp current to use
@@ -336,6 +373,7 @@
struct wled_config_data *wled_cfg;
struct flash_config_data *flash_cfg;
struct rgb_config_data *rgb_cfg;
+ struct mpp_config_data *mpp_cfg;
int max_current;
bool default_on;
int turn_off_delay_ms;
@@ -458,6 +496,68 @@
return 0;
}
+static int qpnp_mpp_set(struct qpnp_led_data *led)
+{
+ int rc, val;
+
+ if (led->cdev.brightness) {
+ val = (led->cdev.brightness * LED_MPP_SINK_MASK) / LED_FULL;
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_SINK_CTRL(led->base),
+ LED_MPP_SINK_MASK, val);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable reg\n");
+ return rc;
+ }
+
+ val = led->mpp_cfg->source_sel | led->mpp_cfg->mode_ctrl;
+
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_MODE_CTRL(led->base), LED_MPP_MODE_MASK,
+ val);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led mode reg\n");
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK,
+ LED_MPP_EN_ENABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable " \
+ "reg\n");
+ return rc;
+ }
+ } else {
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_MODE_CTRL(led->base),
+ LED_MPP_MODE_MASK,
+ LED_MPP_MODE_DISABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led mode reg\n");
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_EN_CTRL(led->base),
+ LED_MPP_EN_MASK,
+ LED_MPP_EN_DISABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write led enable reg\n");
+ return rc;
+ }
+ }
+
+ qpnp_dump_regs(led, mpp_debug_regs, ARRAY_SIZE(mpp_debug_regs));
+
+ return 0;
+}
+
static int qpnp_flash_set(struct qpnp_led_data *led)
{
int rc;
@@ -750,6 +850,12 @@
dev_err(&led->spmi_dev->dev,
"RGB set brightness failed (%d)\n", rc);
break;
+ case QPNP_ID_LED_MPP:
+ rc = qpnp_mpp_set(led);
+ if (rc < 0)
+ dev_err(&led->spmi_dev->dev,
+ "MPP set brightness failed (%d)\n", rc);
+ break;
default:
dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
break;
@@ -772,6 +878,9 @@
case QPNP_ID_RGB_BLUE:
led->cdev.max_brightness = RGB_MAX_LEVEL;
break;
+ case QPNP_ID_LED_MPP:
+ led->cdev.max_brightness = MPP_MAX_LEVEL;
+ break;
default:
dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
return -EINVAL;
@@ -1211,6 +1320,8 @@
dev_err(&led->spmi_dev->dev,
"RGB initialize failed(%d)\n", rc);
break;
+ case QPNP_ID_LED_MPP:
+ break;
default:
dev_err(&led->spmi_dev->dev, "Invalid LED(%d)\n", led->id);
return -EINVAL;
@@ -1536,6 +1647,43 @@
return 0;
}
+static int __devinit qpnp_get_config_mpp(struct qpnp_led_data *led,
+ struct device_node *node)
+{
+ int rc;
+ u32 val;
+
+ led->mpp_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct mpp_config_data), GFP_KERNEL);
+ if (!led->mpp_cfg) {
+ dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,current-setting", &val);
+ if (!rc)
+ led->mpp_cfg->current_setting = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->mpp_cfg->source_sel = LED_MPP_SOURCE_SEL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,source-sel", &val);
+ if (!rc)
+ led->mpp_cfg->source_sel = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->mpp_cfg->mode_ctrl = LED_MPP_MODE_SINK;
+ rc = of_property_read_u32(node, "qcom,mode-ctrl", &val);
+ if (!rc)
+ led->mpp_cfg->mode_ctrl = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ return 0;
+}
+
static int __devinit qpnp_leds_probe(struct spmi_device *spmi)
{
struct qpnp_led_data *led, *led_array;
@@ -1638,6 +1786,13 @@
"Unable to read rgb config data\n");
goto fail_id_check;
}
+ } else if (strncmp(led_label, "mpp", sizeof("mpp")) == 0) {
+ rc = qpnp_get_config_mpp(led, temp);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read mpp config data\n");
+ goto fail_id_check;
+ }
} else {
dev_err(&led->spmi_dev->dev, "No LED matching label\n");
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 22e8400..263241b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -281,13 +281,16 @@
list_for_each_entry(temp_buf_info,
&bufq->share_head, share_list) {
if (!temp_buf_info->buf_used[id]) {
- *buf_info = temp_buf_info;
temp_buf_info->buf_used[id] = 1;
temp_buf_info->buf_get_count++;
if (temp_buf_info->buf_get_count ==
bufq->buf_client_count)
list_del_init(
&temp_buf_info->share_list);
+ if (temp_buf_info->buf_reuse_flag)
+ kfree(temp_buf_info);
+ else
+ *buf_info = temp_buf_info;
spin_unlock_irqrestore(
&bufq->bufq_lock, flags);
return 0;
@@ -322,21 +325,30 @@
}
if (!(*buf_info)) {
- spin_unlock_irqrestore(&bufq->bufq_lock, flags);
- return rc;
- }
-
- (*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
- if (bufq->buf_type == ISP_SHARE_BUF) {
- memset((*buf_info)->buf_used, 0,
- sizeof(uint8_t) * bufq->buf_client_count);
- (*buf_info)->buf_used[id] = 1;
- (*buf_info)->buf_get_count = 1;
- (*buf_info)->buf_put_count = 0;
- list_add_tail(&(*buf_info)->share_list, &bufq->share_head);
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ temp_buf_info = kzalloc(
+ sizeof(struct msm_isp_buffer), GFP_ATOMIC);
+ temp_buf_info->buf_reuse_flag = 1;
+ temp_buf_info->buf_used[id] = 1;
+ temp_buf_info->buf_get_count = 1;
+ list_add_tail(&temp_buf_info->share_list,
+ &bufq->share_head);
+ }
+ } else {
+ (*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ memset((*buf_info)->buf_used, 0,
+ sizeof(uint8_t) * bufq->buf_client_count);
+ (*buf_info)->buf_used[id] = 1;
+ (*buf_info)->buf_get_count = 1;
+ (*buf_info)->buf_put_count = 0;
+ list_add_tail(&(*buf_info)->share_list,
+ &bufq->share_head);
+ }
+ rc = 0;
}
spin_unlock_irqrestore(&bufq->bufq_lock, flags);
- return 0;
+ return rc;
}
static int msm_isp_put_buf(struct msm_isp_buf_mgr *buf_mgr,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
index d4e7c88..066d02a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
@@ -65,6 +65,7 @@
uint8_t buf_used[ISP_SHARE_BUF_CLIENT];
uint8_t buf_get_count;
uint8_t buf_put_count;
+ uint8_t buf_reuse_flag;
};
struct msm_isp_bufq {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 9fd87f3..2b047ad 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -121,7 +121,7 @@
path->vectors[0].ab = MSM_ISP_MIN_AB;
path->vectors[0].ib = MSM_ISP_MIN_IB;
for (i = 0; i < MAX_ISP_CLIENT; i++) {
- if (isp_bandwidth_mgr.client_info[client].active) {
+ if (isp_bandwidth_mgr.client_info[i].active) {
path->vectors[0].ab +=
isp_bandwidth_mgr.client_info[i].ab;
path->vectors[0].ib +=
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 9dcd64c..90cc61c 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -11,7 +11,6 @@
*/
#include <linux/delay.h>
-#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/jiffies.h>
@@ -60,113 +59,6 @@
false : true;
}
-static struct msm_cam_clk_info ispif_8960_clk_info[] = {
- {"csi_pix_clk", 0},
- {"csi_rdi_clk", 0},
- {"csi_pix1_clk", 0},
- {"csi_rdi1_clk", 0},
- {"csi_rdi2_clk", 0},
-};
-
-static struct msm_cam_clk_info ispif_8974_clk_info_vfe0[] = {
- {"camss_vfe_vfe_clk", -1},
- {"camss_csi_vfe_clk", -1},
-};
-
-static struct msm_cam_clk_info ispif_8974_clk_info_vfe1[] = {
- {"camss_vfe_vfe_clk1", -1},
- {"camss_csi_vfe_clk1", -1},
-};
-
-static int msm_ispif_clk_enable_one(struct ispif_device *ispif,
- enum msm_ispif_vfe_intf vfe_intf, int enable)
-{
- int rc = 0;
-
- if (enable)
- pr_debug("enable clk for VFE%d\n", vfe_intf);
- else
- pr_debug("disable clk for VFE%d\n", vfe_intf);
-
- if (ispif->csid_version < CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk[vfe_intf], 2, enable);
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
- goto end;
- }
- } else if (ispif->csid_version == CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk[vfe_intf],
- ARRAY_SIZE(ispif_8960_clk_info),
- enable);
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
- goto end;
- }
- } else if (ispif->csid_version >= CSID_VERSION_V3) {
- if (vfe_intf == VFE0) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev,
- ispif_8974_clk_info_vfe0,
- ispif->ispif_clk[vfe_intf],
- ARRAY_SIZE(ispif_8974_clk_info_vfe0), enable);
- } else {
- rc = msm_cam_clk_enable(&ispif->pdev->dev,
- ispif_8974_clk_info_vfe1,
- ispif->ispif_clk[vfe_intf],
- ARRAY_SIZE(ispif_8974_clk_info_vfe1), enable);
- }
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d, vfeid = %d\n",
- __func__, rc, vfe_intf);
- goto end;
- }
- } else {
- pr_err("%s: unsupported version=%d\n", __func__,
- ispif->csid_version);
- goto end;
- }
-
-end:
- return rc;
-}
-
-static int msm_ispif_clk_enable(struct ispif_device *ispif,
- struct msm_ispif_param_data *params, int enable)
-{
- int rc = 0;
- int i, j;
- uint32_t vfe_intf_mask = 0;
-
- for (i = 0; i < params->num; i++) {
- if (vfe_intf_mask & (1 << params->entries[i].vfe_intf))
- continue;
- rc = msm_ispif_clk_enable_one(ispif,
- params->entries[i].vfe_intf, 1);
- if (rc < 0 && enable) {
- pr_err("%s: unable to enable clocks for VFE %d",
- __func__, params->entries[i].vfe_intf);
- for (j = 0; j < i; j++) {
- /* if VFE clock is not enabled do
- * not disable the clock */
- if (!(vfe_intf_mask & (1 <<
- params->entries[i].vfe_intf)))
- continue;
- msm_ispif_clk_enable_one(ispif,
- params->entries[j].vfe_intf, 0);
- /* remove the VFE ID from the mask */
- vfe_intf_mask &=
- ~(1 << params->entries[i].vfe_intf);
- }
- break;
- }
- vfe_intf_mask |= 1 << params->entries[i].vfe_intf;
- }
- return rc;
-}
-
static struct msm_cam_clk_info ispif_8974_ahb_clk_info[] = {
{"ispif_ahb_clk", -1},
};
@@ -191,139 +83,51 @@
return rc;
}
-static int msm_ispif_intf_reset(struct ispif_device *ispif,
- struct msm_ispif_param_data *params)
-{
-
- int i, rc = 0;
- enum msm_ispif_intftype intf_type;
- int vfe_intf = 0;
- uint32_t data = 0;
-
- for (i = 0; i < params->num; i++) {
- data = STROBED_RST_EN;
- vfe_intf = params->entries[i].vfe_intf;
- intf_type = params->entries[i].intftype;
- ispif->sof_count[params->entries[i].vfe_intf].
- sof_cnt[intf_type] = 0;
-
- switch (intf_type) {
- case PIX0:
- data |= (PIX_0_VFE_RST_STB | PIX_0_CSID_RST_STB);
- break;
- case RDI0:
- data |= (RDI_0_VFE_RST_STB | RDI_0_CSID_RST_STB);
- break;
- case PIX1:
- data |= (PIX_1_VFE_RST_STB | PIX_1_CSID_RST_STB);
- break;
- case RDI1:
- data |= (RDI_1_VFE_RST_STB | RDI_1_CSID_RST_STB);
- break;
- case RDI2:
- data |= (RDI_2_VFE_RST_STB | RDI_2_CSID_RST_STB);
- break;
- default:
- rc = -EINVAL;
- break;
- }
- if (data > 0x1) {
- unsigned long jiffes = msecs_to_jiffies(500);
- long lrc = 0;
- unsigned long flags;
-
- spin_lock_irqsave(
- &ispif->auto_complete_lock, flags);
- ispif->wait_timeout[vfe_intf] = 0;
- init_completion(&ispif->reset_complete[vfe_intf]);
- spin_unlock_irqrestore(
- &ispif->auto_complete_lock, flags);
-
- if (vfe_intf == VFE0)
- msm_camera_io_w(data, ispif->base +
- ISPIF_RST_CMD_ADDR);
- else
- msm_camera_io_w(data, ispif->base +
- ISPIF_RST_CMD_1_ADDR);
- lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete[vfe_intf], jiffes);
- if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld, vfe_id = %d\n",
- __func__, lrc, vfe_intf);
- rc = -EIO;
-
- spin_lock_irqsave(
- &ispif->auto_complete_lock, flags);
- ispif->wait_timeout[vfe_intf] = 1;
- spin_unlock_irqrestore(
- &ispif->auto_complete_lock, flags);
- }
- }
- }
-
- return rc;
-}
-
static int msm_ispif_reset(struct ispif_device *ispif)
{
int rc = 0;
- long lrc = 0;
- unsigned long jiffes = msecs_to_jiffies(500);
- unsigned long flags;
-
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[VFE0] = 0;
- init_completion(&ispif->reset_complete[VFE0]);
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1) {
- ispif->wait_timeout[VFE1] = 0;
- init_completion(&ispif->reset_complete[VFE1]);
- }
- spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
+ int i;
BUG_ON(!ispif);
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
- msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
+ for (i = 0; i < ispif->vfe_info.num_vfe; i++) {
- lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete[VFE0], jiffes);
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_CTRL_0(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(i));
+ msm_camera_io_w(0xFFFFFFFF, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_0(i));
+ msm_camera_io_w(0xFFFFFFFF, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_1(i));
+ msm_camera_io_w(0xFFFFFFFF, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_2(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INPUT_SEL(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
+ msm_camera_io_w(0, ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
- if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
- __func__, lrc, VFE0);
- rc = -EIO;
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 1));
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 2));
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[VFE0] = 1;
- spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
-
- goto end;
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CROP(i, 0));
+ msm_camera_io_w(0, ispif->base +
+ ISPIF_VFE_m_PIX_INTF_n_CROP(i, 1));
}
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1) {
- msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base +
- ISPIF_RST_CMD_1_ADDR);
+ msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
- lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete[VFE1], jiffes);
-
- if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
- __func__, lrc, VFE1);
- rc = -EIO;
-
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[VFE1] = 1;
- spin_unlock_irqrestore(&ispif->auto_complete_lock,
- flags);
- }
-
- }
-
-end:
return rc;
}
@@ -339,7 +143,6 @@
static void msm_ispif_sel_csid_core(struct ispif_device *ispif,
uint8_t intftype, uint8_t csid, uint8_t vfe_intf)
{
- int rc = 0;
uint32_t data;
BUG_ON(!ispif);
@@ -349,19 +152,6 @@
return;
}
- if (ispif->csid_version <= CSID_VERSION_V2) {
- if (ispif->ispif_clk[vfe_intf][intftype] == NULL) {
- CDBG("%s: ispif NULL clk\n", __func__);
- return;
- }
-
- rc = clk_set_rate(ispif->ispif_clk[vfe_intf][intftype], csid);
- if (rc) {
- pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
- return;
- }
- }
-
data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf));
switch (intftype) {
case PIX0:
@@ -536,11 +326,6 @@
return rc;
}
- rc = msm_ispif_clk_enable(ispif, params, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks", __func__);
- return rc;
- }
for (i = 0; i < params->num; i++) {
vfe_intf = params->entries[i].vfe_intf;
if (!msm_ispif_is_intf_valid(ispif->csid_version,
@@ -615,8 +400,6 @@
msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
- msm_ispif_clk_enable(ispif, params, 0);
-
return rc;
}
@@ -709,7 +492,7 @@
static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
- int rc;
+ int rc = 0;
if (ispif->ispif_state != ISPIF_POWER_UP) {
pr_err("%s: ispif invalid state %d\n", __func__,
@@ -718,23 +501,8 @@
return rc;
}
- rc = msm_ispif_clk_enable(ispif, params, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks", __func__);
- return rc;
- }
-
- rc = msm_ispif_intf_reset(ispif, params);
- if (rc) {
- pr_err("%s: msm_ispif_intf_reset failed. rc=%d\n",
- __func__, rc);
- goto end;
- }
-
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
-end:
- msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -757,12 +525,6 @@
return rc;
}
- rc = msm_ispif_clk_enable(ispif, params, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks", __func__);
- return rc;
- }
-
for (i = 0; i < params->num; i++) {
if (!msm_ispif_is_intf_valid(ispif->csid_version,
params->entries[i].vfe_intf)) {
@@ -814,8 +576,6 @@
}
end:
- msm_ispif_clk_enable(ispif, params, 0);
-
return rc;
}
@@ -886,15 +646,6 @@
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
- if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ) {
- unsigned long flags;
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- if (ispif->wait_timeout[VFE0] == 0)
- complete(&ispif->reset_complete[VFE0]);
- spin_unlock_irqrestore(
- &ispif->auto_complete_lock, flags);
- }
-
if (out[VFE0].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ)
pr_err("%s: VFE0 pix0 overflow.\n", __func__);
@@ -910,15 +661,6 @@
ispif_process_irq(ispif, out, VFE0);
}
if (ispif->vfe_info.num_vfe > 1) {
- if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ) {
- unsigned long flags;
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- if (ispif->wait_timeout[VFE1] == 0)
- complete(&ispif->reset_complete[VFE1]);
- spin_unlock_irqrestore(
- &ispif->auto_complete_lock, flags);
- }
-
if (out[VFE1].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ)
pr_err("%s: VFE1 pix0 overflow.\n", __func__);
@@ -973,21 +715,6 @@
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
ispif->csid_version = csid_version;
- rc = msm_ispif_clk_enable_one(ispif, VFE0, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE0", __func__);
- goto error_clk0;
- }
-
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1) {
- rc = msm_ispif_clk_enable_one(ispif, VFE1, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE1",
- __func__);
- goto error_clk1;
- }
- }
ispif->base = ioremap(ispif->mem->start,
resource_size(ispif->mem));
@@ -1022,20 +749,11 @@
iounmap(ispif->base);
end:
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1)
- msm_ispif_clk_enable_one(ispif, VFE1, 0);
-
-error_clk1:
- msm_ispif_clk_enable_one(ispif, VFE0, 0);
-
-error_clk0:
return rc;
}
static void msm_ispif_release(struct ispif_device *ispif)
{
- int i;
BUG_ON(!ispif);
if (ispif->ispif_state != ISPIF_POWER_UP) {
@@ -1044,9 +762,6 @@
return;
}
- for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable_one(ispif, i, 1);
-
/* make sure no streaming going on */
msm_ispif_reset(ispif);
@@ -1056,9 +771,6 @@
iounmap(ispif->base);
- for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable_one(ispif, i, 0);
-
ispif->ispif_state = ISPIF_POWER_DOWN;
}
@@ -1177,7 +889,6 @@
{
int rc;
struct ispif_device *ispif;
- int i;
ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
if (!ispif) {
@@ -1235,9 +946,6 @@
ispif->pdev = pdev;
ispif->ispif_state = ISPIF_POWER_DOWN;
ispif->open_cnt = 0;
- spin_lock_init(&ispif->auto_complete_lock);
- for (i = 0; i < VFE_MAX; i++)
- ispif->wait_timeout[i] = 0;
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
index 945b5b8..fae7a38 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
@@ -47,16 +47,12 @@
void __iomem *base;
struct mutex mutex;
uint8_t start_ack_pending;
- struct completion reset_complete[VFE_MAX];
- spinlock_t auto_complete_lock;
- uint8_t wait_timeout[VFE_MAX];
uint32_t csid_version;
int enb_dump_reg;
uint32_t open_cnt;
struct ispif_sof_count sof_count[VFE_MAX];
struct ispif_intf_cmd applied_intf_cmd[VFE_MAX];
enum msm_ispif_state_t ispif_state;
- struct clk *ispif_clk[VFE_MAX][INTF_MAX];
struct msm_ispif_vfe_info vfe_info;
struct clk *ahb_clk;
};
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 1203d17..8cdaa4b 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -588,7 +588,7 @@
pr_err("%s: Bandwidth registration Failed!\n", __func__);
goto bus_scale_register_failed;
}
- msm_isp_update_bandwidth(ISP_CPP, 981345600, 1600020000);
+ msm_isp_update_bandwidth(ISP_CPP, 981345600, 1066680000);
if (cpp_dev->fs_cpp == NULL) {
cpp_dev->fs_cpp =
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 0d5dc8c..ddf271e 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1057,6 +1057,40 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
break;
}
+ case HAL_PARAM_VENC_SESSION_QP_RANGE:
+ {
+ struct hfi_quantization_range *hfi;
+ struct hfi_quantization_range *hal_range =
+ (struct hfi_quantization_range *) pdata;
+ u32 min_qp, max_qp;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
+ hfi = (struct hfi_quantization_range *)
+ &pkt->rg_property_data[1];
+
+ min_qp = hal_range->min_qp;
+ max_qp = hal_range->max_qp;
+
+ /* We'll be packing in the qp, so make sure we
+ * won't be losing data when masking */
+ if (min_qp > 0xff || max_qp > 0xff) {
+ dprintk(VIDC_ERR, "qp value out of range\n");
+ rc = -ERANGE;
+ break;
+ }
+
+ /* When creating the packet, pack the qp value as
+ * 0xiippbb, where ii = qp range for I-frames,
+ * pp = qp range for P-frames, etc. */
+ hfi->min_qp = min_qp | min_qp << 8 | min_qp << 16;
+ hfi->max_qp = max_qp | max_qp << 8 | max_qp << 16;
+ hfi->layer_id = hal_range->layer_id;
+
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_quantization_range);
+ break;
+ }
case HAL_CONFIG_VENC_INTRA_PERIOD:
{
struct hfi_intra_period *hfi;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 8ce7414..464cb05 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -419,6 +419,30 @@
.cluster = MSM_VENC_CTRL_CLUSTER_QP,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+ .name = "H264 Minimum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 51,
+ .default_value = 1,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ .cluster = MSM_VENC_CTRL_CLUSTER_QP,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+ .name = "H264 Maximum QP",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .minimum = 1,
+ .maximum = 51,
+ .default_value = 51,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ .cluster = MSM_VENC_CTRL_CLUSTER_QP,
+ },
+ {
.id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
.name = "Slice Mode",
.type = V4L2_CTRL_TYPE_MENU,
@@ -1138,6 +1162,7 @@
struct hal_h264_db_control h264_db_control;
struct hal_enable enable;
struct hal_h264_vui_timing_info vui_timing_info;
+ struct hal_quantization_range qp_range;
u32 property_id = 0, property_val = 0;
void *pdata = NULL;
struct v4l2_ctrl *temp_ctrl = NULL;
@@ -1467,6 +1492,44 @@
pdata = &quantization;
break;
}
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: {
+ struct v4l2_ctrl *qp_max;
+
+ qp_max = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MAX_QP);
+ if (ctrl->val >= qp_max->val) {
+ dprintk(VIDC_ERR, "Bad range: Min QP (%d) > Max QP(%d)",
+ ctrl->val, qp_max->val);
+ rc = -ERANGE;
+ break;
+ }
+
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = qp_max->val;
+ qp_range.min_qp = ctrl->val;
+
+ pdata = &qp_range;
+ break;
+ }
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: {
+ struct v4l2_ctrl *qp_min;
+
+ qp_min = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MIN_QP);
+ if (ctrl->val <= qp_min->val) {
+ dprintk(VIDC_ERR, "Bad range: Max QP (%d) < Min QP(%d)",
+ ctrl->val, qp_min->val);
+ rc = -ERANGE;
+ break;
+ }
+
+ property_id = HAL_PARAM_VENC_SESSION_QP_RANGE;
+ qp_range.layer_id = 0;
+ qp_range.max_qp = ctrl->val;
+ qp_range.min_qp = qp_min->val;
+
+ pdata = &qp_range;
+ break;
+ }
case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: {
int temp = 0;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index dc08c64..d925de3 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1282,7 +1282,6 @@
}
hdev = inst->core->device;
-
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
dprintk(VIDC_INFO, "inst: %p is already in state: %d\n",
inst, inst->state);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index c91d1d2..5ba191f 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -130,6 +130,7 @@
HAL_PARAM_VENC_H264_DEBLOCK_CONTROL,
HAL_PARAM_VENC_TEMPORAL_SPATIAL_TRADEOFF,
HAL_PARAM_VENC_SESSION_QP,
+ HAL_PARAM_VENC_SESSION_QP_RANGE,
HAL_CONFIG_VENC_INTRA_PERIOD,
HAL_CONFIG_VENC_IDR_PERIOD,
HAL_CONFIG_VPE_OPERATIONS,
@@ -596,6 +597,12 @@
u32 layer_id;
};
+struct hal_quantization_range {
+ u32 min_qp;
+ u32 max_qp;
+ u32 layer_id;
+};
+
struct hal_intra_period {
u32 pframes;
u32 bframes;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 61adfec..55e3e4e 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -673,7 +673,7 @@
app_id = ret;
if (app_id) {
- pr_warn("App id %d (%s) already exists\n", app_id,
+ pr_debug("App id %d (%s) already exists\n", app_id,
(char *)(req.app_name));
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
@@ -831,7 +831,7 @@
break;
} else {
ptr_app->ref_cnt--;
- pr_warn("Can't unload app(%d) inuse\n",
+ pr_debug("Can't unload app(%d) inuse\n",
ptr_app->app_id);
break;
}
@@ -2316,7 +2316,7 @@
pr_err(" scm call to check if app is loaded failed");
return ret; /* scm call failed */
} else if (ret > 0) {
- pr_warn("App id %d (%s) already exists\n", ret,
+ pr_debug("App id %d (%s) already exists\n", ret,
(char *)(req.app_name));
spin_lock_irqsave(&qseecom.registered_app_list_lock, flags);
list_for_each_entry(entry,
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index da0a5b6..a875c92 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1383,6 +1383,7 @@
if (state == ADC_TM_WARM_STATE) {
if (temp > chip->warm_bat_decidegc) {
+ /* Normal to warm */
bat_warm = true;
bat_cool = false;
chip->adc_param.low_temp =
@@ -1391,6 +1392,7 @@
ADC_TM_COOL_THR_ENABLE;
} else if (temp >
chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
+ /* Cool to normal */
bat_warm = false;
bat_cool = false;
@@ -1401,14 +1403,16 @@
}
} else {
if (temp < chip->cool_bat_decidegc) {
+ /* Normal to cool */
bat_warm = false;
bat_cool = true;
chip->adc_param.high_temp =
chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
chip->adc_param.state_request =
ADC_TM_WARM_THR_ENABLE;
- } else if (temp >
+ } else if (temp <
chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
+ /* Warm to normal */
bat_warm = false;
bat_cool = false;
@@ -1679,10 +1683,10 @@
rc = qpnp_chg_masked_write(chip, chip->chgr_base + 0x62,
0xFF, 0xA0, 1);
- /* HACK: use digital EOC */
+ /* HACK: use analog EOC */
rc = qpnp_chg_masked_write(chip, chip->chgr_base +
CHGR_IBAT_TERM_CHGR,
- 0x88, 0x80, 1);
+ 0x80, 0x00, 1);
break;
case SMBB_BUCK_SUBTYPE:
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 4cdfaeb..2d10f89 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,12 +19,14 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/spmi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/ktime.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/qpnp-regulator.h>
@@ -36,6 +38,7 @@
QPNP_VREG_DEBUG_INIT = BIT(2), /* Show state after probe */
QPNP_VREG_DEBUG_WRITES = BIT(3), /* Show SPMI writes */
QPNP_VREG_DEBUG_READS = BIT(4), /* Show SPMI reads */
+ QPNP_VREG_DEBUG_OCP = BIT(5), /* Show VS OCP IRQ events */
};
static int qpnp_vreg_debug_mask;
@@ -156,9 +159,8 @@
#define QPNP_LDO_SOFT_START_ENABLE_MASK 0x80
/* VS regulator over current protection control register layout */
-#define QPNP_VS_OCP_ENABLE_MASK 0x80
-#define QPNP_VS_OCP_OVERRIDE_MASK 0x01
-#define QPNP_VS_OCP_DISABLE 0x00
+#define QPNP_VS_OCP_OVERRIDE 0x01
+#define QPNP_VS_OCP_NO_OVERRIDE 0x00
/* VS regulator soft start control register layout */
#define QPNP_VS_SOFT_START_ENABLE_MASK 0x80
@@ -168,6 +170,11 @@
#define QPNP_BOOST_CURRENT_LIMIT_ENABLE_MASK 0x80
#define QPNP_BOOST_CURRENT_LIMIT_MASK 0x07
+#define QPNP_VS_OCP_DEFAULT_MAX_RETRIES 10
+#define QPNP_VS_OCP_DEFAULT_RETRY_DELAY_MS 30
+#define QPNP_VS_OCP_FALL_DELAY_US 90
+#define QPNP_VS_OCP_FAULT_DELAY_US 20000
+
/*
* This voltage in uV is returned by get_voltage functions when there is no way
* to determine the current voltage level. It is needed because the regulator
@@ -203,17 +210,22 @@
struct qpnp_regulator {
struct regulator_desc rdesc;
+ struct delayed_work ocp_work;
struct spmi_device *spmi_dev;
struct regulator_dev *rdev;
struct qpnp_voltage_set_points *set_points;
enum qpnp_regulator_logical_type logical_type;
int enable_time;
- int ocp_enable_time;
int ocp_enable;
+ int ocp_irq;
+ int ocp_count;
+ int ocp_max_retries;
+ int ocp_retry_delay_ms;
int system_load;
int hpm_min_load;
u32 write_count;
u32 prev_write_count;
+ ktime_t vs_enable_time;
u16 base_addr;
/* ctrl_reg provides a shadow copy of register values 0x40 to 0x47. */
u8 ctrl_reg[8];
@@ -501,35 +513,11 @@
static int qpnp_regulator_vs_enable(struct regulator_dev *rdev)
{
struct qpnp_regulator *vreg = rdev_get_drvdata(rdev);
- int rc;
- u8 reg;
- if (vreg->ocp_enable == QPNP_REGULATOR_ENABLE) {
- /* Disable OCP */
- reg = QPNP_VS_OCP_DISABLE;
- rc = qpnp_vreg_write(vreg, QPNP_VS_REG_OCP, ®, 1);
- if (rc)
- goto fail;
- }
+ if (vreg->ocp_irq)
+ vreg->vs_enable_time = ktime_get();
- rc = qpnp_regulator_common_enable(rdev);
- if (rc)
- goto fail;
-
- if (vreg->ocp_enable == QPNP_REGULATOR_ENABLE) {
- /* Wait for inrush current to subsided, then enable OCP. */
- udelay(vreg->ocp_enable_time);
- reg = QPNP_VS_OCP_ENABLE_MASK;
- rc = qpnp_vreg_write(vreg, QPNP_VS_REG_OCP, ®, 1);
- if (rc)
- goto fail;
- }
-
- return rc;
-fail:
- vreg_err(vreg, "qpnp_vreg_write failed, rc=%d\n", rc);
-
- return rc;
+ return qpnp_regulator_common_enable(rdev);
}
static int qpnp_regulator_common_disable(struct regulator_dev *rdev)
@@ -785,6 +773,88 @@
return vreg->enable_time;
}
+static int qpnp_regulator_vs_clear_ocp(struct qpnp_regulator *vreg)
+{
+ int rc;
+
+ rc = qpnp_vreg_masked_write(vreg, QPNP_COMMON_REG_ENABLE,
+ QPNP_COMMON_DISABLE, QPNP_COMMON_ENABLE_MASK,
+ &vreg->ctrl_reg[QPNP_COMMON_IDX_ENABLE]);
+ if (rc)
+ vreg_err(vreg, "qpnp_vreg_masked_write failed, rc=%d\n", rc);
+
+ vreg->vs_enable_time = ktime_get();
+
+ rc = qpnp_vreg_masked_write(vreg, QPNP_COMMON_REG_ENABLE,
+ QPNP_COMMON_ENABLE, QPNP_COMMON_ENABLE_MASK,
+ &vreg->ctrl_reg[QPNP_COMMON_IDX_ENABLE]);
+ if (rc)
+ vreg_err(vreg, "qpnp_vreg_masked_write failed, rc=%d\n", rc);
+
+ if (qpnp_vreg_debug_mask & QPNP_VREG_DEBUG_OCP) {
+ pr_info("%s: switch state toggled after OCP event\n",
+ vreg->rdesc.name);
+ }
+
+ return rc;
+}
+
+static void qpnp_regulator_vs_ocp_work(struct work_struct *work)
+{
+ struct delayed_work *dwork
+ = container_of(work, struct delayed_work, work);
+ struct qpnp_regulator *vreg
+ = container_of(dwork, struct qpnp_regulator, ocp_work);
+
+ qpnp_regulator_vs_clear_ocp(vreg);
+
+ return;
+}
+
+static irqreturn_t qpnp_regulator_vs_ocp_isr(int irq, void *data)
+{
+ struct qpnp_regulator *vreg = data;
+ ktime_t ocp_irq_time;
+ s64 ocp_trigger_delay_us;
+
+ ocp_irq_time = ktime_get();
+ ocp_trigger_delay_us = ktime_us_delta(ocp_irq_time,
+ vreg->vs_enable_time);
+
+ /*
+ * Reset the OCP count if there is a large delay between switch enable
+ * and when OCP triggers. This is indicative of a hotplug event as
+ * opposed to a fault.
+ */
+ if (ocp_trigger_delay_us > QPNP_VS_OCP_FAULT_DELAY_US)
+ vreg->ocp_count = 0;
+
+ /* Wait for switch output to settle back to 0 V after OCP triggered. */
+ udelay(QPNP_VS_OCP_FALL_DELAY_US);
+
+ vreg->ocp_count++;
+
+ if (qpnp_vreg_debug_mask & QPNP_VREG_DEBUG_OCP) {
+ pr_info("%s: VS OCP triggered, count = %d, delay = %lld us\n",
+ vreg->rdesc.name, vreg->ocp_count,
+ ocp_trigger_delay_us);
+ }
+
+ if (vreg->ocp_count == 1) {
+ /* Immediately clear the over current condition. */
+ qpnp_regulator_vs_clear_ocp(vreg);
+ } else if (vreg->ocp_count <= vreg->ocp_max_retries) {
+ /* Schedule the over current clear task to run later. */
+ schedule_delayed_work(&vreg->ocp_work,
+ msecs_to_jiffies(vreg->ocp_retry_delay_ms) + 1);
+ } else {
+ vreg_err(vreg, "OCP triggered %d times; no further retries\n",
+ vreg->ocp_count);
+ }
+
+ return IRQ_HANDLED;
+}
+
static const char const *qpnp_print_actions[] = {
[QPNP_REGULATOR_ACTION_INIT] = "initial ",
[QPNP_REGULATOR_ACTION_ENABLE] = "enable ",
@@ -834,7 +904,8 @@
if (type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
|| type == QPNP_REGULATOR_LOGICAL_TYPE_LDO
- || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS) {
+ || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS
+ || type == QPNP_REGULATOR_LOGICAL_TYPE_VS) {
mode = qpnp_regulator_common_get_mode(rdev);
mode_label = mode == REGULATOR_MODE_NORMAL ? "HPM" : "LPM";
}
@@ -903,9 +974,9 @@
pc_mode_label[1] =
mode_reg & QPNP_COMMON_MODE_FOLLOW_AWAKE_MASK ? 'W' : '_';
- pr_info("%s %-11s: %s, pc_en=%s, alt_mode=%s\n",
+ pr_info("%s %-11s: %s, mode=%s, pc_en=%s, alt_mode=%s\n",
action_label, vreg->rdesc.name, enable_label,
- pc_enable_label, pc_mode_label);
+ mode_label, pc_enable_label, pc_mode_label);
break;
case QPNP_REGULATOR_LOGICAL_TYPE_BOOST:
pr_info("%s %-11s: %s, v=%7d uV\n",
@@ -1099,6 +1170,17 @@
pdata->pin_ctrl_enable & QPNP_COMMON_ENABLE_FOLLOW_ALL_MASK;
}
+ /* Set up HPM control. */
+ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
+ || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO
+ || type == QPNP_REGULATOR_LOGICAL_TYPE_VS
+ || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS)
+ && (pdata->hpm_enable != QPNP_REGULATOR_USE_HW_DEFAULT)) {
+ ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_HPM_MASK;
+ ctrl_reg[QPNP_COMMON_IDX_MODE] |=
+ (pdata->hpm_enable ? QPNP_COMMON_MODE_HPM_MASK : 0);
+ }
+
/* Set up auto mode control. */
if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS
|| type == QPNP_REGULATOR_LOGICAL_TYPE_LDO
@@ -1224,7 +1306,8 @@
}
if (pdata->ocp_enable != QPNP_REGULATOR_USE_HW_DEFAULT) {
- reg = pdata->ocp_enable ? QPNP_VS_OCP_ENABLE_MASK : 0;
+ reg = pdata->ocp_enable ? QPNP_VS_OCP_NO_OVERRIDE
+ : QPNP_VS_OCP_OVERRIDE;
rc = qpnp_vreg_write(vreg, QPNP_VS_REG_OCP, ®, 1);
if (rc) {
vreg_err(vreg, "spmi write failed, rc=%d\n",
@@ -1256,6 +1339,11 @@
}
pdata->base_addr = res->start;
+ /* OCP IRQ is optional so ignore get errors. */
+ pdata->ocp_irq = spmi_get_irq_byname(spmi, NULL, "ocp");
+ if (pdata->ocp_irq < 0)
+ pdata->ocp_irq = 0;
+
/*
* Initialize configuration parameters to use hardware default in case
* no value is specified via device tree.
@@ -1269,6 +1357,7 @@
pdata->pin_ctrl_enable = QPNP_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT;
pdata->pin_ctrl_hpm = QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT;
pdata->vs_soft_start_strength = QPNP_VS_SOFT_START_STR_HW_DEFAULT;
+ pdata->hpm_enable = QPNP_REGULATOR_USE_HW_DEFAULT;
/* These bindings are optional, so it is okay if they are not found. */
of_property_read_u32(node, "qcom,auto-mode-enable",
@@ -1276,6 +1365,10 @@
of_property_read_u32(node, "qcom,bypass-mode-enable",
&pdata->bypass_mode_enable);
of_property_read_u32(node, "qcom,ocp-enable", &pdata->ocp_enable);
+ of_property_read_u32(node, "qcom,ocp-max-retries",
+ &pdata->ocp_max_retries);
+ of_property_read_u32(node, "qcom,ocp-retry-delay",
+ &pdata->ocp_retry_delay_ms);
of_property_read_u32(node, "qcom,pull-down-enable",
&pdata->pull_down_enable);
of_property_read_u32(node, "qcom,soft-start-enable",
@@ -1285,12 +1378,11 @@
of_property_read_u32(node, "qcom,pin-ctrl-enable",
&pdata->pin_ctrl_enable);
of_property_read_u32(node, "qcom,pin-ctrl-hpm", &pdata->pin_ctrl_hpm);
+ of_property_read_u32(node, "qcom,hpm-enable", &pdata->hpm_enable);
of_property_read_u32(node, "qcom,vs-soft-start-strength",
&pdata->vs_soft_start_strength);
of_property_read_u32(node, "qcom,system-load", &pdata->system_load);
of_property_read_u32(node, "qcom,enable-time", &pdata->enable_time);
- of_property_read_u32(node, "qcom,ocp-enable-time",
- &pdata->ocp_enable_time);
return rc;
}
@@ -1364,7 +1456,14 @@
vreg->enable_time = pdata->enable_time;
vreg->system_load = pdata->system_load;
vreg->ocp_enable = pdata->ocp_enable;
- vreg->ocp_enable_time = pdata->ocp_enable_time;
+ vreg->ocp_irq = pdata->ocp_irq;
+ vreg->ocp_max_retries = pdata->ocp_max_retries;
+ vreg->ocp_retry_delay_ms = pdata->ocp_retry_delay_ms;
+
+ if (vreg->ocp_max_retries == 0)
+ vreg->ocp_max_retries = QPNP_VS_OCP_DEFAULT_MAX_RETRIES;
+ if (vreg->ocp_retry_delay_ms == 0)
+ vreg->ocp_retry_delay_ms = QPNP_VS_OCP_DEFAULT_RETRY_DELAY_MS;
rdesc = &vreg->rdesc;
rdesc->id = spmi->ctrl->nr;
@@ -1414,18 +1513,37 @@
goto bail;
}
+ if (vreg->logical_type != QPNP_REGULATOR_LOGICAL_TYPE_VS)
+ vreg->ocp_irq = 0;
+
+ if (vreg->ocp_irq) {
+ rc = devm_request_irq(&spmi->dev, vreg->ocp_irq,
+ qpnp_regulator_vs_ocp_isr, IRQF_TRIGGER_RISING, "ocp",
+ vreg);
+ if (rc < 0) {
+ vreg_err(vreg, "failed to request irq %d, rc=%d\n",
+ vreg->ocp_irq, rc);
+ goto bail;
+ }
+
+ INIT_DELAYED_WORK(&vreg->ocp_work, qpnp_regulator_vs_ocp_work);
+ }
+
vreg->rdev = regulator_register(rdesc, &spmi->dev,
&(pdata->init_data), vreg, spmi->dev.of_node);
if (IS_ERR(vreg->rdev)) {
rc = PTR_ERR(vreg->rdev);
vreg_err(vreg, "regulator_register failed, rc=%d\n", rc);
- goto bail;
+ goto cancel_ocp_work;
}
qpnp_vreg_show_state(vreg->rdev, QPNP_REGULATOR_ACTION_INIT);
return 0;
+cancel_ocp_work:
+ if (vreg->ocp_irq)
+ cancel_delayed_work_sync(&vreg->ocp_work);
bail:
if (rc)
vreg_err(vreg, "probe failed, rc=%d\n", rc);
@@ -1445,6 +1563,8 @@
if (vreg) {
regulator_unregister(vreg->rdev);
+ if (vreg->ocp_irq)
+ cancel_delayed_work_sync(&vreg->ocp_work);
kfree(vreg->rdesc.name);
kfree(vreg);
}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 9a864aa..4a3ea76 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -37,8 +37,6 @@
#define QC_DEVID_SAT2 0x4
#define QC_DEVID_PGD 0x5
#define QC_MSM_DEVS 5
-#define INIT_MX_RETRIES 10
-#define DEF_RETRY_MS 10
/* Manager registers */
enum mgr_reg {
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 63d3750..a0179cb 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -631,6 +631,7 @@
if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
struct slim_msg_txn txn;
+ int retries = 0;
u8 wbuf[8];
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.ec = 0;
@@ -638,7 +639,6 @@
txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
txn.la = SLIM_LA_MGR;
- txn.rl = 8;
wbuf[0] = SAT_MAGIC_LSB;
wbuf[1] = SAT_MAGIC_MSB;
wbuf[2] = SAT_MSG_VER;
@@ -655,7 +655,8 @@
/* make sure NGD MSG-Q config goes through */
mb();
}
-
+capability_retry:
+ txn.rl = 8;
ret = ngd_xfer_msg(&dev->ctrl, &txn);
if (!ret) {
enum msm_ctrl_state prev_state = dev->state;
@@ -668,6 +669,13 @@
/* ADSP SSR, send device_up notifications */
if (prev_state == MSM_CTRL_DOWN)
schedule_work(&dev->slave_notify);
+ } else if (ret == -EIO) {
+ pr_info("capability message NACKed, retrying");
+ if (retries < INIT_MX_RETRIES) {
+ msleep(DEF_RETRY_MS);
+ retries++;
+ goto capability_retry;
+ }
}
}
if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 6ff3f19..cf2d26f 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -50,6 +50,8 @@
#define SLIM_MSG_ASM_FIRST_WORD(l, mt, mc, dt, ad) \
((l) | ((mt) << 5) | ((mc) << 8) | ((dt) << 15) | ((ad) << 16))
+#define INIT_MX_RETRIES 10
+#define DEF_RETRY_MS 10
#define MSM_CONCUR_MSG 8
#define SAT_CONCUR_MSG 8
#define DEF_WATERMARK (8 << 1)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 5bbf106..924e8f4 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -127,6 +127,8 @@
#define DBM_TRB_DMA 0x20000000
#define DBM_TRB_EP_NUM(ep) (ep<<24)
+#define USB3_PORTSC (0x430)
+#define PORT_PE (0x1 << 1)
/**
* USB QSCRATCH Hardware registers
*
@@ -213,6 +215,9 @@
bool vbus_active;
bool ext_inuse;
enum dwc3_id_state id_state;
+ unsigned long lpm_flags;
+#define MDWC3_CORECLK_OFF BIT(0)
+#define MDWC3_TCXO_SHUTDOWN BIT(1)
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1588,6 +1593,7 @@
int ret;
bool dcp;
bool host_bus_suspend;
+ bool host_ss_active;
dev_dbg(mdwc->dev, "%s: entering lpm\n", __func__);
@@ -1596,6 +1602,7 @@
return 0;
}
+ host_ss_active = dwc3_msm_read_reg(mdwc->base, USB3_PORTSC) & PORT_PE;
if (mdwc->hs_phy_irq)
disable_irq(mdwc->hs_phy_irq);
@@ -1665,14 +1672,19 @@
/* make sure above writes are completed before turning off clocks */
wmb();
- clk_disable_unprepare(mdwc->core_clk);
+ if (!host_bus_suspend || !host_ss_active) {
+ clk_disable_unprepare(mdwc->core_clk);
+ mdwc->lpm_flags |= MDWC3_CORECLK_OFF;
+ }
clk_disable_unprepare(mdwc->iface_clk);
- if (!host_bus_suspend) {
+ if (!host_bus_suspend)
clk_disable_unprepare(mdwc->utmi_clk);
+ if (!host_bus_suspend) {
/* USB PHY no more requires TCXO */
clk_disable_unprepare(mdwc->xo_clk);
+ mdwc->lpm_flags |= MDWC3_TCXO_SHUTDOWN;
}
if (mdwc->bus_perf_client) {
@@ -1731,16 +1743,18 @@
(mdwc->charger.chg_type == DWC3_PROPRIETARY_CHARGER));
host_bus_suspend = mdwc->host_mode == 1;
- if (!host_bus_suspend) {
+ if (mdwc->lpm_flags & MDWC3_TCXO_SHUTDOWN) {
/* Vote for TCXO while waking up USB HSPHY */
ret = clk_prepare_enable(mdwc->xo_clk);
if (ret)
dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n",
__func__, ret);
-
- clk_prepare_enable(mdwc->utmi_clk);
+ mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN;
}
+ if (!host_bus_suspend)
+ clk_prepare_enable(mdwc->utmi_clk);
+
if (mdwc->otg_xceiv && mdwc->ext_xceiv.otg_capability && !dcp &&
!host_bus_suspend)
dwc3_hsusb_ldo_enable(1);
@@ -1755,7 +1769,10 @@
usleep_range(1000, 1200);
clk_prepare_enable(mdwc->iface_clk);
- clk_prepare_enable(mdwc->core_clk);
+ if (mdwc->lpm_flags & MDWC3_CORECLK_OFF) {
+ clk_prepare_enable(mdwc->core_clk);
+ mdwc->lpm_flags &= ~MDWC3_CORECLK_OFF;
+ }
if (host_bus_suspend) {
/* Disable HV interrupt */
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 453cbaa..887dde7 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -29,6 +29,7 @@
#define DSI_POLL_SLEEP_US 1000
#define DSI_POLL_TIMEOUT_US 16000
#define DSI_ESC_CLK_RATE 19200000
+#define DSI_DMA_CMD_TIMEOUT_MS 200
struct dsi_host_v2_private {
struct completion dma_comp;
@@ -426,18 +427,15 @@
dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
/*If Video enabled, Keep Video and Cmd mode ON */
- if (dsi_ctrl & 0x02)
- dsi_ctrl &= ~0x05;
- else
- dsi_ctrl &= ~0x07;
+
+
+ dsi_ctrl &= ~0x06;
if (mode == DSI_VIDEO_MODE) {
- dsi_ctrl |= 0x03;
+ dsi_ctrl |= 0x02;
intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
} else { /* command mode */
- dsi_ctrl |= 0x05;
- if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
- dsi_ctrl |= 0x02;
+ dsi_ctrl |= 0x04;
intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
DSI_INTR_CMD_MDP_DONE_MASK;
@@ -480,7 +478,7 @@
int msm_dsi_cmd_dma_tx(struct dsi_buf *tp)
{
- int len;
+ int len, rc;
unsigned long size, addr;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
@@ -505,12 +503,17 @@
MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
wmb();
- wait_for_completion_interruptible(&dsi_host_private->dma_comp);
+ rc = wait_for_completion_timeout(&dsi_host_private->dma_comp,
+ msecs_to_jiffies(DSI_DMA_CMD_TIMEOUT_MS));
+ if (rc == 0) {
+ pr_err("DSI command transaction time out\n");
+ rc = -ETIME;
+ }
dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
DMA_TO_DEVICE);
tp->dmap = 0;
- return 0;
+ return rc;
}
int msm_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
@@ -723,6 +726,7 @@
static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
u32 *bitclk_rate,
+ u32 *dsiclk_rate,
u32 *byteclk_rate,
u32 *pclk_rate)
{
@@ -761,10 +765,11 @@
*bitclk_rate /= lanes;
*byteclk_rate = *bitclk_rate / 8;
+ *dsiclk_rate = *byteclk_rate * lanes;
*pclk_rate = *byteclk_rate * lanes * 8 / pdata->panel_info.bpp;
- pr_debug("bitclk=%u, byteclk=%u, pck_=%u\n",
- *bitclk_rate, *byteclk_rate, *pclk_rate);
+ pr_debug("dsiclk_rate=%u, byteclk=%u, pck_=%u\n",
+ *dsiclk_rate, *byteclk_rate, *pclk_rate);
return 0;
}
@@ -777,7 +782,7 @@
u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
u32 ystride, bpp, data;
u32 dummy_xres, dummy_yres;
- u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0;
+ u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0, dsiclk_rate = 0;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
pr_debug("msm_dsi_on\n");
@@ -794,8 +799,10 @@
msm_dsi_phy_sw_reset(dsi_host_private->dsi_base);
msm_dsi_phy_init(dsi_host_private->dsi_base, pdata);
- msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &byteclk_rate, &pclk_rate);
- msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, byteclk_rate, pclk_rate);
+ msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &dsiclk_rate,
+ &byteclk_rate, &pclk_rate);
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, dsiclk_rate,
+ byteclk_rate, pclk_rate);
msm_dsi_prepare_clocks();
msm_dsi_clk_enable();
@@ -879,12 +886,11 @@
int ret = 0;
pr_debug("msm_dsi_off\n");
- msm_dsi_clk_set_rate(0, 0, 0);
+ msm_dsi_controller_cfg(0);
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, 0, 0, 0);
msm_dsi_clk_disable();
msm_dsi_unprepare_clocks();
- /* disable DSI controller */
- msm_dsi_controller_cfg(0);
msm_dsi_ahb_ctrl(0);
ret = msm_dsi_regulator_disable();
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
index 0486c4c..93f2c76 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.c
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -29,6 +29,7 @@
struct clk *dsi_esc_clk;
struct clk *dsi_pixel_clk;
struct clk *dsi_ahb_clk;
+ struct clk *dsi_clk;
int msm_dsi_clk_on;
int msm_dsi_ahb_clk_on;
};
@@ -97,6 +98,13 @@
{
int rc = 0;
+ dsi_io_private->dsi_clk = clk_get(&dev->dev, "dsi_clk");
+ if (IS_ERR(dsi_io_private->dsi_clk)) {
+ pr_err("can't find dsi core_clk\n");
+ rc = PTR_ERR(dsi_io_private->dsi_clk);
+ dsi_io_private->dsi_clk = NULL;
+ return rc;
+ }
dsi_io_private->dsi_byte_clk = clk_get(&dev->dev, "byte_clk");
if (IS_ERR(dsi_io_private->dsi_byte_clk)) {
pr_err("can't find dsi byte_clk\n");
@@ -135,6 +143,10 @@
void msm_dsi_clk_deinit(void)
{
+ if (dsi_io_private->dsi_clk) {
+ clk_put(dsi_io_private->dsi_clk);
+ dsi_io_private->dsi_clk = NULL;
+ }
if (dsi_io_private->dsi_byte_clk) {
clk_put(dsi_io_private->dsi_byte_clk);
dsi_io_private->dsi_byte_clk = NULL;
@@ -156,6 +168,7 @@
int msm_dsi_prepare_clocks(void)
{
+ clk_prepare(dsi_io_private->dsi_clk);
clk_prepare(dsi_io_private->dsi_byte_clk);
clk_prepare(dsi_io_private->dsi_esc_clk);
clk_prepare(dsi_io_private->dsi_pixel_clk);
@@ -164,16 +177,24 @@
int msm_dsi_unprepare_clocks(void)
{
+ clk_unprepare(dsi_io_private->dsi_clk);
clk_unprepare(dsi_io_private->dsi_esc_clk);
clk_unprepare(dsi_io_private->dsi_byte_clk);
clk_unprepare(dsi_io_private->dsi_pixel_clk);
return 0;
}
-int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+int msm_dsi_clk_set_rate(unsigned long esc_rate,
+ unsigned long dsi_rate,
+ unsigned long byte_rate,
unsigned long pixel_rate)
{
int rc;
+ rc = clk_set_rate(dsi_io_private->dsi_clk, dsi_rate);
+ if (rc) {
+ pr_err("dsi_esc_clk - clk_set_rate failed =%d\n", rc);
+ return rc;
+ }
rc = clk_set_rate(dsi_io_private->dsi_esc_clk, esc_rate);
if (rc) {
@@ -202,6 +223,7 @@
return 0;
}
+ clk_enable(dsi_io_private->dsi_clk);
clk_enable(dsi_io_private->dsi_esc_clk);
clk_enable(dsi_io_private->dsi_byte_clk);
clk_enable(dsi_io_private->dsi_pixel_clk);
@@ -217,6 +239,7 @@
return 0;
}
+ clk_disable(dsi_io_private->dsi_clk);
clk_disable(dsi_io_private->dsi_byte_clk);
clk_disable(dsi_io_private->dsi_esc_clk);
clk_disable(dsi_io_private->dsi_pixel_clk);
@@ -246,7 +269,7 @@
void msm_dsi_regulator_deinit(void)
{
- if (dsi_io_private->vdda_vreg) {
+ if (!IS_ERR(dsi_io_private->vdda_vreg)) {
devm_regulator_put(dsi_io_private->vdda_vreg);
dsi_io_private->vdda_vreg = NULL;
}
diff --git a/drivers/video/msm/mdss/dsi_io_v2.h b/drivers/video/msm/mdss/dsi_io_v2.h
index 25ecd7f..285bf30 100644
--- a/drivers/video/msm/mdss/dsi_io_v2.h
+++ b/drivers/video/msm/mdss/dsi_io_v2.h
@@ -29,7 +29,9 @@
int msm_dsi_unprepare_clocks(void);
-int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+int msm_dsi_clk_set_rate(unsigned long esc_rate,
+ unsigned long dsi_rate,
+ unsigned long byte_rate,
unsigned long pixel_rate);
int msm_dsi_clk_enable(void);
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
index 6686de3..e46ea3b 100644
--- a/drivers/video/msm/mdss/dsi_panel_v2.c
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/leds.h>
+#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include "dsi_v2.h"
@@ -32,6 +33,7 @@
int rst_gpio;
int disp_en_gpio;
+ int video_mode_gpio;
char bl_ctrl;
struct regulator *vddio_vreg;
@@ -40,6 +42,9 @@
struct dsi_panel_cmds_list *on_cmds_list;
struct dsi_panel_cmds_list *off_cmds_list;
struct mdss_dsi_phy_ctrl phy_params;
+
+ char *on_cmds;
+ char *off_cmds;
};
static struct dsi_panel_private *panel_private;
@@ -82,15 +87,54 @@
kfree(panel_private->dsi_panel_tx_buf.start);
kfree(panel_private->dsi_panel_rx_buf.start);
- if (panel_private->vddio_vreg)
+ if (!IS_ERR(panel_private->vddio_vreg))
devm_regulator_put(panel_private->vddio_vreg);
- if (panel_private->vdda_vreg)
- devm_regulator_put(panel_private->vddio_vreg);
+ if (!IS_ERR(panel_private->vdda_vreg))
+ devm_regulator_put(panel_private->vdda_vreg);
+ if (panel_private->on_cmds_list) {
+ kfree(panel_private->on_cmds_list->buf);
+ kfree(panel_private->on_cmds_list);
+ }
+ if (panel_private->off_cmds_list) {
+ kfree(panel_private->off_cmds_list->buf);
+ kfree(panel_private->off_cmds_list);
+ }
+
+ kfree(panel_private->on_cmds);
+ kfree(panel_private->off_cmds);
kfree(panel_private);
panel_private = NULL;
}
+int dsi_panel_power(int enable)
+{
+ int ret;
+ if (enable) {
+ ret = regulator_enable(panel_private->vddio_vreg);
+ if (ret) {
+ pr_err("dsi_panel_power regulator enable vddio fail\n");
+ return ret;
+ }
+ ret = regulator_enable(panel_private->vdda_vreg);
+ if (ret) {
+ pr_err("dsi_panel_power regulator enable vdda fail\n");
+ return ret;
+ }
+ } else {
+ ret = regulator_disable(panel_private->vddio_vreg);
+ if (ret) {
+ pr_err("dsi_panel_power regulator disable vddio fail\n");
+ return ret;
+ }
+ ret = regulator_disable(panel_private->vdda_vreg);
+ if (ret) {
+ pr_err("dsi_panel_power regulator dsiable vdda fail\n");
+ return ret;
+ }
+ }
+ return 0;
+}
void dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
{
@@ -113,6 +157,8 @@
pr_debug("%s: enable = %d\n", __func__, enable);
if (enable) {
+ dsi_panel_power(1);
+ gpio_request(panel_private->rst_gpio, "panel_reset");
gpio_set_value(panel_private->rst_gpio, 1);
/*
* these delay values are by experiments currently, will need
@@ -123,12 +169,34 @@
udelay(200);
gpio_set_value(panel_private->rst_gpio, 1);
msleep(20);
- if (gpio_is_valid(panel_private->disp_en_gpio))
+ if (gpio_is_valid(panel_private->disp_en_gpio)) {
+ gpio_request(panel_private->disp_en_gpio,
+ "panel_enable");
gpio_set_value(panel_private->disp_en_gpio, 1);
+ }
+ if (gpio_is_valid(panel_private->video_mode_gpio)) {
+ gpio_request(panel_private->video_mode_gpio,
+ "panel_video_mdoe");
+ if (pdata->panel_info.mipi.mode == DSI_VIDEO_MODE)
+ gpio_set_value(panel_private->video_mode_gpio,
+ 1);
+ else
+ gpio_set_value(panel_private->video_mode_gpio,
+ 0);
+ }
} else {
gpio_set_value(panel_private->rst_gpio, 0);
- if (gpio_is_valid(panel_private->disp_en_gpio))
+ gpio_free(panel_private->rst_gpio);
+
+ if (gpio_is_valid(panel_private->disp_en_gpio)) {
gpio_set_value(panel_private->disp_en_gpio, 0);
+ gpio_free(panel_private->disp_en_gpio);
+ }
+
+ if (gpio_is_valid(panel_private->video_mode_gpio))
+ gpio_free(panel_private->video_mode_gpio);
+
+ dsi_panel_power(0);
}
}
@@ -196,13 +264,42 @@
panel_private->disp_en_gpio = of_get_named_gpio(np,
"qcom,enable-gpio", 0);
panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
+ panel_private->video_mode_gpio = of_get_named_gpio(np,
+ "qcom,mode-selection-gpio", 0);
return 0;
}
static int dsi_panel_parse_regulator(struct platform_device *pdev)
{
+ int ret;
panel_private->vddio_vreg = devm_regulator_get(&pdev->dev, "vddio");
+ if (IS_ERR(panel_private->vddio_vreg)) {
+ pr_err("%s: could not get vddio vreg, rc=%ld\n",
+ __func__, PTR_ERR(panel_private->vddio_vreg));
+ return PTR_ERR(panel_private->vddio_vreg);
+ }
+ ret = regulator_set_voltage(panel_private->vddio_vreg,
+ 1800000,
+ 1800000);
+ if (ret) {
+ pr_err("%s: set voltage failed on vddio_vreg, rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
panel_private->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
+ if (IS_ERR(panel_private->vdda_vreg)) {
+ pr_err("%s: could not get vdda_vreg , rc=%ld\n",
+ __func__, PTR_ERR(panel_private->vdda_vreg));
+ return PTR_ERR(panel_private->vdda_vreg);
+ }
+ ret = regulator_set_voltage(panel_private->vdda_vreg,
+ 2850000,
+ 2850000);
+ if (ret) {
+ pr_err("%s: set voltage failed on vdda_vreg, rc=%d\n",
+ __func__, ret);
+ return ret;
+ }
return 0;
}
@@ -398,180 +495,163 @@
int cmd_plen, data_offset;
const char *data;
const char *on_cmds_state, *off_cmds_state;
- char *on_cmds = NULL, *off_cmds = NULL;
int num_of_on_cmds = 0, num_of_off_cmds = 0;
data = of_get_property(np, "qcom,panel-on-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
- goto parse_init_cmds_error;
+ return -EINVAL;
}
- on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
- if (!on_cmds)
- goto parse_init_cmds_error;
+ panel_private->on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!panel_private->on_cmds)
+ return -ENOMEM;
- memcpy(on_cmds, data, len);
+ memcpy(panel_private->on_cmds, data, len);
data_offset = 0;
cmd_plen = 0;
while ((len - data_offset) >= DT_CMD_HDR) {
data_offset += (DT_CMD_HDR - 1);
- cmd_plen = on_cmds[data_offset++];
+ cmd_plen = panel_private->on_cmds[data_offset++];
data_offset += cmd_plen;
num_of_on_cmds++;
}
if (!num_of_on_cmds) {
pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
- goto parse_init_cmds_error;
+ return -EINVAL;
}
- panel_data->dsi_panel_on_cmds =
+ panel_private->on_cmds_list =
kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
- if (!panel_data->dsi_panel_on_cmds)
- goto parse_init_cmds_error;
+ if (!panel_private->on_cmds_list)
+ return -ENOMEM;
- (panel_data->dsi_panel_on_cmds)->buf =
+ panel_private->on_cmds_list->buf =
kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
GFP_KERNEL);
- if (!(panel_data->dsi_panel_on_cmds)->buf)
- goto parse_init_cmds_error;
+ if (!panel_private->on_cmds_list->buf)
+ return -ENOMEM;
data_offset = 0;
for (i = 0; i < num_of_on_cmds; i++) {
- panel_data->dsi_panel_on_cmds->buf[i].dtype =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].last =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].vc =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].ack =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].wait =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].dlen =
- on_cmds[data_offset++];
- panel_data->dsi_panel_on_cmds->buf[i].payload =
- &on_cmds[data_offset];
- data_offset += (panel_data->dsi_panel_on_cmds->buf[i].dlen);
+ panel_private->on_cmds_list->buf[i].dtype =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].last =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].vc =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].ack =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].wait =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].dlen =
+ panel_private->on_cmds[data_offset++];
+ panel_private->on_cmds_list->buf[i].payload =
+ &panel_private->on_cmds[data_offset];
+ data_offset += (panel_private->on_cmds_list->buf[i].dlen);
}
if (data_offset != len) {
pr_err("%s:%d, Incorrect ON command entries",
__func__, __LINE__);
- goto parse_init_cmds_error;
+ return -EINVAL;
}
- (panel_data->dsi_panel_on_cmds)->size = num_of_on_cmds;
+ panel_private->on_cmds_list->size = num_of_on_cmds;
on_cmds_state = of_get_property(pdev->dev.of_node,
"qcom,on-cmds-dsi-state", NULL);
if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
- (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+ panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
} else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
- (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_HS_MODE;
+ panel_private->on_cmds_list->ctrl_state = DSI_HS_MODE;
} else {
pr_debug("%s: ON cmds state not specified. Set Default\n",
__func__);
- (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+ panel_private->on_cmds_list->ctrl_state = DSI_LP_MODE;
}
- panel_private->on_cmds_list = panel_data->dsi_panel_on_cmds;
+ panel_data->dsi_panel_on_cmds = panel_private->on_cmds_list;
+
data = of_get_property(np, "qcom,panel-off-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
- goto parse_init_cmds_error;
+ return -EINVAL;
}
- off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
- if (!off_cmds)
- goto parse_init_cmds_error;
+ panel_private->off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!panel_private->off_cmds)
+ return -ENOMEM;
- memcpy(off_cmds, data, len);
+ memcpy(panel_private->off_cmds, data, len);
data_offset = 0;
cmd_plen = 0;
while ((len - data_offset) >= DT_CMD_HDR) {
data_offset += (DT_CMD_HDR - 1);
- cmd_plen = off_cmds[data_offset++];
+ cmd_plen = panel_private->off_cmds[data_offset++];
data_offset += cmd_plen;
num_of_off_cmds++;
}
if (!num_of_off_cmds) {
pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
- goto parse_init_cmds_error;
+ return -ENOMEM;
}
- panel_data->dsi_panel_off_cmds =
+ panel_private->off_cmds_list =
kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
- if (!panel_data->dsi_panel_off_cmds)
- goto parse_init_cmds_error;
+ if (!panel_private->off_cmds_list)
+ return -ENOMEM;
- (panel_data->dsi_panel_off_cmds)->buf = kzalloc(num_of_off_cmds
+ panel_private->off_cmds_list->buf = kzalloc(num_of_off_cmds
* sizeof(struct dsi_cmd_desc),
GFP_KERNEL);
- if (!(panel_data->dsi_panel_off_cmds)->buf)
- goto parse_init_cmds_error;
+ if (!panel_private->off_cmds_list->buf)
+ return -ENOMEM;
data_offset = 0;
for (i = 0; i < num_of_off_cmds; i++) {
- panel_data->dsi_panel_off_cmds->buf[i].dtype =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].last =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].vc =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].ack =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].wait =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].dlen =
- off_cmds[data_offset++];
- panel_data->dsi_panel_off_cmds->buf[i].payload =
- &off_cmds[data_offset];
- data_offset += (panel_data->dsi_panel_off_cmds->buf[i].dlen);
+ panel_private->off_cmds_list->buf[i].dtype =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].last =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].vc =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].ack =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].wait =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].dlen =
+ panel_private->off_cmds[data_offset++];
+ panel_private->off_cmds_list->buf[i].payload =
+ &panel_private->off_cmds[data_offset];
+ data_offset += (panel_private->off_cmds_list->buf[i].dlen);
}
if (data_offset != len) {
pr_err("%s:%d, Incorrect OFF command entries",
__func__, __LINE__);
- goto parse_init_cmds_error;
+ return -EINVAL;
}
- (panel_data->dsi_panel_off_cmds)->size = num_of_off_cmds;
- off_cmds_state = of_get_property(pdev->dev.of_node,
+ panel_private->off_cmds_list->size = num_of_off_cmds;
+ off_cmds_state = of_get_property(pdev->dev.of_node,
"qcom,off-cmds-dsi-state", NULL);
if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
- (panel_data->dsi_panel_off_cmds)->ctrl_state =
+ panel_private->off_cmds_list->ctrl_state =
DSI_LP_MODE;
} else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
- (panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_HS_MODE;
+ panel_private->off_cmds_list->ctrl_state = DSI_HS_MODE;
} else {
pr_debug("%s: ON cmds state not specified. Set Default\n",
__func__);
- (panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_LP_MODE;
+ panel_private->off_cmds_list->ctrl_state = DSI_LP_MODE;
}
- panel_private->off_cmds_list = panel_data->dsi_panel_on_cmds;
- kfree(on_cmds);
- kfree(off_cmds);
+ panel_data->dsi_panel_off_cmds = panel_private->off_cmds_list;
return 0;
-parse_init_cmds_error:
- if (panel_data->dsi_panel_on_cmds) {
- kfree((panel_data->dsi_panel_on_cmds)->buf);
- kfree(panel_data->dsi_panel_on_cmds);
- panel_data->dsi_panel_on_cmds = NULL;
- }
- if (panel_data->dsi_panel_off_cmds) {
- kfree((panel_data->dsi_panel_off_cmds)->buf);
- kfree(panel_data->dsi_panel_off_cmds);
- panel_data->dsi_panel_off_cmds = NULL;
- }
-
- kfree(on_cmds);
- kfree(off_cmds);
- return -EINVAL;
}
static int dsi_panel_parse_backlight(struct platform_device *pdev,
@@ -709,6 +789,7 @@
vendor_pdata.on = dsi_panel_on;
vendor_pdata.off = dsi_panel_off;
+ vendor_pdata.reset = dsi_panel_reset;
vendor_pdata.bl_fnc = dsi_panel_bl_ctrl;
rc = dsi_panel_device_register_v2(pdev, &vendor_pdata,
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 5e46bf5..5833796 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -29,6 +29,14 @@
if (!panel_common_data || !pdata)
return -ENODEV;
+ if (dsi_intf.op_mode_config)
+ dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
+
+ pr_debug("panel off commands\n");
+ if (panel_common_data->off)
+ panel_common_data->off(pdata);
+
+ pr_debug("turn off dsi controller\n");
if (dsi_intf.off)
rc = dsi_intf.off(pdata);
@@ -37,9 +45,9 @@
return rc;
}
- pr_debug("dsi_off reset\n");
- if (panel_common_data->off)
- panel_common_data->off(pdata);
+ pr_debug("turn off panel power\n");
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 0);
return rc;
}
@@ -53,8 +61,6 @@
if (!panel_common_data || !pdata)
return -ENODEV;
- if (panel_common_data->reset)
- panel_common_data->reset(1);
pr_debug("dsi_on DSI controller ont\n");
if (dsi_intf.on)
@@ -64,6 +70,9 @@
pr_err("mdss_dsi_on DSI failed %d\n", rc);
return rc;
}
+ pr_debug("dsi_on power on panel\n");
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 1);
pr_debug("dsi_on DSI panel ont\n");
if (panel_common_data->on)
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index fa868ab..f68527c 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -189,7 +189,7 @@
struct mdss_panel_info panel_info;
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
- void (*reset)(int enable);
+ void (*reset)(struct mdss_panel_data *pdata, int enable);
void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
struct dsi_panel_cmds_list *dsi_panel_on_cmds;
struct dsi_panel_cmds_list *dsi_panel_off_cmds;
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 890b00b..52243eb 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -47,7 +47,7 @@
#include "mdp3_hwio.h"
#include "mdp3_ctrl.h"
-#define MDP_CORE_HW_VERSION 0x03030304
+#define MDP_CORE_HW_VERSION 0x03040310
struct mdp3_hw_resource *mdp3_res;
#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
@@ -302,16 +302,7 @@
return ret;
}
-int mdp3_vsync_clk_enable(int enable)
-{
- int ret = 0;
- pr_debug("vsync clk enable=%d\n", enable);
- mutex_lock(&mdp3_res->res_mutex);
- mdp3_clk_update(MDP3_CLK_VSYNC, enable);
- mutex_unlock(&mdp3_res->res_mutex);
- return ret;
-}
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate)
{
@@ -400,6 +391,9 @@
if (rc)
return rc;
+ rc = mdp3_clk_register("dsi_clk", MDP3_CLK_DSI);
+ if (rc)
+ return rc;
return rc;
}
@@ -409,6 +403,7 @@
clk_put(mdp3_res->clocks[MDP3_CLK_CORE]);
clk_put(mdp3_res->clocks[MDP3_CLK_VSYNC]);
clk_put(mdp3_res->clocks[MDP3_CLK_LCDC]);
+ clk_put(mdp3_res->clocks[MDP3_CLK_DSI]);
}
int mdp3_clk_enable(int enable)
@@ -421,6 +416,7 @@
rc = mdp3_clk_update(MDP3_CLK_AHB, enable);
rc |= mdp3_clk_update(MDP3_CLK_CORE, enable);
rc |= mdp3_clk_update(MDP3_CLK_VSYNC, enable);
+ rc |= mdp3_clk_update(MDP3_CLK_DSI, enable);
mutex_unlock(&mdp3_res->res_mutex);
return rc;
}
@@ -577,12 +573,14 @@
int rc;
rc = mdp3_clk_update(MDP3_CLK_AHB, 1);
+ rc |= mdp3_clk_update(MDP3_CLK_CORE, 1);
if (rc)
return rc;
mdp3_res->mdp_rev = MDP3_REG_READ(MDP3_REG_HW_VERSION);
rc = mdp3_clk_update(MDP3_CLK_AHB, 0);
+ rc |= mdp3_clk_update(MDP3_CLK_CORE, 0);
if (rc)
pr_err("fail to turn off the MDP3_CLK_AHB clk\n");
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index c853664..5774e5a 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -29,6 +29,7 @@
MDP3_CLK_CORE,
MDP3_CLK_VSYNC,
MDP3_CLK_LCDC,
+ MDP3_CLK_DSI,
MDP3_MAX_CLK
};
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index e07c0a4..99b7604 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -28,7 +28,7 @@
void vsync_notify_handler(void *arg)
{
- struct mdp3_session_data *session = (struct mdp3_session_data *)session;
+ struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
complete(&session->vsync_comp);
}
@@ -100,18 +100,30 @@
.attrs = vsync_fs_attrs,
};
-static int mdp3_ctrl_res_req_dma(struct msm_fb_data_type *mfd, int status)
+static int mdp3_ctrl_res_req_bus(struct msm_fb_data_type *mfd, int status)
{
int rc = 0;
if (status) {
struct mdss_panel_info *panel_info = mfd->panel_info;
int ab = 0;
int ib = 0;
- unsigned long core_clk = 0;
- int vtotal = 0;
ab = panel_info->xres * panel_info->yres * 4;
ab *= panel_info->mipi.frame_rate;
ib = (ab * 3) / 2;
+ rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib);
+ } else {
+ rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0);
+ }
+ return rc;
+}
+
+static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status)
+{
+ int rc = 0;
+ if (status) {
+ struct mdss_panel_info *panel_info = mfd->panel_info;
+ unsigned long core_clk;
+ int vtotal;
vtotal = panel_info->lcdc.v_back_porch +
panel_info->lcdc.v_front_porch +
panel_info->lcdc.v_pulse_width +
@@ -126,10 +138,8 @@
if (rc)
return rc;
- mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib);
} else {
rc = mdp3_clk_enable(false);
- rc |= mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0);
}
return rc;
}
@@ -285,13 +295,25 @@
}
mutex_lock(&mdp3_session->lock);
if (mdp3_session->status) {
- pr_info("fb%d is on already", mfd->index);
+ pr_debug("fb%d is on already", mfd->index);
goto on_error;
}
- rc = mdp3_ctrl_res_req_dma(mfd, 1);
+ /* request bus bandwidth before DSI DMA traffic */
+ rc = mdp3_ctrl_res_req_bus(mfd, 1);
+ if (rc)
+ pr_err("fail to request bus resource\n");
+
+ panel = mdp3_session->panel;
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
if (rc) {
- pr_err("resource request for dma on failed\n");
+ pr_err("fail to turn on the panel\n");
+ goto on_error;
+ }
+ rc = mdp3_ctrl_res_req_clk(mfd, 1);
+ if (rc) {
+ pr_err("fail to request mdp clk resource\n");
goto on_error;
}
@@ -304,16 +326,9 @@
rc = mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
if (rc) {
pr_err("display interface init failed\n");
- goto on_error;
- }
- panel = mdp3_session->panel;
- if (panel->event_handler)
- rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
- if (rc) {
- pr_err("fail to turn on the panel\n");
goto on_error;
}
@@ -348,26 +363,31 @@
mutex_lock(&mdp3_session->lock);
if (!mdp3_session->status) {
- pr_info("fb%d is off already", mfd->index);
+ pr_debug("fb%d is off already", mfd->index);
goto off_error;
}
- panel = mdp3_session->panel;
- if (panel->event_handler)
- rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
-
- if (rc)
- pr_err("fail to turn off the panel\n");
+ pr_debug("mdp3_ctrl_off stop mdp3 dma engine\n");
rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
if (rc)
pr_err("fail to stop the MDP3 dma\n");
- rc = mdp3_ctrl_res_req_dma(mfd, 0);
+ pr_debug("mdp3_ctrl_off stop dsi panel and controller\n");
+ panel = mdp3_session->panel;
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
if (rc)
- pr_err("resource release for dma on failed\n");
+ pr_err("fail to turn off the panel\n");
+ pr_debug("mdp3_ctrl_off release bus and clock\n");
+ rc = mdp3_ctrl_res_req_bus(mfd, 0);
+ if (rc)
+ pr_err("mdp bus resource release failed\n");
+ rc = mdp3_ctrl_res_req_clk(mfd, 0);
+ if (rc)
+ pr_err("mdp clock resource release failed\n");
off_error:
mdp3_session->status = 0;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index a5903cf..c3957c5 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1431,6 +1431,7 @@
int i, fence_cnt = 0, ret = 0;
int acq_fen_fd[MDP_MAX_FENCE_FD];
struct sync_fence *fence;
+ u32 threshold;
if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
(mfd->timeline == NULL))
@@ -1464,8 +1465,13 @@
if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
mdss_fb_wait_for_fence(mfd);
+ if (mfd->panel.type == WRITEBACK_PANEL)
+ threshold = 1;
+ else
+ threshold = 2;
+
mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
- mfd->timeline_value + 2);
+ mfd->timeline_value + threshold);
if (mfd->cur_rel_sync_pt == NULL) {
pr_err("%s: cannot create sync point", __func__);
ret = -ENOMEM;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index daa7f1a..d1fdbab 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -129,6 +129,7 @@
u16 width;
u16 height;
u32 dst_format;
+ bool is_secure;
u32 bus_ab_quota;
u32 bus_ib_quota;
@@ -290,6 +291,7 @@
u32 params_changed;
unsigned long smp[MAX_PLANES];
+ unsigned long smp_reserved[MAX_PLANES];
struct mdss_mdp_data back_buf;
struct mdss_mdp_data front_buf;
@@ -454,6 +456,9 @@
void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer);
+int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe);
+void mdss_mdp_smp_unreserve(struct mdss_mdp_pipe *pipe);
+
int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
u32 *ftch_y_id, u32 type, u32 num_base, u32 len);
int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 5bc077c..abec9b9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -289,6 +289,7 @@
}
mutex_lock(&mdss_mdp_ctl_lock);
ctl->ref_cnt--;
+ ctl->is_secure = false;
ctl->power_on = false;
ctl->start_fnc = NULL;
ctl->stop_fnc = NULL;
@@ -1084,14 +1085,6 @@
stage);
}
- if (mixercfg == MDSS_MDP_LM_BORDER_COLOR &&
- pipe->src_fmt->alpha_enable &&
- pipe->dst.w == mixer->width &&
- pipe->dst.h == mixer->height) {
- pr_debug("setting pipe=%d as BG_PIPE\n", pipe->num);
- bgalpha = 1;
- }
-
mixercfg |= stage << (3 * pipe->num);
mdp_mixer_write(mixer, off + MDSS_MDP_REG_LM_OP_MODE, blend_op);
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index ecbdaf0..5221106 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -348,6 +348,8 @@
#define MDSS_MDP_REG_WB_OUT_SIZE 0x074
#define MDSS_MDP_REG_WB_ALPHA_X_VALUE 0x078
#define MDSS_MDP_REG_WB_CSC_BASE 0x260
+#define MDSS_MDP_REG_WB_DST_ADDR_SW_STATUS 0x2B0
+
enum mdss_mdp_dspp_index {
MDSS_MDP_DSPP0,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index b4d5014..0c08eda 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -390,6 +390,7 @@
ctx->callback_arg = wb_args->priv_data;
flush_bits = BIT(16); /* WB */
+ mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_ADDR_SW_STATUS, ctl->is_secure);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, flush_bits);
INIT_COMPLETION(ctx->wb_comp);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 5fc4cc4..48bab7f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -374,8 +374,8 @@
pr_err("Can't switch mixer %d->%d pnum %d!\n",
pipe->mixer->num, mixer->num,
pipe->num);
- mdss_mdp_pipe_unmap(pipe);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit_fail;
}
pr_debug("switching pipe mixer %d->%d pnum %d\n",
pipe->mixer->num, mixer->num,
@@ -474,6 +474,12 @@
}
}
+ ret = mdss_mdp_smp_reserve(pipe);
+ if (ret) {
+ pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
+ goto exit_fail;
+ }
+
pipe->params_changed++;
req->id = pipe->ndx;
@@ -483,6 +489,25 @@
mdss_mdp_pipe_unmap(pipe);
return ret;
+
+exit_fail:
+ mdss_mdp_pipe_unmap(pipe);
+
+ mutex_lock(&mfd->lock);
+ if (pipe->play_cnt == 0) {
+ pr_debug("failed for pipe %d\n", pipe->num);
+ list_del(&pipe->used_list);
+ mdss_mdp_pipe_destroy(pipe);
+ }
+
+ /* invalidate any overlays in this framebuffer after failure */
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
+ pr_debug("freeing allocations for pipe %d\n", pipe->num);
+ mdss_mdp_smp_unreserve(pipe);
+ pipe->params_changed = 0;
+ }
+ mutex_unlock(&mfd->lock);
+ return ret;
}
static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
@@ -732,15 +757,16 @@
} else if (pipe->front_buf.num_planes) {
buf = &pipe->front_buf;
} else {
- pr_warn("pipe queue without buffer\n");
- buf = NULL;
+ pr_warn("pipe queue w/o buffer. unstaging layer\n");
+ mdss_mdp_mixer_pipe_unstage(pipe);
+ continue;
}
ret = mdss_mdp_pipe_queue_data(pipe, buf);
if (IS_ERR_VALUE(ret)) {
pr_warn("Unable to queue data for pnum=%d\n",
pipe->num);
- mdss_mdp_overlay_free_buf(buf);
+ mdss_mdp_mixer_pipe_unstage(pipe);
}
}
@@ -816,12 +842,13 @@
if (ndx == BORDERFILL_NDX) {
pr_debug("borderfill disable\n");
mdp5_data->borderfill_enable = false;
- return 0;
+ ret = 0;
+ goto done;
}
if (!mfd->panel_power_on) {
- mutex_unlock(&mdp5_data->ov_lock);
- return -EPERM;
+ ret = -EPERM;
+ goto done;
}
pr_debug("unset ndx=%x\n", ndx);
@@ -831,6 +858,7 @@
else
ret = mdss_mdp_overlay_release(mfd, ndx);
+done:
mutex_unlock(&mdp5_data->ov_lock);
return ret;
@@ -972,14 +1000,14 @@
return ret;
if (!mfd->panel_power_on) {
- mutex_unlock(&mdp5_data->ov_lock);
- return -EPERM;
+ ret = -EPERM;
+ goto done;
}
ret = mdss_mdp_overlay_start(mfd);
if (ret) {
pr_err("unable to start overlay %d (%d)\n", mfd->index, ret);
- return ret;
+ goto done;
}
if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
@@ -992,6 +1020,7 @@
ret = mdss_mdp_overlay_queue(mfd, req);
}
+done:
mutex_unlock(&mdp5_data->ov_lock);
return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 746705d..0f65530 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -40,17 +40,18 @@
return readl_relaxed(pipe->base + reg);
}
-static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
+static u32 mdss_mdp_smp_mmb_reserve(unsigned long *existing,
+ unsigned long *reserve, size_t n)
{
u32 i, mmb;
/* reserve more blocks if needed, but can't free mmb at this point */
- for (i = bitmap_weight(smp, SMP_MB_CNT); i < n; i++) {
+ for (i = bitmap_weight(existing, SMP_MB_CNT); i < n; i++) {
if (bitmap_full(mdss_mdp_smp_mmb_pool, SMP_MB_CNT))
break;
mmb = find_first_zero_bit(mdss_mdp_smp_mmb_pool, SMP_MB_CNT);
- set_bit(mmb, smp);
+ set_bit(mmb, reserve);
set_bit(mmb, mdss_mdp_smp_mmb_pool);
}
return i;
@@ -74,10 +75,17 @@
return cnt;
}
-static void mdss_mdp_smp_mmb_free(unsigned long *smp)
+static void mdss_mdp_smp_mmb_amend(unsigned long *smp, unsigned long *extra)
+{
+ bitmap_or(smp, smp, extra, SMP_MB_CNT);
+ bitmap_zero(extra, SMP_MB_CNT);
+}
+
+static void mdss_mdp_smp_mmb_free(unsigned long *smp, bool write)
{
if (!bitmap_empty(smp, SMP_MB_CNT)) {
- mdss_mdp_smp_mmb_set(MDSS_MDP_SMP_CLIENT_UNUSED, smp);
+ if (write)
+ mdss_mdp_smp_mmb_set(MDSS_MDP_SMP_CLIENT_UNUSED, smp);
bitmap_andnot(mdss_mdp_smp_mmb_pool, mdss_mdp_smp_mmb_pool,
smp, SMP_MB_CNT);
bitmap_zero(smp, SMP_MB_CNT);
@@ -104,19 +112,33 @@
static void mdss_mdp_smp_free(struct mdss_mdp_pipe *pipe)
{
+ int i;
+
mutex_lock(&mdss_mdp_smp_lock);
- mdss_mdp_smp_mmb_free(&pipe->smp[0]);
- mdss_mdp_smp_mmb_free(&pipe->smp[1]);
- mdss_mdp_smp_mmb_free(&pipe->smp[2]);
+ for (i = 0; i < MAX_PLANES; i++) {
+ mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+ mdss_mdp_smp_mmb_free(&pipe->smp[i], true);
+ }
mutex_unlock(&mdss_mdp_smp_lock);
}
-static int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
+void mdss_mdp_smp_unreserve(struct mdss_mdp_pipe *pipe)
+{
+ int i;
+
+ mutex_lock(&mdss_mdp_smp_lock);
+ for (i = 0; i < MAX_PLANES; i++)
+ mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+ mutex_unlock(&mdss_mdp_smp_lock);
+}
+
+int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 num_blks = 0, reserved = 0;
struct mdss_mdp_plane_sizes ps;
- int i, rc;
+ int i;
+ int rc = 0;
u32 nlines;
if (pipe->bwc_mode) {
@@ -140,29 +162,29 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < ps.num_planes; i++) {
nlines = pipe->bwc_mode ? ps.rau_h[i] : 2;
- num_blks = DIV_ROUND_UP(nlines * ps.ystride[i],
- mdss_res->smp_mb_size);
+ num_blks = DIV_ROUND_UP(nlines * ps.ystride[i], SMP_MB_SIZE);
if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
num_blks = roundup_pow_of_two(num_blks);
pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
num_blks, pipe->num, i);
- reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp[i], num_blks);
+ reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp[i],
+ &pipe->smp_reserved[i], num_blks);
if (reserved < num_blks)
break;
}
if (reserved < num_blks) {
- pr_err("insufficient MMB blocks\n");
+ pr_debug("insufficient MMB blocks\n");
for (; i >= 0; i--)
- mdss_mdp_smp_mmb_free(&pipe->smp[i]);
- return -ENOMEM;
+ mdss_mdp_smp_mmb_free(&pipe->smp_reserved[i], false);
+ rc = -ENOMEM;
}
mutex_unlock(&mdss_mdp_smp_lock);
- return 0;
+ return rc;
}
static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
@@ -171,8 +193,10 @@
int cnt = 0;
mutex_lock(&mdss_mdp_smp_lock);
- for (i = 0; i < MAX_PLANES; i++)
+ for (i = 0; i < MAX_PLANES; i++) {
+ mdss_mdp_smp_mmb_amend(&pipe->smp[i], &pipe->smp_reserved[i]);
cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+ }
mdss_mdp_smp_set_wm_levels(pipe, cnt);
mutex_unlock(&mdss_mdp_smp_lock);
return 0;
@@ -307,14 +331,16 @@
mutex_lock(&mdss_mdp_sspp_lock);
pipe = mdss_mdp_pipe_search(mdata, ndx);
- if (!pipe)
- return ERR_PTR(-EINVAL);
+ if (!pipe) {
+ pipe = ERR_PTR(-EINVAL);
+ goto error;
+ }
if (mdss_mdp_pipe_map(pipe))
- return ERR_PTR(-EACCES);
+ pipe = ERR_PTR(-EACCES);
+error:
mutex_unlock(&mdss_mdp_sspp_lock);
-
return pipe;
}
@@ -645,13 +671,6 @@
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
opmode);
- ret = mdss_mdp_smp_reserve(pipe);
- if (ret) {
- pr_err("unable to reserve smp for pnum=%d\n",
- pipe->num);
- goto done;
- }
-
mdss_mdp_smp_alloc(pipe);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 5a0c27e..8bd5674 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -1523,11 +1523,13 @@
if (copy_to_user(config->c0_c1_data, local_cfg.c2_data,
config->len * sizeof(u32))) {
ret = -EFAULT;
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
goto igc_config_exit;
}
if (copy_to_user(config->c2_data, local_cfg.c0_c1_data,
config->len * sizeof(u32))) {
ret = -EFAULT;
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
goto igc_config_exit;
}
*copyback = 1;
@@ -1716,16 +1718,19 @@
pp_read_argc_lut(&local_cfg, argc_offset);
if (copy_to_user(config->r_data,
&mdss_pp_res->gc_lut_r[disp_num][0], tbl_size)) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ret = -EFAULT;
goto argc_config_exit;
}
if (copy_to_user(config->g_data,
&mdss_pp_res->gc_lut_g[disp_num][0], tbl_size)) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ret = -EFAULT;
goto argc_config_exit;
}
if (copy_to_user(config->b_data,
&mdss_pp_res->gc_lut_b[disp_num][0], tbl_size)) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ret = -EFAULT;
goto argc_config_exit;
}
@@ -1796,6 +1801,7 @@
if (copy_to_user(config->data,
&mdss_pp_res->enhist_lut[disp_num][0],
ENHIST_LUT_ENTRIES * sizeof(u32))) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ret = -EFAULT;
goto enhist_config_exit;
}
@@ -2035,6 +2041,7 @@
if (IS_ERR_OR_NULL(pipe))
continue;
if (!pipe || pipe->num > MDSS_MDP_SSPP_VIG2) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ret = -EINVAL;
pr_warn("Invalid Hist pipe (%d)", i);
goto hist_exit;
@@ -2153,7 +2160,7 @@
i = MDSS_PP_ARG_MASK & block;
if (!i) {
pr_warn("Must pass pipe arguments, %d", i);
- goto hist_stop_exit;
+ goto hist_stop_clk;
}
for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
@@ -2173,7 +2180,7 @@
ctl_base);
mdss_mdp_pipe_unmap(pipe);
if (ret)
- goto hist_stop_exit;
+ goto hist_stop_clk;
}
} else if (PP_LOCAT(block) == MDSS_PP_DSPP_CFG) {
for (i = 0; i < mixer_cnt; i++) {
@@ -2185,13 +2192,14 @@
ret = pp_histogram_disable(hist_info, done_bit,
ctl_base);
if (ret)
- goto hist_stop_exit;
+ goto hist_stop_clk;
mdss_pp_res->pp_disp_flags[disp_num] |=
PP_FLAGS_DIRTY_HIST_COL;
}
}
-hist_stop_exit:
+hist_stop_clk:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+hist_stop_exit:
if (!ret && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG))
mdss_mdp_pp_setup(ctl);
return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index a027dd9..016c973 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -201,9 +201,16 @@
rot_pipe->params_changed++;
}
+ ret = mdss_mdp_smp_reserve(rot->pipe);
+ if (ret) {
+ pr_err("unable to mdss_mdp_smp_reserve rot data\n");
+ return ret;
+ }
+
ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
if (ret) {
pr_err("unable to queue rot data\n");
+ mdss_mdp_smp_unreserve(rot->pipe);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 4de6d03..60f05ca 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -240,7 +240,7 @@
ps->ystride[1] = 32 * 2;
} else if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
ps->rau_cnt = DIV_ROUND_UP(w, 32);
- ps->ystride[0] = 32 * 4;
+ ps->ystride[0] = 32 * 4 * fmt->bpp;
ps->ystride[1] = 0;
ps->rau_h[0] = 4;
ps->rau_h[1] = 0;
@@ -250,8 +250,8 @@
}
stride_off = DIV_ROUND_UP(ps->rau_cnt, 8);
- ps->ystride[0] = ps->ystride[0] * ps->rau_cnt * fmt->bpp + stride_off;
- ps->ystride[1] = ps->ystride[1] * ps->rau_cnt * fmt->bpp + stride_off;
+ ps->ystride[0] = ps->ystride[0] * ps->rau_cnt + stride_off;
+ ps->ystride[1] = ps->ystride[1] * ps->rau_cnt + stride_off;
ps->num_planes = 2;
return 0;
@@ -262,8 +262,7 @@
{
struct mdss_mdp_format_params *fmt;
int i, rc;
- u32 bpp, stride_off;
-
+ u32 bpp, ystride0_off, ystride1_off;
if (ps == NULL)
return -EINVAL;
@@ -281,12 +280,14 @@
rc = mdss_mdp_get_rau_strides(w, h, fmt, ps);
if (rc)
return rc;
- stride_off = DIV_ROUND_UP(h, ps->rau_h[0]);
- ps->ystride[0] = ps->ystride[0] + ps->ystride[1];
- ps->plane_size[0] = ps->ystride[0] * stride_off;
+ ystride0_off = DIV_ROUND_UP(h, ps->rau_h[0]);
+ ystride1_off = DIV_ROUND_UP(h, ps->rau_h[1]);
+ ps->plane_size[0] = (ps->ystride[0] * ystride0_off) +
+ (ps->ystride[1] * ystride1_off);
+ ps->ystride[0] += ps->ystride[1];
ps->ystride[1] = 2;
- ps->plane_size[1] = ps->rau_cnt * ps->ystride[1] * stride_off;
-
+ ps->plane_size[1] = ps->rau_cnt * ps->ystride[1] *
+ (ystride0_off + ystride1_off);
} else {
if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
ps->num_planes = 1;
@@ -346,43 +347,38 @@
int mdss_mdp_data_check(struct mdss_mdp_data *data,
struct mdss_mdp_plane_sizes *ps)
{
+ struct mdss_mdp_img_data *prev, *curr;
+ int i;
+
if (!ps)
return 0;
if (!data || data->num_planes == 0)
return -ENOMEM;
- if (data->bwc_enabled) {
- data->num_planes = ps->num_planes;
- data->p[1].addr = data->p[0].addr + ps->plane_size[0];
- } else {
- struct mdss_mdp_img_data *prev, *curr;
- int i;
+ pr_debug("srcp0=%x len=%u frame_size=%u\n", data->p[0].addr,
+ data->p[0].len, ps->total_size);
- pr_debug("srcp0=%x len=%u frame_size=%u\n", data->p[0].addr,
- data->p[0].len, ps->total_size);
-
- for (i = 0; i < ps->num_planes; i++) {
- curr = &data->p[i];
- if (i >= data->num_planes) {
- u32 psize = ps->plane_size[i-1];
- prev = &data->p[i-1];
- if (prev->len > psize) {
- curr->len = prev->len - psize;
- prev->len = psize;
- }
- curr->addr = prev->addr + psize;
+ for (i = 0; i < ps->num_planes; i++) {
+ curr = &data->p[i];
+ if (i >= data->num_planes) {
+ u32 psize = ps->plane_size[i-1];
+ prev = &data->p[i-1];
+ if (prev->len > psize) {
+ curr->len = prev->len - psize;
+ prev->len = psize;
}
- if (curr->len < ps->plane_size[i]) {
- pr_err("insufficient mem=%u p=%d len=%u\n",
- curr->len, i, ps->plane_size[i]);
- return -ENOMEM;
- }
- pr_debug("plane[%d] addr=%x len=%u\n", i,
- curr->addr, curr->len);
+ curr->addr = prev->addr + psize;
}
- data->num_planes = ps->num_planes;
+ if (curr->len < ps->plane_size[i]) {
+ pr_err("insufficient mem=%u p=%d len=%u\n",
+ curr->len, i, ps->plane_size[i]);
+ return -ENOMEM;
+ }
+ pr_debug("plane[%d] addr=%x len=%u\n", i,
+ curr->addr, curr->len);
}
+ data->num_planes = ps->num_planes;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index c19e07a..7ccf1b9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -132,7 +132,13 @@
pr_debug("setting secure=%d\n", enable);
+ ctl->is_secure = enable;
wb->is_secure = enable;
+
+ /* newer revisions don't require secure src pipe for secure session */
+ if (ctl->mdata->mdp_rev > MDSS_MDP_HW_REV_100)
+ return 0;
+
pipe = wb->secure_pipe;
if (!enable) {
@@ -243,6 +249,7 @@
mdss_mdp_pipe_destroy(wb->secure_pipe);
mutex_unlock(&wb->lock);
+ mdp5_data->ctl->is_secure = false;
mdp5_data->wb = NULL;
mutex_unlock(&mdss_mdp_wb_buf_lock);
diff --git a/drivers/video/msm/mdss/mdss_qpic.c b/drivers/video/msm/mdss/mdss_qpic.c
index be02113..fa6bd3d 100644
--- a/drivers/video/msm/mdss/mdss_qpic.c
+++ b/drivers/video/msm/mdss/mdss_qpic.c
@@ -428,7 +428,7 @@
param[0]);
param++;
bytes_left -= 4;
- space++;
+ space--;
} else if (bytes_left == 2) {
QPIC_OUTPW(QPIC_REG_QPIC_LCDC_FIFO_DATA_PORT0,
*(u16 *)param);
diff --git a/include/linux/regulator/qpnp-regulator.h b/include/linux/regulator/qpnp-regulator.h
index ec580ab..c7afeb5 100644
--- a/include/linux/regulator/qpnp-regulator.h
+++ b/include/linux/regulator/qpnp-regulator.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -93,12 +93,24 @@
* @system_load: Load in uA present on regulator that is not captured
* by any consumer request
* @enable_time: Time in us to delay after enabling the regulator
- * @ocp_enable: 1 = Enable over current protection (OCP) for voltage
- * switch type regulators so that they latch off
- * automatically when over current is detected
+ * @ocp_enable: 1 = Allow over current protection (OCP) to be
+ * enabled for voltage switch type regulators so
+ * that they latch off automatically when over
+ * current is detected. OCP is enabled when in HPM
+ * or auto mode.
* 0 = Disable OCP
* QPNP_REGULATOR_USE_HW_DEFAULT = do not modify
* OCP state
+ * @ocp_irq: IRQ number of the voltage switch OCP IRQ. If
+ * specified the voltage switch will be toggled off
+ * and back on when OCP triggers in order to handle
+ * high in-rush current.
+ * @ocp_max_retries: Maximum number of times to try toggling a voltage
+ * switch off and back on as a result of
+ * consecutive over current events.
+ * @ocp_retry_delay_ms: Time to delay in milliseconds between each
+ * voltage switch toggle after an over current
+ * event takes place.
* @boost_current_limit: This parameter sets the current limit of boost type
* regulators. Its value should be one of
* QPNP_BOOST_CURRENT_LIMIT_*. If its value is
@@ -117,9 +129,6 @@
* its value is QPNP_VS_SOFT_START_STR_HW_DEFAULT,
* then the soft start strength will be left at its
* default hardware value.
- * @ocp_enable_time: Time to delay in us between enabling a switch and
- * subsequently enabling over current protection
- * (OCP) for the switch
* @auto_mode_enable: 1 = Enable automatic hardware selection of regulator
* mode (HPM vs LPM). Auto mode is not available
* on boost type regulators
@@ -132,6 +141,18 @@
* 0 = Do not enable bypass mode
* QPNP_REGULATOR_USE_HW_DEFAULT = do not modify
* bypass mode state
+ * @hpm_enable: 1 = Enable high power mode (HPM), also referred to
+ * as NPM. HPM consumes more ground current than
+ * LPM, but it can source significantly higher load
+ * current. HPM is not available on boost type
+ * regulators. For voltage switch type regulators,
+ * HPM implies that over current protection and
+ * soft start are active all the time. This
+ * configuration can be overwritten by changing the
+ * regulator's mode dynamically.
+ * 0 = Do not enable HPM
+ * QPNP_REGULATOR_USE_HW_DEFAULT = do not modify
+ * HPM state
* @base_addr: SMPI base address for the regulator peripheral
*/
struct qpnp_regulator_platform_data {
@@ -142,12 +163,15 @@
int system_load;
int enable_time;
int ocp_enable;
+ int ocp_irq;
+ int ocp_max_retries;
+ int ocp_retry_delay_ms;
enum qpnp_boost_current_limit boost_current_limit;
int soft_start_enable;
enum qpnp_vs_soft_start_str vs_soft_start_strength;
- int ocp_enable_time;
int auto_mode_enable;
int bypass_mode_enable;
+ int hpm_enable;
u16 base_addr;
};
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index b175073..7f4a46c 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4626,7 +4626,7 @@
raw_spin_lock(&this_rq->lock);
- if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
+ if (!pulled_task || time_after(jiffies, this_rq->next_balance)) {
/*
* We are going idle. next_balance may be set based on
* a busy processor. So reset next_balance.
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index ad96ae3..08d7277 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -125,7 +125,7 @@
atomic_t audio_cond;
atomic_t audio_exit;
spinlock_t audio_lock;
- struct mutex protect_lock;
+ struct mutex state_process_lock;
struct workqueue_struct *audio_ocmem_workqueue;
struct workqueue_struct *voice_ocmem_workqueue;
bool ocmem_en;
@@ -252,6 +252,7 @@
if (ret != 0) {
pr_err("%s: get low power segments from DSP failed, rc=%d\n",
__func__, ret);
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
goto fail_cmd;
}
}
@@ -273,7 +274,9 @@
buf = ocmem_allocate_nb(cid, AUDIO_OCMEM_BUF_SIZE);
if (IS_ERR_OR_NULL(buf)) {
pr_err("%s: failed: %d\n", __func__, cid);
- return -ENOMEM;
+ ret = -ENOMEM;
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
+ goto fail_cmd;
}
set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_ALLOC);
@@ -285,7 +288,7 @@
if (!buf->len) {
pr_debug("%s: buf.len is 0, waiting for ocmem region\n",
__func__);
- mutex_unlock(&audio_ocmem_lcl.protect_lock);
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
(atomic_read(&audio_ocmem_lcl.audio_cond) == 0) ||
(atomic_read(&audio_ocmem_lcl.audio_exit) == 1));
@@ -302,7 +305,7 @@
goto fail_cmd;
}
clear_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_GROW);
- mutex_trylock(&audio_ocmem_lcl.protect_lock);
+ mutex_trylock(&audio_ocmem_lcl.state_process_lock);
}
pr_debug("%s: buf->len: %ld\n", __func__, (audio_ocmem_lcl.buf)->len);
@@ -333,7 +336,7 @@
_MAP_RESPONSE_BIT_MASK_) != 0);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
- mutex_unlock(&audio_ocmem_lcl.protect_lock);
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
pr_debug("%s: audio_cond[%d] audio_state[0x%x]\n", __func__,
atomic_read(&audio_ocmem_lcl.audio_cond),
atomic_read(&audio_ocmem_lcl.audio_state));
@@ -344,7 +347,7 @@
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
(atomic_read(&audio_ocmem_lcl.audio_state) &
_BIT_MASK_) != 0);
-
+ mutex_lock(&audio_ocmem_lcl.state_process_lock);
state_bit = get_state_to_process(&audio_ocmem_lcl.audio_state);
switch (state_bit) {
case OCMEM_STATE_MAP_COMPL:
@@ -502,6 +505,7 @@
atomic_read(&audio_ocmem_lcl.audio_state));
break;
}
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
}
ret = 0;
fail_cmd:
@@ -531,7 +535,7 @@
wake_up(&audio_ocmem_lcl.audio_wait);
- mutex_unlock(&audio_ocmem_lcl.protect_lock);
+ mutex_unlock(&audio_ocmem_lcl.state_process_lock);
pr_debug("%s: exit\n", __func__);
return 0;
}
@@ -654,7 +658,7 @@
container_of(work, struct audio_ocmem_workdata, work);
en = audio_ocm_work->en;
- mutex_lock(&audio_ocmem_lcl.protect_lock);
+ mutex_lock(&audio_ocmem_lcl.state_process_lock);
/* if previous work waiting for ocmem - signal it to exit */
atomic_set(&audio_ocmem_lcl.audio_exit, 1);
pr_debug("%s: acquired mutex for %d\n", __func__, en);
@@ -889,7 +893,7 @@
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_DEFAULT);
atomic_set(&audio_ocmem_lcl.audio_exit, 0);
spin_lock_init(&audio_ocmem_lcl.audio_lock);
- mutex_init(&audio_ocmem_lcl.protect_lock);
+ mutex_init(&audio_ocmem_lcl.state_process_lock);
audio_ocmem_lcl.ocmem_en = true;
audio_ocmem_lcl.audio_ocmem_running = false;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 8257023..17934eb 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -30,11 +30,11 @@
#include <sound/tlv.h>
#include <sound/asound.h>
#include <sound/pcm_params.h>
-#include <mach/qdsp6v2/q6core.h>
#include "msm-pcm-routing-v2.h"
#include "msm-dolby-dap-config.h"
#include "q6voice.h"
+#include "q6core.h"
struct msm_pcm_routing_bdai_data {
u16 port_id; /* AFE port ID */
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 63af271..2b0d155 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -80,6 +80,8 @@
static int32_t afe_callback(struct apr_client_data *data, void *priv)
{
+ int i;
+
if (!data) {
pr_err("%s: Invalid param data\n", __func__);
return -EINVAL;
@@ -87,6 +89,12 @@
if (data->opcode == RESET_EVENTS) {
pr_debug("q6afe: reset event = %d %d apr[%p]\n",
data->reset_event, data->reset_proc, this_afe.apr);
+
+ for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+ this_afe.afe_cal_addr[i].cal_paddr = 0;
+ this_afe.afe_cal_addr[i].cal_size = 0;
+ }
+
if (this_afe.apr) {
apr_reset(this_afe.apr);
atomic_set(&this_afe.state, 0);
diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c
index 557b326..42cbcd1 100644
--- a/sound/soc/msm/qdsp6v2/q6core.c
+++ b/sound/soc/msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,7 +32,7 @@
struct avcs_cmd_rsp_get_low_power_segments_info_t *lp_ocm_payload;
};
-struct q6core_str q6core_lcl;
+static struct q6core_str q6core_lcl;
static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
{
@@ -40,7 +40,7 @@
uint32_t nseg;
int i, j;
- pr_info("core msg: payload len = %u, apr resp opcode = 0x%X\n",
+ pr_debug("core msg: payload len = %u, apr resp opcode = 0x%X\n",
data->payload_size, data->opcode);
switch (data->opcode) {
@@ -121,6 +121,33 @@
pr_err("%s: Unable to register CORE\n", __func__);
}
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
+{
+ struct adsp_dolby_manufacturer_id payload;
+ int rc = 0;
+ pr_debug("%s manufacturer_id :%d\n", __func__, manufacturer_id);
+ ocm_core_open();
+ if (q6core_lcl.core_handle_q) {
+ payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ payload.hdr.pkt_size =
+ sizeof(struct adsp_dolby_manufacturer_id);
+ payload.hdr.src_port = 0;
+ payload.hdr.dest_port = 0;
+ payload.hdr.token = 0;
+ payload.hdr.opcode = ADSP_CMD_SET_DOLBY_MANUFACTURER_ID;
+ payload.manufacturer_id = manufacturer_id;
+ pr_debug("Send Dolby security opcode=%x manufacturer ID = %d\n",
+ payload.hdr.opcode, payload.manufacturer_id);
+ rc = apr_send_pkt(q6core_lcl.core_handle_q,
+ (uint32_t *)&payload);
+ if (rc < 0)
+ pr_err("%s: SET_DOLBY_MANUFACTURER_ID failed op[0x%x]rc[%d]\n",
+ __func__, payload.hdr.opcode, rc);
+ }
+ return rc;
+}
+
int core_get_low_power_segments(
struct avcs_cmd_rsp_get_low_power_segments_info_t **lp_memseg)
{
diff --git a/sound/soc/msm/qdsp6v2/q6core.h b/sound/soc/msm/qdsp6v2/q6core.h
index ff611d5..39bf4ab 100644
--- a/sound/soc/msm/qdsp6v2/q6core.h
+++ b/sound/soc/msm/qdsp6v2/q6core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -90,4 +90,13 @@
int core_get_low_power_segments(
struct avcs_cmd_rsp_get_low_power_segments_info_t **);
+#define ADSP_CMD_SET_DOLBY_MANUFACTURER_ID 0x00012918
+
+struct adsp_dolby_manufacturer_id {
+ struct apr_hdr hdr;
+ int manufacturer_id;
+};
+
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id);
+
#endif /* __Q6CORE_H__ */
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 40595bf..519f325 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1767,7 +1767,12 @@
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
+ !((be->dpcm[stream].state == SND_SOC_DPCM_STATE_START) &&
+ ((fe->dpcm[stream].state != SND_SOC_DPCM_STATE_START) &&
+ (fe->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
+ (fe->dpcm[stream].state !=
+ SND_SOC_DPCM_STATE_SUSPEND))))
continue;
dev_dbg(be->dev, "dpcm: hw_free BE %s\n",