Merge "defconfig: msm8610: Use correct csi and ispif version"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
new file mode 100644
index 0000000..9b69037
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
@@ -0,0 +1,26 @@
+* RPM RBCPR
+
+The RBCPR(Rapid Bridge Core Power Reduction) is module on RPM that controls
+the voltage level on the chip based on feedback received through various
+sensors on the chip that allow compensation of the chip process variation,
+temperature etc.
+RPM maintains RBCPR (Rapid Bridge Core Power Reduction) related stats in
+data memory. This module allows users to read those stats.
+
+The required properties for rpm-stats are:
+
+- compatible: "qcom,rpmrbcpr-stats"
+- reg: Pointer to the start of the RPM Data Memory. The size of the memory
+ is inclusive of the entire RPM data memory.
+- qcom,start_offset: The offset at which the RBCPR stats are maintained. The
+ driver module reads this parameter to get another offset
+ that contain the rbcpr stats.
+
+
+Example:
+
+qcom,rpm-rbcpr-stats@fc000000 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0xfc000000 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+};
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index adb93b8..3095b0a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -12,11 +12,11 @@
- reg: Specifies the SPMI address and size for this PON (power-on) peripheral
- interrupts: Specifies the interrupt associated with PON.
- interrupt-names: Specify the interrupt names associated with interrupts. Must be
- one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr".
- Bark interrupts are associated with system reset configuration
- to allow default reset configuration to be activated. If system
- reset configuration is not supported then bark interrupts are
- nops.
+ one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr",
+ "kpdpwr-resin-bark". Bark interrupts are associated with system
+ reset configuration to allow default reset configuration to be
+ activated. If system reset configuration is not supported then
+ bark interrupts are nops.
Optional properties:
- qcom,pon-dbc-delay The debounce delay for the power-key interrupt
@@ -34,6 +34,8 @@
to reset the system. This property can only be
used by one device on the system. It is an error
to include it more than once.
+- qcom,s3-debounce The debounce delay for stage3 reset trigger in
+ secs. The values range from 0 to 128.
All the below properties are in the sub-node section (properties of the child
node).
@@ -82,9 +84,13 @@
reg = <0x800 0x100>;
interrupts = <0x0 0x8 0x0>,
<0x0 0x8 0x1>,
- <0x0 0x8 0x4>;
- interrupt-names = "kpdpwr", "resin", "resin-bark";
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+ qcom,s3-debounce = <32>;
qcom,pon_1 {
qcom,pon-type = <0>;
@@ -96,9 +102,18 @@
qcom,pon-type = <1>;
qcom,support-reset = <1>;
qcom,pull-up = <1>;
- qcom,s1-timer = <3072>;
+ qcom,s1-timer = <0>;
qcom,s2-timer = <2000>;
qcom,s2-type = <1>;
linux,code = <114>;
};
- }
+
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ qcom,pull-up = <1>;
+ };
+ };
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
new file mode 100644
index 0000000..1ecad71
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -0,0 +1,580 @@
+/* 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.
+ */
+
+&soc {
+ qcom,mdss_dsi_nt35596_1080p_video {
+ compatible = "qcom,mdss-dsi-panel";
+ label = "nt35596 1080p video mode dsi panel";
+ status = "disable";
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+ qcom,rst-gpio = <&msmgpio 25 0>;
+ qcom,mdss-pan-res = <1080 1920>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-dest = "display_1";
+ qcom,mdss-pan-porch-values = <32 8 32 18 2 2>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-bl-levels = <1 4095>;
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <2>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
+ qcom,mdss-pan-dsi-dlane-swap = <0>;
+ qcom,mdss-pan-dsi-t-clk = <0x38 0x1e>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
+ 20 00 01];
+ qcom,panel-phy-timingSettings = [f9 3d 34 00 58 4d
+ 36 3f 53 03 04 00];
+ qcom,panel-phy-strengthCtrl = [ff 06];
+ qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
+ 00 00];
+ qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+ 00 00 00 00 05 00 00 01 97 /* lane1 config */
+ 00 00 00 00 0a 00 00 01 97 /* lane2 config */
+ 00 00 00 00 0f 00 00 01 97 /* lane3 config */
+ 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+ qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 1F 45
+ 29 01 00 00 00 00 02 24 4F
+ 29 01 00 00 00 00 02 38 C8
+ 29 01 00 00 00 00 02 39 2C
+ 29 01 00 00 00 00 02 1E BB
+ 29 01 00 00 00 00 02 1D 0F
+ 29 01 00 00 00 00 02 7E B1
+ 29 01 00 00 00 00 02 FF 00
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 35 01
+ 29 01 00 00 00 00 02 BA 03
+ 29 01 00 00 00 00 02 FF 01
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 00 01
+ 29 01 00 00 00 00 02 01 55
+ 29 01 00 00 00 00 02 02 40
+ 29 01 00 00 00 00 02 05 00
+ 29 01 00 00 00 00 02 06 1B
+ 29 01 00 00 00 00 02 07 24
+ 29 01 00 00 00 00 02 08 0C
+ 29 01 00 00 00 00 02 0B 87
+ 29 01 00 00 00 00 02 0C 87
+ 29 01 00 00 00 00 02 0E B0
+ 29 01 00 00 00 00 02 0F B3
+ 29 01 00 00 00 00 02 11 10
+ 29 01 00 00 00 00 02 12 10
+ 29 01 00 00 00 00 02 13 05
+ 29 01 00 00 00 00 02 14 4A
+ 29 01 00 00 00 00 02 15 18
+ 29 01 00 00 00 00 02 16 18
+ 29 01 00 00 00 00 02 18 00
+ 29 01 00 00 00 00 02 19 77
+ 29 01 00 00 00 00 02 1A 55
+ 29 01 00 00 00 00 02 1B 13
+ 29 01 00 00 00 00 02 1C 00
+ 29 01 00 00 00 00 02 1D 00
+ 29 01 00 00 00 00 02 1E 13
+ 29 01 00 00 00 00 02 1F 00
+ 29 01 00 00 00 00 02 23 00
+ 29 01 00 00 00 00 02 24 00
+ 29 01 00 00 00 00 02 25 00
+ 29 01 00 00 00 00 02 26 00
+ 29 01 00 00 00 00 02 27 00
+ 29 01 00 00 00 00 02 28 00
+ 29 01 00 00 00 00 02 35 00
+ 29 01 00 00 00 00 02 66 00
+ 29 01 00 00 00 00 02 58 82
+ 29 01 00 00 00 00 02 59 02
+ 29 01 00 00 00 00 02 5A 02
+ 29 01 00 00 00 00 02 5B 02
+ 29 01 00 00 00 00 02 5C 82
+ 29 01 00 00 00 00 02 5D 82
+ 29 01 00 00 00 00 02 5E 02
+ 29 01 00 00 00 00 02 5F 02
+ 29 01 00 00 00 00 02 72 31
+ 29 01 00 00 00 00 02 FF 05
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 00 01
+ 29 01 00 00 00 00 02 01 0B
+ 29 01 00 00 00 00 02 02 0C
+ 29 01 00 00 00 00 02 03 09
+ 29 01 00 00 00 00 02 04 0A
+ 29 01 00 00 00 00 02 05 00
+ 29 01 00 00 00 00 02 06 0F
+ 29 01 00 00 00 00 02 07 10
+ 29 01 00 00 00 00 02 08 00
+ 29 01 00 00 00 00 02 09 00
+ 29 01 00 00 00 00 02 0A 00
+ 29 01 00 00 00 00 02 0B 00
+ 29 01 00 00 00 00 02 0C 00
+ 29 01 00 00 00 00 02 0D 13
+ 29 01 00 00 00 00 02 0E 15
+ 29 01 00 00 00 00 02 0F 17
+ 29 01 00 00 00 00 02 10 01
+ 29 01 00 00 00 00 02 11 0B
+ 29 01 00 00 00 00 02 12 0C
+ 29 01 00 00 00 00 02 13 09
+ 29 01 00 00 00 00 02 14 0A
+ 29 01 00 00 00 00 02 15 00
+ 29 01 00 00 00 00 02 16 0F
+ 29 01 00 00 00 00 02 17 10
+ 29 01 00 00 00 00 02 18 00
+ 29 01 00 00 00 00 02 19 00
+ 29 01 00 00 00 00 02 1A 00
+ 29 01 00 00 00 00 02 1B 00
+ 29 01 00 00 00 00 02 1C 00
+ 29 01 00 00 00 00 02 1D 13
+ 29 01 00 00 00 00 02 1E 15
+ 29 01 00 00 00 00 02 1F 17
+ 29 01 00 00 00 00 02 20 00
+ 29 01 00 00 00 00 02 21 03
+ 29 01 00 00 00 00 02 22 01
+ 29 01 00 00 00 00 02 23 40
+ 29 01 00 00 00 00 02 24 40
+ 29 01 00 00 00 00 02 25 ED
+ 29 01 00 00 00 00 02 29 58
+ 29 01 00 00 00 00 02 2A 12
+ 29 01 00 00 00 00 02 2B 01
+ 29 01 00 00 00 00 02 4B 06
+ 29 01 00 00 00 00 02 4C 11
+ 29 01 00 00 00 00 02 4D 20
+ 29 01 00 00 00 00 02 4E 02
+ 29 01 00 00 00 00 02 4F 02
+ 29 01 00 00 00 00 02 50 20
+ 29 01 00 00 00 00 02 51 61
+ 29 01 00 00 00 00 02 52 01
+ 29 01 00 00 00 00 02 53 63
+ 29 01 00 00 00 00 02 54 77
+ 29 01 00 00 00 00 02 55 ED
+ 29 01 00 00 00 00 02 5B 00
+ 29 01 00 00 00 00 02 5C 00
+ 29 01 00 00 00 00 02 5D 00
+ 29 01 00 00 00 00 02 5E 00
+ 29 01 00 00 00 00 02 5F 15
+ 29 01 00 00 00 00 02 60 75
+ 29 01 00 00 00 00 02 61 00
+ 29 01 00 00 00 00 02 62 00
+ 29 01 00 00 00 00 02 63 00
+ 29 01 00 00 00 00 02 64 00
+ 29 01 00 00 00 00 02 65 00
+ 29 01 00 00 00 00 02 66 00
+ 29 01 00 00 00 00 02 67 00
+ 29 01 00 00 00 00 02 68 04
+ 29 01 00 00 00 00 02 69 00
+ 29 01 00 00 00 00 02 6A 00
+ 29 01 00 00 00 00 02 6C 40
+ 29 01 00 00 00 00 02 75 01
+ 29 01 00 00 00 00 02 76 01
+ 29 01 00 00 00 00 02 7A 80
+ 29 01 00 00 00 00 02 7B C5
+ 29 01 00 00 00 00 02 7C D8
+ 29 01 00 00 00 00 02 7D 60
+ 29 01 00 00 00 00 02 7F 10
+ 29 01 00 00 00 00 02 80 81
+ 29 01 00 00 00 00 02 83 05
+ 29 01 00 00 00 00 02 93 08
+ 29 01 00 00 00 00 02 94 10
+ 29 01 00 00 00 00 02 8A 00
+ 29 01 00 00 00 00 02 9B 0F
+ 29 01 00 00 00 00 02 EA FF
+ 29 01 00 00 00 00 02 EC 00
+ 29 01 00 00 00 00 02 FF 01
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 75 00
+ 29 01 00 00 00 00 02 76 8E
+ 29 01 00 00 00 00 02 77 00
+ 29 01 00 00 00 00 02 78 90
+ 29 01 00 00 00 00 02 79 00
+ 29 01 00 00 00 00 02 7A B2
+ 29 01 00 00 00 00 02 7B 00
+ 29 01 00 00 00 00 02 7C C7
+ 29 01 00 00 00 00 02 7D 00
+ 29 01 00 00 00 00 02 7E D7
+ 29 01 00 00 00 00 02 7F 00
+ 29 01 00 00 00 00 02 80 E9
+ 29 01 00 00 00 00 02 81 00
+ 29 01 00 00 00 00 02 82 F9
+ 29 01 00 00 00 00 02 83 01
+ 29 01 00 00 00 00 02 84 01
+ 29 01 00 00 00 00 02 85 01
+ 29 01 00 00 00 00 02 86 0B
+ 29 01 00 00 00 00 02 87 01
+ 29 01 00 00 00 00 02 88 3A
+ 29 01 00 00 00 00 02 89 01
+ 29 01 00 00 00 00 02 8A 5D
+ 29 01 00 00 00 00 02 8B 01
+ 29 01 00 00 00 00 02 8C 94
+ 29 01 00 00 00 00 02 8D 01
+ 29 01 00 00 00 00 02 8E BC
+ 29 01 00 00 00 00 02 8F 02
+ 29 01 00 00 00 00 02 90 00
+ 29 01 00 00 00 00 02 91 02
+ 29 01 00 00 00 00 02 92 39
+ 29 01 00 00 00 00 02 93 02
+ 29 01 00 00 00 00 02 94 3A
+ 29 01 00 00 00 00 02 95 02
+ 29 01 00 00 00 00 02 96 6B
+ 29 01 00 00 00 00 02 97 02
+ 29 01 00 00 00 00 02 98 A2
+ 29 01 00 00 00 00 02 99 02
+ 29 01 00 00 00 00 02 9A C7
+ 29 01 00 00 00 00 02 9B 02
+ 29 01 00 00 00 00 02 9C FB
+ 29 01 00 00 00 00 02 9D 03
+ 29 01 00 00 00 00 02 9E 20
+ 29 01 00 00 00 00 02 9F 03
+ 29 01 00 00 00 00 02 A0 54
+ 29 01 00 00 00 00 02 A2 03
+ 29 01 00 00 00 00 02 A3 6D
+ 29 01 00 00 00 00 02 A4 03
+ 29 01 00 00 00 00 02 A5 80
+ 29 01 00 00 00 00 02 A6 03
+ 29 01 00 00 00 00 02 A7 81
+ 29 01 00 00 00 00 02 A9 03
+ 29 01 00 00 00 00 02 AA C7
+ 29 01 00 00 00 00 02 AB 03
+ 29 01 00 00 00 00 02 AC F0
+ 29 01 00 00 00 00 02 AD 03
+ 29 01 00 00 00 00 02 AE F8
+ 29 01 00 00 00 00 02 AF 03
+ 29 01 00 00 00 00 02 B0 FD
+ 29 01 00 00 00 00 02 B1 03
+ 29 01 00 00 00 00 02 B2 FE
+ 29 01 00 00 00 00 02 B3 00
+ 29 01 00 00 00 00 02 B4 8E
+ 29 01 00 00 00 00 02 B5 00
+ 29 01 00 00 00 00 02 B6 90
+ 29 01 00 00 00 00 02 B7 00
+ 29 01 00 00 00 00 02 B8 B2
+ 29 01 00 00 00 00 02 B9 00
+ 29 01 00 00 00 00 02 BA C7
+ 29 01 00 00 00 00 02 BB 00
+ 29 01 00 00 00 00 02 BC D7
+ 29 01 00 00 00 00 02 BD 00
+ 29 01 00 00 00 00 02 BE E9
+ 29 01 00 00 00 00 02 BF 00
+ 29 01 00 00 00 00 02 C0 F9
+ 29 01 00 00 00 00 02 C1 01
+ 29 01 00 00 00 00 02 C2 01
+ 29 01 00 00 00 00 02 C3 01
+ 29 01 00 00 00 00 02 C4 0B
+ 29 01 00 00 00 00 02 C5 01
+ 29 01 00 00 00 00 02 C6 3A
+ 29 01 00 00 00 00 02 C7 01
+ 29 01 00 00 00 00 02 C8 5D
+ 29 01 00 00 00 00 02 C9 01
+ 29 01 00 00 00 00 02 CA 94
+ 29 01 00 00 00 00 02 CB 01
+ 29 01 00 00 00 00 02 CC BC
+ 29 01 00 00 00 00 02 CD 02
+ 29 01 00 00 00 00 02 CE 00
+ 29 01 00 00 00 00 02 CF 02
+ 29 01 00 00 00 00 02 D0 39
+ 29 01 00 00 00 00 02 D1 02
+ 29 01 00 00 00 00 02 D2 3A
+ 29 01 00 00 00 00 02 D3 02
+ 29 01 00 00 00 00 02 D4 6B
+ 29 01 00 00 00 00 02 D5 02
+ 29 01 00 00 00 00 02 D6 A2
+ 29 01 00 00 00 00 02 D7 02
+ 29 01 00 00 00 00 02 D8 C7
+ 29 01 00 00 00 00 02 D9 02
+ 29 01 00 00 00 00 02 DA FB
+ 29 01 00 00 00 00 02 DB 03
+ 29 01 00 00 00 00 02 DC 20
+ 29 01 00 00 00 00 02 DD 03
+ 29 01 00 00 00 00 02 DE 54
+ 29 01 00 00 00 00 02 DF 03
+ 29 01 00 00 00 00 02 E0 6D
+ 29 01 00 00 00 00 02 E1 03
+ 29 01 00 00 00 00 02 E2 80
+ 29 01 00 00 00 00 02 E3 03
+ 29 01 00 00 00 00 02 E4 81
+ 29 01 00 00 00 00 02 E5 03
+ 29 01 00 00 00 00 02 E6 C7
+ 29 01 00 00 00 00 02 E7 03
+ 29 01 00 00 00 00 02 E8 F0
+ 29 01 00 00 00 00 02 E9 03
+ 29 01 00 00 00 00 02 EA F8
+ 29 01 00 00 00 00 02 EB 03
+ 29 01 00 00 00 00 02 EC FD
+ 29 01 00 00 00 00 02 ED 03
+ 29 01 00 00 00 00 02 EE FE
+ 29 01 00 00 00 00 02 EF 00
+ 29 01 00 00 00 00 02 F0 03
+ 29 01 00 00 00 00 02 F1 00
+ 29 01 00 00 00 00 02 F2 0B
+ 29 01 00 00 00 00 02 F3 00
+ 29 01 00 00 00 00 02 F4 0D
+ 29 01 00 00 00 00 02 F5 00
+ 29 01 00 00 00 00 02 F6 4A
+ 29 01 00 00 00 00 02 F7 00
+ 29 01 00 00 00 00 02 F8 71
+ 29 01 00 00 00 00 02 F9 00
+ 29 01 00 00 00 00 02 FA 8C
+ 29 01 00 00 00 00 02 FF 02
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 00 00
+ 29 01 00 00 00 00 02 01 A1
+ 29 01 00 00 00 00 02 02 00
+ 29 01 00 00 00 00 02 03 B6
+ 29 01 00 00 00 00 02 04 00
+ 29 01 00 00 00 00 02 05 C9
+ 29 01 00 00 00 00 02 06 00
+ 29 01 00 00 00 00 02 07 FD
+ 29 01 00 00 00 00 02 08 01
+ 29 01 00 00 00 00 02 09 29
+ 29 01 00 00 00 00 02 0A 01
+ 29 01 00 00 00 00 02 0B 6B
+ 29 01 00 00 00 00 02 0C 01
+ 29 01 00 00 00 00 02 0D 9E
+ 29 01 00 00 00 00 02 0E 01
+ 29 01 00 00 00 00 02 0F EB
+ 29 01 00 00 00 00 02 10 02
+ 29 01 00 00 00 00 02 11 25
+ 29 01 00 00 00 00 02 12 02
+ 29 01 00 00 00 00 02 13 27
+ 29 01 00 00 00 00 02 14 02
+ 29 01 00 00 00 00 02 15 5C
+ 29 01 00 00 00 00 02 16 02
+ 29 01 00 00 00 00 02 17 95
+ 29 01 00 00 00 00 02 18 02
+ 29 01 00 00 00 00 02 19 BA
+ 29 01 00 00 00 00 02 1A 02
+ 29 01 00 00 00 00 02 1B EC
+ 29 01 00 00 00 00 02 1C 03
+ 29 01 00 00 00 00 02 1D 0C
+ 29 01 00 00 00 00 02 1E 03
+ 29 01 00 00 00 00 02 1F 34
+ 29 01 00 00 00 00 02 20 03
+ 29 01 00 00 00 00 02 21 3F
+ 29 01 00 00 00 00 02 22 03
+ 29 01 00 00 00 00 02 23 48
+ 29 01 00 00 00 00 02 24 03
+ 29 01 00 00 00 00 02 25 49
+ 29 01 00 00 00 00 02 26 03
+ 29 01 00 00 00 00 02 27 6B
+ 29 01 00 00 00 00 02 28 03
+ 29 01 00 00 00 00 02 29 7E
+ 29 01 00 00 00 00 02 2A 03
+ 29 01 00 00 00 00 02 2B 8F
+ 29 01 00 00 00 00 02 2D 03
+ 29 01 00 00 00 00 02 2F 9E
+ 29 01 00 00 00 00 02 30 03
+ 29 01 00 00 00 00 02 31 A0
+ 29 01 00 00 00 00 02 32 00
+ 29 01 00 00 00 00 02 33 03
+ 29 01 00 00 00 00 02 34 00
+ 29 01 00 00 00 00 02 35 0B
+ 29 01 00 00 00 00 02 36 00
+ 29 01 00 00 00 00 02 37 0D
+ 29 01 00 00 00 00 02 38 00
+ 29 01 00 00 00 00 02 39 4A
+ 29 01 00 00 00 00 02 3A 00
+ 29 01 00 00 00 00 02 3B 71
+ 29 01 00 00 00 00 02 3D 00
+ 29 01 00 00 00 00 02 3F 8C
+ 29 01 00 00 00 00 02 40 00
+ 29 01 00 00 00 00 02 41 A1
+ 29 01 00 00 00 00 02 42 00
+ 29 01 00 00 00 00 02 43 B6
+ 29 01 00 00 00 00 02 44 00
+ 29 01 00 00 00 00 02 45 C9
+ 29 01 00 00 00 00 02 46 00
+ 29 01 00 00 00 00 02 47 FD
+ 29 01 00 00 00 00 02 48 01
+ 29 01 00 00 00 00 02 49 29
+ 29 01 00 00 00 00 02 4A 01
+ 29 01 00 00 00 00 02 4B 6B
+ 29 01 00 00 00 00 02 4C 01
+ 29 01 00 00 00 00 02 4D 9E
+ 29 01 00 00 00 00 02 4E 01
+ 29 01 00 00 00 00 02 4F EB
+ 29 01 00 00 00 00 02 50 02
+ 29 01 00 00 00 00 02 51 25
+ 29 01 00 00 00 00 02 52 02
+ 29 01 00 00 00 00 02 53 27
+ 29 01 00 00 00 00 02 54 02
+ 29 01 00 00 00 00 02 55 5C
+ 29 01 00 00 00 00 02 56 02
+ 29 01 00 00 00 00 02 58 95
+ 29 01 00 00 00 00 02 59 02
+ 29 01 00 00 00 00 02 5A BA
+ 29 01 00 00 00 00 02 5B 02
+ 29 01 00 00 00 00 02 5C EC
+ 29 01 00 00 00 00 02 5D 03
+ 29 01 00 00 00 00 02 5E 0C
+ 29 01 00 00 00 00 02 5F 03
+ 29 01 00 00 00 00 02 60 34
+ 29 01 00 00 00 00 02 61 03
+ 29 01 00 00 00 00 02 62 3F
+ 29 01 00 00 00 00 02 63 03
+ 29 01 00 00 00 00 02 64 48
+ 29 01 00 00 00 00 02 65 03
+ 29 01 00 00 00 00 02 66 49
+ 29 01 00 00 00 00 02 67 03
+ 29 01 00 00 00 00 02 68 6B
+ 29 01 00 00 00 00 02 69 03
+ 29 01 00 00 00 00 02 6A 7E
+ 29 01 00 00 00 00 02 6B 03
+ 29 01 00 00 00 00 02 6C 8F
+ 29 01 00 00 00 00 02 6D 03
+ 29 01 00 00 00 00 02 6E 9E
+ 29 01 00 00 00 00 02 6F 03
+ 29 01 00 00 00 00 02 70 A0
+ 29 01 00 00 00 00 02 71 00
+ 29 01 00 00 00 00 02 72 FB
+ 29 01 00 00 00 00 02 73 00
+ 29 01 00 00 00 00 02 74 FD
+ 29 01 00 00 00 00 02 75 01
+ 29 01 00 00 00 00 02 76 05
+ 29 01 00 00 00 00 02 77 01
+ 29 01 00 00 00 00 02 78 0D
+ 29 01 00 00 00 00 02 79 01
+ 29 01 00 00 00 00 02 7A 17
+ 29 01 00 00 00 00 02 7B 01
+ 29 01 00 00 00 00 02 7C 1F
+ 29 01 00 00 00 00 02 7D 01
+ 29 01 00 00 00 00 02 7E 28
+ 29 01 00 00 00 00 02 7F 01
+ 29 01 00 00 00 00 02 80 32
+ 29 01 00 00 00 00 02 81 01
+ 29 01 00 00 00 00 02 82 38
+ 29 01 00 00 00 00 02 83 01
+ 29 01 00 00 00 00 02 84 53
+ 29 01 00 00 00 00 02 85 01
+ 29 01 00 00 00 00 02 86 72
+ 29 01 00 00 00 00 02 87 01
+ 29 01 00 00 00 00 02 88 9B
+ 29 01 00 00 00 00 02 89 01
+ 29 01 00 00 00 00 02 8A C3
+ 29 01 00 00 00 00 02 8B 02
+ 29 01 00 00 00 00 02 8C 01
+ 29 01 00 00 00 00 02 8D 02
+ 29 01 00 00 00 00 02 8E 36
+ 29 01 00 00 00 00 02 8F 02
+ 29 01 00 00 00 00 02 90 37
+ 29 01 00 00 00 00 02 91 02
+ 29 01 00 00 00 00 02 92 69
+ 29 01 00 00 00 00 02 93 02
+ 29 01 00 00 00 00 02 94 A1
+ 29 01 00 00 00 00 02 95 02
+ 29 01 00 00 00 00 02 96 C8
+ 29 01 00 00 00 00 02 97 02
+ 29 01 00 00 00 00 02 98 FF
+ 29 01 00 00 00 00 02 99 03
+ 29 01 00 00 00 00 02 9A 26
+ 29 01 00 00 00 00 02 9B 03
+ 29 01 00 00 00 00 02 9C 69
+ 29 01 00 00 00 00 02 9D 03
+ 29 01 00 00 00 00 02 9E 88
+ 29 01 00 00 00 00 02 9F 03
+ 29 01 00 00 00 00 02 A0 F8
+ 29 01 00 00 00 00 02 A2 03
+ 29 01 00 00 00 00 02 A3 F9
+ 29 01 00 00 00 00 02 A4 03
+ 29 01 00 00 00 00 02 A5 FE
+ 29 01 00 00 00 00 02 A6 03
+ 29 01 00 00 00 00 02 A7 FE
+ 29 01 00 00 00 00 02 A9 03
+ 29 01 00 00 00 00 02 AA FE
+ 29 01 00 00 00 00 02 AB 03
+ 29 01 00 00 00 00 02 AC FE
+ 29 01 00 00 00 00 02 AD 03
+ 29 01 00 00 00 00 02 AE FE
+ 29 01 00 00 00 00 02 AF 00
+ 29 01 00 00 00 00 02 B0 FB
+ 29 01 00 00 00 00 02 B1 00
+ 29 01 00 00 00 00 02 B2 FD
+ 29 01 00 00 00 00 02 B3 01
+ 29 01 00 00 00 00 02 B4 05
+ 29 01 00 00 00 00 02 B5 01
+ 29 01 00 00 00 00 02 B6 0D
+ 29 01 00 00 00 00 02 B7 01
+ 29 01 00 00 00 00 02 B8 17
+ 29 01 00 00 00 00 02 B9 01
+ 29 01 00 00 00 00 02 BA 1F
+ 29 01 00 00 00 00 02 BB 01
+ 29 01 00 00 00 00 02 BC 28
+ 29 01 00 00 00 00 02 BD 01
+ 29 01 00 00 00 00 02 BE 32
+ 29 01 00 00 00 00 02 BF 01
+ 29 01 00 00 00 00 02 C0 38
+ 29 01 00 00 00 00 02 C1 01
+ 29 01 00 00 00 00 02 C2 53
+ 29 01 00 00 00 00 02 C3 01
+ 29 01 00 00 00 00 02 C4 72
+ 29 01 00 00 00 00 02 C5 01
+ 29 01 00 00 00 00 02 C6 9B
+ 29 01 00 00 00 00 02 C7 01
+ 29 01 00 00 00 00 02 C8 C3
+ 29 01 00 00 00 00 02 C9 02
+ 29 01 00 00 00 00 02 CA 01
+ 29 01 00 00 00 00 02 CB 02
+ 29 01 00 00 00 00 02 CC 36
+ 29 01 00 00 00 00 02 CD 02
+ 29 01 00 00 00 00 02 CE 37
+ 29 01 00 00 00 00 02 CF 02
+ 29 01 00 00 00 00 02 D0 69
+ 29 01 00 00 00 00 02 D1 02
+ 29 01 00 00 00 00 02 D2 A1
+ 29 01 00 00 00 00 02 D3 02
+ 29 01 00 00 00 00 02 D4 C8
+ 29 01 00 00 00 00 02 D5 02
+ 29 01 00 00 00 00 02 D6 FF
+ 29 01 00 00 00 00 02 D7 03
+ 29 01 00 00 00 00 02 D8 26
+ 29 01 00 00 00 00 02 D9 03
+ 29 01 00 00 00 00 02 DA 69
+ 29 01 00 00 00 00 02 DB 03
+ 29 01 00 00 00 00 02 DC 88
+ 29 01 00 00 00 00 02 DD 03
+ 29 01 00 00 00 00 02 DE F8
+ 29 01 00 00 00 00 02 DF 03
+ 29 01 00 00 00 00 02 E0 F9
+ 29 01 00 00 00 00 02 E1 03
+ 29 01 00 00 00 00 02 E2 FE
+ 29 01 00 00 00 00 02 E3 03
+ 29 01 00 00 00 00 02 E4 FE
+ 29 01 00 00 00 00 02 E5 03
+ 29 01 00 00 00 00 02 E6 FE
+ 29 01 00 00 00 00 02 E7 03
+ 29 01 00 00 00 00 02 E8 FE
+ 29 01 00 00 00 00 02 E9 03
+ 29 01 00 00 00 00 02 EA FE
+ 29 01 00 00 00 00 02 FF 01
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 FF 02
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 FF 04
+ 29 01 00 00 00 00 02 FB 01
+ 29 01 00 00 00 00 02 FF 00
+ 29 01 00 00 00 00 02 D3 14
+ 29 01 00 00 00 00 02 D4 14
+ 29 01 00 00 96 00 02 11 00
+ 29 01 00 00 00 00 02 FF 00
+ 29 01 00 00 00 00 02 35 00
+ 29 01 00 00 78 00 02 29 00];
+
+ qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b4e557e..ce050a4 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -46,10 +46,13 @@
reg = <0x800 0x100>;
interrupts = <0x0 0x8 0x0>,
<0x0 0x8 0x1>,
- <0x0 0x8 0x4>;
- interrupt-names = "kpdpwr", "resin", "resin-bark";
+ <0x0 0x8 0x4>,
+ <0x0 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
qcom,pon-dbc-delay = <15625>;
qcom,system-reset;
+ qcom,s3-debounce = <32>;
qcom,pon_1 {
qcom,pon-type = <0>;
@@ -66,6 +69,15 @@
qcom,s2-type = <1>;
linux,code = <114>;
};
+
+ qcom,pon_3 {
+ qcom,pon-type = <3>;
+ qcom,support-reset = <1>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ qcom,pull-up = <1>;
+ };
};
bif_ctrl: qcom,bsi@1b00 {
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 456b60c..d625b95 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -33,6 +33,21 @@
reg = <27>;
linux,contiguous-region = <&qsecom_mem>;
};
+
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x0bf00000 0x1A00000>;
+ };
+
+ qcom,ion-heap@26 { /* MODEM HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <26>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x08000000 0x3F00000>;
+ };
+
};
};
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 22e7aa0..90225c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -57,6 +57,27 @@
status = "ok";
};
+ i2c@f9925000 { /* BLSP-1 QUP-3 */
+ kionix@f {
+ compatible = "kionix,kxtj9";
+ reg = <0x0f>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <81 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vio-supply = <&pm8110_l14>;
+ kionix,min_interval = <5>;
+ kionix,init_interval = <200>;
+ kionix,axis_map_x = <1>;
+ kionix,axis_map_y = <0>;
+ kionix,axis_map_z = <2>;
+ kionix,g-range = <2>;
+ kionix,negate-x;
+ kionix,negate-y;
+ kionix,negate-z;
+ kionix,res-12bit;
+ };
+ };
+
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index a62df58..7e1b201 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -237,6 +237,7 @@
android_usb@fe8050c8 {
compatible = "qcom,android-usb";
reg = <0xfe8050c8 0xc8>;
+ qcom,android-usb-swfi-latency = <1>;
};
sdcc1: qcom,sdcc@f9824000 {
@@ -418,7 +419,7 @@
qcom,msm-mem-hole {
compatible = "qcom,msm-mem-hole";
- qcom,memblock-remove = <0x07B00000 0x6400000>; /* Address and Size of Hole */
+ qcom,memblock-remove = <0x07b00000 0x6400000>; /* Address and Size of Hole */
};
qcom,wdt@f9017000 {
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 178a1ee..eed1aae 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -328,18 +328,23 @@
<50 172>, /* usb1_hs_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 56>, /* modem_watchdog */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 70>, /* iommu_pmon_nonsecure_irq */
+ <0xff 97>, /* iommu_nonsecure_irq */
+ <0xff 105>, /* iommu_pmon_nonsecure_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
<0xff 176>, /* o_wcss_apss_smsm_irq */
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
- <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 179>, /* o_wcss_apss_asic_intr */
+ <0xff 181>, /* wcnss watchdog */
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
<0xff 190>, /* lpass_irq_out_apcs(2) */
@@ -358,6 +363,7 @@
<0xff 205>, /* rpm_ipc(25) */
<0xff 206>, /* rpm_ipc(26) */
<0xff 207>, /* rpm_ipc(27) */
+ <0xff 211>, /* usb_dwc3_otg */
<0xff 240>; /* summary_irq_kpss */
qcom,gpio-parent = <&msmgpio>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 96e78ac..0240039 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -115,12 +115,12 @@
<49880000 1496000>;
qcom,dec-ddr-ab-ib = <0 0>,
<208000 303000>,
- <536000 303000>,
- <1012000 303000>,
- <2024000 606000>,
- <3240000 970000>,
- <4048000 1212000>,
- <4264000 1279000>;
+ <536000 1600000>,
+ <1012000 1600000>,
+ <2024000 1600000>,
+ <3240000 1600000>,
+ <4048000 1600000>,
+ <4264000 1600000>;
qcom,iommu-groups = <&venus_domain_ns &venus_domain_sec_bitstream
&venus_domain_sec_pixel &venus_domain_sec_non_pixel>;
qcom,iommu-group-buffer-types = <0xfff 0x91 0x42 0x120>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index fc0636e..f4553e0 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -878,7 +878,6 @@
interrupt-parent = <&intc>;
interrupts = <0 131 0>, <0 179 0>;
interrupt-names = "irq", "otg_irq";
- tx-fifo-resize;
};
};
@@ -1223,7 +1222,7 @@
qcom,iris-vddxo-supply = <&pm8941_l6>;
qcom,iris-vddrfa-supply = <&pm8941_l11>;
qcom,iris-vddpa-supply = <&pm8941_l19>;
- qcom,iris-vdddig-supply = <&pm8941_l3>;
+ qcom,iris-vdddig-supply = <&pm8941_s3>;
gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>, <&msmgpio 39 0>, <&msmgpio 40 0>;
qcom,has-48mhz-xo;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 7bbd528..ba6377c 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -45,6 +45,11 @@
qcom,direct-connect-irqs = <8>;
};
+ qcom,msm-imem@fe805000 {
+ compatible = "qcom,msm-imem";
+ reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
+ };
+
timer@f9020000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 81699b6..968daff 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -87,4 +87,13 @@
qcom,bus-width = <4>;
status = "disabled";
};
+
+ qcom,wdt@f9017000 {
+ compatible = "qcom,msm-watchdog";
+ reg = <0xf9017000 0x1000>;
+ interrupts = <0 3 0>, <0 4 0>;
+ qcom,bark-time = <11000>;
+ qcom,pet-time = <10000>;
+ qcom,ipi-ping;
+ };
};
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index e801467..9d104fd 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -283,6 +283,7 @@
CONFIG_MSMB_CAMERA=y
CONFIG_OV9724=y
CONFIG_SP1628=y
+CONFIG_GC0339=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -378,3 +379,4 @@
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 1df43fa..0587e50 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -280,6 +280,7 @@
CONFIG_MSM_CSI22_HEADER=y
CONFIG_OV9724=y
CONFIG_SP1628=y
+CONFIG_GC0339=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_MSM_WFD=y
@@ -420,3 +421,4 @@
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 85fa764..8bf7ec9 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2372,6 +2372,15 @@
RBCPR (Rapid Bridge Core Power Reduction) information . The drivers
outputs the message via a debugfs node.
+config MSM_RPM_RBCPR_STATS_V2_LOG
+ tristate "MSM Resource Power Manager RPBCPR Stat Driver"
+ depends on DEBUG_FS
+ help
+ This option enables v2 of the rpmrbcpr_stats driver which reads RPM
+ memory for statistics pertaining to RPM's RBCPR(Rapid Bridge Core
+ Power Reduction) driver. The drivers outputs the message via a
+ debugfs node.
+
config MSM_DIRECT_SCLK_ACCESS
bool "Direct access to the SCLK timer"
default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c07dc1..e9a236e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -333,6 +333,7 @@
obj-$(CONFIG_MSM_MPM) += mpm.o
obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
obj-$(CONFIG_MSM_RPM_RBCPR_STATS_LOG) += rpm_rbcpr_stats.o
+obj-$(CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG) += rpm_rbcpr_stats_v2.o
obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
obj-$(CONFIG_MSM_TZ_LOG) += tz_log.o
obj-$(CONFIG_MSM_XO) += msm_xo.o
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 475e8a1..c572291 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -113,6 +113,7 @@
* @region_end: address where relocatable region ends or highest address for
* non-relocatable images
* @region: region allocated for relocatable images
+ * @unvoted_flag: flag to keep track if we have unvoted or not.
*
* This struct contains data for a pil_desc that should not be exposed outside
* of this file. This structure points to the descriptor and the descriptor
@@ -132,6 +133,7 @@
struct ion_handle *region;
struct pil_image_info __iomem *info;
int id;
+ int unvoted_flag;
};
/**
@@ -184,15 +186,21 @@
}
EXPORT_SYMBOL(pil_get_entry_addr);
-static void pil_proxy_work(struct work_struct *work)
+static void __pil_proxy_unvote(struct pil_priv *priv)
{
- struct delayed_work *delayed = to_delayed_work(work);
- struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
struct pil_desc *desc = priv->desc;
desc->ops->proxy_unvote(desc);
wake_unlock(&priv->wlock);
module_put(desc->owner);
+
+}
+
+static void pil_proxy_unvote_work(struct work_struct *work)
+{
+ struct delayed_work *delayed = to_delayed_work(work);
+ struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
+ __pil_proxy_unvote(priv);
}
static int pil_proxy_vote(struct pil_desc *desc)
@@ -206,6 +214,10 @@
if (ret)
wake_unlock(&priv->wlock);
}
+
+ if (desc->proxy_unvote_irq)
+ enable_irq(desc->proxy_unvote_irq);
+
return ret;
}
@@ -237,8 +249,13 @@
static irqreturn_t proxy_unvote_intr_handler(int irq, void *dev_id)
{
struct pil_desc *desc = dev_id;
+ struct pil_priv *priv = desc->priv;
- schedule_delayed_work(&desc->priv->proxy, 0);
+ if (!desc->priv->unvoted_flag) {
+ desc->priv->unvoted_flag = 1;
+ __pil_proxy_unvote(priv);
+ }
+
return IRQ_HANDLED;
}
@@ -651,6 +668,7 @@
goto release_fw;
}
+ desc->priv->unvoted_flag = 0;
ret = pil_proxy_vote(desc);
if (ret) {
pil_err(desc, "Failed to proxy vote\n");
@@ -687,10 +705,19 @@
void pil_shutdown(struct pil_desc *desc)
{
struct pil_priv *priv = desc->priv;
+
if (desc->ops->shutdown)
desc->ops->shutdown(desc);
- if (proxy_timeout_ms == 0 && desc->ops->proxy_unvote)
- desc->ops->proxy_unvote(desc);
+
+ if (desc->proxy_unvote_irq) {
+ disable_irq(desc->proxy_unvote_irq);
+ if (!desc->priv->unvoted_flag)
+ pil_proxy_unvote(desc, 1);
+ return;
+ }
+
+ if (!proxy_timeout_ms)
+ pil_proxy_unvote(desc, 1);
else
flush_delayed_work(&priv->proxy);
}
@@ -741,7 +768,8 @@
__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
if (desc->proxy_unvote_irq > 0) {
- ret = request_irq(desc->proxy_unvote_irq,
+ ret = request_threaded_irq(desc->proxy_unvote_irq,
+ NULL,
proxy_unvote_intr_handler,
IRQF_TRIGGER_RISING|IRQF_SHARED,
desc->name, desc);
@@ -751,11 +779,12 @@
ret);
goto err;
}
+ disable_irq(desc->proxy_unvote_irq);
}
snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
- INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
+ INIT_DELAYED_WORK(&priv->proxy, pil_proxy_unvote_work);
INIT_LIST_HEAD(&priv->segs);
return 0;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 8cf6011..b83202b 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -628,15 +628,8 @@
if (ret)
return ret;
ret = pil_boot(&drv->desc);
- if (ret) {
+ if (ret)
pil_shutdown(&drv->q6->desc);
- /*
- * We know now that the unvote interrupt is not coming.
- * Remove the proxy votes immediately.
- */
- if (drv->q6->desc.proxy_unvote_irq)
- pil_q6v5_mss_remove_proxy_votes(&drv->q6->desc);
- }
return ret;
}
diff --git a/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
new file mode 100644
index 0000000..8f0ccd4
--- /dev/null
+++ b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
@@ -0,0 +1,430 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/sort.h>
+#include <asm/uaccess.h>
+#include <mach/msm_iomap.h>
+
+#define RBCPR_BUF_LEN 8000
+#define RBCPR_STATS_MAX_SIZE SZ_2K
+#define RBCPR_MAX_RAILS 4
+#define RBCPR_NUM_RECMNDS 3
+#define RBCPR_NUM_CORNERS 3
+
+#define FIELD(a) ((strnstr(#a, "->", 80) + 2))
+#define PRINT(buf, pos, format, ...) \
+ ((pos < RBCPR_BUF_LEN) ? snprintf((buf + pos), (RBCPR_BUF_LEN - pos),\
+ format, ## __VA_ARGS__) : 0)
+
+enum {
+ CORNER_OFF,
+ CORNER_SVS,
+ CORNER_NOMINAL,
+ CORNER_TURBO,
+ CORNER_MAX,
+};
+
+struct rbcpr_recmnd_data_type {
+ uint32_t microvolts;
+ uint64_t timestamp;
+};
+
+struct rbcpr_corners_data_type {
+ uint32_t efuse_adjustment;
+ uint32_t programmed_voltage;
+ uint32_t isr_count;
+ uint32_t min_count;
+ uint32_t max_count;
+ struct rbcpr_recmnd_data_type rbcpr_recmnd[RBCPR_NUM_RECMNDS];
+};
+
+struct rbcpr_rail_stats_type {
+ uint32_t num_corners;
+ uint32_t num_latest_recommends;
+ struct rbcpr_corners_data_type rbcpr_corners[RBCPR_NUM_CORNERS];
+ uint32_t current_corner;
+ uint32_t railway_voltage;
+ uint32_t off_corner;
+ uint32_t margin;
+};
+
+struct rbcpr_stats_type {
+ uint32_t num_rails;
+ uint32_t status;
+ struct rbcpr_rail_stats_type *rbcpr_rail;
+};
+
+struct rbcpr_data_type {
+ void __iomem *start;
+ uint32_t len;
+ char buf[RBCPR_BUF_LEN];
+};
+
+static char *rbcpr_rail_labels[] = {
+ [0] = "VDD-CX",
+ [1] = "VDD-GFX",
+};
+
+static char *rbcpr_corner_string[] = {
+ [CORNER_OFF] = "CORNERS_OFF",
+ [CORNER_SVS] = "SVS",
+ [CORNER_NOMINAL] = "NOMINAL",
+ [CORNER_TURBO] = "TURBO",
+};
+#define CORNER_STRING(a) \
+ ((a >= CORNER_MAX) ? "INVALID Corner" : rbcpr_corner_string[a])
+
+static struct rbcpr_data_type *rbcpr_data;
+static struct rbcpr_stats_type *rbcpr_stats;
+
+static void msm_rpmrbcpr_read_rpm_data(void)
+{
+ uint32_t start_offset;
+ uint32_t stats_size;
+
+ start_offset = offsetof(struct rbcpr_stats_type, rbcpr_rail);
+ stats_size =
+ rbcpr_stats->num_rails * sizeof(struct rbcpr_rail_stats_type);
+
+ if (stats_size > RBCPR_STATS_MAX_SIZE) {
+ pr_err("%s: Max copy size exceeded. stats size %d max %d",
+ __func__, stats_size, RBCPR_STATS_MAX_SIZE);
+ return;
+ }
+
+ memcpy_fromio(rbcpr_stats->rbcpr_rail,
+ (rbcpr_data->start + start_offset), stats_size);
+}
+
+static uint32_t msm_rpmrbcpr_print_data(void)
+{
+ uint32_t pos = 0;
+ uint32_t i, j, k;
+ struct rbcpr_rail_stats_type *rail;
+ struct rbcpr_corners_data_type *corner;
+ struct rbcpr_recmnd_data_type *rbcpr_recmnd;
+ char *buf = rbcpr_data->buf;
+
+ pos += PRINT(buf, pos, ":RBCPR STATS\n");
+ pos += PRINT(buf, pos, "(%s: %d)", FIELD(rbcpr_stats->num_rails),
+ rbcpr_stats->num_rails);
+ pos += PRINT(buf, pos, "(%s: %d)\n", FIELD(rbcpr_stats->status),
+ rbcpr_stats->status);
+
+
+ for (i = 0; i < rbcpr_stats->num_rails; i++) {
+ rail = &rbcpr_stats->rbcpr_rail[i];
+ pos += PRINT(buf, pos, ":%s Rail Data\n", rbcpr_rail_labels[i]);
+ pos += PRINT(buf, pos, "(%s: %s)",
+ FIELD(rail->current_corner),
+ CORNER_STRING(rail->current_corner));
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(rail->railway_voltage), rail->railway_voltage);
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(rail->off_corner), rail->off_corner);
+ pos += PRINT(buf, pos, "(%s: %d)\n",
+ FIELD(rail->margin), rail->margin);
+
+ for (j = 0; j < RBCPR_NUM_CORNERS; j++) {
+ pos += PRINT(buf, pos, "\t\tCorner Data:%s ",
+ CORNER_STRING(j + 1));
+ corner = &rail->rbcpr_corners[j];
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(corner->efuse_adjustment),
+ corner->efuse_adjustment);
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(corner->programmed_voltage),
+ corner->programmed_voltage);
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(corner->isr_count), corner->isr_count);
+ pos += PRINT(buf, pos, "(%s: %d)",
+ FIELD(corner->min_count), corner->min_count);
+ pos += PRINT(buf, pos, "(%s: %d)\n",
+ FIELD(corner->max_count), corner->max_count);
+
+
+ for (k = 0; k < RBCPR_NUM_RECMNDS; k++) {
+ rbcpr_recmnd = &corner->rbcpr_recmnd[k];
+ pos += PRINT(buf, pos,
+ "\t\t\t\tVoltage History[%d] ", k);
+ pos += PRINT(buf, pos, " (%s: %d) ",
+ FIELD(rbcpr_recmd->microvolts),
+ rbcpr_recmnd->microvolts);
+ pos += PRINT(buf, pos, " (%s: %lld)\n",
+ FIELD(rbcpr_recmd->timestamp),
+ rbcpr_recmnd->timestamp);
+ }
+ }
+ }
+
+ return pos;
+}
+
+
+static int msm_rpmrbcpr_file_read(struct file *file, char __user *bufu,
+ size_t count, loff_t *ppos)
+{
+ struct rbcpr_data_type *pdata = file->private_data;
+ int ret = 0;
+ int status_counter;
+ static DEFINE_MUTEX(rbcpr_lock);
+
+ mutex_lock(&rbcpr_lock);
+ if (!pdata) {
+ pr_err("%s pdata is null", __func__);
+ ret = -EINVAL;
+ goto exit_rpmrbcpr_file_read;
+ }
+
+ if (!bufu || count < 0) {
+ pr_err("%s count %d ", __func__, count);
+ ret = -EINVAL;
+ goto exit_rpmrbcpr_file_read;
+ }
+
+ if (*ppos > pdata->len || !*ppos) {
+ /* Read RPM stats */
+ status_counter = readl_relaxed(pdata->start +
+ offsetof(struct rbcpr_stats_type, status));
+ if (status_counter != rbcpr_stats->status) {
+ msm_rpmrbcpr_read_rpm_data();
+ rbcpr_stats->status = status_counter;
+ }
+ pdata->len = msm_rpmrbcpr_print_data();
+ *ppos = 0;
+ }
+
+ /* copy to user data*/
+ ret = simple_read_from_buffer(bufu, count, ppos, pdata->buf,
+ pdata->len);
+exit_rpmrbcpr_file_read:
+ mutex_unlock(&rbcpr_lock);
+ return ret;
+}
+
+static int msm_rpmrbcpr_file_open(struct inode *inode, struct file *file)
+{
+ file->private_data = rbcpr_data;
+
+ if (!rbcpr_data->start)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int msm_rpmrbcpr_file_close(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static const struct file_operations msm_rpmrbcpr_fops = {
+ .owner = THIS_MODULE,
+ .open = msm_rpmrbcpr_file_open,
+ .read = msm_rpmrbcpr_file_read,
+ .release = msm_rpmrbcpr_file_close,
+ .llseek = no_llseek,
+};
+
+static int msm_rpmrbcpr_memalloc(struct platform_device *pdev)
+{
+ void *addr = NULL;
+ int ret = 0;
+ uint32_t num_latest_recommends = 0;
+ uint32_t num_corners = 0;
+
+ rbcpr_stats->num_rails = readl_relaxed(rbcpr_data->start);
+
+ if (rbcpr_stats->num_rails > RBCPR_MAX_RAILS) {
+ pr_err("%s: Invalid number of RPM RBCPR rails %d",
+ __func__, rbcpr_stats->num_rails);
+ rbcpr_stats->num_rails = 0;
+ ret = -EFAULT;
+ goto rbcpr_memalloc_fail;
+ }
+
+ rbcpr_stats->rbcpr_rail =
+ devm_kzalloc(&pdev->dev,
+ sizeof(struct rbcpr_rail_stats_type) *
+ rbcpr_stats->num_rails, GFP_KERNEL);
+
+ if (!rbcpr_stats->rbcpr_rail) {
+ ret = -ENOMEM;
+ goto rbcpr_memalloc_fail;
+ }
+
+ addr = rbcpr_data->start + offsetof(struct rbcpr_stats_type,
+ rbcpr_rail);
+
+ /* Each rail has the same number of corners and number of latest
+ recommended values. Read these from the first rail and check them
+ to make sure the values are valid. (RPM doesn't 0 initialize this
+ memory region, so its possible we end up with bogus values if the
+ rbcpr driver is not initialized.).
+ */
+ num_corners = readl_relaxed(addr);
+ num_latest_recommends = readl_relaxed(addr +
+ offsetof(struct rbcpr_rail_stats_type,
+ num_latest_recommends));
+
+ if ((num_latest_recommends != RBCPR_NUM_RECMNDS)
+ || (num_corners != RBCPR_NUM_CORNERS)) {
+ pr_err("%s: Invalid num corners %d, num recmnds %d",
+ __func__, num_corners, num_latest_recommends);
+ ret = -EFAULT;
+ goto rbcpr_memalloc_fail;
+ }
+
+rbcpr_memalloc_fail:
+ return ret;
+}
+
+static int __devinit msm_rpmrbcpr_probe(struct platform_device *pdev)
+{
+ struct dentry *dent;
+ int ret = 0;
+ struct resource *res = NULL;
+ void __iomem *start_ptr = NULL;
+ uint32_t rbcpr_start_addr = 0;
+ char *key = NULL;
+ uint32_t start_addr;
+
+ rbcpr_data = devm_kzalloc(&pdev->dev,
+ sizeof(struct rbcpr_data_type), GFP_KERNEL);
+
+ if (!rbcpr_data)
+ return -ENOMEM;
+
+ rbcpr_stats = devm_kzalloc(&pdev->dev,
+ sizeof(struct rbcpr_stats_type), GFP_KERNEL);
+
+ if (!rbcpr_stats) {
+ pr_err("%s: Failed to allocate memory for RBCPR stats",
+ __func__);
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ pr_err("%s: Failed to get IO resource from platform device",
+ __func__);
+ ret = -ENXIO;
+ goto rbcpr_probe_fail;
+ }
+
+ key = "qcom,start-offset";
+ ret = of_property_read_u32(pdev->dev.of_node, key, &start_addr);
+
+ if (ret) {
+ pr_err("%s: Failed to get start offset", __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ start_addr += res->start;
+ start_ptr = ioremap_nocache(start_addr, 4);
+
+ if (!start_ptr) {
+ pr_err("%s: Failed to remap RBCPR start pointer",
+ __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ rbcpr_start_addr = res->start + readl_relaxed(start_ptr);
+
+ if ((rbcpr_start_addr > (res->end - RBCPR_STATS_MAX_SIZE)) ||
+ (rbcpr_start_addr < start_addr)) {
+ pr_err("%s: Invalid start address for rbcpr stats 0x%x",
+ __func__, rbcpr_start_addr);
+ goto rbcpr_probe_fail;
+ }
+
+ rbcpr_data->start = devm_ioremap_nocache(&pdev->dev, rbcpr_start_addr,
+ RBCPR_STATS_MAX_SIZE);
+
+ if (!rbcpr_data->start) {
+ pr_err("%s: Failed to remap RBCPR start address",
+ __func__);
+ goto rbcpr_probe_fail;
+ }
+
+ ret = msm_rpmrbcpr_memalloc(pdev);
+
+ if (ret)
+ goto rbcpr_probe_fail;
+
+ dent = debugfs_create_file("rpm_rbcpr", S_IRUGO, NULL,
+ pdev->dev.platform_data, &msm_rpmrbcpr_fops);
+
+ if (!dent) {
+ pr_err("%s: error debugfs_create_file failed\n", __func__);
+ ret = -ENOMEM;
+ goto rbcpr_probe_fail;
+ }
+
+ platform_set_drvdata(pdev, dent);
+rbcpr_probe_fail:
+ iounmap(start_ptr);
+ return ret;
+}
+
+static int __devexit msm_rpmrbcpr_remove(struct platform_device *pdev)
+{
+ struct dentry *dent;
+
+ dent = platform_get_drvdata(pdev);
+ debugfs_remove(dent);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static struct of_device_id rpmrbcpr_stats_table[] = {
+ {.compatible = "qcom,rpmrbcpr-stats"},
+ {},
+};
+
+static struct platform_driver msm_rpmrbcpr_driver = {
+ .probe = msm_rpmrbcpr_probe,
+ .remove = __devexit_p(msm_rpmrbcpr_remove),
+ .driver = {
+ .name = "msm_rpmrbcpr_stats",
+ .owner = THIS_MODULE,
+ .of_match_table = rpmrbcpr_stats_table,
+ },
+};
+
+static int __init msm_rpmrbcpr_init(void)
+{
+ return platform_driver_register(&msm_rpmrbcpr_driver);
+}
+
+static void __exit msm_rpmrbcpr_exit(void)
+{
+ platform_driver_unregister(&msm_rpmrbcpr_driver);
+}
+
+module_init(msm_rpmrbcpr_init);
+module_exit(msm_rpmrbcpr_exit);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index e98fff2..83d94f1 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -87,7 +87,7 @@
static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access,
struct smq_phy_page *pages, int nr_elems)
{
- struct vm_area_struct *vma;
+ struct vm_area_struct *vma, *vmaend;
uint32_t start = buf_page_start(addr);
uint32_t end = buf_page_start((void *)((uint32_t)addr + sz - 1));
uint32_t len = nr_pages << PAGE_SHIFT;
@@ -101,14 +101,14 @@
VERIFY(err, 0 != (vma = find_vma(current->mm, start)));
if (err)
goto bail;
- VERIFY(err, ((uint32_t)addr + sz) <= vma->vm_end);
+ VERIFY(err, 0 != (vmaend = find_vma(current->mm, end)));
if (err)
goto bail;
n = 0;
VERIFY(err, 0 == follow_pfn(vma, start, &pfn));
if (err)
goto bail;
- VERIFY(err, 0 == follow_pfn(vma, end, &pfnend));
+ VERIFY(err, 0 == follow_pfn(vmaend, end, &pfnend));
if (err)
goto bail;
VERIFY(err, (pfn + nr_pages - 1) == pfnend);
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 39b9a46..7fc9a9c 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -824,7 +824,14 @@
struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
u32 tmp[DES_EXPKEY_WORDS];
- int ret = des_ekey(tmp, key);
+ int ret;
+
+ if (!key) {
+ pr_err("%s Inavlid key pointer\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = des_ekey(tmp, key);
if ((ctx->flags & QCRYPTO_CTX_USE_HW_KEY) == QCRYPTO_CTX_USE_HW_KEY) {
pr_err("%s HW KEY usage not supported for DES algorithm\n",
@@ -843,14 +850,9 @@
}
ctx->enc_key_len = len;
- if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY)) {
- if (key != NULL) {
- memcpy(ctx->enc_key, key, len);
- } else {
- pr_err("%s Inavlid key pointer\n", __func__);
- return -EINVAL;
- }
- }
+ if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY))
+ memcpy(ctx->enc_key, key, len);
+
return 0;
};
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 29855f7..a757a22 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2735,6 +2735,9 @@
{
unsigned int in, out;
+ if (countable > 1)
+ return;
+
adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
if (countable == 0)
@@ -2790,6 +2793,9 @@
{
unsigned int in, out, bit;
+ if (countable > 2)
+ return;
+
adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
if (countable == 0)
bit = VBIF_PERF_PWR_CNT_0;
@@ -2823,12 +2829,6 @@
unsigned int val = 0;
struct a3xx_perfcounter_register *reg;
- if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
- return;
-
- if (counter >= a3xx_perfcounter_reglist[group].count)
- return;
-
/* Special cases */
if (group == KGSL_PERFCOUNTER_GROUP_PWR)
return a3xx_perfcounter_enable_pwr(device, countable);
@@ -2837,6 +2837,12 @@
else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
return a3xx_perfcounter_enable_vbif_pwr(device, countable);
+ if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
+ return;
+
+ if (counter >= a3xx_perfcounter_reglist[group].count)
+ return;
+
reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
/* Select the desired perfcounter */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index becb4ef..5fda9d7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -59,6 +59,8 @@
struct sg_table *table;
};
+static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
+
/**
* kgsl_hang_check() - Check for GPU hang
* data: KGSL device structure
@@ -255,6 +257,9 @@
struct kgsl_mem_entry,
refcount);
+ /* Detach from process list */
+ kgsl_mem_entry_detach_process(entry);
+
if (entry->memtype != KGSL_MEM_ENTRY_KERNEL)
kgsl_driver.stats.mapped -= entry->memdesc.size;
@@ -286,23 +291,46 @@
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
/**
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree
+ * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
+ * assign it with a gpu address space before insertion
* @process: the process that owns the memory
* @entry: the memory entry
*
- * Insert a kgsl_mem_entry in to the rb_tree for searching by GPU address.
- * Not all mem_entries will have gpu addresses when first created, so this
- * function may be called after creation when the GPU address is finally
- * assigned.
+ * @returns - 0 on succcess else error code
+ *
+ * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
+ * The assignment of gpu address and insertion into list needs to
+ * happen with the memory lock held to avoid race conditions between
+ * gpu address being selected and some other thread looking through the
+ * rb list in search of memory based on gpuaddr
+ * This function should be called with processes memory spinlock held
*/
-static void
+static int
kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
struct kgsl_mem_entry *entry)
{
+ int ret = 0;
struct rb_node **node;
struct rb_node *parent = NULL;
- spin_lock(&process->mem_lock);
+ assert_spin_locked(&process->mem_lock);
+ /*
+ * If cpu=gpu map is used then caller needs to set the
+ * gpu address
+ */
+ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+ if (!entry->memdesc.gpuaddr)
+ goto done;
+ } else if (entry->memdesc.gpuaddr) {
+ WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+ ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc);
+ if (ret)
+ goto done;
+ }
node = &process->mem_rb.rb_node;
@@ -321,7 +349,27 @@
rb_link_node(&entry->node, parent, node);
rb_insert_color(&entry->node, &process->mem_rb);
- spin_unlock(&process->mem_lock);
+done:
+ return ret;
+}
+
+/**
+ * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked
+ * process - Pointer to process private to which memory belongs
+ * entry - Memory entry to untrack
+ *
+ * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be
+ * called with processes spin lock held
+ */
+static void
+kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
+ struct kgsl_mem_entry *entry)
+{
+ assert_spin_locked(&process->mem_lock);
+ if (entry->memdesc.gpuaddr) {
+ kgsl_mmu_put_gpuaddr(process->pagetable, &entry->memdesc);
+ rb_erase(&entry->node, &entry->priv->mem_rb);
+ }
}
/**
@@ -360,8 +408,19 @@
}
entry->priv = process;
- if (entry->memdesc.gpuaddr != 0)
- kgsl_mem_entry_track_gpuaddr(process, entry);
+ spin_lock(&process->mem_lock);
+ ret = kgsl_mem_entry_track_gpuaddr(process, entry);
+ if (ret)
+ idr_remove(&process->mem_idr, entry->id);
+ spin_unlock(&process->mem_lock);
+ if (ret)
+ goto err;
+ /* map the memory after unlocking if gpuaddr has been assigned */
+ if (entry->memdesc.gpuaddr) {
+ ret = kgsl_mmu_map(process->pagetable, &entry->memdesc);
+ if (ret)
+ kgsl_mem_entry_detach_process(entry);
+ }
err:
return ret;
}
@@ -370,37 +429,23 @@
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
{
- bool had_gpuaddr = false;
-
if (entry == NULL)
return;
- /*
- * Unmap the entry first so that there isn't a period of
- * time where kgsl doesn't know about the address range
- * but it is still present in the pagetable. Unmapping will
- * clear the gpuaddr field, so remember if we had a mapping,
- * and an rbtree entry for later.
- */
- had_gpuaddr = entry->memdesc.gpuaddr != 0;
- kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+ /* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */
+ kgsl_mmu_unmap(entry->priv->pagetable, &entry->memdesc);
spin_lock(&entry->priv->mem_lock);
+ kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
if (entry->id != 0)
idr_remove(&entry->priv->mem_idr, entry->id);
entry->id = 0;
- if (had_gpuaddr)
- rb_erase(&entry->node, &entry->priv->mem_rb);
-
+ entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
spin_unlock(&entry->priv->mem_lock);
- entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
entry->priv = NULL;
-
-
- kgsl_mem_entry_put(entry);
}
/* Allocate a new context id */
@@ -759,7 +804,7 @@
rcu_read_unlock();
if (entry == NULL)
break;
- kgsl_mem_entry_detach_process(entry);
+ kgsl_mem_entry_put(entry);
/*
* Always start back at the beginning, to
* ensure all entries are removed,
@@ -1069,12 +1114,13 @@
kgsl_sharedmem_find_region(struct kgsl_process_private *private,
unsigned int gpuaddr, size_t size)
{
- struct rb_node *node = private->mem_rb.rb_node;
+ struct rb_node *node;
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
return NULL;
spin_lock(&private->mem_lock);
+ node = private->mem_rb.rb_node;
while (node != NULL) {
struct kgsl_mem_entry *entry;
@@ -1124,16 +1170,19 @@
* @size: length of the region.
*
* Checks that there are no existing allocations within an address
- * region.
+ * region. This function should be called with processes spin lock
+ * held.
*/
-int
+static int
kgsl_sharedmem_region_empty(struct kgsl_process_private *private,
unsigned int gpuaddr, size_t size)
{
int result = 1;
unsigned int gpuaddr_end = gpuaddr + size;
- struct rb_node *node = private->mem_rb.rb_node;
+ struct rb_node *node;
+
+ assert_spin_locked(&private->mem_lock);
if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
return 0;
@@ -1142,7 +1191,6 @@
if (gpuaddr_end < gpuaddr)
return 0;
- spin_lock(&private->mem_lock);
node = private->mem_rb.rb_node;
while (node != NULL) {
struct kgsl_mem_entry *entry;
@@ -1163,7 +1211,6 @@
break;
}
}
- spin_unlock(&private->mem_lock);
return result;
}
@@ -1191,6 +1238,30 @@
return entry;
}
+/**
+ * kgsl_mem_entry_set_pend() - Set the pending free flag of a memory entry
+ * @entry - The memory entry
+ *
+ * @returns - true if pending flag was 0 else false
+ *
+ * This function will set the pending free flag if it is previously unset. Used
+ * to prevent race condition between ioctls calling free/freememontimestamp
+ * on the same entry. Whichever thread set's the flag first will do the free.
+ */
+static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
+{
+ bool ret = false;
+ spin_lock(&entry->priv->mem_lock);
+ if (entry && entry->pending_free) {
+ ret = false;
+ } else if (entry) {
+ entry->pending_free = 1;
+ ret = true;
+ }
+ spin_unlock(&entry->priv->mem_lock);
+ return ret;
+}
+
/*call all ioctl sub functions with driver locked*/
static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
@@ -1469,7 +1540,7 @@
{
struct kgsl_mem_entry *entry = priv;
trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0);
- kgsl_mem_entry_detach_process(entry);
+ kgsl_mem_entry_put(entry);
}
static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv,
@@ -1488,11 +1559,12 @@
"invalid gpuaddr %08x\n", gpuaddr);
return -EINVAL;
}
- if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ if (!kgsl_mem_entry_set_pend(entry)) {
+ KGSL_DRV_WARN(dev_priv->device,
+ "Cannot set pending bit for gpuaddr %08x\n", gpuaddr);
kgsl_mem_entry_put(entry);
return -EBUSY;
}
- entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
trace_kgsl_mem_timestamp_queue(device, entry, context_id,
kgsl_readtimestamp(device, context,
@@ -1592,8 +1664,7 @@
param->gpuaddr);
return -EINVAL;
}
-
- if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ if (!kgsl_mem_entry_set_pend(entry)) {
kgsl_mem_entry_put(entry);
return -EBUSY;
}
@@ -1605,7 +1676,12 @@
entry->memdesc.size,
entry->memdesc.flags);
- kgsl_mem_entry_detach_process(entry);
+ /*
+ * First kgsl_mem_entry_put is for the reference that we took in
+ * this function when calling kgsl_sharedmem_find, second one is
+ * to free the memory since this is a free ioctl
+ */
+ kgsl_mem_entry_put(entry);
kgsl_mem_entry_put(entry);
return 0;
}
@@ -1624,7 +1700,7 @@
return -EINVAL;
}
- if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+ if (!kgsl_mem_entry_set_pend(entry)) {
kgsl_mem_entry_put(entry);
return -EBUSY;
}
@@ -1636,7 +1712,12 @@
entry->memdesc.size,
entry->memdesc.flags);
- kgsl_mem_entry_detach_process(entry);
+ /*
+ * First kgsl_mem_entry_put is for the reference that we took in
+ * this function when calling kgsl_sharedmem_find_id, second one is
+ * to free the memory since this is a free ioctl
+ */
+ kgsl_mem_entry_put(entry);
kgsl_mem_entry_put(entry);
return 0;
}
@@ -2111,18 +2192,15 @@
else if (entry->memdesc.size >= SZ_64K)
kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
- result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
- if (result)
- goto error_put_file_ptr;
-
- /* Adjust the returned value for a non 4k aligned offset */
- param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
/* echo back flags */
param->flags = entry->memdesc.flags;
result = kgsl_mem_entry_attach_process(entry, private);
if (result)
- goto error_unmap;
+ goto error_attach;
+
+ /* Adjust the returned value for a non 4k aligned offset */
+ param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped,
kgsl_driver.stats.mapped_max);
@@ -2133,9 +2211,7 @@
return result;
-error_unmap:
- kgsl_mmu_unmap(private->pagetable, &entry->memdesc);
-error_put_file_ptr:
+error_attach:
switch (entry->memtype) {
case KGSL_MEM_ENTRY_PMEM:
case KGSL_MEM_ENTRY_ASHMEM:
@@ -2395,10 +2471,6 @@
if (result)
return result;
- result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
- if (result)
- goto err;
-
result = kgsl_mem_entry_attach_process(entry, private);
if (result != 0)
goto err;
@@ -2432,12 +2504,6 @@
if (result != 0)
goto err;
- if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
- result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
- if (result)
- goto err;
- }
-
result = kgsl_mem_entry_attach_process(entry, private);
if (result != 0)
goto err;
@@ -3021,8 +3087,30 @@
ret = ALIGN(ret, (1 << align));
/*make sure there isn't a GPU only mapping at this address */
- if (kgsl_sharedmem_region_empty(private, ret, orig_len))
+ spin_lock(&private->mem_lock);
+ if (kgsl_sharedmem_region_empty(private, ret, orig_len)) {
+ int ret_val;
+ /*
+ * We found a free memory map, claim it here with
+ * memory lock held
+ */
+ entry->memdesc.gpuaddr = ret;
+ /* This should never fail */
+ ret_val = kgsl_mem_entry_track_gpuaddr(private, entry);
+ spin_unlock(&private->mem_lock);
+ BUG_ON(ret_val);
+ /* map cannot be called with lock held */
+ ret_val = kgsl_mmu_map(private->pagetable,
+ &entry->memdesc);
+ if (ret_val) {
+ spin_lock(&private->mem_lock);
+ kgsl_mem_entry_untrack_gpuaddr(private, entry);
+ spin_unlock(&private->mem_lock);
+ ret = ret_val;
+ }
break;
+ }
+ spin_unlock(&private->mem_lock);
trace_kgsl_mem_unmapped_area_collision(entry, addr, orig_len,
ret);
@@ -3079,17 +3167,6 @@
if (ret)
return ret;
- if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
- entry->memdesc.gpuaddr = vma->vm_start;
-
- ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
- if (ret) {
- kgsl_mem_entry_put(entry);
- return ret;
- }
- kgsl_mem_entry_track_gpuaddr(private, entry);
- }
-
vma->vm_flags |= entry->memdesc.ops->vmflags(&entry->memdesc);
vma->vm_private_data = entry;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 0983111..d05d391 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -156,8 +156,8 @@
#define KGSL_MEMDESC_GLOBAL BIT(1)
/* The memdesc is frozen during a snapshot */
#define KGSL_MEMDESC_FROZEN BIT(2)
-/* The memdesc is scheduled to be freed on a timestamp */
-#define KGSL_MEMDESC_FREE_PENDING BIT(3)
+/* The memdesc is mapped into a pagetable */
+#define KGSL_MEMDESC_MAPPED BIT(3)
/* shared memory allocation */
struct kgsl_memdesc {
@@ -195,6 +195,8 @@
/* back pointer to private structure under whose context this
* allocation is made */
struct kgsl_process_private *priv;
+ /* Initialized to 0, set to 1 when entry is marked for freeing */
+ int pending_free;
};
#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 007f89a..daeefd0 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -224,10 +224,23 @@
return result;
}
+ result = kgsl_mmu_get_gpuaddr(priv->pagetable,
+ &priv->memdesc);
+ if (result) {
+ DRM_ERROR(
+ "kgsl_mmu_get_gpuaddr failed. result = %d\n",
+ result);
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ return result;
+ }
result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (result) {
DRM_ERROR(
"kgsl_mmu_map failed. result = %d\n", result);
+ kgsl_mmu_put_gpuaddr(priv->pagetable,
+ &priv->memdesc);
ion_free(kgsl_drm_ion_client,
priv->ion_handle);
priv->ion_handle = NULL;
@@ -273,10 +286,17 @@
priv->memdesc.sglen++;
}
+ result = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+ if (result) {
+ DRM_ERROR(
+ "kgsl_mmu_get_gpuaddr failed. result = %d\n", result);
+ goto memerr;
+ }
result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (result) {
DRM_ERROR(
"kgsl_mmu_map failed. result = %d\n", result);
+ kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
goto memerr;
}
@@ -311,8 +331,10 @@
if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
return;
- if (priv->memdesc.gpuaddr)
+ if (priv->memdesc.gpuaddr) {
kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+ kgsl_mmu_put_gpuaddr(priv->memdesc.pagetable, &priv->memdesc);
+ }
/* ION will take care of freeing the sg table. */
priv->memdesc.sg = NULL;
@@ -645,9 +667,21 @@
priv->memdesc.sglen++;
}
+ ret = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+ if (ret) {
+ DRM_ERROR("kgsl_mmu_get_gpuaddr failed. ret = %d\n", ret);
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ kgsl_mmu_putpagetable(priv->pagetable);
+ drm_gem_object_release(obj);
+ kfree(priv);
+ return -ENOMEM;
+ }
ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (ret) {
DRM_ERROR("kgsl_mmu_map failed. ret = %d\n", ret);
+ kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
ion_free(kgsl_drm_ion_client,
priv->ion_handle);
priv->ion_handle = NULL;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 12a4b25..952019f 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -613,15 +613,20 @@
}
EXPORT_SYMBOL(kgsl_mh_start);
+/**
+ * kgsl_mmu_get_gpuaddr - Assign a memdesc with a gpuadddr from the gen pool
+ * @pagetable - pagetable whose pool is to be used
+ * @memdesc - memdesc to which gpuaddr is assigned
+ *
+ * returns - 0 on success else error code
+ */
int
-kgsl_mmu_map(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc)
+kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc)
{
- int ret;
struct gen_pool *pool = NULL;
int size;
int page_align = ilog2(PAGE_SIZE);
- unsigned int protflags = kgsl_memdesc_protflags(memdesc);
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
if (memdesc->sglen == 1) {
@@ -693,6 +698,28 @@
return -ENOMEM;
}
}
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_get_gpuaddr);
+
+int
+kgsl_mmu_map(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc)
+{
+ int ret = 0;
+ int size;
+ unsigned int protflags = kgsl_memdesc_protflags(memdesc);
+
+ if (!memdesc->gpuaddr)
+ return -EINVAL;
+ /* Only global mappings should be mapped multiple times */
+ if (!kgsl_memdesc_is_global(memdesc) &&
+ (KGSL_MEMDESC_MAPPED & memdesc->priv))
+ return -EINVAL;
+ /* Add space for the guard page when allocating the mmu VA. */
+ size = memdesc->size;
+ if (kgsl_memdesc_has_guard_page(memdesc))
+ size += PAGE_SIZE;
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
@@ -702,7 +729,7 @@
spin_lock(&pagetable->lock);
if (ret)
- goto err_free_gpuaddr;
+ goto done;
/* Keep track of the statistics for the sysfs files */
@@ -713,34 +740,76 @@
pagetable->stats.max_mapped);
spin_unlock(&pagetable->lock);
+ memdesc->priv |= KGSL_MEMDESC_MAPPED;
return 0;
-err_free_gpuaddr:
+done:
spin_unlock(&pagetable->lock);
- if (pool)
- gen_pool_free(pool, memdesc->gpuaddr, size);
- memdesc->gpuaddr = 0;
return ret;
}
EXPORT_SYMBOL(kgsl_mmu_map);
+/**
+ * kgsl_mmu_put_gpuaddr - Free a gpuaddress from memory pool
+ * @pagetable - pagetable whose pool memory is freed from
+ * @memdesc - memdesc whose gpuaddress is freed
+ *
+ * returns - 0 on success else error code
+ */
+int
+kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc)
+{
+ struct gen_pool *pool;
+ int size;
+
+ if (memdesc->size == 0 || memdesc->gpuaddr == 0)
+ return 0;
+
+ if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
+ goto done;
+
+ /* Add space for the guard page when freeing the mmu VA. */
+ size = memdesc->size;
+ if (kgsl_memdesc_has_guard_page(memdesc))
+ size += PAGE_SIZE;
+
+ pool = pagetable->pool;
+
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+ if (kgsl_memdesc_is_global(memdesc))
+ pool = pagetable->kgsl_pool;
+ else if (kgsl_memdesc_use_cpu_map(memdesc))
+ pool = NULL;
+ }
+ if (pool)
+ gen_pool_free(pool, memdesc->gpuaddr, size);
+ /*
+ * Don't clear the gpuaddr on global mappings because they
+ * may be in use by other pagetables
+ */
+done:
+ if (!kgsl_memdesc_is_global(memdesc))
+ memdesc->gpuaddr = 0;
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);
+
int
kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc)
{
- struct gen_pool *pool;
int size;
unsigned int start_addr = 0;
unsigned int end_addr = 0;
- if (memdesc->size == 0 || memdesc->gpuaddr == 0)
- return 0;
+ if (memdesc->size == 0 || memdesc->gpuaddr == 0 ||
+ !(KGSL_MEMDESC_MAPPED & memdesc->priv))
+ return -EINVAL;
- if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
- memdesc->gpuaddr = 0;
+ if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
return 0;
- }
/* Add space for the guard page when freeing the mmu VA. */
size = memdesc->size;
@@ -767,24 +836,8 @@
pagetable->stats.mapped -= size;
spin_unlock(&pagetable->lock);
-
- pool = pagetable->pool;
-
- if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
- if (kgsl_memdesc_is_global(memdesc))
- pool = pagetable->kgsl_pool;
- else if (kgsl_memdesc_use_cpu_map(memdesc))
- pool = NULL;
- }
- if (pool)
- gen_pool_free(pool, memdesc->gpuaddr, size);
-
- /*
- * Don't clear the gpuaddr on global mappings because they
- * may be in use by other pagetables
- */
if (!kgsl_memdesc_is_global(memdesc))
- memdesc->gpuaddr = 0;
+ memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
return 0;
}
EXPORT_SYMBOL(kgsl_mmu_unmap);
@@ -805,9 +858,12 @@
gpuaddr = memdesc->gpuaddr;
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
- result = kgsl_mmu_map(pagetable, memdesc);
+ result = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
if (result)
goto error;
+ result = kgsl_mmu_map(pagetable, memdesc);
+ if (result)
+ goto error_put_gpuaddr;
/*global mappings must have the same gpu address in all pagetables*/
if (gpuaddr && gpuaddr != memdesc->gpuaddr) {
@@ -818,6 +874,8 @@
return result;
error_unmap:
kgsl_mmu_unmap(pagetable, memdesc);
+error_put_gpuaddr:
+ kgsl_mmu_put_gpuaddr(pagetable, memdesc);
error:
return result;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 27cfc40..faba81e 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -222,10 +222,14 @@
int kgsl_mmu_close(struct kgsl_device *device);
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
+int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc);
int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
+int kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
void kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id,
uint32_t flags);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 01f0768..2939df6 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -781,8 +781,10 @@
if (memdesc == NULL || memdesc->size == 0)
return;
- if (memdesc->gpuaddr)
+ if (memdesc->gpuaddr) {
kgsl_mmu_unmap(memdesc->pagetable, memdesc);
+ kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc);
+ }
if (memdesc->ops && memdesc->ops->free)
memdesc->ops->free(memdesc);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 985b9b8..9f84690 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -260,6 +260,11 @@
ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
if (ret)
return ret;
+ ret = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
+ if (ret) {
+ kgsl_sharedmem_free(memdesc);
+ return ret;
+ }
ret = kgsl_mmu_map(pagetable, memdesc);
if (ret)
kgsl_sharedmem_free(memdesc);
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 116fb72..3a30970 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -155,6 +155,15 @@
1280 * 270. It does not support auto focus. It supports
few special effects like saturation.
+config SP1628
+ bool "Sensor SP1628 (YUV 720P)"
+ depends on MSMB_CAMERA
+ ---help---
+ SP1628 is SuperPix YUV sensor. It supports 720P preview
+ and snapshot. The preview and snapshot resolution shall be
+ 1280 * 270. It does not support auto focus. It supports
+ few special effects like mono.
+
config OV8825
bool "OmniVision OV8825 (BAYER 8MP)"
depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index c79e8e3..df72328 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -817,6 +817,7 @@
cpp_dev->cpp_open_cnt++;
if (cpp_dev->cpp_open_cnt == 1) {
cpp_init_hardware(cpp_dev);
+ iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
cpp_init_mem(cpp_dev);
cpp_dev->state = CPP_STATE_IDLE;
}
@@ -853,6 +854,7 @@
if (cpp_dev->cpp_open_cnt == 0) {
msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
cpp_deinit_mem(cpp_dev);
+ iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
cpp_release_hardware(cpp_dev);
cpp_dev->state = CPP_STATE_OFF;
}
@@ -1465,6 +1467,7 @@
return msm_register_domain(&cpp_fw_layout);
}
+
static int __devinit cpp_probe(struct platform_device *pdev)
{
struct cpp_device *cpp_dev;
@@ -1579,7 +1582,6 @@
cpp_dev->msm_sd.sd.entity.revision = cpp_dev->msm_sd.sd.devnode->num;
cpp_dev->state = CPP_STATE_BOOT;
cpp_init_hardware(cpp_dev);
- iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
msm_camera_io_w(0x0, cpp_dev->base +
MSM_CPP_MICRO_IRQGEN_MASK);
@@ -1597,7 +1599,6 @@
cpp_dev->cpp_open_cnt = 0;
cpp_dev->is_firmware_loaded = 0;
return rc;
-
ERROR3:
release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
ERROR2:
@@ -1627,7 +1628,6 @@
return 0;
}
- iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
msm_sd_unregister(&cpp_dev->msm_sd);
release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
release_mem_region(cpp_dev->vbif_mem->start,
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 300daca..c188105 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
@@ -30,6 +30,7 @@
static struct msm_actuator msm_vcm_actuator_table;
static struct msm_actuator msm_piezo_actuator_table;
+static struct i2c_driver msm_actuator_i2c_driver;
static struct msm_actuator *actuators[] = {
&msm_vcm_actuator_table,
&msm_piezo_actuator_table,
@@ -549,7 +550,11 @@
pr_err("failed\n");
return -EINVAL;
}
- *subdev_id = a_ctrl->pdev->id;
+ if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ *subdev_id = a_ctrl->pdev->id;
+ else
+ *subdev_id = a_ctrl->subdev_id;
+
CDBG("subdev_id %d\n", *subdev_id);
CDBG("Exit\n");
return 0;
@@ -684,6 +689,11 @@
.core = &msm_actuator_subdev_core_ops,
};
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+ {"qcom,actuator", (kernel_ulong_t)NULL},
+ { }
+};
+
static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -691,19 +701,46 @@
struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
CDBG("Enter\n");
+ if (client == NULL) {
+ pr_err("msm_actuator_i2c_probe: client is null\n");
+ rc = -EINVAL;
+ goto probe_failure;
+ }
+
+ act_ctrl_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+ GFP_KERNEL);
+ if (!act_ctrl_t) {
+ pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
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);
+
+ rc = of_property_read_u32(client->dev.of_node, "cell-index",
+ &act_ctrl_t->subdev_id);
+ CDBG("cell-index %d, rc %d\n", act_ctrl_t->subdev_id, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ act_ctrl_t->i2c_driver = &msm_actuator_i2c_driver;
act_ctrl_t->i2c_client.client = client;
+ act_ctrl_t->curr_step_pos = 0,
+ act_ctrl_t->curr_region_index = 0,
/* 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;
+
+ act_ctrl_t->cam_name = act_ctrl_t->subdev_id;
+ CDBG("act_ctrl_t->cam_name: %d", act_ctrl_t->cam_name);
/* 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);
@@ -720,7 +757,7 @@
act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
act_ctrl_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
msm_sd_register(&act_ctrl_t->msm_sd);
- CDBG("succeeded\n");
+ pr_info("msm_actuator_i2c_probe: succeeded\n");
CDBG("Exit\n");
probe_failure:
@@ -795,17 +832,21 @@
return rc;
}
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
- {"msm_actuator", (kernel_ulong_t)NULL},
- { }
+static const struct of_device_id msm_actuator_i2c_dt_match[] = {
+ {.compatible = "qcom,actuator"},
+ {}
};
+MODULE_DEVICE_TABLE(of, msm_actuator_i2c_dt_match);
+
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",
+ .name = "qcom,actuator",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_actuator_i2c_dt_match,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
index c616307..c4a4137 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -80,6 +80,7 @@
struct msm_camera_i2c_reg_tbl *i2c_reg_tbl;
uint16_t i2c_tbl_index;
enum cci_i2c_master_t cci_master;
+ uint32_t subdev_id;
};
#endif
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 0388484..eb8320f 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -262,6 +262,9 @@
chip = pwm->chip;
+ if (!pwm->banks)
+ pwm->banks = (PM_PWM_BANK_LO | PM_PWM_BANK_HI);
+
if (pwm->banks & PM_PWM_BANK_LO) {
if (enable)
reg = chip->lo_bank_mask | (1 << pwm->pwm_id);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3986cdd..e285bfa 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3747,6 +3747,7 @@
{
struct msmsdcc_host *host = mmc_priv(mmc);
unsigned long flags;
+ bool prev_pwrsave, curr_pwrsave;
int rc = 0;
switch (ios->signal_voltage) {
@@ -3779,7 +3780,9 @@
* low voltage is required
*/
spin_lock_irqsave(&host->lock, flags);
-
+ prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+ MCI_CLK_PWRSAVE);
+ curr_pwrsave = prev_pwrsave;
/*
* Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
* register until they become all zeros.
@@ -3792,9 +3795,12 @@
}
/* Stop SD CLK output. */
- writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
- MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_sync_reg_wr(host);
+ if (!prev_pwrsave) {
+ writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+ MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
+ curr_pwrsave = true;
+ }
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -3815,6 +3821,7 @@
writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
msmsdcc_sync_reg_wr(host);
+ curr_pwrsave = false;
spin_unlock_irqrestore(&host->lock, flags);
/*
@@ -3835,10 +3842,9 @@
}
out_unlock:
- /* Enable PWRSAVE */
- writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
- MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_sync_reg_wr(host);
+ /* Restore the correct PWRSAVE state */
+ if (prev_pwrsave ^ curr_pwrsave)
+ msmsdcc_set_pwrsave(mmc, prev_pwrsave);
spin_unlock_irqrestore(&host->lock, flags);
out:
return rc;
@@ -3877,17 +3883,24 @@
int rc = 0;
unsigned long flags;
u32 wait_cnt;
+ bool prev_pwrsave, curr_pwrsave;
spin_lock_irqsave(&host->lock, flags);
+ prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+ MCI_CLK_PWRSAVE);
+ curr_pwrsave = prev_pwrsave;
/*
* Make sure that clock is always enabled when DLL
* tuning is in progress. Keeping PWRSAVE ON may
* turn off the clock. So let's disable the PWRSAVE
* here and re-enable it once tuning is completed.
*/
- writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
- & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_sync_reg_wr(host);
+ if (prev_pwrsave) {
+ writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
+ & ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
+ curr_pwrsave = false;
+ }
/* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
@@ -3930,10 +3943,9 @@
}
out:
- /* re-enable PWRSAVE */
- writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
- MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
- msmsdcc_sync_reg_wr(host);
+ /* Restore the correct PWRSAVE state */
+ if (prev_pwrsave ^ curr_pwrsave)
+ msmsdcc_set_pwrsave(host->mmc, prev_pwrsave);
spin_unlock_irqrestore(&host->lock, flags);
return rc;
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index c02daa4..2251f2f 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -100,7 +100,7 @@
{"qcom,iris-vddpa", VREG_NULL_CONFIG, 2900000, 0,
3000000, 515000, NULL},
{"qcom,iris-vdddig", VREG_NULL_CONFIG, 1225000, 0,
- 1300000, 10000, NULL},
+ 1800000, 10000, NULL},
};
/* WCNSS regulators for Pronto hardware */
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index d378838..087cfa8 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -43,9 +43,14 @@
#define QPNP_PON_RESIN_S2_TIMER(base) (base + 0x45)
#define QPNP_PON_RESIN_S2_CNTL(base) (base + 0x46)
#define QPNP_PON_RESIN_S2_CNTL2(base) (base + 0x47)
+#define QPNP_PON_KPDPWR_RESIN_S1_TIMER(base) (base + 0x48)
+#define QPNP_PON_KPDPWR_RESIN_S2_TIMER(base) (base + 0x49)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL(base) (base + 0x4A)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL2(base) (base + 0x4B)
#define QPNP_PON_PS_HOLD_RST_CTL(base) (base + 0x5A)
#define QPNP_PON_PS_HOLD_RST_CTL2(base) (base + 0x5B)
#define QPNP_PON_TRIGGER_EN(base) (base + 0x80)
+#define QPNP_PON_S3_DBC_CTL(base) (base + 0x75)
#define QPNP_PON_WARM_RESET_TFT BIT(4)
@@ -65,6 +70,7 @@
#define QPNP_PON_RESIN_N_SET BIT(1)
#define QPNP_PON_CBLPWR_N_SET BIT(2)
#define QPNP_PON_RESIN_BARK_N_SET BIT(4)
+#define QPNP_PON_KPDPWR_RESIN_BARK_N_SET BIT(5)
#define QPNP_PON_RESET_EN BIT(7)
#define QPNP_PON_WARM_RESET BIT(0)
@@ -73,6 +79,8 @@
/* Ranges */
#define QPNP_PON_S1_TIMER_MAX 10256
#define QPNP_PON_S2_TIMER_MAX 2000
+#define QPNP_PON_S3_TIMER_SECS_MAX 128
+#define QPNP_PON_S3_DBC_DELAY_MASK 0x07
#define QPNP_PON_RESET_TYPE_MAX 0xF
#define PON_S1_COUNT_MAX 0xF
@@ -83,6 +91,7 @@
PON_KPDPWR,
PON_RESIN,
PON_CBLPWR,
+ PON_KPDPWR_RESIN,
};
struct qpnp_pon_config {
@@ -325,6 +334,9 @@
case PON_CBLPWR:
pon_rt_bit = QPNP_PON_CBLPWR_N_SET;
break;
+ case PON_KPDPWR_RESIN:
+ pon_rt_bit = QPNP_PON_KPDPWR_RESIN_BARK_N_SET;
+ break;
default:
return -EINVAL;
}
@@ -364,6 +376,11 @@
return IRQ_HANDLED;
}
+static irqreturn_t qpnp_kpdpwr_resin_bark_irq(int irq, void *_pon)
+{
+ return IRQ_HANDLED;
+}
+
static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
{
int rc;
@@ -477,6 +494,9 @@
case PON_CBLPWR:
pull_bit = QPNP_PON_CBLPWR_PULL_UP;
break;
+ case PON_KPDPWR_RESIN:
+ pull_bit = QPNP_PON_KPDPWR_PULL_UP | QPNP_PON_RESIN_PULL_UP;
+ break;
default:
return -EINVAL;
}
@@ -505,6 +525,10 @@
s1_timer_addr = QPNP_PON_RESIN_S1_TIMER(pon->base);
s2_timer_addr = QPNP_PON_RESIN_S2_TIMER(pon->base);
break;
+ case PON_KPDPWR_RESIN:
+ s1_timer_addr = QPNP_PON_KPDPWR_RESIN_S1_TIMER(pon->base);
+ s2_timer_addr = QPNP_PON_KPDPWR_RESIN_S2_TIMER(pon->base);
+ break;
default:
return -EINVAL;
}
@@ -624,6 +648,20 @@
return rc;
}
break;
+ case PON_KPDPWR_RESIN:
+ if (cfg->support_reset) {
+ rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+ qpnp_kpdpwr_resin_bark_irq,
+ IRQF_TRIGGER_RISING,
+ "qpnp_kpdpwr_resin_bark", pon);
+ if (rc < 0) {
+ dev_err(&pon->spmi->dev,
+ "Can't request %d IRQ\n",
+ cfg->bark_irq);
+ return rc;
+ }
+ }
+ break;
default:
return -EINVAL;
}
@@ -663,11 +701,11 @@
int rc = 0, i = 0;
struct device_node *pp = NULL;
struct qpnp_pon_config *cfg;
- u8 reg;
+ u8 pon_ver;
/* Check if it is rev B */
rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
- QPNP_PON_REVISION2(pon->base), ®, 1);
+ QPNP_PON_REVISION2(pon->base), &pon_ver, 1);
if (rc) {
dev_err(&pon->spmi->dev,
"Unable to read addr=%x, rc(%d)\n",
@@ -714,7 +752,7 @@
}
}
- if (reg == QPNP_PON_REV_B) {
+ if (pon_ver == QPNP_PON_REV_B) {
cfg->s2_cntl_addr =
QPNP_PON_KPDPWR_S2_CNTL(pon->base);
cfg->s2_cntl2_addr =
@@ -752,7 +790,7 @@
}
}
- if (reg == QPNP_PON_REV_B) {
+ if (pon_ver == QPNP_PON_REV_B) {
cfg->s2_cntl_addr =
QPNP_PON_RESIN_S2_CNTL(pon->base);
cfg->s2_cntl2_addr =
@@ -772,6 +810,36 @@
return rc;
}
break;
+ case PON_KPDPWR_RESIN:
+ rc = of_property_read_u32(pp, "qcom,support-reset",
+ &cfg->support_reset);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pon->spmi->dev,
+ "Unable to read 'support-reset'\n");
+ return rc;
+ }
+
+ if (cfg->support_reset) {
+ cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
+ NULL, "kpdpwr-resin-bark");
+ if (cfg->bark_irq < 0) {
+ dev_err(&pon->spmi->dev,
+ "Unable to get kpdpwr-resin-bark irq\n");
+ return cfg->bark_irq;
+ }
+ }
+
+ if (pon_ver == QPNP_PON_REV_B) {
+ cfg->s2_cntl_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+ cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL2(pon->base);
+ } else {
+ cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+ QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+ }
+
+ break;
default:
dev_err(&pon->spmi->dev, "PON RESET %d not supported",
cfg->pon_type);
@@ -819,13 +887,14 @@
"Incorrect reset type specified\n");
return -EINVAL;
}
+
}
/*
* Get the standard-key parameters. This might not be
* specified if there is no key mapping on the reset line.
*/
rc = of_property_read_u32(pp, "linux,code", &cfg->key_code);
- if (rc && rc == -EINVAL) {
+ if (rc && rc != -EINVAL) {
dev_err(&pon->spmi->dev,
"Unable to read key-code\n");
return rc;
@@ -896,7 +965,7 @@
struct qpnp_pon *pon;
struct resource *pon_resource;
struct device_node *itr = NULL;
- u32 delay = 0;
+ u32 delay = 0, s3_debounce = 0;
int rc, sys_reset;
pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
@@ -956,6 +1025,32 @@
}
}
+ /* program s3 debounce */
+ rc = of_property_read_u32(pon->spmi->dev.of_node,
+ "qcom,s3-debounce", &s3_debounce);
+ if (rc) {
+ if (rc != -EINVAL) {
+ dev_err(&pon->spmi->dev, "Unable to read s3 timer\n");
+ return rc;
+ }
+ } else {
+ if (s3_debounce > QPNP_PON_S3_TIMER_SECS_MAX) {
+ dev_info(&pon->spmi->dev,
+ "Exceeded S3 max value, set it to max\n");
+ s3_debounce = QPNP_PON_S3_TIMER_SECS_MAX;
+ }
+
+ /* 0 is a special value to indicate instant s3 reset */
+ if (s3_debounce != 0)
+ s3_debounce = ilog2(s3_debounce);
+ rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_DBC_CTL(pon->base),
+ QPNP_PON_S3_DBC_DELAY_MASK, s3_debounce);
+ if (rc) {
+ dev_err(&spmi->dev, "Unable to set S3 debounce\n");
+ return rc;
+ }
+ }
+
dev_set_drvdata(&spmi->dev, pon);
INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4d464c1..7f669d8 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -245,6 +245,48 @@
#define UARTDM_TO_MSM(uart_port) \
container_of((uart_port), struct msm_hs_port, uport)
+
+static int msm_hs_ioctl(struct uart_port *uport, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0, state = 1;
+ enum msm_hs_clk_states_e clk_state;
+ unsigned long flags;
+ struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+ switch (cmd) {
+ case MSM_ENABLE_UART_CLOCK: {
+ pr_debug("%s():ENABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+ msm_hs_request_clock_on(&msm_uport->uport);
+ break;
+ }
+ case MSM_DISABLE_UART_CLOCK: {
+ pr_debug("%s():DISABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+ msm_hs_request_clock_off(&msm_uport->uport);
+ break;
+ }
+ case MSM_GET_UART_CLOCK_STATUS: {
+ /* Return value 0 - UART CLOCK is OFF
+ * Return value 1 - UART CLOCK is ON */
+ pr_debug("%s():GET UART CLOCK STATUS: cmd=%d\n", __func__, cmd);
+ spin_lock_irqsave(&msm_uport->uport.lock, flags);
+ clk_state = msm_uport->clk_state;
+ spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
+ if (clk_state <= MSM_HS_CLK_OFF)
+ state = 0;
+ ret = state;
+ break;
+ }
+ default: {
+ pr_debug("%s():Unknown cmd specified: cmd=%d\n", __func__, cmd);
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ }
+
+ return ret;
+}
+
static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -3307,6 +3349,7 @@
.release_port = msm_hs_release_port,
.request_port = msm_hs_request_port,
.flush_buffer = msm_hs_flush_buffer,
+ .ioctl = msm_hs_ioctl,
};
module_init(msm_serial_hs_init);
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index cdd0450..cd24f23 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -32,6 +32,10 @@
#define ADM1_CRCI_GSBI6_RX_SEL 0x800
#define ADM1_CRCI_GSBI6_TX_SEL 0x400
+#define MSM_ENABLE_UART_CLOCK 13
+#define MSM_DISABLE_UART_CLOCK 14
+#define MSM_GET_UART_CLOCK_STATUS 15
+
enum msm_hsl_regs {
UARTDM_MR1,
UARTDM_MR2,
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6aeb26e..f31481f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -381,15 +381,29 @@
*/
static u32 dwc3_msm_ssusb_read_phycreg(void *base, u32 addr)
{
+ bool first_read = true;
+
iowrite32(addr, base + SS_CR_PROTOCOL_DATA_IN_REG);
iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_ADDR_REG);
while (ioread32(base + SS_CR_PROTOCOL_CAP_ADDR_REG))
cpu_relax();
+ /*
+ * Due to hardware bug, first read of SSPHY register might be
+ * incorrect. Hence as workaround, SW should perform SSPHY register
+ * read twice, but use only second read and ignore first read.
+ */
+retry:
iowrite32(0x1, base + SS_CR_PROTOCOL_READ_REG);
while (ioread32(base + SS_CR_PROTOCOL_READ_REG))
cpu_relax();
+ if (first_read) {
+ ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
+ first_read = false;
+ goto retry;
+ }
+
return ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1059a4d..63698de 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,6 +36,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -56,6 +57,11 @@
#include "debug.h"
#include "io.h"
+static bool tx_fifo_resize_enable;
+module_param(tx_fifo_resize_enable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(tx_fifo_resize_enable,
+ "Enable allocating Tx fifo for endpoints");
+
/**
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
* @dwc: pointer to our context structure
@@ -178,7 +184,7 @@
int mdwidth;
int num;
- if (!dwc->needs_fifo_resize)
+ if (!dwc->needs_fifo_resize && !tx_fifo_resize_enable)
return 0;
ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index ff2287e..55f5b80 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -662,7 +662,7 @@
{
struct adb_dev *dev = _adb_dev;
- printk(KERN_INFO "adb_bind_config\n");
+ pr_debug("adb_bind_config\n");
dev->cdev = c->cdev;
dev->function.name = "adb";
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index f095efb..6dcc3b4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -1121,7 +1121,7 @@
goto fail;
}
- pr_info("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
+ pr_debug("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
__func__, dev->port_num,
gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
dev->port.in->name, dev->port.out->name);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index edcafcc..c71d79c 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -639,6 +639,7 @@
gbam_epout_complete, GFP_ATOMIC);
if (ret) {
pr_err("%s: rx req allocation failed\n", __func__);
+ spin_unlock_irqrestore(&port->port_lock_ul, flags);
return;
}
@@ -655,6 +656,7 @@
if (ret) {
pr_err("%s: tx req allocation failed\n", __func__);
gbam_free_requests(ep, &d->rx_idle);
+ spin_unlock_irqrestore(&port->port_lock_dl, flags);
return;
}
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index c2e8943..0b89dd0 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb.h>
#include <linux/usb/msm_hsusb_hw.h>
#define MSM_USB_BASE (hcd->regs)
@@ -51,7 +52,13 @@
/* Use the AHB transactor */
writel_relaxed(0x08, USB_AHBMODE);
/* Disable streaming mode and select host mode */
- writel(0x13, USB_USBMODE);
+ writel_relaxed(0x13, USB_USBMODE);
+
+ if (ehci->transceiver->flags & ENABLE_SECONDARY_PHY) {
+ ehci_dbg(ehci, "using secondary hsphy\n");
+ writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+ USB_PHY_CTRL2);
+ }
ehci_port_power(ehci, 1);
return 0;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 111f26b..c168907 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1881,8 +1881,6 @@
{
int delta = 0;
- if (headroom < NET_SKB_PAD)
- headroom = NET_SKB_PAD;
if (headroom > skb_headroom(skb))
delta = headroom - skb_headroom(skb);
diff --git a/scripts/build-all.py b/scripts/build-all.py
index 4789af7..c585e4a 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -88,6 +88,7 @@
r'[fm]sm[0-9]*_defconfig',
r'apq*_defconfig',
r'qsd*_defconfig',
+ r'msmkrypton*_defconfig',
)
for p in arch_pats:
for n in glob.glob('arch/arm/configs/' + p):
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 807cdad..f3c6ef8 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -50,6 +50,11 @@
#define MSM8X10_WCD_I2S_MASTER_MODE_MASK 0x08
#define MSM8X10_DINO_CODEC_BASE_ADDR 0xFE043000
+#define MSM8x10_TLMM_CDC_PULL_CTL 0xFD512050
+#define HELICON_CORE_0_I2C_ADDR 0x0d
+#define HELICON_CORE_1_I2C_ADDR 0x77
+#define HELICON_CORE_2_I2C_ADDR 0x66
+#define HELICON_CORE_3_I2C_ADDR 0x55
#define MAX_MSM8X10_WCD_DEVICE 4
#define CODEC_DT_MAX_PROP_SIZE 40
@@ -2400,6 +2405,15 @@
}
EXPORT_SYMBOL_GPL(msm8x10_wcd_hs_detect);
+static int msm8x10_wcd_bringup(struct snd_soc_codec *codec)
+{
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
+ snd_soc_write(codec, MSM8X10_WCD_A_CHIP_CTL, 0x00);
+ usleep_range(5000, 5000);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+ return 0;
+}
+
static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
{
struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2422,6 +2436,7 @@
codec->control_data = dev_get_drvdata(codec->dev);
snd_soc_codec_set_drvdata(codec, msm8x10_wcd);
msm8x10_wcd->codec = codec;
+ msm8x10_wcd_bringup(codec);
msm8x10_wcd_codec_init_reg(codec);
msm8x10_wcd_update_reg_defaults(codec);
@@ -2557,13 +2572,27 @@
kfree(msm8x10->supplies);
}
-static int msm8x10_wcd_bringup(struct msm8x10_wcd *msm8x10)
+static int msm8x10_wcd_pads_config(void)
{
- msm8x10->read_dev = msm8x10_wcd_reg_read;
- msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
- msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CHIP_CTL, 0x00);
- usleep_range(5000, 5000);
- msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+ /* Set I2C pads as pull up and rest of pads as no pull */
+ iowrite32(0x03C00000, ioremap(MSM8x10_TLMM_CDC_PULL_CTL, 4));
+ usleep_range(100, 200);
+ return 0;
+}
+
+
+static int msm8x10_wcd_clk_init(void)
+{
+ /* Div-2 */
+ iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
+ iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
+ iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
+ iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
+ /* Digital codec clock enable */
+ iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+ /* Set the update bit to make the settings go through */
+ iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
+ usleep_range(100, 200);
return 0;
}
@@ -2573,11 +2602,8 @@
mutex_init(&msm8x10->xfer_lock);
mutex_init(&msm8x10->pm_lock);
msm8x10->wlock_holders = 0;
-
- iowrite32(0x03C00000, ioremap(0xFD512050, 4));
- usleep_range(5000, 5000);
-
- msm8x10_wcd_bringup(msm8x10);
+ msm8x10_wcd_pads_config();
+ msm8x10_wcd_clk_init();
return 0;
}
@@ -2589,15 +2615,44 @@
struct msm8x10_wcd_pdata *pdata;
static int device_id;
struct device *dev;
+ enum apr_subsys_state q6_state;
- dev_dbg(&client->dev, "%s:slave addr = 0x%x device_id = %d\n",
- __func__, client->addr, device_id);
+ dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+ __func__, __LINE__, client->addr, device_id);
- if (device_id > 0) {
- msm8x10_wcd_modules[device_id++].client = client;
+ switch (client->addr) {
+ case HELICON_CORE_0_I2C_ADDR:
+ msm8x10_wcd_modules[0].client = client;
+ break;
+ case HELICON_CORE_1_I2C_ADDR:
+ msm8x10_wcd_modules[1].client = client;
+ goto rtn;
+ case HELICON_CORE_2_I2C_ADDR:
+ msm8x10_wcd_modules[2].client = client;
+ goto rtn;
+ case HELICON_CORE_3_I2C_ADDR:
+ msm8x10_wcd_modules[3].client = client;
+ goto rtn;
+ default:
+ ret = -EINVAL;
goto rtn;
}
+ q6_state = apr_get_q6_state();
+ if ((q6_state == APR_SUBSYS_DOWN) &&
+ (client->addr == HELICON_CORE_0_I2C_ADDR)) {
+ dev_info(&client->dev, "defering %s, adsp_state %d\n", __func__,
+ q6_state);
+ return -EPROBE_DEFER;
+ } else
+ dev_info(&client->dev, "adsp is ready\n");
+
+ dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+ __func__, __LINE__, client->addr, device_id);
+
+ if (client->addr != HELICON_CORE_0_I2C_ADDR)
+ goto rtn;
+
dev = &client->dev;
if (client->dev.of_node) {
dev_dbg(&client->dev, "%s:Platform data from device tree\n",
@@ -2619,7 +2674,6 @@
}
msm8x10->dev = &client->dev;
- msm8x10_wcd_modules[device_id++].client = client;
msm8x10->read_dev = msm8x10_wcd_reg_read;
msm8x10->write_dev = msm8x10_wcd_reg_write;
ret = msm8x10_wcd_enable_supplies(msm8x10, pdata);
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index d250e0a..08a2725 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -23,6 +23,15 @@
#define MSM8X10_WCD_NUM_IRQ_REGS 3
#define MAX_REGULATOR 7
#define MSM8X10_WCD_REG_VAL(reg, val) {reg, 0, val}
+#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL 0xFE03B004
+#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR 0xFE02C000
+#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR 0xFE02C004
+#define MSM8X10_DINO_LPASS_DIGCODEC_M 0xFE02C008
+#define MSM8X10_DINO_LPASS_DIGCODEC_N 0xFE02C00C
+#define MSM8X10_DINO_LPASS_DIGCODEC_D 0xFE02C010
+#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR 0xFE02C014
+#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR 0xFE02C018
+
#define MSM8X10_WCD_IS_DINO_REG(reg) \
(((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
diff --git a/sound/soc/msm/msm-pcm-host-voice.c b/sound/soc/msm/msm-pcm-host-voice.c
index 36826cc..2eafc1d 100644
--- a/sound/soc/msm/msm-pcm-host-voice.c
+++ b/sound/soc/msm/msm-pcm-host-voice.c
@@ -941,7 +941,8 @@
struct hpcm_buf_node, list);
list_del(&buf_node->list);
spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
- ret = copy_from_user(&buf_node->frame, buf, count);
+ ret = copy_from_user(&buf_node->frame.voc_pkt,
+ buf, count);
buf_node->frame.len = count;
spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
list_add_tail(&buf_node->list, &dai_data->filled_queue);
@@ -986,7 +987,9 @@
struct hpcm_buf_node, list);
list_del(&buf_node->list);
spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
- ret = copy_to_user(buf, &buf_node->frame, count);
+ ret = copy_to_user(buf,
+ &buf_node->frame.voc_pkt,
+ count);
if (ret) {
pr_err("%s: Copy to user retuned %d\n",
__func__, ret);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 22cd61a..9782b2d 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -126,6 +126,7 @@
static struct clk *codec_clk;
static int clk_users;
static int vdd_spkr_gpio = -1;
+static int msm_proxy_rx_ch = 2;
static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
bool dapm)
@@ -235,6 +236,8 @@
static const char *const slim0_rx_ch_text[] = {"One", "Two"};
static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven", "Eight"};
static const struct soc_enum msm_enum[] = {
SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
@@ -349,6 +352,23 @@
return 0;
}
+static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+ msm_proxy_rx_ch);
+ ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
+ return 0;
+}
+
+static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
+ pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+ msm_proxy_rx_ch);
+ return 1;
+}
static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -364,15 +384,31 @@
return 0;
}
-static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
- struct snd_pcm_hw_params *params)
+static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
+ SNDRV_PCM_HW_PARAM_RATE);
- pr_debug("%s()\n", __func__);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
+
+ if (channels->max < 2)
+ channels->min = channels->max = 2;
+ channels->min = channels->max = msm_proxy_rx_ch;
rate->min = rate->max = 48000;
+ return 0;
+}
+static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ rate->min = rate->max = 48000;
return 0;
}
@@ -535,6 +571,7 @@
static const struct soc_enum msm_snd_enum[] = {
SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+ SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -546,6 +583,8 @@
msm8226_auxpcm_rate_get, msm8226_auxpcm_rate_put),
SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
msm_btsco_rate_get, msm_btsco_rate_put),
+ SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[2],
+ msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
};
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -1049,7 +1088,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
- .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1063,7 +1102,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
- .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
.ignore_suspend = 1,
},
/* HDMI Hostless */
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index ce6cfea..a076246 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -40,14 +40,6 @@
static int msm_proxy_rx_ch = 2;
static struct snd_soc_jack hs_jack;
-#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL 0xFE03B004
-#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR 0xFE02C000
-#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR 0xFE02C004
-#define MSM8X10_DINO_LPASS_DIGCODEC_M 0xFE02C008
-#define MSM8X10_DINO_LPASS_DIGCODEC_N 0xFE02C00C
-#define MSM8X10_DINO_LPASS_DIGCODEC_D 0xFE02C010
-#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR 0xFE02C014
-#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR 0xFE02C018
/*
* There is limitation for the clock root selection from
@@ -89,7 +81,8 @@
0,
};
-static atomic_t aud_init_rsc_ref;
+static atomic_t mclk_rsc_ref;
+static struct mutex cdc_mclk_mutex;
static int msm8x10_mclk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@@ -103,69 +96,9 @@
};
-/*
- * This function will be replaced by
- * afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
- * in the future after LPASS API fix
- */
-static int msm_enable_lpass_mclk(void)
-{
- /* Select the codec root */
- iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
- ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
- 4));
- /* Div-2 */
- iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
- /* Digital codec clock enable */
- iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
- /* AHB clock enable */
- iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
- /* Set the update bit to make the settings go through */
- iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
-
- return 0;
-}
-
-static int msm_enable_mclk_root(u16 port_id, struct afe_digital_clk_cfg *cfg)
-{
- int ret = 0;
- /*
- * msm_enable_lpass_mclk() function call will be replaced by
- * ret = afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
- * in the future. Currentlt there is a bug in LPASS plan which
- * doesn't consider the digital codec clock. It will be fixed soon
- * in new Q6 image
- */
- msm_enable_lpass_mclk();
- pr_debug("%s(): return = %d\n", __func__, ret);
- return ret;
-}
-
static int msm_config_mclk(u16 port_id, struct afe_digital_clk_cfg *cfg)
{
- /* Select the codec root */
- iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
- ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
- 4));
- /* Div-2 */
- iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
- /* Digital codec clock enable */
- if (cfg->clk_val == 0) {
- iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
- pr_debug("%s(line %d)\n", __func__, __LINE__);
- } else {
- iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
- pr_debug("%s(line %d)\n", __func__, __LINE__);
- }
iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
- /* AHB clock enable */
- iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
/* Set the update bit to make the settings go through */
iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
@@ -173,42 +106,6 @@
}
-static int msm_config_mi2s_clk(int enable)
-{
- int ret = 0;
- pr_debug("%s(line %d):enable = %x\n", __func__, __LINE__, enable);
- if (enable) {
- digital_cdc_clk.clk_val = 9600000;
- mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
- mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
- ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
- &mi2s_rx_clk);
- mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
- mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
- ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
- &mi2s_tx_clk);
- if (ret < 0)
- pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
- } else {
- digital_cdc_clk.clk_val = 0;
- mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
- mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
- ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
- &mi2s_rx_clk);
- mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
- mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
- ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
- &mi2s_tx_clk);
- if (ret < 0)
- pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
- }
- ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
- return ret;
-}
-
-
static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -284,7 +181,6 @@
pr_err("%s:afe_set_lpass_clock failed\n", __func__);
}
- ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
return ret;
}
@@ -293,20 +189,27 @@
{
int ret = 0;
- pr_debug("%s: enable = %d codec name %s enable %x\n",
- __func__, enable, codec->name, enable);
+ mutex_lock(&cdc_mclk_mutex);
+
+ pr_debug("%s: enable = %d codec name %s enable %d mclk ref counter %d\n",
+ __func__, enable, codec->name, enable,
+ atomic_read(&mclk_rsc_ref));
if (enable) {
- digital_cdc_clk.clk_val = 9600000;
- msm_config_mi2s_clk(1);
- ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
- &digital_cdc_clk);
- msm8x10_wcd_mclk_enable(codec, 1, dapm);
+ if (atomic_inc_return(&mclk_rsc_ref) == 1) {
+ digital_cdc_clk.clk_val = 9600000;
+ msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+ &digital_cdc_clk);
+ msm8x10_wcd_mclk_enable(codec, 1, dapm);
+ }
} else {
- msm8x10_wcd_mclk_enable(codec, 0, dapm);
- ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
- &digital_cdc_clk);
- msm_config_mi2s_clk(0);
+ if (atomic_dec_return(&mclk_rsc_ref) == 0) {
+ digital_cdc_clk.clk_val = 0;
+ msm8x10_wcd_mclk_enable(codec, 0, dapm);
+ msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+ &digital_cdc_clk);
+ }
}
+ mutex_unlock(&cdc_mclk_mutex);
return ret;
}
@@ -363,27 +266,17 @@
pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));
- pr_debug("%s(): aud_init_rsc_ref counter = %d\n",
- __func__, atomic_read(&aud_init_rsc_ref));
- if (atomic_inc_return(&aud_init_rsc_ref) != 1)
- goto exit;
-
snd_soc_dapm_new_controls(dapm, msm8x10_dapm_widgets,
ARRAY_SIZE(msm8x10_dapm_widgets));
snd_soc_dapm_sync(dapm);
- ret = msm_enable_mclk_root(AFE_PORT_ID_SECONDARY_MI2S_RX,
- &digital_cdc_clk);
ret = snd_soc_jack_new(codec, "Headset Jack",
SND_JACK_HEADSET, &hs_jack);
-
if (ret) {
pr_err("%s: Failed to create headset jack\n", __func__);
- return ret;
}
-exit:
return ret;
}
@@ -804,9 +697,8 @@
ret);
goto err;
}
-
- atomic_set(&aud_init_rsc_ref, 0);
-
+ mutex_init(&cdc_mclk_mutex);
+ atomic_set(&mclk_rsc_ref, 0);
return 0;
err:
return ret;
@@ -817,7 +709,7 @@
struct snd_soc_card *card = platform_get_drvdata(pdev);
snd_soc_unregister_card(card);
-
+ mutex_destroy(&cdc_mclk_mutex);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2fabca1..87bee75 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2761,6 +2761,12 @@
/* reset LCH mode */
v->lch_mode = 0;
+ /* clear mute setting */
+ v->dev_rx.dev_mute = common.default_mute_val;
+ v->dev_tx.dev_mute = common.default_mute_val;
+ v->stream_rx.stream_mute = common.default_mute_val;
+ v->stream_tx.stream_mute = common.default_mute_val;
+
/* detach VOCPROC and wait for response from mvm */
mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -4182,6 +4188,15 @@
pr_err("setup voice failed\n");
goto fail;
}
+
+ ret = voice_send_vol_index_cmd(v);
+ if (ret < 0)
+ pr_err("voice volume failed\n");
+
+ ret = voice_send_stream_mute_cmd(v);
+ if (ret < 0)
+ pr_err("voice mute failed\n");
+
ret = voice_send_start_voice_cmd(v);
if (ret < 0) {
pr_err("start voice failed\n");
@@ -4891,7 +4906,7 @@
memset(&common, 0, sizeof(struct common_data));
/* set default value */
- common.default_mute_val = 1; /* default is mute */
+ common.default_mute_val = 0; /* default is un-mute */
common.default_vol_val = 0;
common.default_sample_val = 8000;
@@ -4907,8 +4922,8 @@
/* initialize dev_rx and dev_tx */
common.voice[i].dev_rx.volume = common.default_vol_val;
- common.voice[i].dev_rx.dev_mute = 0;
- common.voice[i].dev_tx.dev_mute = 0;
+ common.voice[i].dev_rx.dev_mute = common.default_mute_val;
+ common.voice[i].dev_tx.dev_mute = common.default_mute_val;
common.voice[i].stream_rx.stream_mute = common.default_mute_val;
common.voice[i].stream_tx.stream_mute = common.default_mute_val;