Merge "defconfig: add gc0339 driver config define for msm8x10 qrd board"
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/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index a8b3065..4b20e9f 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -638,6 +638,9 @@
interrupt-names = "hc_irq", "pwr_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
+
vdd-supply = <&pm8941_l21>;
vdd-io-supply = <&pm8941_l13>;
diff --git a/arch/arm/boot/dts/apq8074-v2.dtsi b/arch/arm/boot/dts/apq8074-v2.dtsi
index 76eb14b..c700a5c 100644
--- a/arch/arm/boot/dts/apq8074-v2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.dtsi
@@ -50,3 +50,8 @@
status = "disabled";
};
+&sdcc3 {
+ qcom,sup-voltages = <2000 2000>;
+ status = "ok";
+};
+
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/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-cdp.dts
index 2b18491..ef14249 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-cdp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226-v2.dtsi"
/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm MSM 8226v2 CDP";
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-mtp.dts
index f15dd4c..24f822b 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-mtp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226-v2.dtsi"
/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm MSM 8226v2 MTP";
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd.dts b/arch/arm/boot/dts/msm8226-v2-qrd.dts
index 1a89d78..ad6d154 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226-v2.dtsi"
/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm MSM 8226v2 QRD";
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index d471bec..b26ba49 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -17,3 +17,4 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-camera.dtsi"
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-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index af0e3e4..d0fc1dc 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -20,8 +20,6 @@
mdss_fb0: qcom,mdss_fb_primary {
cell-index = <0>;
compatible = "qcom,mdss-fb";
- qcom,memory-reservation-type = "EBI1";
- qcom,memory-reservation-size = <0x300000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..e3bd631
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+&i2c {
+ qcom,camera@7d {
+ compatible = "qcom,hi256";
+ reg = <0x7d>;
+ qcom,slave-id = <0x40 0x04 0xc0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "hi256";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 8000 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x03>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+
+};
+
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 42367b3..90225c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -14,6 +14,7 @@
/include/ "msm8610.dtsi"
/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
/ {
model = "Qualcomm MSM 8610 QRD";
@@ -56,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/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 7a91d40..3da01f7 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -14,6 +14,7 @@
/dts-v1/;
/include/ "msm8926.dtsi"
/include/ "msm8226-cdp.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm MSM 8926 CDP";
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-mtp.dts
index fea925d..dc6e60e 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-mtp.dts
@@ -14,6 +14,7 @@
/dts-v1/;
/include/ "msm8926.dtsi"
/include/ "msm8226-mtp.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm MSM 8926 MTP";
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index e056b7e..8497ba2 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8926.dtsi"
/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp.dtsi"
/ {
model = "Qualcomm MSM 8926 QRD";
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 6f3f592..3a8369b 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-camera.dtsi"
/ {
model = "Qualcomm MSM 8926";
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 4a9820d..26c5b8f 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -15,7 +15,7 @@
actuator0: qcom,actuator@18 {
cell-index = <0>;
- reg = <0x18 0x0>;
+ reg = <0x18>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
};
@@ -29,7 +29,7 @@
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
- reg = <0x6e 0x0>;
+ reg = <0x6e>;
qcom,slave-id = <0x6e 0x0 0x3121>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
@@ -116,7 +116,7 @@
qcom,camera@6c {
compatible = "qcom,ov2720";
- reg = <0x6c 0x0>;
+ reg = <0x6c>;
qcom,slave-id = <0x6c 0x300A 0x2720>;
qcom,csiphy-sd-index = <2>;
qcom,csid-sd-index = <2>;
@@ -153,7 +153,7 @@
qcom,camera@90 {
compatible = "qcom,mt9m114";
- reg = <0x90 0x0>;
+ reg = <0x90>;
qcom,slave-id = <0x90 0x0 0x2481>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
index e84a47d..31f3a90 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-dragonboard.dtsi
@@ -15,7 +15,7 @@
actuator0: qcom,actuator@18 {
cell-index = <0>;
- reg = <0x18 0x0>;
+ reg = <0x18>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
};
@@ -29,7 +29,7 @@
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
- reg = <0x6e 0x0>;
+ reg = <0x6e>;
qcom,slave-id = <0x6e 0x0 0x3121>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
@@ -105,7 +105,7 @@
qcom,camera@6c {
compatible = "qcom,ov2720";
- reg = <0x6c 0x0>;
+ reg = <0x6c>;
qcom,slave-id = <0x6c 0x300A 0x2720>;
qcom,csiphy-sd-index = <2>;
qcom,csid-sd-index = <0>;
@@ -140,7 +140,7 @@
qcom,camera@90 {
compatible = "qcom,mt9m114";
- reg = <0x90 0x0>;
+ reg = <0x90>;
qcom,slave-id = <0x90 0x0 0x2481>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index a822af5..3d2308d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -403,6 +403,10 @@
};
&pm8941_bms {
+ qcom,enable-fcc-learning;
+ qcom,min-fcc-learning-soc = <20>;
+ qcom,min-fcc-ocv-pc = <30>;
+ qcom,min-fcc-learning-samples = <5>;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index e798fc0..28111fa 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -352,6 +352,10 @@
};
&pm8941_bms {
+ qcom,enable-fcc-learning;
+ qcom,min-fcc-learning-soc = <20>;
+ qcom,min-fcc-ocv-pc = <30>;
+ qcom,min-fcc-learning-samples = <5>;
status = "ok";
};
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 0f590b0..c27e863 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -271,6 +271,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_HI256=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -377,3 +378,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 87b4016..a1b0920 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -269,6 +269,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
+CONFIG_HI256=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSI20_HEADER=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/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 6734da8..28e8092 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1067,6 +1067,41 @@
wake_up_all(&cmdbuf->queue);
}
+static int dvb_dvr_external_input_only(struct dmxdev *dmxdev)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+ size_t tsp_size;
+
+ if (dmxdev->demux->get_tsp_size)
+ tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux);
+ else
+ tsp_size = 188;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (tsp_size == 188)
+ flags = caps.playback_188_tsp.flags;
+ else
+ flags = caps.playback_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1082,7 +1117,9 @@
return -EOPNOTSUPP;
if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
- (!src->data) || (!cmdbuf->data))
+ !src->data || !cmdbuf->data ||
+ (dvb_dvr_external_input_only(dmxdev) &&
+ (dmxdev->dvr_input_buffer_mode == DMX_BUFFER_MODE_INTERNAL)))
return -EINVAL;
if ((file->f_flags & O_NONBLOCK) &&
@@ -1238,7 +1275,7 @@
if (buf->size == size)
return 0;
- if ((!size) || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size || (buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
newmem = vmalloc_user(size);
@@ -1282,10 +1319,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1543,7 +1576,8 @@
if (buf->size == size)
return 0;
- if ((!size) || (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
+ if (!size ||
+ (dmxdevfilter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
if (dmxdevfilter->state >= DMXDEV_STATE_GO)
return -EBUSY;
@@ -1580,10 +1614,6 @@
(mode != DMX_BUFFER_MODE_EXTERNAL))
return -EINVAL;
- if ((mode == DMX_BUFFER_MODE_INTERNAL) &&
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
- return -EINVAL;
-
if ((mode == DMX_BUFFER_MODE_EXTERNAL) &&
(!dmxdev->demux->map_buffer || !dmxdev->demux->unmap_buffer))
return -EINVAL;
@@ -1765,8 +1795,15 @@
int found_pid;
struct dmxdev_feed *feed;
struct dmxdev_feed *ts_feed = NULL;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!idx_params ||
+ !(caps.caps & DMX_CAP_VIDEO_INDEXING) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1907,10 +1944,16 @@
int first_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
!params->size ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -1974,9 +2017,15 @@
int found_buffer;
struct dmxdev_feed *feed;
struct ts_insertion_buffer *ts_buffer, *tmp;
+ struct dmx_caps caps;
+
+ if (!dmxdevfilter->dev->demux->get_caps)
+ return -EINVAL;
+
+ dmxdevfilter->dev->demux->get_caps(dmxdevfilter->dev->demux, &caps);
if (!params ||
- !(dmxdevfilter->dev->capabilities & DMXDEV_CAP_TS_INSERTION) ||
+ !(caps.caps & DMX_CAP_TS_INSERTION) ||
(dmxdevfilter->state < DMXDEV_STATE_SET) ||
(dmxdevfilter->type != DMXDEV_TYPE_PES) ||
((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
@@ -2122,15 +2171,21 @@
enum dmx_playback_mode_t playback_mode)
{
struct dmxdev *dmxdev = dmxdevfilter->dev;
+ struct dmx_caps caps;
+
+ if (dmxdev->demux->get_caps)
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+ else
+ caps.caps = 0;
if ((playback_mode != DMX_PB_MODE_PUSH) &&
(playback_mode != DMX_PB_MODE_PULL))
return -EINVAL;
if (((dmxdev->source < DMX_SOURCE_DVR0) ||
- !dmxdev->demux->set_playback_mode ||
- !(dmxdev->capabilities & DMXDEV_CAP_PULL_MODE)) &&
- (playback_mode == DMX_PB_MODE_PULL))
+ !dmxdev->demux->set_playback_mode ||
+ !(caps.caps & DMX_CAP_PULL_MODE)) &&
+ (playback_mode == DMX_PB_MODE_PULL))
return -EPERM;
if (dmxdevfilter->state == DMXDEV_STATE_GO)
@@ -3083,6 +3138,43 @@
return 0;
}
+static int dvb_filter_external_buffer_only(struct dmxdev *dmxdev,
+ struct dmxdev_filter *filter)
+{
+ struct dmx_caps caps;
+ int is_external_only;
+ int flags;
+
+ /*
+ * For backward compatibility, default assumes that
+ * external only buffers are not supported.
+ */
+ flags = 0;
+ if (dmxdev->demux->get_caps) {
+ dmxdev->demux->get_caps(dmxdev->demux, &caps);
+
+ if (filter->type == DMXDEV_TYPE_SEC)
+ flags = caps.section.flags;
+ else if (filter->params.pes.output == DMX_OUT_DECODER)
+ /* For decoder filters dmxdev buffer is not required */
+ flags = 0;
+ else if (filter->params.pes.output == DMX_OUT_TAP)
+ flags = caps.pes.flags;
+ else if (filter->dmx_tsp_format == DMX_TSP_FORMAT_188)
+ flags = caps.recording_188_tsp.flags;
+ else
+ flags = caps.recording_192_tsp.flags;
+ }
+
+ if (!(flags & DMX_BUFFER_INTERNAL_SUPPORT) &&
+ (flags & DMX_BUFFER_EXTERNAL_SUPPORT))
+ is_external_only = 1;
+ else
+ is_external_only = 0;
+
+ return is_external_only;
+}
+
static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
{
struct dmxdev *dmxdev = filter->dev;
@@ -3098,14 +3190,18 @@
if (!filter->buffer.data) {
if ((filter->buffer_mode == DMX_BUFFER_MODE_EXTERNAL) ||
- (dmxdev->capabilities & DMXDEV_CAP_EXTERNAL_BUFFS_ONLY))
+ dvb_filter_external_buffer_only(dmxdev, filter))
return -ENOMEM;
+
mem = vmalloc_user(filter->buffer.size);
if (!mem)
return -ENOMEM;
spin_lock_irq(&filter->dev->lock);
filter->buffer.data = mem;
spin_unlock_irq(&filter->dev->lock);
+ } else if ((filter->buffer_mode == DMX_BUFFER_MODE_INTERNAL) &&
+ dvb_filter_external_buffer_only(dmxdev, filter)) {
+ return -ENOMEM;
}
filter->eos_state = 0;
@@ -3577,10 +3673,13 @@
struct dmx_decoder_buffers *dec_buffs;
struct dmx_caps caps;
- if (NULL == dmxdev || NULL == filter || NULL == buffs)
+ if (!dmxdev || !filter || !buffs)
return -EINVAL;
dec_buffs = &filter->decoder_buffers;
+ if (!dmxdev->demux->get_caps)
+ return -EINVAL;
+
dmxdev->demux->get_caps(dmxdev->demux, &caps);
if ((buffs->buffers_size == 0) ||
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 49e5e1b..4e306e8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -196,11 +196,6 @@
int filternum;
int capabilities;
#define DMXDEV_CAP_DUPLEX 0x01
-#define DMXDEV_CAP_PULL_MODE 0x02
-#define DMXDEV_CAP_INDEXING 0x04
-#define DMXDEV_CAP_EXTERNAL_BUFFS_ONLY 0x08
-#define DMXDEV_CAP_TS_INSERTION 0x10
-
enum dmx_playback_mode_t playback_mode;
dmx_source_t source;
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 525a545..3a30970 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -137,6 +137,15 @@
hfr video at 60, 90 and 120 fps. This sensor driver does
not support auto focus.
+config HI256
+ bool "Hynix hi256 (YUV 2MP)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 8 MP Bayer Sensor with auto focus.uses
+ 2 mipi lanes, preview config = 1632*1224 30 fps,
+ snapshot config = 3264 * 2448 at 18 fps.
+ 2 lanes max fps is 18, 4 lanes max fps is 24.
+
config MT9M114
bool "Sensor MT9M114 (YUV 1.26MP)"
depends on MSMB_CAMERA
@@ -146,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/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 29369de..ef3f57f 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -548,7 +548,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = dvb_demux->feednum;
@@ -599,7 +600,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -700,11 +700,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tsif_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index a2ce428..8e628f6 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1614,7 +1614,8 @@
return -EINVAL;
}
- caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA;
+ caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_DECODER_DATA |
+ DMX_CAP_TS_INSERTION | DMX_CAP_VIDEO_INDEXING;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -1623,9 +1624,9 @@
caps->section_filter_length = DMX_FILTER_SIZE;
caps->num_demod_inputs = TSIF_COUNT;
caps->num_memory_inputs = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
- caps->max_bitrate = 144;
- caps->demod_input_max_bitrate = 72;
- caps->memory_input_max_bitrate = 72;
+ caps->max_bitrate = 192;
+ caps->demod_input_max_bitrate = 96;
+ caps->memory_input_max_bitrate = 96;
/* Buffer requirements */
caps->section.flags =
@@ -1665,7 +1666,6 @@
caps->playback_192_tsp.max_size = 0xFFFFFFFF;
caps->playback_192_tsp.size_alignment = 0;
caps->decoder.flags =
- DMX_BUFFER_CONTIGUOUS_MEM |
DMX_BUFFER_SECURED_IF_DECRYPTED |
DMX_BUFFER_EXTERNAL_SUPPORT |
DMX_BUFFER_INTERNAL_SUPPORT |
@@ -1758,11 +1758,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_stc = mpq_tspp_dmx_get_stc;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 60e3cb4..1ab9da1 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
@@ -73,7 +73,7 @@
}
caps->caps = DMX_CAP_PULL_MODE | DMX_CAP_VIDEO_INDEXING |
- DMX_CAP_VIDEO_DECODER_DATA;
+ DMX_CAP_VIDEO_DECODER_DATA | DMX_CAP_TS_INSERTION;
caps->num_decoders = MPQ_ADAPTER_MAX_NUM_OF_INTERFACES;
caps->num_demux_devices = CONFIG_DVB_MPQ_NUM_DMX_DEVICES;
caps->num_pid_filters = TSPP_MAX_PID_FILTER_NUM;
@@ -140,11 +140,7 @@
/* Now initailize the dmx-dev object */
mpq_demux->dmxdev.filternum = MPQ_MAX_DMX_FILES;
mpq_demux->dmxdev.demux = &mpq_demux->demux.dmx;
- mpq_demux->dmxdev.capabilities =
- DMXDEV_CAP_DUPLEX |
- DMXDEV_CAP_PULL_MODE |
- DMXDEV_CAP_INDEXING |
- DMXDEV_CAP_TS_INSERTION;
+ mpq_demux->dmxdev.capabilities = DMXDEV_CAP_DUPLEX;
mpq_demux->dmxdev.demux->set_source = mpq_dmx_set_source;
mpq_demux->dmxdev.demux->get_caps = mpq_tspp_dmx_get_caps;
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/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index c39de83..1069dd5 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -172,7 +172,6 @@
static struct usb_bam_ctx_type ctx;
static struct device *hsic_host_dev;
-static bool hsic_host_dev_resumed_from_cons_request;
static int __usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
void *param, bool trigger_cb_per_pipe);
@@ -899,7 +898,6 @@
break;
case HSIC_BAM:
- hsic_host_dev_resumed_from_cons_request = true;
usb_bam_resume_hsic_host();
@@ -969,8 +967,6 @@
(int)hsic_host_dev);
pm_runtime_put(hsic_host_dev);
info.in_lpm[HSIC_BAM] = true;
- /* In case consumer release before resume happned */
- hsic_host_dev_resumed_from_cons_request = false;
}
}
@@ -1336,9 +1332,6 @@
void msm_bam_wait_for_hsic_prod_granted(void)
{
- if (hsic_host_dev_resumed_from_cons_request)
- return;
-
ctx.is_bam_inactivity[HSIC_BAM] = false;
/* Get back to resume state including wakeup ipa */
@@ -1356,11 +1349,8 @@
* and clocked on. Therefore we can now set the inactivity
* timer to the hsic bam hw.
*/
- if (ctx.inactivity_timer_ms[HSIC_BAM] &&
- !hsic_host_dev_resumed_from_cons_request)
+ if (ctx.inactivity_timer_ms[HSIC_BAM])
usb_bam_set_inactivity_timer(HSIC_BAM);
-
- hsic_host_dev_resumed_from_cons_request = false;
}
bool msm_bam_hsic_lpm_ok(void)
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index d9a216d..47e90aa 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -2263,7 +2263,6 @@
pr_err("tm measure failed: %d\n", rc);
return rc;
}
- mutex_lock(&chip->vbat_monitor_mutex);
if (wake_lock_active(&chip->low_voltage_wake_lock)) {
pr_debug("battery removed, releasing wakelock\n");
wake_unlock(&chip->low_voltage_wake_lock);
@@ -2272,7 +2271,6 @@
pr_debug("battery removed, removing in_cv_range state\n");
chip->in_cv_range = false;
}
- mutex_unlock(&chip->vbat_monitor_mutex);
return 0;
}
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_mtp.c b/drivers/usb/gadget/f_mtp.c
index 4586d80..a4192ca 100644
--- a/drivers/usb/gadget/f_mtp.c
+++ b/drivers/usb/gadget/f_mtp.c
@@ -558,17 +558,15 @@
struct mtp_dev *dev = fp->private_data;
struct usb_composite_dev *cdev = dev->cdev;
struct usb_request *req;
- int r = count, xfer;
+ int r = count, xfer, len;
int ret = 0;
DBG(cdev, "mtp_read(%d)\n", count);
- if (count > mtp_rx_req_len)
- return -EINVAL;
+ len = ALIGN(count, dev->ep_out->maxpacket);
- if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
- DBG(cdev, "%s - count(%d) not multiple of mtu(%d)\n", __func__,
- count, dev->ep_out->maxpacket);
+ if (len > mtp_rx_req_len)
+ return -EINVAL;
/* we will block until we're online */
DBG(cdev, "mtp_read: waiting for online state\n");
@@ -591,7 +589,7 @@
requeue_req:
/* queue a request */
req = dev->rx_req[0];
- req->length = mtp_rx_req_len;
+ req->length = len;
dev->rx_done = 0;
ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL);
if (ret < 0) {
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/dvb/dmx.h b/include/linux/dvb/dmx.h
index ce9e5b9..bd954ee 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -528,6 +528,9 @@
/* Indicates whether demux support sending data directly to subtitle decoder */
#define DMX_CAP_SUBTITLE_DECODER_DATA 0x10
+/* Indicates whether TS insertion is supported */
+#define DMX_CAP_TS_INSERTION 0x20
+
/* Number of decoders demux can output data to */
int num_decoders;
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;