Merge "cfg80211: enable TDLS on P2P client interfaces"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
index d930799..3d70a9b 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
@@ -62,6 +62,28 @@
1. This value shift is necessary to work around
limitations in the regulator framework which
treat 0 uV as an error.
+- qcom,use-voltage-floor-corner: Flag that signifies if regulator_set_voltage
+ calls should modify the floor corner parameter
+ instead of the voltage parameter. When used,
+ voltages specified inside of the regulator
+ framework represent corners that have been
+ incremented by 1. The properties
+ qcom,use-voltage-corner and
+ qcom,use-voltage-floor-corner are mutually
+ exclusive. Only one may be specified for a
+ given regulator.
+- qcom,always-send-voltage: Flag which indicates that updates to the voltage
+ or voltage corner set point should always be
+ sent immediately to the RPM. If this flag is
+ not specified, then voltage set point updates
+ are only sent if the given regulator has also
+ been enabled by a Linux consumer.
+- qcom,always-send-current: Flag which indicates that updates to the load
+ current should always be sent immediately to the
+ RPM. If this flag is not specified, then load
+ current updates are only sent if the given
+ regulator has also been enabled by a Linux
+ consumer.
The following properties specify initial values for parameters to be sent to the
RPM in regulator requests.
- qcom,init-enable: 0 = regulator disabled
@@ -94,25 +116,9 @@
BIT(2) = follow HW2_EN signal
BIT(3) = follow HW3_EN signal
BIT(4) = follow PMIC awake state
-- qcom,init-frequency: Switching frequency in MHz for SMPS regulators.
- Supported values are:
- 0 = Don't care about frequency used
- 1 = 19.20
- 2 = 9.60
- 3 = 6.40
- 4 = 4.80
- 5 = 3.84
- 6 = 3.20
- 7 = 2.74
- 8 = 2.40
- 9 = 2.13
- 10 = 1.92
- 11 = 1.75
- 12 = 1.60
- 13 = 1.48
- 14 = 1.37
- 15 = 1.28
- 16 = 1.20
+- qcom,init-frequency: Switching frequency divisor for SMPS regulators.
+ Supported values are n = 0 to 31 where
+ freq = 19.2 MHz / (n + 1).
- qcom,init-head-room: Voltage head room in mV required for the
regulator. This head room value should be used
in situations where the device connected to the
@@ -165,6 +171,10 @@
0 = Allow RPM to utilize LDO bypass mode
if possible
1 = Disallow LDO bypass mode
+- qcom,init-voltage-floor-corner: Minimum performance corner to use if any
+ processor in the system is awake. This property
+ supports the same values as
+ qcom,init-voltage-corner.
All properties specified within the core regulator framework can also be used in
second level nodes. These bindings can be found in:
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
new file mode 100644
index 0000000..c012eec
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
@@ -0,0 +1,32 @@
+Qualcomm SPM Regulators
+
+spm-regulator is a regulator device which supports PMIC processor supply
+regulators via the SPM module.
+
+Required properties:
+- compatible: Must be "qcom,spm-regulator"
+- reg: Specifies the SPMI address and size for this regulator device
+- regulator-name: A string used as a descriptive name for the regulator
+
+Required structure:
+- A qcom,spm-regulator node must be a child of an SPMI node that has specified
+ the spmi-slave-container property
+
+All properties specified within the core regulator framework can also be used.
+These bindings can be found in regulator.txt.
+
+Example:
+ qcom,spmi@fc4c0000 {
+
+ qcom,pm8226@1 {
+ spmi-slave-container;
+
+ spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
+ regulator-name = "8226_s2";
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1275000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index b9bac1d..812a895 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -51,12 +51,17 @@
Required properties for RGB led:
- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
- qcom,pwm-channel: pwm channel the led will operate on
+
+Required properties for PWM mode only:
- qcom,pwm-us: time the pwm device will modulate at (us)
Required properties for LPG mode only:
-- qcom,duty-ms: duty cycle time the led will operate at (ms)
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
Optional properties for RGB led:
- linux,default-trigger: trigger the led from external modules such as display
@@ -90,12 +95,14 @@
linux,name = "led:rgb_blue";
qcom,mode = <1>;
qcom,pwm-channel = <4>;
- qcom,pwm-us = <1000>;
- qcom,duty-ms = <20>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
qcom,duty-pcts = [00 19 32 4B 64
64 4B 32 19 00];
+ qcom,lut-flags = <3>;
+ qcom,pause-lo = <0>;
+ qcom,pause-hi = <0>;
+ qcom,ramp-step-ms = <255>;
qcom,max-current = <12>;
qcom,default-state = "on";
qcom,turn-off-delay-ms = <500>;
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
new file mode 100644
index 0000000..34c344a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -0,0 +1,27 @@
+QPNP-MISC
+
+QPNP-MISC provides a way to read the PMIC part number and revision.
+
+Required properties:
+- compatible : should be "qcom,qpnp-misc"
+- reg : offset and length of the PMIC peripheral register map.
+
+Example:
+ qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+ }
+ };
diff --git a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
index 7b9feae..6c3e98e 100644
--- a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
+++ b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
@@ -2,15 +2,15 @@
Required properties:
- compatible: Can be "qca,ar6004-sdio" for SDIO device and
- "qca,ar6004-hsic" for HSIC devcie.
+ "qca,ar6004-hsic" for HSIC device. For AR6003, "qca,ar6003-sdio" can be
+ used.
- qca,chip-pwd-l-gpios: specify GPIO for CHIP_PWD_L.
Optional Properties:
- cell-index: WLAN Hardware index.
- qca,pm-enable-gpios: Specify this GPIO if internal PMU needs to be used.
- - qca,ar6004-vbatt-supply: Specify this if VBATT is provided through a
- regulator.
- - qca,ar6004-vdd-io-supply: Specify this if VDD-IO is provided through a
+ - qca,vbatt-supply: Specify this if VBATT is provided through a regulator.
+ - qca,vdd-io-supply: Specify this if VDD-IO is provided through a
regulator.
Example:
@@ -20,5 +20,5 @@
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>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 320c3e4a..d174157 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ pm8941_misc: qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+
qcom,revid@100 {
compatible = "qcom,qpnp-revid";
reg = <0x100 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 800cd8f..c303061 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -89,6 +89,28 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 Internal1",
+ "MIC BIAS1 Internal1", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic",
+ "DMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic1",
+ "DMIC2", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic2",
+ "DMIC3", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic3",
+ "DMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic4";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 3d1fe19..a18bad3 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -89,6 +89,20 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 4fa37d6..e137ee2 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -89,6 +89,20 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index c39d987..448a5be 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,18 +10,16 @@
* GNU General Public License for more details.
*/
-/* QPNP controlled regulators: */
+/* SPM controlled regulators: */
&spmi_bus {
qcom,pm8226@1 {
- pm8226_s2: regulator@1700 {
- status = "okay";
+ pm8226_s2: spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
regulator-name = "8226_s2";
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1150000>;
- regulator-always-on;
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1275000>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 5239f24..5f51520 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -227,29 +227,6 @@
sound {
compatible = "qcom,msm8226-audio-tapan";
qcom,model = "msm8226-tapan-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "SPK_OUT", "MCLK",
- "SPK_OUT", "EXT_VDD_SPKR",
- "AMIC1", "MIC BIAS1 Internal1",
- "MIC BIAS1 Internal1", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCRight Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic",
- "DMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Digital Mic1",
- "DMIC2", "MIC BIAS1 External",
- "MIC BIAS1 External", "Digital Mic2",
- "DMIC3", "MIC BIAS3 External",
- "MIC BIAS3 External", "Digital Mic3",
- "DMIC4", "MIC BIAS3 External",
- "MIC BIAS3 External", "Digital Mic4";
-
qcom,tapan-mclk-clk-freq = <9600000>;
};
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
new file mode 100644
index 0000000..390c02a
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -0,0 +1,26 @@
+/* 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/ "msm8610.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+ qcom,msm-id = <147 1 0>;
+
+ serial@f991f000 {
+ status = "ok";
+ };
+};
+
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
new file mode 100644
index 0000000..70ac0e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -0,0 +1,26 @@
+/* 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/ "msm8610.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+ qcom,msm-id = <147 8 0>;
+
+ serial@f991f000 {
+ status = "ok";
+ };
+};
+
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 53d0d5d..b6a6c74 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -429,6 +429,28 @@
compatible = "qcom,msm-pcm-hostless";
};
+ qcom,mss@fc880000 {
+ compatible = "qcom,pil-q6v5-mss";
+ reg = <0xfc880000 0x100>,
+ <0xfd485000 0x400>,
+ <0xfc820000 0x020>,
+ <0xfc401680 0x004>,
+ <0x0d1fc000 0x4000>,
+ <0xfd485194 0x4>;
+ reg-names = "qdsp6_base", "halt_base", "rmb_base",
+ "restart_reg", "metadata_base", "cxrail_bhs_reg";
+
+ interrupts = <0 24 1>;
+ vdd_mss-supply = <&pm8110_s1>;
+ vdd_cx-supply = <&pm8110_s1_corner>;
+ vdd_mx-supply = <&pm8110_l3>;
+ vdd_pll-supply = <&pm8110_l10>;
+ qcom,vdd_pll = <1800000>;
+ qcom,is-loadable;
+ qcom,firmware-name = "mba";
+ qcom,pil-self-auth;
+ };
+
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 5eff79c..b125138 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -93,6 +93,15 @@
qcom,use-voltage-corner;
compatible = "qcom,rpm-regulator-smd";
};
+ pm8841_s2_floor_corner: regulator-s2-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8841_s2_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
};
rpm-regulator-smpb3 {
@@ -121,6 +130,15 @@
regulator-max-microvolt = <7>;
qcom,init-voltage-corner = <3>; /* SVS SOC */
};
+ pm8841_s4_floor_corner: regulator-s4-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8841_s4_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
};
rpm-regulator-smpa1 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 9172029..b06419d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -140,31 +140,27 @@
qcom,pipe0 {
label = "hsusb-ipa-out-0";
- qcom,usb-bam-mem-type = <0>;
+ qcom,usb-bam-mem-type = <2>;
qcom,bam-type = <1>;
qcom,dir = <0>;
qcom,pipe-num = <0>;
qcom,peer-bam = <2>;
qcom,src-bam-physical-address = <0xf9a44000>;
qcom,src-bam-pipe-index = <1>;
- qcom,data-fifo-offset = <0x2200>;
- qcom,data-fifo-size = <0x1e00>;
- qcom,descriptor-fifo-offset = <0x2100>;
- qcom,descriptor-fifo-size = <0x100>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
};
qcom,pipe1 {
label = "hsusb-ipa-in-0";
- qcom,usb-bam-mem-type = <0>;
+ qcom,usb-bam-mem-type = <2>;
qcom,bam-type = <1>;
qcom,dir = <1>;
qcom,pipe-num = <0>;
qcom,peer-bam = <2>;
qcom,dst-bam-physical-address = <0xf9a44000>;
qcom,dst-bam-pipe-index = <0>;
- qcom,data-fifo-offset = <0x300>;
- qcom,data-fifo-size = <0x1e00>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x300>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
};
qcom,pipe2 {
label = "hsusb-qdss-in-0";
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 663e937..2f5f7f0 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -292,6 +292,7 @@
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 2de81d4d1..4aebfdb 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -297,6 +297,7 @@
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
CONFIG_QPNP_REVID=y
+CONFIG_QPNP_MISC=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 048e191..18b1c5a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -428,6 +428,7 @@
select ARM_HAS_SG_CHAIN
select REGULATOR
select MSM_RPM_REGULATOR_SMD
+ select MSM_SPM_REGULATOR
config ARCH_MSM8226
bool "MSM8226"
@@ -463,6 +464,7 @@
select ARM_HAS_SG_CHAIN
select REGULATOR
select MSM_RPM_REGULATOR_SMD
+ select MSM_SPM_REGULATOR
select MSM_JTAG_MM if CORESIGHT_ETM
endmenu
@@ -1823,7 +1825,6 @@
config MSM_HW3D
tristate "MSM Hardware 3D Register Driver"
depends on ANDROID_PMEM
- default y
help
Provides access to registers needed by the userspace OpenGL|ES
library.
@@ -2062,6 +2063,16 @@
be used on systems which contain an RPM which communicates with the
application processor over SMD.
+config MSM_SPM_REGULATOR
+ bool "SPM regulator driver"
+ depends on REGULATOR && SPMI && OF_SPMI
+ help
+ Enable support for the SPM regulator driver which is used for
+ setting voltages of processor supply regulators via the SPM module
+ found inside of the MSM chips. The SPM regulator driver can be used
+ on MSM systems where the APSS processor cores are supplied by their
+ own PMIC regulator.
+
config MSM_SMCMOD
tristate "Secure Monitor Call (SMC) Module"
default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f7b6503..d3acbc7 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -210,6 +210,7 @@
endif
obj-$(CONFIG_MSM_RPM_REGULATOR_SMD) += rpm-regulator-smd.o
+obj-$(CONFIG_MSM_SPM_REGULATOR) += spm-regulator.o
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
obj-y += subsystem_notif.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index fcbd74d..73ea435 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -57,7 +57,7 @@
{ 1, 300000, PLL0, 4, 2, 1150000, 1150000, 4 },
{ 1, 384000, ACPUPLL, 5, 0, 1150000, 1150000, 4 },
{ 1, 600000, PLL0, 4, 0, 1150000, 1150000, 6 },
- { 1, 787200, ACPUPLL, 5, 0, 1150000, 1150000, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0, 998400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0, 1190400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0 }
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 0654a0d..b3364b0 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -3531,19 +3531,6 @@
}
#endif
-static struct android_pmem_platform_data android_pmem_pdata = {
- .name = "pmem",
- .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
- .cached = 1,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = { .platform_data = &android_pmem_pdata },
-};
-
#ifndef CONFIG_SPI_QSD
static int lcdc_gpio_array_num[] = {
45, /* spi_clk */
@@ -4021,32 +4008,6 @@
.id = -1,
};
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
- .name = "pmem_adsp",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
- .name = "pmem_audio",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_adsp_device = {
- .name = "android_pmem",
- .id = 2,
- .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct platform_device android_pmem_audio_device = {
- .name = "android_pmem",
- .id = 4,
- .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -5395,7 +5356,6 @@
#ifdef CONFIG_I2C_SSBI
&msm_device_ssbi7,
#endif
- &android_pmem_device,
&msm_fb_device,
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
&msm_v4l2_video_overlay_device,
@@ -5407,8 +5367,6 @@
&msm_rotator_device,
#endif
&lcdc_sharp_panel_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
&msm_device_i2c,
&msm_device_i2c_2,
&msm_device_uart_dm1,
@@ -7234,39 +7192,6 @@
#endif
}
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-
- android_pmem_adsp_pdata.size = size;
- android_pmem_audio_pdata.size = pmem_audio_size;
- android_pmem_pdata.size = pmem_sf_size;
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
- msm7x30_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
- reserve_memory_for(&android_pmem_pdata);
- msm7x30_reserve_table[MEMTYPE_EBI0].size += pmem_kernel_ebi0_size;
-#endif
-#endif
-}
-
static void __init reserve_mdp_memory(void)
{
mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -7294,8 +7219,6 @@
static void __init msm7x30_calculate_reserve_sizes(void)
{
fix_sizes();
- size_pmem_devices();
- reserve_pmem_memory();
reserve_mdp_memory();
size_ion_devices();
reserve_ion_memory();
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index cc478da..a690033 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,22 +169,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -2760,19 +2752,12 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
+static const int *vdd_sr2_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3511,23 +3496,23 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8226: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_dig_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8226: Unable to get the sr2_pll regulator!");
/*
* These regulators are used at boot. Ensure they stay on
* while the clock framework comes online.
*/
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
/*
* Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c517c10..930f9e3 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -445,22 +445,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -550,20 +542,13 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
+static const int *vdd_sr2_pll_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
-
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
+ vdd_sr2_pll_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3546,16 +3531,16 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8610: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_sr2_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
/*
* TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3564,7 +3549,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e9824a6..e040d7f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -638,22 +638,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -5490,8 +5482,8 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5501,7 +5493,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
@@ -5556,8 +5548,8 @@
sdcc3_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
sdcc4_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5567,7 +5559,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
}
struct clock_init_data msm8974_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 9648320..d8e4ed5 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -278,22 +278,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
/* TODO: Needs to confirm the below values */
#define RPM_MISC_CLK_TYPE 0x306b6c63
@@ -344,6 +336,7 @@
static struct pll_vote_clk gpll0_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.soft_vote = &soft_vote_gpll0,
@@ -360,6 +353,7 @@
static struct pll_vote_clk gpll0_activeonly_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.soft_vote = &soft_vote_gpll0,
@@ -2060,12 +2054,12 @@
clk_ops_local_pll.enable = sr_pll_clk_enable_9625;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-9625: Unable to get the vdd_dig regulator!");
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index e0ee084..ecd25fc 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/list.h>
+#include <linux/regulator/consumer.h>
#include <trace/events/power.h>
#include <mach/clk-provider.h>
#include "clock.h"
@@ -53,20 +54,39 @@
/* Update voltage level given the current votes. */
static int update_vdd(struct clk_vdd_class *vdd_class)
{
- int level, rc;
+ int level, rc = 0, i;
+ struct regulator **r = vdd_class->regulator;
+ const int **vdd_uv = vdd_class->vdd_uv;
+ int max_level = vdd_class->num_levels - 1;
- for (level = vdd_class->num_levels-1; level > 0; level--)
+ for (level = max_level; level > 0; level--)
if (vdd_class->level_votes[level])
break;
if (level == vdd_class->cur_level)
return 0;
- rc = vdd_class->set_vdd(vdd_class, level);
+ for (i = 0; i < vdd_class->num_regulators; i++) {
+ rc = regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+ if (rc)
+ goto set_voltage_fail;
+ }
+ if (vdd_class->set_vdd && !vdd_class->num_regulators)
+ rc = vdd_class->set_vdd(vdd_class, level);
+
if (!rc)
vdd_class->cur_level = level;
return rc;
+
+set_voltage_fail:
+ level = vdd_class->cur_level;
+ for (i--; i >= 0; i--)
+ regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+
+ return rc;
}
/* Vote for a voltage level. */
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 475b483..528e9d5 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -21,6 +21,7 @@
#include <linux/clkdev.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
/*
@@ -42,14 +43,23 @@
/**
* struct clk_vdd_class - Voltage scaling class
* @class_name: name of the class
- * @set_vdd: function to call when applying a new voltage setting
- * @level_votes: array of votes for each level
+ * @regulator: array of regulators.
+ * @num_regulators: size of regulator array. Standard regulator APIs will be
+ used if this field > 0.
+ * @set_vdd: function to call when applying a new voltage setting.
+ * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
+ regulator.
+ * @level_votes: array of votes for each level.
+ * @num_levels: specifies the size of level_votes array.
* @cur_level: the currently set voltage level
* @lock: lock to protect this struct
*/
struct clk_vdd_class {
const char *class_name;
+ struct regulator **regulator;
+ int num_regulators;
int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+ const int **vdd_uv;
int *level_votes;
int num_levels;
unsigned long cur_level;
@@ -66,6 +76,20 @@
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .vdd_uv = _vdd_uv, \
+ .regulator = (struct regulator * [_num_regulators]) {}, \
+ .num_regulators = _num_regulators, \
+ .level_votes = (int [_num_levels]) {}, \
+ .num_levels = _num_levels, \
+ .cur_level = _num_levels, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+#define VDD_UV(...) ((int []){__VA_ARGS__})
+
enum handoff {
HANDOFF_ENABLED_CLK,
HANDOFF_DISABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index 2fdd99c..f460a4e 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,12 +28,6 @@
#define MPQ8092_QGIC_DIST_PHYS 0xF9000000
#define MPQ8092_QGIC_DIST_SIZE SZ_4K
-#define MPQ8092_QGIC_CPU_PHYS 0xF9002000
-#define MPQ8092_QGIC_CPU_SIZE SZ_4K
-
-#define MPQ8092_APCS_GCC_PHYS 0xF9011000
-#define MPQ8092_APCS_GCC_SIZE SZ_4K
-
#define MPQ8092_TLMM_PHYS 0xFD510000
#define MPQ8092_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 81b3c48..ac3e912 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,9 +28,6 @@
#define MSM8226_QGIC_DIST_PHYS 0xF9000000
#define MSM8226_QGIC_DIST_SIZE SZ_4K
-#define MSM8226_QGIC_CPU_PHYS 0xF9002000
-#define MSM8226_QGIC_CPU_SIZE SZ_4K
-
#define MSM8226_APCS_GCC_PHYS 0xF9011000
#define MSM8226_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 594b1cc..ec3c210 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,12 +28,6 @@
#define MSM8974_QGIC_DIST_PHYS 0xF9000000
#define MSM8974_QGIC_DIST_SIZE SZ_4K
-#define MSM8974_QGIC_CPU_PHYS 0xF9002000
-#define MSM8974_QGIC_CPU_SIZE SZ_4K
-
-#define MSM8974_APCS_GCC_PHYS 0xF9011000
-#define MSM8974_APCS_GCC_SIZE SZ_4K
-
#define MSM8974_TLMM_PHYS 0xFD510000
#define MSM8974_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 341bbe3..9a8bfc1 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,12 +28,6 @@
#define MSM9625_QGIC_DIST_PHYS 0xF9000000
#define MSM9625_QGIC_DIST_SIZE SZ_4K
-#define MSM9625_QGIC_CPU_PHYS 0xF9002000
-#define MSM9625_QGIC_CPU_SIZE SZ_4K
-
-#define MSM9625_APCS_GCC_PHYS 0xF9011000
-#define MSM9625_APCS_GCC_SIZE SZ_4K
-
#define MSM9625_TMR_PHYS 0xF9021000
#define MSM9625_TMR_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
index 8283622..0a33055 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
@@ -28,9 +28,6 @@
#define MSMZINC_QGIC_DIST_PHYS 0xF9000000
#define MSMZINC_QGIC_DIST_SIZE SZ_4K
-#define MSMZINC_QGIC_CPU_PHYS 0xF9002000
-#define MSMZINC_QGIC_CPU_SIZE SZ_4K
-
#define MSMZINC_TLMM_PHYS 0xFD510000
#define MSMZINC_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 9cf9517..d3706cd 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,15 +47,14 @@
#define MSM8625_WARM_BOOT_PHYS 0x0FD00000
-
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
- defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
- defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM7X27) || \
- defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
- defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
- defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
- defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610) || \
- defined(CONFIG_ARCH_MSMZINC)
+/* Legacy single-target iomap */
+#if defined(CONFIG_ARCH_QSD8X50)
+#include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
+#elif defined(CONFIG_ARCH_FSM9XXX)
+#include "msm_iomap-fsm9xxx.h"
+#else
/* Unified iomap */
@@ -136,18 +135,6 @@
#include "msm_iomap-8226.h"
#include "msm_iomap-8610.h"
-#else
-/* Legacy single-target iomap */
-#if defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "msm_iomap-8x60.h"
-#elif defined(CONFIG_ARCH_FSM9XXX)
-#include "msm_iomap-fsm9xxx.h"
-#else
-#error "Target compiled without IO map\n"
-#endif
-
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index ff1b3c5..45f2646 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -74,6 +74,10 @@
of_machine_is_compatible("qcom,msm8610-sim")
#define machine_is_msm8610_rumi() \
of_machine_is_compatible("qcom,msm8610-rumi")
+#define machine_is_msm8610_mtp() \
+ of_machine_is_compatible("qcom,msm8610-mtp")
+#define machine_is_msm8610_cdp() \
+ of_machine_is_compatible("qcom,msm8610-cdp")
#define early_machine_is_msmzinc() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
#define machine_is_msmzinc_sim() \
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index c71a79a..19c7acd 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,8 +301,6 @@
#ifdef CONFIG_ARCH_MSM8974
static struct map_desc msm_8974_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
- MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
MSM_CHIP_DEVICE(TLMM, MSM8974),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
{
@@ -326,7 +324,6 @@
#ifdef CONFIG_ARCH_MSMZINC
static struct map_desc msm_zinc_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSMZINC),
- MSM_CHIP_DEVICE(QGIC_CPU, MSMZINC),
MSM_CHIP_DEVICE(TLMM, MSMZINC),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -488,9 +485,7 @@
#ifdef CONFIG_ARCH_MSM9625
static struct map_desc msm9625_io_desc[] __initdata = {
- MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -515,8 +510,6 @@
#ifdef CONFIG_ARCH_MPQ8092
static struct map_desc mpq8092_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
- MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
- MSM_CHIP_DEVICE(APCS_GCC, MPQ8092),
MSM_CHIP_DEVICE(TLMM, MPQ8092),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -538,7 +531,6 @@
#ifdef CONFIG_ARCH_MSM8226
static struct map_desc msm_8226_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
MSM_CHIP_DEVICE(TLMM, MSM8226),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 5f11806..786dad8 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -191,6 +191,10 @@
BUG_ON(mr_candidate == NULL);
/* bump mt up against the top of the region */
mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+ ret = memblock_reserve(mt->start, mt->size);
+ BUG_ON(ret);
+ ret = memblock_free(mt->start, mt->size);
+ BUG_ON(ret);
ret = memblock_remove(mt->start, mt->size);
BUG_ON(ret);
}
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 2ceb06d..599b24c 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -58,6 +58,7 @@
#define RMB_PMI_CODE_LENGTH 0x18
#define VDD_MSS_UV 1050000
+#define MAX_VDD_MSS_UV 1150000
#define MAX_VDD_MX_UV 1150000
#define PROXY_TIMEOUT_MS 10000
@@ -739,7 +740,7 @@
if (IS_ERR(q6->vreg_mx))
return PTR_ERR(q6->vreg_mx);
- ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, VDD_MSS_UV);
+ ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, MAX_VDD_MSS_UV);
if (ret)
dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index d83a140..eb9c388 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include "adsp.h"
#include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
#include <mach/debug_mm.h>
struct adsp_ion_info {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 4d03dca..62d6d58 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -17,7 +17,6 @@
*/
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <mach/qdsp5/qdsp5vdeccmdi.h>
#include "adsp.h"
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index 7819395..608f544 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -16,7 +16,6 @@
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
@@ -110,7 +109,6 @@
audpp_cmd_cfg_object_params_eqalizer eq;
struct audrec_session_info session_info;
/*pmem info*/
- int pmem_fd;
unsigned long paddr;
unsigned long kvaddr;
unsigned long pmem_len;
@@ -1136,7 +1134,6 @@
{
int rc = 0;
unsigned long flags = 0;
- struct msm_audio_pmem_info info;
MM_DBG("%s\n", __func__);
@@ -1156,23 +1153,6 @@
MM_ERR("AUDPP returned err =%d\n", rc);
spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
break;
- case AUDIO_REGISTER_PMEM:
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info))) {
- MM_ERR("Cannot copy from user\n");
- return -EFAULT;
- }
- rc = get_pmem_file(info.fd, &acdb_data.paddr,
- &acdb_data.kvaddr,
- &acdb_data.pmem_len,
- &acdb_data.file);
- if (rc == 0)
- acdb_data.pmem_fd = info.fd;
- break;
- case AUDIO_DEREGISTER_PMEM:
- if (acdb_data.pmem_fd)
- put_pmem_file(acdb_data.file);
- break;
case AUDIO_SET_ACDB_BLK:
MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
index 7249bb1..ad74ca3 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
@@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
#include <linux/export.h>
#include "adsp.h"
#include <mach/debug_mm.h>
@@ -87,71 +86,6 @@
res; \
})
-static int adsp_pmem_check(struct msm_adsp_module *module,
- void *vaddr, unsigned long len)
-{
- struct adsp_pmem_region *region_elt;
- struct hlist_node *node;
- struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
-
- hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("module %s:"
- " region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- module->name,
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int adsp_pmem_add(struct msm_adsp_module *module,
- struct adsp_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct adsp_pmem_region *region;
- int rc = -EINVAL;
-
- mutex_lock(&module->pmem_regions_lock);
- region = kmalloc(sizeof(*region), GFP_KERNEL);
- if (!region) {
- rc = -ENOMEM;
- goto end;
- }
- INIT_HLIST_NODE(®ion->list);
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
- }
-
- rc = adsp_pmem_check(module, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
- }
-
- region->vaddr = info->vaddr;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
-
- hlist_add_head(®ion->list, &module->pmem_regions);
-end:
- mutex_unlock(&module->pmem_regions_lock);
- return rc;
-}
-
static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
unsigned long len, struct adsp_pmem_region **region)
{
@@ -417,24 +351,6 @@
return rc;
}
-static int adsp_pmem_del(struct msm_adsp_module *module)
-{
- struct hlist_node *node, *tmp;
- struct adsp_pmem_region *region;
-
- mutex_lock(&module->pmem_regions_lock);
- hlist_for_each_safe(node, tmp, &module->pmem_regions) {
- region = hlist_entry(node, struct adsp_pmem_region, list);
- hlist_del(node);
- put_pmem_file(region->file);
- kfree(region);
- }
- mutex_unlock(&module->pmem_regions_lock);
- BUG_ON(!hlist_empty(&module->pmem_regions));
-
- return 0;
-}
-
static long adsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct adsp_device *adev = filp->private_data;
@@ -466,21 +382,11 @@
return adsp_set_clkrate(adev->module, clk_rate);
}
- case ADSP_IOCTL_REGISTER_PMEM: {
- struct adsp_pmem_info info;
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- return -EFAULT;
- return adsp_pmem_add(adev->module, &info);
- }
-
case ADSP_IOCTL_ABORT_EVENT_READ:
adev->abort = 1;
wake_up(&adev->event_wait);
break;
- case ADSP_IOCTL_UNREGISTER_PMEM:
- return adsp_pmem_del(adev->module);
-
default:
break;
}
@@ -498,8 +404,6 @@
/* clear module before putting it to avoid race with open() */
adev->module = NULL;
- rc = adsp_pmem_del(module);
-
msm_adsp_put(module);
return rc;
}
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac.c b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
index 883da2b..fbce5d6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio_aac.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
index a878e12..cf1f58d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
@@ -26,7 +26,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_aac.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <mach/msm_memtypes.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
index 5d7cfd7..85378be 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
@@ -16,7 +16,6 @@
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
@@ -1287,7 +1286,6 @@
{
int rc = 0;
unsigned long flags = 0;
- struct msm_audio_pmem_info info;
MM_DBG("%s\n", __func__);
@@ -1308,23 +1306,6 @@
MM_ERR("AUDPP returned err =%d\n", rc);
spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
break;
- case AUDIO_REGISTER_PMEM:
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info))) {
- MM_ERR("Cannot copy from user\n");
- return -EFAULT;
- }
- rc = get_pmem_file(info.fd, &acdb_data.paddr,
- &acdb_data.kvaddr,
- &acdb_data.pmem_len,
- &acdb_data.file);
- if (rc == 0)
- acdb_data.pmem_fd = info.fd;
- break;
- case AUDIO_DEREGISTER_PMEM:
- if (acdb_data.pmem_fd)
- put_pmem_file(acdb_data.file);
- break;
case AUDIO_SET_ACDB_BLK:
MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 7cc3e29..632aa0d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -34,7 +34,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index c8b4171..bd4f6e1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -37,7 +37,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index 66d0a9e..e5706c7 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -37,7 +37,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index 2d9327e..ed946f9 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_fm.c b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
index cffa7e7..27548ac 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_fm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
@@ -29,7 +29,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0390edf..bda2e4d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
@@ -1095,103 +1094,6 @@
return rc;
}
-static int audmp3_pmem_check(struct audio *audio,
- void *vaddr, unsigned long len)
-{
- struct audmp3_pmem_region *region_elt;
- struct audmp3_pmem_region t = { .vaddr = vaddr, .len = len };
-
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int audmp3_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audmp3_pmem_region *region;
- int rc = -EINVAL;
-
- MM_DBG("\n"); /* Macro prints the file name and function */
- region = kmalloc(sizeof(*region), GFP_KERNEL);
-
- if (!region) {
- rc = -ENOMEM;
- goto end;
- }
-
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
- }
-
- rc = audmp3_pmem_check(audio, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
- }
-
- region->vaddr = info->vaddr;
- region->fd = info->fd;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
- region->ref_cnt = 0;
- MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
- region->vaddr, region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
-end:
- return rc;
-}
-
-static int audmp3_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- struct audmp3_pmem_region *region;
- struct list_head *ptr, *next;
- int rc = -EINVAL;
-
- MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audmp3_pmem_region, list);
-
- if ((region->fd == info->fd) &&
- (region->vaddr == info->vaddr)) {
- if (region->ref_cnt) {
- MM_DBG("region %p in use ref_cnt %d\n",
- region, region->ref_cnt);
- break;
- }
- MM_DBG("remove region fd %d vaddr %p \n",
- info->fd, info->vaddr);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
static int audmp3_pmem_lookup_vaddr(struct audio *audio, void *addr,
unsigned long len, struct audmp3_pmem_region **region)
{
@@ -1688,25 +1590,6 @@
break;
}
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audmp3_pmem_add(audio, &info);
- break;
- }
-
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_DEREGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audmp3_pmem_remove(audio, &info);
- break;
- }
case AUDIO_ASYNC_WRITE:
if (audio->drv_status & ADRV_STATUS_FSYNC)
rc = -EBUSY;
@@ -2105,21 +1988,6 @@
return rc;
}
-static void audmp3_reset_pmem_region(struct audio *audio)
-{
- struct audmp3_pmem_region *region;
- struct list_head *ptr, *next;
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audmp3_pmem_region, list);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- }
-
- return;
-}
-
static int audio_release(struct inode *inode, struct file *file)
{
struct audio *audio = file->private_data;
@@ -2130,7 +1998,6 @@
audio_disable(audio);
audio->drv_ops.out_flush(audio);
audio->drv_ops.in_flush(audio);
- audmp3_reset_pmem_region(audio);
msm_adsp_put(audio->audplay);
audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_out.c b/arch/arm/mach-msm/qdsp5v2/audio_out.c
index e5c59ba..712c9f3 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_out.c
@@ -30,7 +30,6 @@
#include <linux/wakelock.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
#include <linux/pm_qos.h>
#include <mach/msm_adsp.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index ea8fc83..cbd2913 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
@@ -743,99 +742,6 @@
return rc;
}
-static int audpcm_pmem_check(struct audio *audio,
- void *vaddr, unsigned long len)
-{
- struct audpcm_pmem_region *region_elt;
- struct audpcm_pmem_region t = { .vaddr = vaddr, .len = len };
-
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int audpcm_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audpcm_pmem_region *region;
- int rc = -EINVAL;
-
- MM_DBG("\n"); /* Macro prints the file name and function */
- region = kmalloc(sizeof(*region), GFP_KERNEL);
- if (!region)
- return -ENOMEM;
-
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- return -EINVAL;
- }
-
- rc = audpcm_pmem_check(audio, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- return rc;
- }
-
- region->vaddr = info->vaddr;
- region->fd = info->fd;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
- region->ref_cnt = 0;
- MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
- region->vaddr, region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
- return rc;
-}
-
-static int audpcm_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- struct audpcm_pmem_region *region;
- struct list_head *ptr, *next;
- int rc = -EINVAL;
-
- MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audpcm_pmem_region, list);
-
- if ((region->fd == info->fd) &&
- (region->vaddr == info->vaddr)) {
- if (region->ref_cnt) {
- MM_DBG("region %p in use ref_cnt %d\n", region,
- region->ref_cnt);
- break;
- }
- MM_DBG("remove region fd %d vaddr %p \n", info->fd,
- info->vaddr);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
static int audpcm_pmem_lookup_vaddr(struct audio *audio, void *addr,
unsigned long len, struct audpcm_pmem_region **region)
{
@@ -1124,26 +1030,6 @@
rc = audpp_pause(audio->dec_id, (int) arg);
break;
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audpcm_pmem_add(audio, &info);
- break;
- }
-
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_DEREGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audpcm_pmem_remove(audio, &info);
- break;
- }
-
case AUDIO_ASYNC_WRITE:
if (audio->drv_status & ADRV_STATUS_FSYNC)
rc = -EBUSY;
@@ -1344,21 +1230,6 @@
return rc;
}
-static void audpcm_reset_pmem_region(struct audio *audio)
-{
- struct audpcm_pmem_region *region;
- struct list_head *ptr, *next;
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audpcm_pmem_region, list);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- }
-
- return;
-}
-
static int audio_release(struct inode *inode, struct file *file)
{
struct audio *audio = file->private_data;
@@ -1369,7 +1240,6 @@
auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id);
audio_disable(audio);
audio->drv_ops.out_flush(audio);
- audpcm_reset_pmem_region(audio);
msm_adsp_put(audio->audplay);
audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index bb360be..33ca7a1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -33,7 +33,6 @@
#include <linux/debugfs.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 84cfed6..44fc10f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -35,7 +35,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
#include <linux/msm_audio_wmapro.h>
diff --git a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
index 5895867..9143b5a 100644
--- a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
@@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/gpio.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
index 24d2117..1cb9775 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
@@ -32,7 +32,6 @@
#include <linux/wakelock.h>
#include <linux/pm_qos.h>
-#include <linux/android_pmem.h>
#include <linux/msm_q6vdec.h>
#include <mach/cpuidle.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6venc.c b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
index 4704ae7..a2b4b6e 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6venc.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
@@ -22,7 +22,6 @@
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/msm_q6venc.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6/q6audio.c b/arch/arm/mach-msm/qdsp6/q6audio.c
index f660bdc..9404c3d 100644
--- a/arch/arm/mach-msm/qdsp6/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/q6audio.c
@@ -22,7 +22,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/firmware.h>
#include <linux/miscdevice.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/fm.c b/arch/arm/mach-msm/qdsp6v2/fm.c
index 3d72b97..23bb716 100644
--- a/arch/arm/mach-msm/qdsp6v2/fm.c
+++ b/arch/arm/mach-msm/qdsp6v2/fm.c
@@ -30,7 +30,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 8c96b1a..55ce4b1 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.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
@@ -69,6 +69,7 @@
RPM_REGULATOR_PARAM_FREQ_REASON,
RPM_REGULATOR_PARAM_CORNER,
RPM_REGULATOR_PARAM_BYPASS,
+ RPM_REGULATOR_PARAM_FLOOR_CORNER,
RPM_REGULATOR_PARAM_MAX,
};
@@ -108,12 +109,13 @@
PARAM(MODE_SMPS, 0, 1, 0, 0, "ssmd", 0, 2, "qcom,init-smps-mode"),
PARAM(PIN_CTRL_ENABLE, 1, 1, 1, 0, "pcen", 0, 0xF, "qcom,init-pin-ctrl-enable"),
PARAM(PIN_CTRL_MODE, 1, 1, 1, 0, "pcmd", 0, 0x1F, "qcom,init-pin-ctrl-mode"),
- PARAM(FREQUENCY, 0, 1, 0, 1, "freq", 0, 16, "qcom,init-frequency"),
+ PARAM(FREQUENCY, 0, 1, 0, 1, "freq", 0, 31, "qcom,init-frequency"),
PARAM(HEAD_ROOM, 1, 0, 0, 1, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
PARAM(QUIET_MODE, 0, 1, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
PARAM(FREQ_REASON, 0, 1, 0, 1, "resn", 0, 8, "qcom,init-freq-reason"),
PARAM(CORNER, 1, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
PARAM(BYPASS, 1, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
+ PARAM(FLOOR_CORNER, 1, 1, 0, 0, "vfc", 0, 6, "qcom,init-voltage-floor-corner"),
};
struct rpm_vreg_request {
@@ -147,6 +149,8 @@
struct list_head list;
bool set_active;
bool set_sleep;
+ bool always_send_voltage;
+ bool always_send_current;
struct rpm_vreg_request req;
int system_load;
int min_uV;
@@ -390,6 +394,13 @@
return rc;
}
+#define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
+{ \
+ _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
+ = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
+ _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
+}
+
#define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
{ \
_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
@@ -410,20 +421,6 @@
}
/*
- * The RPM treats freq=0 as a special value meaning that this consumer does not
- * care what the SMPS switching freqency is.
- */
-#define RPM_REGULATOR_FREQ_DONT_CARE 0
-
-static inline void rpm_vreg_freqency_aggr(u32 *freq, u32 consumer_freq)
-{
- if (consumer_freq != RPM_REGULATOR_FREQ_DONT_CARE
- && (consumer_freq < *freq
- || *freq == RPM_REGULATOR_FREQ_DONT_CARE))
- *freq = consumer_freq;
-}
-
-/*
* Aggregation is performed on each parameter based on the way that the RPM
* aggregates that type internally between RPM masters.
*/
@@ -436,13 +433,13 @@
RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
- rpm_vreg_freqency_aggr(¶m_aggr[RPM_REGULATOR_PARAM_FREQUENCY],
- param_reg[RPM_REGULATOR_PARAM_FREQUENCY]);
+ RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
+ RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
}
static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -633,8 +630,12 @@
prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);
- /* Only send a new voltage if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new voltage if the regulator is currently enabled or
+ * if the regulator has been configured to always send voltage updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -687,8 +688,13 @@
prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
RPM_VREG_SET_PARAM(reg, CORNER, corner);
- /* Only send a new voltage if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new voltage corner if the regulator is currently enabled
+ * or if the regulator has been configured to always send voltage
+ * updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -709,6 +715,61 @@
+ RPM_REGULATOR_CORNER_NONE;
}
+static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+ int rc = 0;
+ int corner;
+ u32 prev_corner;
+
+ /*
+ * Translate from values which work as inputs in the
+ * regulator_set_voltage function to the actual corner values
+ * sent to the RPM.
+ */
+ corner = min_uV - RPM_REGULATOR_CORNER_NONE;
+
+ if (corner < params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min
+ || corner > params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max) {
+ vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
+ corner, params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min,
+ params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max);
+ return -EINVAL;
+ }
+
+ rpm_vreg_lock(reg->rpm_vreg);
+
+ prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
+ RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);
+
+ /*
+ * Only send a new voltage floor corner if the regulator is currently
+ * enabled or if the regulator has been configured to always send
+ * voltage updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ rc = rpm_vreg_aggregate_requests(reg);
+
+ if (rc) {
+ vreg_err(reg, "set voltage corner failed, rc=%d", rc);
+ RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_corner);
+ }
+
+ rpm_vreg_unlock(reg->rpm_vreg);
+
+ return rc;
+}
+
+static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
+{
+ struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+
+ return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER]
+ + RPM_REGULATOR_CORNER_NONE;
+}
+
static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -737,8 +798,13 @@
return -EINVAL;
}
- /* Only send a new mode value if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new load current value if the regulator is currently
+ * enabled or if the regulator has been configured to always send
+ * current updates.
+ */
+ if (reg->always_send_current
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -1035,6 +1101,18 @@
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops ldo_floor_corner_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage_floor_corner,
+ .get_voltage = rpm_vreg_get_voltage_floor_corner,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops smps_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1059,6 +1137,18 @@
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops smps_floor_corner_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage_floor_corner,
+ .get_voltage = rpm_vreg_get_voltage_floor_corner,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops switch_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1192,12 +1282,30 @@
* is specified in the device node (SMPS and LDO only).
*/
if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
+ if (of_property_read_bool(node,
+ "qcom,use-voltage-floor-corner")) {
+ dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
+ __func__);
+ goto fail_free_reg;
+ }
+
if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
reg->rdesc.ops = &smps_corner_ops;
else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
reg->rdesc.ops = &ldo_corner_ops;
+ } else if (of_property_read_bool(node,
+ "qcom,use-voltage-floor-corner")) {
+ if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
+ reg->rdesc.ops = &smps_floor_corner_ops;
+ else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
+ reg->rdesc.ops = &ldo_floor_corner_ops;
}
+ reg->always_send_voltage
+ = of_property_read_bool(node, "qcom,always-send-voltage");
+ reg->always_send_current
+ = of_property_read_bool(node, "qcom,always-send-current");
+
if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
reg->rdesc.n_voltages = 0;
else
diff --git a/arch/arm/mach-msm/spm-regulator.c b/arch/arm/mach-msm/spm-regulator.c
new file mode 100644
index 0000000..00817c0
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.c
@@ -0,0 +1,405 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include "spm.h"
+#include "spm-regulator.h"
+
+#define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator"
+
+struct voltage_range {
+ int min_uV;
+ int set_point_min_uV;
+ int max_uV;
+ int step_uV;
+};
+
+/* Properties for FTS2 type QPNP PMIC regulators. */
+
+static const struct voltage_range fts2_range0 = {0, 350000, 1275000, 5000};
+static const struct voltage_range fts2_range1 = {0, 700000, 2040000, 10000};
+
+/* Specifies the PMIC internal slew rate in uV/us. */
+#define QPNP_FTS2_SLEW_RATE 6000
+
+#define QPNP_FTS2_REG_TYPE 0x04
+#define QPNP_FTS2_REG_SUBTYPE 0x05
+#define QPNP_FTS2_REG_VOLTAGE_RANGE 0x40
+#define QPNP_FTS2_REG_VOLTAGE_SETPOINT 0x41
+
+#define QPNP_FTS2_TYPE 0x1C
+#define QPNP_FTS2_SUBTYPE 0x08
+
+struct spm_vreg {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+ struct spmi_device *spmi_dev;
+ const struct voltage_range *range;
+ int uV;
+ int last_set_uV;
+ unsigned vlevel;
+ unsigned last_set_vlevel;
+ bool online;
+ u16 spmi_base_addr;
+};
+
+static int _spm_regulator_set_voltage(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ if (vreg->vlevel == vreg->last_set_vlevel)
+ return 0;
+
+ rc = msm_spm_apcs_set_vdd(vreg->vlevel);
+ if (rc) {
+ pr_err("%s: msm_spm_set_vdd failed %d\n", vreg->rdesc.name, rc);
+ return rc;
+ }
+
+ if (vreg->uV > vreg->last_set_uV) {
+ /* Wait for voltage to stabalize. */
+ udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV,
+ QPNP_FTS2_SLEW_RATE));
+ }
+ vreg->last_set_uV = vreg->uV;
+ vreg->last_set_vlevel = vreg->vlevel;
+
+ return rc;
+}
+
+static int spm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ const struct voltage_range *range = vreg->range;
+ int uV = min_uV;
+ unsigned vlevel;
+
+ if (uV < range->set_point_min_uV && max_uV >= range->set_point_min_uV)
+ uV = range->set_point_min_uV;
+
+ if (uV < range->set_point_min_uV || uV > range->max_uV) {
+ pr_err("%s: request v=[%d, %d] is outside possible v=[%d, %d]\n",
+ vreg->rdesc.name, min_uV, max_uV,
+ range->set_point_min_uV, range->max_uV);
+ return -EINVAL;
+ }
+
+ vlevel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV);
+ uV = vlevel * range->step_uV + range->min_uV;
+
+ if (uV > max_uV) {
+ pr_err("%s: request v=[%d, %d] cannot be met by any set point\n",
+ vreg->rdesc.name, min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ vreg->vlevel = vlevel;
+ vreg->uV = uV;
+ *selector = vlevel -
+ (vreg->range->set_point_min_uV - vreg->range->min_uV)
+ / vreg->range->step_uV;
+
+ if (!vreg->online)
+ return 0;
+
+ return _spm_regulator_set_voltage(rdev);
+}
+
+static int spm_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->uV;
+}
+
+static int spm_regulator_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ if (selector >= vreg->rdesc.n_voltages)
+ return 0;
+
+ return selector * vreg->range->step_uV + vreg->range->set_point_min_uV;
+}
+
+static int spm_regulator_enable(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = _spm_regulator_set_voltage(rdev);
+
+ if (!rc)
+ vreg->online = true;
+
+ return rc;
+}
+
+static int spm_regulator_disable(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ vreg->online = false;
+
+ return 0;
+}
+
+static int spm_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->online;
+}
+
+static struct regulator_ops spm_regulator_ops = {
+ .get_voltage = spm_regulator_get_voltage,
+ .set_voltage = spm_regulator_set_voltage,
+ .list_voltage = spm_regulator_list_voltage,
+ .enable = spm_regulator_enable,
+ .disable = spm_regulator_disable,
+ .is_enabled = spm_regulator_is_enabled,
+};
+
+static int qpnp_fts2_check_type(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 type[2];
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_TYPE, type, 2);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (type[0] != QPNP_FTS2_TYPE || type[1] != QPNP_FTS2_SUBTYPE) {
+ dev_err(&vreg->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+ __func__, type[0], type[1]);
+ return -ENODEV;
+ }
+
+ return rc;
+}
+
+static int qpnp_fts2_init_range(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 reg = 0;
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_RANGE, ®, 1);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (reg == 0x00) {
+ vreg->range = &fts2_range0;
+ } else if (reg == 0x01) {
+ vreg->range = &fts2_range1;
+ } else {
+ dev_err(&vreg->spmi_dev->dev, "%s: voltage range=%d is invalid\n",
+ __func__, reg);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int qpnp_fts2_init_voltage(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 reg = 0;
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_SETPOINT, ®, 1);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vreg->vlevel = reg;
+ vreg->uV = vreg->vlevel * vreg->range->step_uV + vreg->range->min_uV;
+ vreg->last_set_uV = vreg->uV;
+
+ return rc;
+}
+
+static int __devinit spm_regulator_probe(struct spmi_device *spmi)
+{
+ struct device_node *node = spmi->dev.of_node;
+ struct regulator_init_data *init_data;
+ struct spm_vreg *vreg;
+ struct resource *res;
+ int rc;
+
+ if (!node) {
+ dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+ return -ENODEV;
+ }
+
+ vreg = devm_kzalloc(&spmi->dev, sizeof(*vreg), GFP_KERNEL);
+ if (!vreg) {
+ pr_err("allocation failed.\n");
+ return -ENOMEM;
+ }
+ vreg->spmi_dev = spmi;
+
+ res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&spmi->dev, "%s: node is missing base address\n",
+ __func__);
+ return -EINVAL;
+ }
+ vreg->spmi_base_addr = res->start;
+
+ rc = qpnp_fts2_check_type(vreg);
+ if (rc)
+ return rc;
+
+ /*
+ * The FTS2 regulator must be initialized to range 0 or range 1 during
+ * PMIC power on sequence. Once it is set, it cannot be changed
+ * dynamically.
+ */
+ rc = qpnp_fts2_init_range(vreg);
+ if (rc)
+ return rc;
+
+ rc = qpnp_fts2_init_voltage(vreg);
+ if (rc)
+ return rc;
+
+ init_data = of_get_regulator_init_data(&spmi->dev, node);
+ if (!init_data) {
+ dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ init_data->constraints.input_uV = init_data->constraints.max_uV;
+ init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS
+ | REGULATOR_CHANGE_VOLTAGE;
+
+ if (!init_data->constraints.name) {
+ dev_err(&spmi->dev, "%s: node is missing regulator name\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ vreg->rdesc.name = init_data->constraints.name;
+ vreg->rdesc.type = REGULATOR_VOLTAGE;
+ vreg->rdesc.owner = THIS_MODULE;
+ vreg->rdesc.ops = &spm_regulator_ops;
+ vreg->rdesc.n_voltages
+ = (vreg->range->max_uV - vreg->range->set_point_min_uV)
+ / vreg->range->step_uV + 1;
+
+ vreg->rdev = regulator_register(&vreg->rdesc, &spmi->dev,
+ init_data, vreg, node);
+ if (IS_ERR(vreg->rdev)) {
+ rc = PTR_ERR(vreg->rdev);
+ dev_err(&spmi->dev, "%s: regulator_register failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ dev_set_drvdata(&spmi->dev, vreg);
+
+ pr_info("name=%s, range=%d\n", vreg->rdesc.name,
+ (vreg->range == &fts2_range0) ? 0 : 1);
+
+ return rc;
+}
+
+static int __devexit spm_regulator_remove(struct spmi_device *spmi)
+{
+ struct spm_vreg *vreg = dev_get_drvdata(&spmi->dev);
+
+ regulator_unregister(vreg->rdev);
+
+ return 0;
+}
+
+static struct of_device_id spm_regulator_match_table[] = {
+ { .compatible = SPM_REGULATOR_DRIVER_NAME, },
+ {}
+};
+
+static const struct spmi_device_id spm_regulator_id[] = {
+ { SPM_REGULATOR_DRIVER_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spmi, spm_regulator_id);
+
+static struct spmi_driver spm_regulator_driver = {
+ .driver = {
+ .name = SPM_REGULATOR_DRIVER_NAME,
+ .of_match_table = spm_regulator_match_table,
+ .owner = THIS_MODULE,
+ },
+ .probe = spm_regulator_probe,
+ .remove = __devexit_p(spm_regulator_remove),
+ .id_table = spm_regulator_id,
+};
+
+/**
+ * spm_regulator_init() - register spmi driver for spm-regulator
+ *
+ * This initialization function should be called in systems in which driver
+ * registration ordering must be controlled precisely.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init spm_regulator_init(void)
+{
+ static bool has_registered;
+
+ if (has_registered)
+ return 0;
+ else
+ has_registered = true;
+
+ return spmi_driver_register(&spm_regulator_driver);
+}
+EXPORT_SYMBOL(spm_regulator_init);
+
+static void __exit spm_regulator_exit(void)
+{
+ spmi_driver_unregister(&spm_regulator_driver);
+}
+
+arch_initcall(spm_regulator_init);
+module_exit(spm_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPM regulator driver");
+MODULE_ALIAS("platform:spm-regulator");
diff --git a/arch/arm/mach-msm/spm-regulator.h b/arch/arm/mach-msm/spm-regulator.h
new file mode 100644
index 0000000..394aecc
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+#define _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+
+#include <linux/err.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_MSM_SPM_REGULATOR
+int __init spm_regulator_init(void);
+#else
+static inline int __init spm_regulator_init(void) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index 11dc436..84e8df5 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.c
@@ -708,23 +708,18 @@
*/
tzdiag_phy_iobase = readl_relaxed(virt_iobase);
- if (!pdev->dev.of_node) {
+ /*
+ * Map the 4KB diagnostic information area
+ */
+ tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+ tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
- /*
- * Map the 4KB diagnostic information area
- */
- tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
- tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
-
- if (!tzdbg.virt_iobase) {
- dev_err(&pdev->dev,
- "%s: ERROR could not ioremap: start=%p, len=%u\n",
- __func__, (void *) tzdiag_phy_iobase,
- DEBUG_MAX_RW_BUF);
- return -ENXIO;
- }
- } else {
- tzdbg.virt_iobase = virt_iobase;
+ if (!tzdbg.virt_iobase) {
+ dev_err(&pdev->dev,
+ "%s: ERROR could not ioremap: start=%p, len=%u\n",
+ __func__, (void *) tzdiag_phy_iobase,
+ DEBUG_MAX_RW_BUF);
+ return -ENXIO;
}
ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f385fc4..1c8a25d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -708,12 +708,12 @@
if (arch_is_coherent() || nommu()) {
__dma_free_buffer(page, size);
+ } else if (__free_from_pool(cpu_addr, size)) {
+ return;
} else if (!IS_ENABLED(CONFIG_CMA)) {
__dma_free_remap(cpu_addr, size, false);
__dma_free_buffer(page, size);
} else {
- if (__free_from_pool(cpu_addr, size))
- return;
/*
* Non-atomic allocations cannot be freed with IRQs disabled
*/
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index ed91480..45c9023 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -227,7 +227,7 @@
pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
(unsigned long)base, (unsigned long)size / SZ_1M);
- dma_contiguous_reserve_area(size, &base, 0, name);
+ dma_contiguous_reserve_area(size, &base, MEMBLOCK_ALLOC_ANYWHERE, name);
return 0;
}
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index fe8cf57..583add9 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -41,6 +41,7 @@
#define CRYPTO_CONFIG_RESET 0xE001F
#define QCE_MAX_NUM_DSCR 0x400
#define QCE_SIZE_BAM_DSCR 0x08
+#define QCE_SECTOR_SIZE 0x200
static DEFINE_MUTEX(bam_register_cnt);
struct bam_registration_info {
@@ -445,6 +446,7 @@
uint32_t enck_size_in_word = 0;
uint32_t key_size;
bool use_hw_key = false;
+ bool use_pipe_key = false;
uint32_t encr_cfg = 0;
uint32_t ivsize = creq->ivsize;
int i;
@@ -456,6 +458,7 @@
key_size = creq->encklen;
_byte_stream_to_net_words(enckey32, creq->enckey, key_size);
+ pce = cmdlistinfo->go_proc;
/* check for null key. If null, use hw key*/
enck_size_in_word = key_size/sizeof(uint32_t);
@@ -463,15 +466,22 @@
if (enckey32[i] != 0)
break;
}
- pce = cmdlistinfo->go_proc;
if (i == enck_size_in_word) {
use_hw_key = true;
pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
pce_dev->phy_iobase);
- } else {
+ }
+ if (use_hw_key == false) {
+ for (i = 0; i < enck_size_in_word; i++) {
+ if (enckey32[i] != 0xFFFFFFFF)
+ break;
+ }
+ if (i == enck_size_in_word)
+ use_pipe_key = true;
+ }
+ if (use_hw_key == false)
pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
pce_dev->phy_iobase);
- }
if ((creq->op == QCE_REQ_AEAD) && (creq->mode == QCE_MODE_CCM)) {
uint32_t authklen32 = creq->encklen/sizeof(uint32_t);
@@ -600,7 +610,10 @@
/* write xts du size */
pce = cmdlistinfo->encr_xts_du_size;
- pce->data = creq->cryptlen;
+ if (use_pipe_key == true)
+ pce->data = QCE_SECTOR_SIZE;
+ else
+ pce->data = creq->cryptlen;
}
if (creq->mode != QCE_MODE_ECB) {
if (creq->mode == QCE_MODE_XTS)
@@ -653,6 +666,10 @@
break;
} /* end of switch (creq->mode) */
+ if (use_pipe_key)
+ encr_cfg |= (CRYPTO_USE_PIPE_KEY_ENCR_ENABLED
+ << CRYPTO_USE_PIPE_KEY_ENCR);
+
/* write encr seg cfg */
pce = cmdlistinfo->encr_seg_cfg;
if ((creq->alg == CIPHER_ALG_DES) || (creq->alg == CIPHER_ALG_3DES)) {
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 1f73d47..33e6fed 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -54,6 +54,11 @@
.name = ION_VMALLOC_HEAP_NAME,
},
{
+ .id = ION_SYSTEM_CONTIG_HEAP_ID,
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = ION_KMALLOC_HEAP_NAME,
+ },
+ {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_SECURE_DMA,
.name = ION_MM_HEAP_NAME,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index d7bf36e..a76ed87 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -470,7 +470,7 @@
int offset = type0_pkt_offset(*ptr);
int i;
- for (i = 0; i < size; i++, offset++) {
+ for (i = 0; i < size - 1; i++, offset++) {
/* Visiblity stream buffer */
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 9e0a147..202edc0 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -142,6 +142,7 @@
#define RGB_LED_ENABLE_MASK 0xE0
#define RGB_LED_SRC_MASK 0x03
#define QPNP_LED_PWM_FLAGS (PM_PWM_LUT_LOOP | PM_PWM_LUT_RAMP_UP)
+#define QPNP_LUT_RAMP_STEP_DEFAULT 255
#define PWM_LUT_MAX_SIZE 63
#define RGB_LED_DISABLE 0x00
@@ -957,7 +958,7 @@
return -EINVAL;
}
rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
- led->rgb_cfg->pwm_period_us,
+ PM_PWM_PERIOD_MIN, /* ignored by hardware */
led->rgb_cfg->duty_cycles->duty_pcts,
led->rgb_cfg->lut_params);
if (rc < 0) {
@@ -1227,11 +1228,13 @@
else
return rc;
- rc = of_property_read_u32(node, "qcom,pwm-us", &val);
- if (!rc)
- led->rgb_cfg->pwm_period_us = val;
- else
- return rc;
+ if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+ rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+ if (!rc)
+ led->rgb_cfg->pwm_period_us = val;
+ else
+ return rc;
+ }
if (led->rgb_cfg->mode == RGB_MODE_LPG) {
led->rgb_cfg->duty_cycles =
@@ -1243,12 +1246,6 @@
return -ENOMEM;
}
- rc = of_property_read_u32(node, "qcom,duty-ms", &val);
- if (!rc)
- led->rgb_cfg->duty_cycles->duty_ms = (u8) val;
- else
- return rc;
-
prop = of_find_property(node, "qcom,duty-pcts",
&led->rgb_cfg->duty_cycles->num_duty_pcts);
if (!prop) {
@@ -1294,12 +1291,37 @@
} else
return rc;
+ led->rgb_cfg->lut_params.lut_pause_hi = 0;
+ rc = of_property_read_u32(node, "qcom,pause-hi", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.lut_pause_hi = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.lut_pause_lo = 0;
+ rc = of_property_read_u32(node, "qcom,pause-lo", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.lut_pause_lo = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.ramp_step_ms =
+ QPNP_LUT_RAMP_STEP_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.ramp_step_ms = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+ rc = of_property_read_u32(node, "qcom,lut-flags", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.flags = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
led->rgb_cfg->lut_params.idx_len =
led->rgb_cfg->duty_cycles->num_duty_pcts;
- led->rgb_cfg->lut_params.lut_pause_hi = 0;
- led->rgb_cfg->lut_params.lut_pause_lo = 0;
- led->rgb_cfg->lut_params.ramp_step_ms = 255;
- led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
}
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index e939c2b..e1b978f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -27,7 +27,6 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#endif
-static struct msm_actuator_ctrl_t msm_actuator_t;
static struct msm_actuator msm_vcm_actuator_table;
static struct msm_actuator msm_piezo_actuator_table;
@@ -618,103 +617,21 @@
.close = msm_actuator_close,
};
-static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
{
- int rc = 0;
- struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+ struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+ void __user *argp = (void __user *)arg;
CDBG("Enter\n");
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- pr_err("i2c_check_functionality failed\n");
- goto probe_failure;
+ CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ return msm_actuator_get_subdev_id(a_ctrl, argp);
+ case VIDIOC_MSM_ACTUATOR_CFG:
+ return msm_actuator_config(a_ctrl, argp);
+ default:
+ return -ENOIOCTLCMD;
}
-
- act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
- CDBG("client = %x\n", (unsigned int) client);
- act_ctrl_t->i2c_client.client = client;
- /* Set device type as I2C */
- act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
- act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
-
- /* Assign name for sub device */
- snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
- "%s", act_ctrl_t->i2c_driver->driver.name);
-
- /* Initialize sub device */
- v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
- act_ctrl_t->i2c_client.client,
- act_ctrl_t->act_v4l2_subdev_ops);
- v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
- act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
- act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
- act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
- act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
- msm_sd_register(&act_ctrl_t->msm_sd);
- CDBG("succeeded\n");
- CDBG("Exit\n");
-
-probe_failure:
- return rc;
-}
-
-static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
-{
- int32_t rc = 0;
- struct msm_camera_cci_client *cci_client = NULL;
- CDBG("Enter\n");
-
- if (!pdev->dev.of_node) {
- pr_err("of_node NULL\n");
- return -EINVAL;
- }
-
- rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
- &pdev->id);
- CDBG("cell-index %d, rc %d\n", pdev->id, rc);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- return rc;
- }
-
- rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
- &msm_actuator_t.cci_master);
- CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t.cci_master, rc);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- return rc;
- }
-
- msm_actuator_t.cam_name = pdev->id;
-
- /* Set platform device handle */
- msm_actuator_t.pdev = pdev;
- /* Set device type as platform device */
- msm_actuator_t.act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
- msm_actuator_t.i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
- msm_actuator_t.i2c_client.cci_client = kzalloc(sizeof(
- struct msm_camera_cci_client), GFP_KERNEL);
- if (!msm_actuator_t.i2c_client.cci_client) {
- pr_err("failed no memory\n");
- return -ENOMEM;
- }
-
- cci_client = msm_actuator_t.i2c_client.cci_client;
- cci_client->cci_subdev = msm_cci_get_subdev();
- v4l2_subdev_init(&msm_actuator_t.msm_sd.sd,
- msm_actuator_t.act_v4l2_subdev_ops);
- v4l2_set_subdevdata(&msm_actuator_t.msm_sd.sd, &msm_actuator_t);
- msm_actuator_t.msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
- msm_actuator_t.msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- snprintf(msm_actuator_t.msm_sd.sd.name,
- ARRAY_SIZE(msm_actuator_t.msm_sd.sd.name), "msm_actuator");
- media_entity_init(&msm_actuator_t.msm_sd.sd.entity, 0, NULL, 0);
- msm_actuator_t.msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
- msm_actuator_t.msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
- msm_sd_register(&msm_actuator_t.msm_sd);
- CDBG("Exit\n");
- return rc;
}
static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
@@ -735,64 +652,6 @@
return rc;
}
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
- {"msm_actuator", (kernel_ulong_t)&msm_actuator_t},
- { }
-};
-
-static struct i2c_driver msm_actuator_i2c_driver = {
- .id_table = msm_actuator_i2c_id,
- .probe = msm_actuator_i2c_probe,
- .remove = __exit_p(msm_actuator_i2c_remove),
- .driver = {
- .name = "msm_actuator",
- },
-};
-
-static const struct of_device_id msm_actuator_dt_match[] = {
- {.compatible = "qcom,actuator", .data = &msm_actuator_t},
- {}
-};
-
-MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
-
-static struct platform_driver msm_actuator_platform_driver = {
- .driver = {
- .name = "qcom,actuator",
- .owner = THIS_MODULE,
- .of_match_table = msm_actuator_dt_match,
- },
-};
-
-static int __init msm_actuator_init_module(void)
-{
- int32_t rc = 0;
- CDBG("Enter\n");
- rc = platform_driver_probe(msm_actuator_t.pdriver,
- msm_actuator_platform_probe);
- if (!rc)
- return rc;
- CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
- return i2c_add_driver(msm_actuator_t.i2c_driver);
-}
-
-static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int cmd, void *arg)
-{
- struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
- void __user *argp = (void __user *)arg;
- CDBG("Enter\n");
- CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
- switch (cmd) {
- case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
- return msm_actuator_get_subdev_id(a_ctrl, argp);
- case VIDIOC_MSM_ACTUATOR_CFG:
- return msm_actuator_config(a_ctrl, argp);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
{
int rc = 0;
@@ -817,17 +676,156 @@
.core = &msm_actuator_subdev_core_ops,
};
-static struct msm_actuator_ctrl_t msm_actuator_t = {
- .i2c_driver = &msm_actuator_i2c_driver,
- .pdriver = &msm_actuator_platform_driver,
- .act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+ CDBG("Enter\n");
- .curr_step_pos = 0,
- .curr_region_index = 0,
- .actuator_mutex = &msm_actuator_mutex,
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("i2c_check_functionality failed\n");
+ goto probe_failure;
+ }
+ act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
+ CDBG("client = %x\n", (unsigned int) client);
+ act_ctrl_t->i2c_client.client = client;
+ /* Set device type as I2C */
+ act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
+ act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
+ act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+ act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+ /* Assign name for sub device */
+ snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
+ "%s", act_ctrl_t->i2c_driver->driver.name);
+
+ /* Initialize sub device */
+ v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
+ act_ctrl_t->i2c_client.client,
+ act_ctrl_t->act_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
+ act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+ act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
+ act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ msm_sd_register(&act_ctrl_t->msm_sd);
+ CDBG("succeeded\n");
+ CDBG("Exit\n");
+
+probe_failure:
+ return rc;
+}
+
+static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ struct msm_camera_cci_client *cci_client = NULL;
+ struct msm_actuator_ctrl_t *msm_actuator_t = NULL;
+ CDBG("Enter\n");
+
+ if (!pdev->dev.of_node) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+
+ msm_actuator_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+ GFP_KERNEL);
+ if (!msm_actuator_t) {
+ pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+ &pdev->id);
+ CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
+ &msm_actuator_t->cci_master);
+ CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t->cci_master, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+ msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
+ msm_actuator_t->cam_name = pdev->id;
+
+ /* Set platform device handle */
+ msm_actuator_t->pdev = pdev;
+ /* Set device type as platform device */
+ msm_actuator_t->act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+ msm_actuator_t->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+ msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof(
+ struct msm_camera_cci_client), GFP_KERNEL);
+ if (!msm_actuator_t->i2c_client.cci_client) {
+ pr_err("failed no memory\n");
+ return -ENOMEM;
+ }
+
+ cci_client = msm_actuator_t->i2c_client.cci_client;
+ cci_client->cci_subdev = msm_cci_get_subdev();
+ v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
+ msm_actuator_t->act_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
+ msm_actuator_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+ msm_actuator_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(msm_actuator_t->msm_sd.sd.name,
+ ARRAY_SIZE(msm_actuator_t->msm_sd.sd.name), "msm_actuator");
+ media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
+ msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ msm_sd_register(&msm_actuator_t->msm_sd);
+ CDBG("Exit\n");
+ return rc;
+}
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+ {"msm_actuator", (kernel_ulong_t)NULL},
+ { }
};
+static struct i2c_driver msm_actuator_i2c_driver = {
+ .id_table = msm_actuator_i2c_id,
+ .probe = msm_actuator_i2c_probe,
+ .remove = __exit_p(msm_actuator_i2c_remove),
+ .driver = {
+ .name = "msm_actuator",
+ },
+};
+
+static const struct of_device_id msm_actuator_dt_match[] = {
+ {.compatible = "qcom,actuator", .data = NULL},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
+
+static struct platform_driver msm_actuator_platform_driver = {
+ .driver = {
+ .name = "qcom,actuator",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_actuator_dt_match,
+ },
+};
+
+static int __init msm_actuator_init_module(void)
+{
+ int32_t rc = 0;
+ CDBG("Enter\n");
+ rc = platform_driver_probe(&msm_actuator_platform_driver,
+ msm_actuator_platform_probe);
+ if (!rc)
+ return rc;
+ CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&msm_actuator_i2c_driver);
+}
+
static struct msm_actuator msm_vcm_actuator_table = {
.act_type = ACTUATOR_VCM,
.func_tbl = {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e8096d1..2573a16 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -639,6 +639,15 @@
to the fuse block. Currently this is supported only
on FSM targets.
+config QPNP_MISC
+ tristate "QPNP Misc Peripheral"
+ depends on SPMI
+ help
+ Say 'y' here to include support for the Qualcomm QPNP MISC
+ peripheral. The MISC peripheral holds the USB ID interrupt
+ and the driver provides an API to check if this interrupt
+ is available on the current PMIC chip.
+
config USB_HSIC_SMSC_HUB
tristate "Support for HSIC based MSM on-chip SMSC3503 HUB"
depends on USB_EHCI_MSM_HSIC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f80f3f2..327d1ec 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -70,3 +70,4 @@
obj-$(CONFIG_QSEECOM) += qseecom.o
obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
obj-$(CONFIG_TI_DRV2667) += ti_drv2667.o
+obj-$(CONFIG_QPNP_MISC) += qpnp-misc.o
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
new file mode 100644
index 0000000..608be81
--- /dev/null
+++ b/drivers/misc/qpnp-misc.c
@@ -0,0 +1,167 @@
+/* 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.
+ */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/qpnp-misc.h>
+
+#define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
+
+#define REVID_REVISION2 0x1
+
+static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
+static LIST_HEAD(qpnp_misc_dev_list);
+
+/**
+ * struct qpnp_misc_dev - holds controller device specific information
+ * @list: Doubly-linked list parameter linking to other
+ * qpnp_misc devices.
+ * @mutex: Mutex lock that is used to ensure mutual
+ * exclusion between probing and accessing misc
+ * driver information
+ * @dev: Device pointer to the misc device
+ * @resource: Resource pointer that holds base address
+ * @spmi: Spmi pointer which holds spmi information
+ */
+struct qpnp_misc_dev {
+ struct list_head list;
+ struct mutex mutex;
+ struct device *dev;
+ struct resource *resource;
+ struct spmi_device *spmi;
+};
+
+static struct of_device_id qpnp_misc_match_table[] = {
+ { .compatible = QPNP_MISC_DEV_NAME },
+ {}
+};
+
+static u8 qpnp_read_byte(struct spmi_device *spmi, u16 addr)
+{
+ int rc;
+ u8 val;
+
+ rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &val, 1);
+ if (rc) {
+ pr_err("SPMI read failed rc=%d\n", rc);
+ return 0;
+ }
+ return val;
+}
+
+#define REV2_IRQ_AVAILABLE_VERSION 2
+static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
+{
+ u8 rev2;
+
+ rev2 = qpnp_read_byte(dev->spmi,
+ dev->resource->start + REVID_REVISION2);
+ pr_debug("rev2 0x%x\n", rev2);
+
+ if (rev2 >= REV2_IRQ_AVAILABLE_VERSION)
+ return 1;
+
+ return 0;
+}
+
+int qpnp_misc_irqs_available(struct device *consumer_dev)
+{
+ struct device_node *misc_node = NULL;
+ struct qpnp_misc_dev *mdev = NULL;
+ struct qpnp_misc_dev *mdev_found = NULL;
+
+ misc_node = of_parse_phandle(consumer_dev->of_node, "qcom,misc-ref", 0);
+ if (!misc_node) {
+ pr_debug("Could not find qcom,misc-ref property in %s\n",
+ consumer_dev->of_node->full_name);
+ return 0;
+ }
+
+ mutex_lock(&qpnp_misc_dev_list_mutex);
+ list_for_each_entry(mdev, &qpnp_misc_dev_list, list) {
+ if (mdev->dev->of_node == misc_node) {
+ mdev_found = mdev;
+ break;
+ }
+ }
+ mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+ if (!mdev_found) {
+ /* No MISC device was found. This API should only
+ * be called by drivers which have specified the
+ * misc phandle in their device tree node */
+ pr_err("no probed misc device found\n");
+ return -EPROBE_DEFER;
+ }
+
+ return __misc_irqs_available(mdev_found);
+}
+
+static int __devinit qpnp_misc_probe(struct spmi_device *spmi)
+{
+ struct resource *resource;
+ struct qpnp_misc_dev *mdev = ERR_PTR(-EINVAL);
+
+ resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!resource) {
+ pr_err("Unable to get spmi resource for MISC\n");
+ return -EINVAL;
+ }
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev) {
+ pr_err("allocation failed\n");
+ return -ENOMEM;
+ }
+
+ mdev->spmi = spmi;
+ mdev->dev = &(spmi->dev);
+ mdev->resource = resource;
+
+ mutex_lock(&qpnp_misc_dev_list_mutex);
+ list_add_tail(&mdev->list, &qpnp_misc_dev_list);
+ mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+ pr_debug("probed successfully\n");
+ return 0;
+}
+
+static struct spmi_driver qpnp_misc_driver = {
+ .probe = qpnp_misc_probe,
+ .driver = {
+ .name = QPNP_MISC_DEV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = qpnp_misc_match_table,
+ },
+};
+
+static int __init qpnp_misc_init(void)
+{
+ return spmi_driver_register(&qpnp_misc_driver);
+}
+
+static void __exit qpnp_misc_exit(void)
+{
+ return spmi_driver_unregister(&qpnp_misc_driver);
+}
+
+module_init(qpnp_misc_init);
+module_exit(qpnp_misc_exit);
+
+MODULE_DESCRIPTION(QPNP_MISC_DEV_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" QPNP_MISC_DEV_NAME);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 444b627..2769709 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -103,6 +103,10 @@
0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
};
+static int disable_slots;
+/* root can write, others read */
+module_param(disable_slots, int, S_IRUGO|S_IWUSR);
+
/* This structure keeps information per regulator */
struct sdhci_msm_reg_data {
/* voltage regulator handle */
@@ -2081,6 +2085,19 @@
/* Extract platform data */
if (pdev->dev.of_node) {
+ ret = of_alias_get_id(pdev->dev.of_node, "sdhc");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get slot index %d\n",
+ ret);
+ goto pltfm_free;
+ }
+ if (disable_slots & (1 << (ret - 1))) {
+ dev_info(&pdev->dev, "%s: Slot %d disabled\n", __func__,
+ ret);
+ ret = -ENODEV;
+ goto pltfm_free;
+ }
+
msm_host->pdata = sdhci_msm_populate_pdata(&pdev->dev);
if (!msm_host->pdata) {
dev_err(&pdev->dev, "DT parsing error\n");
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index a194c49..08cf71e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1518,8 +1518,8 @@
struct soc_params params;
if (!chip->battery_present) {
- pr_debug("battery gone, reporting 0\n");
- new_calculated_soc = 0;
+ pr_debug("battery gone, reporting 100\n");
+ new_calculated_soc = 100;
goto done_calculating;
}
calculate_soc_params(chip, raw, ¶ms, batt_temp);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f3b39d4a..84672d7 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -32,6 +32,7 @@
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/qpnp-misc.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/regulator/consumer.h>
#include <linux/power_supply.h>
@@ -2395,17 +2396,30 @@
if (msm->ext_xceiv.otg_capability) {
msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
if (msm->pmic_id_irq > 0) {
- ret = devm_request_irq(&pdev->dev, msm->pmic_id_irq,
- dwc3_pmic_id_irq,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING,
- "dwc3_msm_pmic_id", msm);
- if (ret) {
- dev_err(&pdev->dev, "irqreq IDINT failed\n");
+ /* check if PMIC ID IRQ is supported */
+ ret = qpnp_misc_irqs_available(&pdev->dev);
+
+ if (ret == -EPROBE_DEFER) {
+ /* qpnp hasn't probed yet; defer dwc probe */
goto disable_hs_ldo;
+ } else if (ret == 0) {
+ msm->pmic_id_irq = 0;
+ } else {
+ ret = devm_request_irq(&pdev->dev,
+ msm->pmic_id_irq,
+ dwc3_pmic_id_irq,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "dwc3_msm_pmic_id", msm);
+ if (ret) {
+ dev_err(&pdev->dev, "irqreq IDINT failed\n");
+ goto disable_hs_ldo;
+ }
+ enable_irq_wake(msm->pmic_id_irq);
}
- enable_irq_wake(msm->pmic_id_irq);
- } else {
+ }
+
+ if (msm->pmic_id_irq <= 0) {
/* If no PMIC ID IRQ, use ADC for ID pin detection */
queue_work(system_nrt_wq, &msm->init_adc_work.work);
device_create_file(&pdev->dev, &dev_attr_adc_enable);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 207fbf3..dd41638 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -82,6 +82,7 @@
u8 clk_ena;
u8 fs_ena;
u8 vsync_ena;
+ unsigned long min_mdp_clk;
u32 res_init;
u32 bus_hdl;
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index abef27d..7dc4f49 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-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
@@ -333,6 +333,9 @@
return -ENODEV;
}
+ debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
+ (u32 *)&mdata->min_mdp_clk);
+
mdata->debug_data = mdd;
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index a8eeec6..749afd8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -520,11 +520,15 @@
return ret;
}
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate)
+void mdss_mdp_set_clk_rate(unsigned long rate)
{
struct mdss_data_type *mdata = mdss_res;
unsigned long clk_rate;
struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC);
+ unsigned long min_clk_rate;
+
+ min_clk_rate = max(rate, mdata->min_mdp_clk);
+
if (clk) {
mutex_lock(&mdp_clk_lock);
if (min_clk_rate < mdata->max_mdp_clk_rate)
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 43456ca..14c1e52 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
u32 flush_bits;
u32 play_cnt;
+ u32 underrun_cnt;
u16 width;
u16 height;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index e2c3b23..dab8674 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -244,12 +244,17 @@
rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
+
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
+ ctl->intf_num);
}
mdss_mdp_video_set_vsync_handler(ctl, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
NULL, NULL);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+ NULL, NULL);
ctx->ref_cnt--;
ctl->priv_data = NULL;
@@ -304,6 +309,17 @@
return rc;
}
+static void mdss_mdp_video_underrun_intr_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ if (unlikely(!ctl))
+ return;
+
+ ctl->underrun_cnt++;
+ pr_warn("display underrun detected for ctl=%d count=%d\n", ctl->num,
+ ctl->underrun_cnt);
+}
+
static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_video_ctx *ctx;
@@ -332,6 +348,8 @@
pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
wmb();
@@ -390,6 +408,8 @@
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
mdss_mdp_video_vsync_intr_done, ctl);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+ mdss_mdp_video_underrun_intr_done, ctl);
itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 4699e0d..7ff6414 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -81,14 +81,22 @@
static 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;
- rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format, pipe->src.w,
- pipe->src.h, &ps);
- if (rc)
- return rc;
+ if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+ pipe->src_fmt->is_yuv) {
+ ps.num_planes = 2;
+ ps.ystride[0] = pipe->src.w;
+ ps.ystride[1] = pipe->src.w;
+ } else {
+ rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
+ pipe->src.w, pipe->src.h, &ps);
+ if (rc)
+ return rc;
+ }
if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
return -EINVAL;
@@ -98,7 +106,7 @@
num_blks = DIV_ROUND_UP(2 * ps.ystride[i],
mdss_res->smp_mb_size);
- if (mdss_res->mdp_rev == MDSS_MDP_HW_REV_100)
+ 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",
@@ -124,7 +132,7 @@
{
int i;
mutex_lock(&mdss_mdp_smp_lock);
- for (i = 0; i < pipe->src_planes.num_planes; i++)
+ for (i = 0; i < MAX_PLANES; i++)
mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
mutex_unlock(&mdss_mdp_smp_lock);
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 1c0d306..077b4e4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -35,6 +35,10 @@
MDP_INTR_VSYNC_INTF_1,
MDP_INTR_VSYNC_INTF_2,
MDP_INTR_VSYNC_INTF_3,
+ MDP_INTR_UNDERRUN_INTF_0,
+ MDP_INTR_UNDERRUN_INTF_1,
+ MDP_INTR_UNDERRUN_INTF_2,
+ MDP_INTR_UNDERRUN_INTF_3,
MDP_INTR_PING_PONG_0,
MDP_INTR_PING_PONG_1,
MDP_INTR_PING_PONG_2,
@@ -56,6 +60,9 @@
{
int index = -1;
switch (intr_type) {
+ case MDSS_MDP_IRQ_INTF_UNDER_RUN:
+ index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0);
+ break;
case MDSS_MDP_IRQ_INTF_VSYNC:
index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0);
break;
@@ -128,6 +135,18 @@
if (isr == 0)
goto mdp_isr_done;
+ if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0);
+
+ if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1);
+
+ if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2);
+
+ if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3);
+
if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index add65ac..2341068 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -103,8 +103,6 @@
return postpone_send;
}
-
-
void mhl_msc_send_work(struct work_struct *work)
{
struct mhl_tx_ctrl *mhl_ctrl =
@@ -202,7 +200,6 @@
return 0;
}
-
int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
struct msc_command_struct *req)
{
@@ -286,8 +283,6 @@
return 0;
}
-
-
int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
u8 sub_cmd, u8 cmd_data)
{
@@ -315,7 +310,6 @@
return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
}
-
int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
{
struct msc_command_struct req;
@@ -340,7 +334,6 @@
return ret;
}
-
static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
u8 key_code, u16 input_key_code)
{
@@ -352,8 +345,6 @@
input_sync(mhl_ctrl->input);
}
-
-
int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
{
u8 index = key_code & 0x7f;
@@ -392,7 +383,6 @@
return 0;
}
-
static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
{
switch (action_code) {
@@ -400,7 +390,14 @@
mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
break;
case MHL_RAP_CONTENT_OFF:
- mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+ /*
+ * instead of only disabling tmds
+ * send power button press - CONTENT_OFF
+ */
+ input_report_key(mhl_ctrl->input, KEY_VENDOR, 1);
+ input_sync(mhl_ctrl->input);
+ input_report_key(mhl_ctrl->input, KEY_VENDOR, 0);
+ input_sync(mhl_ctrl->input);
break;
default:
break;
@@ -413,9 +410,9 @@
u8 error_code;
bool tmds_en;
+ tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
switch (action_code) {
case MHL_RAP_POLL:
- tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
if (tmds_en)
error_code = MHL_RAPK_NO_ERROR;
else
@@ -423,8 +420,12 @@
break;
case MHL_RAP_CONTENT_ON:
case MHL_RAP_CONTENT_OFF:
- mhl_rap_action(mhl_ctrl, action_code);
- error_code = MHL_RAPK_NO_ERROR;
+ if (tmds_en) {
+ mhl_rap_action(mhl_ctrl, action_code);
+ error_code = MHL_RAPK_NO_ERROR;
+ } else {
+ error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+ }
break;
default:
error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
@@ -437,7 +438,6 @@
error_code);
}
-
int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
u8 sub_cmd, u8 cmd_data)
{
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 41f7c29..2ad1ab2 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -86,7 +86,7 @@
struct drm_kgsl_gem_create_from_ion)
/* Maximum number of sub buffers per GEM object */
-#define DRM_KGSL_GEM_MAX_BUFFERS 2
+#define DRM_KGSL_GEM_MAX_BUFFERS 3
/* Memory types - these define the source and caching policies
of the GEM memory chunk */
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index a683ed4..95c4e6a 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -40,6 +40,7 @@
ION_CP_MFC_HEAP_ID = 12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+ ION_SYSTEM_CONTIG_HEAP_ID = 21,
ION_ADSP_HEAP_ID = 22,
ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
ION_SF_HEAP_ID = 24,
@@ -90,6 +91,7 @@
#define ION_ADSP_HEAP_NAME "adsp"
#define ION_VMALLOC_HEAP_NAME "vmalloc"
+#define ION_KMALLOC_HEAP_NAME "kmalloc"
#define ION_AUDIO_HEAP_NAME "audio"
#define ION_SF_HEAP_NAME "sf"
#define ION_MM_HEAP_NAME "mm"
diff --git a/include/linux/qpnp-misc.h b/include/linux/qpnp-misc.h
new file mode 100644
index 0000000..b241e5d
--- /dev/null
+++ b/include/linux/qpnp-misc.h
@@ -0,0 +1,38 @@
+/* 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.
+ */
+
+#ifndef __QPNP_MISC_H
+#define __QPNP_MISC_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_MISC
+/**
+ * qpnp_misc_irqs_available - check if IRQs are available
+ *
+ * @consumer_dev: device struct
+ *
+ * This function returns true if the MISC interrupts are available
+ * based on a check in the MISC peripheral revision registers.
+ *
+ * Any consumer of this function needs to reference a MISC device phandle
+ * using the qcom,misc-ref in their device tree node.
+ */
+
+int qpnp_misc_irqs_available(struct device *consumer_dev);
+#else
+static int qpnp_misc_irq_available(struct device *consumer_dev)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 78d1749..80738ba 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -338,6 +338,7 @@
s32 dmic_5_6_clk_cnt;
u32 anc_slot;
+ bool anc_func;
/*track taiko interface type*/
u8 intf_type;
@@ -505,6 +506,56 @@
return 0;
}
+static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
+ return 0;
+}
+
+static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ mutex_lock(&dapm->codec->mutex);
+ taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+ dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
+
+ if (taiko->anc_func == true) {
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_enable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_disable_pin(dapm, "HPHR");
+ snd_soc_dapm_disable_pin(dapm, "HPHL");
+ snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "EAR");
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_enable_pin(dapm, "HPHR");
+ snd_soc_dapm_enable_pin(dapm, "HPHL");
+ snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+ snd_soc_dapm_enable_pin(dapm, "EAR PA");
+ snd_soc_dapm_enable_pin(dapm, "EAR");
+ }
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
+ return 0;
+}
+
static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -915,6 +966,15 @@
SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
};
+static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum taiko_anc_func_enum =
+ SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
+
+static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum tabla_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
+};
+
/*cut of frequency for high pass filter*/
static const char * const cf_text[] = {
"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
@@ -1054,8 +1114,10 @@
SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
taiko_put_anc_slot),
+ SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
+ taiko_put_anc_func),
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -2184,101 +2246,6 @@
return 0;
}
-static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- const char *filename;
- const struct firmware *fw;
- int i;
- int ret;
- int num_anc_slots;
- struct anc_header *anc_head;
- struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
- u32 anc_writes_size = 0;
- int anc_size_remaining;
- u32 *anc_ptr;
- u16 reg;
- u8 mask, val;
-
- pr_debug("%s %d\n", __func__, event);
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
-
- filename = "wcd9320/wcd9320_anc.bin";
-
- ret = request_firmware(&fw, filename, codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
- ret);
- return -ENODEV;
- }
-
- if (fw->size < sizeof(struct anc_header)) {
- dev_err(codec->dev, "Not enough data\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- /* First number is the number of register writes */
- anc_head = (struct anc_header *)(fw->data);
- anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
- anc_size_remaining = fw->size - sizeof(struct anc_header);
- num_anc_slots = anc_head->num_anc_slots;
-
- if (taiko->anc_slot >= num_anc_slots) {
- dev_err(codec->dev, "Invalid ANC slot selected\n");
- release_firmware(fw);
- return -EINVAL;
- }
-
- for (i = 0; i < num_anc_slots; i++) {
-
- if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -EINVAL;
- }
- anc_writes_size = (u32)(*anc_ptr);
- anc_size_remaining -= sizeof(u32);
- anc_ptr += 1;
-
- if (anc_writes_size * TAIKO_PACKED_REG_SIZE
- > anc_size_remaining) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- if (taiko->anc_slot == i)
- break;
-
- anc_size_remaining -= (anc_writes_size *
- TAIKO_PACKED_REG_SIZE);
- anc_ptr += anc_writes_size;
- }
- if (i == num_anc_slots) {
- dev_err(codec->dev, "Selected ANC slot not present\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- for (i = 0; i < anc_writes_size; i++) {
- TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
- mask, val);
- snd_soc_write(codec, reg, val);
- }
- release_firmware(fw);
-
- break;
- case SND_SOC_DAPM_POST_PMD:
- snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
- snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
- break;
- }
- return 0;
-}
-
static int taiko_codec_config_mad(struct snd_soc_codec *codec)
{
int ret;
@@ -2780,6 +2747,106 @@
return 0;
}
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ const char *filename;
+ const struct firmware *fw;
+ int i;
+ int ret;
+ int num_anc_slots;
+ struct anc_header *anc_head;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u32 anc_writes_size = 0;
+ int anc_size_remaining;
+ u32 *anc_ptr;
+ u16 reg;
+ u8 mask, val, old_val;
+
+
+ if (taiko->anc_func == 0)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ filename = "wcd9320/wcd9320_anc.bin";
+
+ ret = request_firmware(&fw, filename, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ if (fw->size < sizeof(struct anc_header)) {
+ dev_err(codec->dev, "Not enough data\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ /* First number is the number of register writes */
+ anc_head = (struct anc_header *)(fw->data);
+ anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+ anc_size_remaining = fw->size - sizeof(struct anc_header);
+ num_anc_slots = anc_head->num_anc_slots;
+
+ if (taiko->anc_slot >= num_anc_slots) {
+ dev_err(codec->dev, "Invalid ANC slot selected\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ for (i = 0; i < num_anc_slots; i++) {
+ if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ anc_writes_size = (u32)(*anc_ptr);
+ anc_size_remaining -= sizeof(u32);
+ anc_ptr += 1;
+
+ if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+ > anc_size_remaining) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ if (taiko->anc_slot == i)
+ break;
+
+ anc_size_remaining -= (anc_writes_size *
+ TAIKO_PACKED_REG_SIZE);
+ anc_ptr += anc_writes_size;
+ }
+ if (i == num_anc_slots) {
+ dev_err(codec->dev, "Selected ANC slot not present\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+ for (i = 0; i < anc_writes_size; i++) {
+ TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+ mask, val);
+ old_val = snd_soc_read(codec, reg);
+ snd_soc_write(codec, reg, (old_val & ~mask) |
+ (val & mask));
+ }
+ release_firmware(fw);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msleep(40);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+ msleep(20);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+ break;
+ }
+ return 0;
+}
+
static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2835,6 +2902,46 @@
return 0;
}
+static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ if (w->shift == 4) {
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->shift == 4) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
+ msleep(30);
+ }
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ msleep(40);
+ }
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ }
+ case SND_SOC_DAPM_POST_PMD:
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ break;
+ }
+ return ret;
+}
+
static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
4, 0, NULL, 0),
@@ -3022,9 +3129,10 @@
{"EAR_PA_MIXER", NULL, "DAC1"},
{"DAC1", NULL, "RX_BIAS"},
+ {"ANC EAR", NULL, "ANC EAR PA"},
+ {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
- {"ANC", NULL, "ANC1 FB MUX"},
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
@@ -3038,18 +3146,28 @@
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
{"HPHR DAC", NULL, "RX_BIAS"},
- {"ANC", NULL, "ANC1 MUX"},
- {"ANC", NULL, "ANC2 MUX"},
+ {"ANC HEADPHONE", NULL, "ANC HPHL"},
+ {"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+ {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+ {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
{"ANC1 MUX", "ADC1", "ADC1"},
{"ANC1 MUX", "ADC2", "ADC2"},
{"ANC1 MUX", "ADC3", "ADC3"},
{"ANC1 MUX", "ADC4", "ADC4"},
+ {"ANC1 MUX", "DMIC1", "DMIC1"},
+ {"ANC1 MUX", "DMIC2", "DMIC2"},
+ {"ANC1 MUX", "DMIC3", "DMIC3"},
+ {"ANC1 MUX", "DMIC4", "DMIC4"},
+ {"ANC1 MUX", "DMIC5", "DMIC5"},
+ {"ANC1 MUX", "DMIC6", "DMIC6"},
{"ANC2 MUX", "ADC1", "ADC1"},
{"ANC2 MUX", "ADC2", "ADC2"},
{"ANC2 MUX", "ADC3", "ADC3"},
{"ANC2 MUX", "ADC4", "ADC4"},
- {"ANC", NULL, "CDC_CONN"},
+ {"ANC HPHR", NULL, "CDC_CONN"},
{"DAC1", "Switch", "CLASS_H_DSM MUX"},
{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
@@ -3095,8 +3213,8 @@
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
- {"RX1 CHAIN", NULL, "ANC"},
- {"RX2 CHAIN", NULL, "ANC"},
+ {"RX1 MIX2", NULL, "ANC1 MUX"},
+ {"RX2 MIX2", NULL, "ANC2 MUX"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -3429,6 +3547,14 @@
(reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
return 1;
+ /* ANC filter registers are not cacheable */
+ if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
+ (reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
+ return 1;
+ if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
+ (reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
+ return 1;
+
/* Digital gain register is not cacheable so we have to write
* the setting even it is the same
*/
@@ -4457,6 +4583,32 @@
return 0;
}
+static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = taiko_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
+ msleep(40);
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+ break;
+ }
+ return ret;
+}
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
@@ -4754,10 +4906,20 @@
SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
- SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
- taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
+ SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+ taiko_codec_enable_anc_hph,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+ taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUTPUT("ANC EAR"),
+ SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ taiko_codec_enable_anc_ear,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
SND_SOC_DAPM_INPUT("AMIC2"),
@@ -5700,6 +5862,14 @@
(void) taiko_setup_irqs(taiko);
atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+ mutex_lock(&dapm->codec->mutex);
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
codec->ignore_pmdown_time = 1;
return ret;