Merge "ALSA: core: free card runtime memory"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 4e3abc2..a0b2f6d 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -22,16 +22,12 @@
should be 1 for SVS corner
- regulator-max-microvolt: Maximum corner value as max constraint, which
should be 4 for SUPER_TURBO or 3 for TURBO
-- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
- the power of qcom,pvs-fuse[num-of-bits]. The location or
- 0-based index of an element in the list corresponds
- to the bin number. The value of each integer
- corresponds to the PVS process speed of the APC
- silicon for a chip with one of these cases:
- 1 = APC_PVS_SLOW
- 2 = APC_PVS_NOM
- 3 = APC_PVS_FAST
- 0 or other values = No PVS
+- qcom,pvs-init-voltage: A list of integers whose length is equal to 2
+ to the power of qcom,pvs-fuse[num-of-bits]. The
+ location or 0-based index of an element in the
+ list corresponds to the bin number. The value of
+ each integer corresponds to the initial voltage
+ of the PVS bin in turbo mode in microvolts.
- qcom,pvs-corner-ceiling-slow: Ceiling voltages of all corners for APC_PVS_SLOW
- qcom,pvs-corner-ceiling-nom: Ceiling voltages of all corners for APC_PVS_NOM
- qcom,pvs-corner-ceiling-fast: Ceiling voltages of all corners for APC_PVS_FAST
@@ -155,8 +151,14 @@
qcom,pvs-fuse-redun-sel = <22 24 3 2>;
qcom,pvs-fuse-redun = <22 27 5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+ qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000
+ 1310000 1300000 1290000 1280000
+ 1270000 1260000 1250000 1240000
+ 1230000 1220000 1210000 1200000
+ 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000>;
qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 8fd813c..4f9307a 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -18,10 +18,14 @@
- synaptics,button-map : virtual key code mappings to be used
- synaptics,x-flip : modify orientation of the x axis
- synaptics,y-flip : modify orientation of the y axis
- - synaptics,panel-x : panel x dimension
- - synaptics,panel-y : panel y dimension
+ - synaptics,panel-coords : touch panel min x, min y, max x and
+ max y resolution
+ - synaptics,display-coords : display min x, min y, max x and
+ max y resolution
+ - synaptics,reset-delay : reset delay for controller (ms), default 100
- synaptics,fw-image-name : name of firmware .img file in /etc/firmware
- synaptics,power-down : fully power down regulators in suspend
+ - synaptics,do-lockdown : perform one time lockdown procedure
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
index 95be46c..3bb63de 100644
--- a/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/qpnp-pwm.txt
@@ -18,6 +18,8 @@
- qcom,channel-id: channel Id for the PWM.
Optional device bindings:
+- qcom,force-pwm-size: For certain LPG channels, PWM size can be forced.
+ Possible values 6, 7, 8 and 9.
- qcom,channel-owner: A string value to supply owner information.
- qcom,mode-select: 0 = PWM mode
1 = LPG mode
@@ -110,6 +112,7 @@
<0xb040 0x80>;
reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
qcom,channel-id = <1>;
+ qcom,force-pwm-size = <9>;
qcom,period = <6000000>;
status = "okay";
qcom,pwm {
diff --git a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
index 645e91b..9d244d8 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
@@ -26,13 +26,13 @@
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <480>;
qcom,mdss-dsi-panel-height = <800>;
- qcom,mdss-dsi-h-front-porch = <90>;
- qcom,mdss-dsi-h-back-porch = <90>;
- qcom,mdss-dsi-h-pulse-width = <17>;
+ qcom,mdss-dsi-h-front-porch = <70>;
+ qcom,mdss-dsi-h-back-porch = <100>;
+ qcom,mdss-dsi-h-pulse-width = <40>;
qcom,mdss-dsi-h-sync-skew = <0>;
- qcom,mdss-dsi-v-back-porch = <2>;
- qcom,mdss-dsi-v-front-porch = <11>;
- qcom,mdss-dsi-v-pulse-width = <3>;
+ qcom,mdss-dsi-v-back-porch = <6>;
+ qcom,mdss-dsi-v-front-porch = <6>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
@@ -41,17 +41,63 @@
qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
- qcom,mdss-dsi-on-command = [29 01 00 00 01 00 04 B9 FF 83 79
- 23 01 00 00 01 00 02 BA 51
- 29 01 00 00 01 00 14 B1 00 50 44 EA 8D 08 11 0F 0F 24 2C 9A 1A 42 0B 6E F1 00 E6
- 29 01 00 00 01 00 0e B2 00 00 3C 08 04 19 22 00 FF 08 04 19 20
- 29 01 00 00 01 00 20 B4 80 08 00 32 10 03 32 13 70 32 10 08 37 01 28 05 37 08 3C 20 44 44 08 00 40 08 28 08 30 30 04
- 23 01 00 00 01 00 02 cc 02
- 29 01 00 00 01 00 30 D5 00 00 08 00 01 05 00 03 00 88 88 88 88 23 01 67 45 02 13 88 88 88 88 88 88 88 88 88 88 54 76 10 32 31 20 88 88 88 88 88 88 00 00 00 00 00 00
- 29 01 00 00 01 00 24 E0 79 00 00 02 1C 1F 33 28 3E 07 0E 0F 15 17 16 16 13 19 00 00 02 1C 1F 33 28 3E 07 0E 0F 15 17 16 16 13 19
- 29 01 00 00 01 00 05 B6 00 A6 00 A6
- 05 01 00 00 96 00 02 11 00
- 05 01 00 00 78 00 02 29 00];
+ qcom,mdss-dsi-on-command = [
+ 39 01 00 00 00 00 04
+ B9 FF 83 79
+ 39 01 00 00 00 00 03
+ BA 51 93
+ 39 01 00 00 00 00 14
+ B1 00 50 44
+ EA 8D 08 11
+ 11 11 27 2F
+ 9A 1A 42 0B
+ 6E F1 00 E6
+ 39 01 00 00 00 00 0E
+ B2 00 00 3C
+ 08 04 19 22
+ 00 FF 08 04
+ 19 20
+ 39 01 00 00 00 00 20
+ B4 82 08 00
+ 32 10 03 32
+ 13 70 32 10
+ 08 37 01 28
+ 07 37 08 3C
+ 08 44 44 08
+ 00 40 08 28
+ 08 30 30 04
+ 39 01 00 00 00 00 30
+ D5 00 00 0A
+ 00 01 05 00
+ 03 00 88 88
+ 88 88 23 01
+ 67 45 02 13
+ 88 88 88 88
+ 88 88 88 88
+ 88 88 54 76
+ 10 32 31 20
+ 88 88 88 88
+ 88 88 00 00
+ 00 00 00 00
+ 39 01 00 00 00 00 24
+ E0 79 05 0F
+ 14 26 29 3F
+ 2B 44 04 0E
+ 12 15 18 16
+ 16 12 15 05
+ 0F 14 26 29
+ 3F 2B 44 04
+ 0E 12 15 18
+ 16 16 12 15
+ 23 01 00 00 00 00 02
+ cc 02
+ 39 01 00 00 00 00 05
+ B6 00 9C 00 9C
+ 05 01 00 00 96 00 02
+ 11 00
+ 05 01 00 00 78 00 02
+ 29 00
+ ];
qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
05 01 00 00 78 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
@@ -63,7 +109,7 @@
qcom,mdss-dsi-bllp-power-mode;
qcom,mdss-dsi-lane-0-state;
qcom,mdss-dsi-lane-1-state;
- qcom,mdss-dsi-panel-timings = [5d 12 0c 00 33 39 10 16 15 03 04 00];
+ qcom,mdss-dsi-panel-timings = [75 1A 11 00 3D 45 15 1D 1C 03 04 00];
qcom,mdss-dsi-t-clk-post = <0x04>;
qcom,mdss-dsi-t-clk-pre = <0x1b>;
qcom,mdss-dsi-bl-min-level = <1>;
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
index 74e7ffc..89a5063 100644
--- a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -25,7 +25,7 @@
qcom,mdss-dsi-virtual-channel-id = <0>;
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <480>;
- qcom,mdss-dsi-panel-height = <800>;
+ qcom,mdss-dsi-panel-height = <854>;
qcom,mdss-dsi-h-front-porch = <80>;
qcom,mdss-dsi-h-back-porch = <54>;
qcom,mdss-dsi-h-pulse-width = <8>;
@@ -41,96 +41,213 @@
qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
- qcom,mdss-dsi-on-command = [29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 04 ff 80 09 01
- 29 01 00 00 00 00 02 00 80
- 29 01 00 00 00 00 03 ff 80 09
- 29 01 00 00 00 00 02 00 80
- 29 01 00 00 00 00 02 d6 48
- 29 01 00 00 00 00 02 00 03
- 29 01 00 00 00 00 02 ff 01
- 29 01 00 00 00 00 02 00 B4
- 29 01 00 00 00 00 02 C0 10
- 29 01 00 00 00 00 02 00 82
- 29 01 00 00 00 00 02 C5 A3
- 29 01 00 00 00 00 02 00 90
- 29 01 00 00 00 00 03 C5 96 87
- 29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 03 D8 74 72
- 29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 02 D9 56
- 29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 11 E1 00 06 0A 07 03 16 08 0A 04 06 07 08 0F 23 22 05
- 29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 11 E2 00 06 0A 07 03 16 08 0A 04 06 07 08 0F 23 22 05
- 29 01 00 00 00 00 02 00 81
- 29 01 00 00 00 00 02 C1 77
- 29 01 00 00 00 00 02 00 A0
- 29 01 00 00 00 00 02 C1 EA
- 29 01 00 00 00 00 02 00 A1
- 29 01 00 00 00 00 02 C1 08
- 29 01 00 00 00 00 02 00 89
- 29 01 00 00 00 00 02 C4 08
- 29 01 00 00 00 00 02 00 81
- 29 01 00 00 00 00 02 C4 83
- 29 01 00 00 00 00 02 00 92
- 29 01 00 00 00 00 02 C5 01
- 29 01 00 00 00 00 02 00 B1
- 29 01 00 00 00 00 02 C5 A9
- 29 01 00 00 00 00 02 00 92
- 29 01 00 00 00 00 02 B3 45
- 29 01 00 00 00 00 02 00 90
- 29 01 00 00 00 00 02 B3 02
- 29 01 00 00 00 00 02 00 80
- 29 01 00 00 00 00 06 C0 00 58 00 14 16
- 29 01 00 00 00 00 02 00 80
- 29 01 00 00 00 00 02 C4 30
- 29 01 00 00 00 00 02 00 90
- 29 01 00 00 00 00 07 C0 00 44 00 00 00 03
- 29 01 00 00 00 00 02 00 A6
- 29 01 00 00 00 00 04 C1 01 00 00
- 29 01 00 00 00 00 02 00 80
- 29 01 00 00 00 00 0D CE 87 03 00 85 03 00 86 03 00 84 03 00
- 29 01 00 00 00 00 02 00 A0
- 29 01 00 00 00 00 0f CE 38 03 03 58 00 00 00 38 02 03 59 00 00 00
- 29 01 00 00 00 00 02 00 B0
- 29 01 00 00 00 00 0f CE 38 01 03 5A 00 00 00 38 00 03 5B 00 00 00
- 29 01 00 00 00 00 02 00 C0
- 29 01 00 00 00 00 0f CE 30 00 03 5C 00 00 00 30 01 03 5D 00 00 00
- 29 01 00 00 00 00 02 00 D0
- 29 01 00 00 00 00 0f CE 30 02 03 5E 00 00 00 30 03 03 5F 00 00 00
- 29 01 00 00 00 00 02 00 C7
- 29 01 00 00 00 00 02 CF 00
- 29 01 00 00 00 00 02 00 C9
- 29 01 00 00 00 00 02 CF 00
- 29 01 00 00 00 00 02 00 D0
- 29 01 00 00 00 00 02 CF 00
- 29 01 00 00 00 00 02 00 C4
- 29 01 00 00 00 00 07 CB 04 04 04 04 04 04
- 29 01 00 00 00 00 02 00 D9
- 29 01 00 00 00 00 07 CB 04 04 04 04 04 04
- 29 01 00 00 00 00 02 00 84
- 29 01 00 00 00 00 07 CC 0C 0A 10 0E 03 04
- 29 01 00 00 00 00 02 00 9E
- 29 01 00 00 00 00 02 CC 0B
- 29 01 00 00 00 00 02 00 A0
- 29 01 00 00 00 00 06 CC 09 0F 0D 01 02
- 29 01 00 00 00 00 02 00 B4
- 29 01 00 00 00 00 07 CC 0D 0F 09 0B 02 01
- 29 01 00 00 00 00 02 00 CE
- 29 01 00 00 00 00 02 CC 0E
- 29 01 00 00 00 00 02 00 D0
- 29 01 00 00 00 00 06 CC 10 0A 0C 04 03
- 29 01 00 00 00 00 02 00 00
- 29 01 00 00 00 00 04 ff ff ff ff
- 05 01 00 00 78 00 02 11 00
- 05 01 00 00 32 00 02 29 00];
+ qcom,mdss-dsi-on-command = [
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 04
+ ff 80 09 01
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 03
+ ff 80 09
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 02
+ d6 48
+ 29 01 00 00 00 00 02
+ 00 03
+ 29 01 00 00 00 00 02
+ ff 01
+ 29 01 00 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 00 02
+ C0 10
+ 29 01 00 00 00 00 02
+ 00 82
+ 29 01 00 00 00 00 02
+ C5 A3
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 03
+ C5 96 87
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 03
+ D8 74 72
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 02
+ D9 56
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 11
+ E1 00 06 0A
+ 07 03 16 08
+ 0A 04 06 07
+ 08 0F 23 22
+ 05
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 11
+ E2 00 06 0A
+ 07 03 16 08
+ 0A 04 06 07
+ 08 0F 23 22
+ 05
+ 29 01 00 00 00 00 02
+ 00 81
+ 29 01 00 00 00 00 02
+ C1 77
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 02
+ C1 EA
+ 29 01 00 00 00 00 02
+ 00 A1
+ 29 01 00 00 00 00 02
+ C1 08
+ 29 01 00 00 00 00 02
+ 00 89
+ 29 01 00 00 00 00 02
+ C4 08
+ 29 01 00 00 00 00 02
+ 00 81
+ 29 01 00 00 00 00 02
+ C4 83
+ 29 01 00 00 00 00 02
+ 00 92
+ 29 01 00 00 00 00 02
+ C5 01
+ 29 01 00 00 00 00 02
+ 00 B1
+ 29 01 00 00 00 00 02
+ C5 A9
+ 29 01 00 00 00 00 02
+ 00 92
+ 29 01 00 00 00 00 02
+ B3 45
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 02
+ B3 02
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 06
+ C0 00 58 00
+ 14 16
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 02
+ C4 30
+ 29 01 00 00 00 00 02
+ 00 90
+ 29 01 00 00 00 00 07
+ C0 00 44 00
+ 00 00 03
+ 29 01 00 00 00 00 02
+ 00 A6
+ 29 01 00 00 00 00 04
+ C1 01 00 00
+ 29 01 00 00 00 00 02
+ 00 80
+ 29 01 00 00 00 00 0D
+ CE 87 03 00
+ 85 03 00 86
+ 03 00 84 03
+ 00
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 0f
+ CE 38 03 03
+ 58 00 00 00
+ 38 02 03 59
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 B0
+ 29 01 00 00 00 00 0f
+ CE 38 01 03
+ 5A 00 00 00
+ 38 00 03 5B
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 C0
+ 29 01 00 00 00 00 0f
+ CE 30 00 03
+ 5C 00 00 00
+ 30 01 03 5D
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 0f
+ CE 30 02 03
+ 5E 00 00 00
+ 30 03 03 5F
+ 00 00 00
+ 29 01 00 00 00 00 02
+ 00 C7
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 C9
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 02
+ CF 00
+ 29 01 00 00 00 00 02
+ 00 C4
+ 29 01 00 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 00 02
+ 00 D9
+ 29 01 00 00 00 00 07
+ CB 04 04 04
+ 04 04 04
+ 29 01 00 00 00 00 02
+ 00 84
+ 29 01 00 00 00 00 07
+ CC 0C 0A 10
+ 0E 03 04
+ 29 01 00 00 00 00 02
+ 00 9E
+ 29 01 00 00 00 00 02
+ CC 0B
+ 29 01 00 00 00 00 02
+ 00 A0
+ 29 01 00 00 00 00 06
+ CC 09 0F 0D
+ 01 02
+ 29 01 00 00 00 00 02
+ 00 B4
+ 29 01 00 00 00 00 07
+ CC 0D 0F 09
+ 0B 02 01
+ 29 01 00 00 00 00 02
+ 00 CE
+ 29 01 00 00 00 00 02
+ CC 0E
+ 29 01 00 00 00 00 02
+ 00 D0
+ 29 01 00 00 00 00 06
+ CC 10 0A 0C
+ 04 03
+ 29 01 00 00 00 00 02
+ 00 00
+ 29 01 00 00 00 00 04
+ ff ff ff ff
+ 05 01 00 00 78 00 02
+ 11 00
+ 05 01 00 00 32 00 02
+ 29 00
+ ];
qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
05 01 00 00 78 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
- qcom,mdss-dsi-h-sync-pulse = <1>;
- qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-h-sync-pulse = <0>;
+ qcom,mdss-dsi-traffic-mode = <1>;
qcom,mdss-dsi-lane-map = <1>;
qcom,mdss-dsi-bllp-eof-power-mode;
qcom,mdss-dsi-bllp-power-mode;
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
index f0957f8..f6e6df8 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -42,31 +42,105 @@
qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
- qcom,mdss-dsi-on-command = [05 01 00 00 00 00 02 01 00
- 23 01 00 00 00 00 02 b0 04
- 29 01 00 00 00 00 03 b3 02 00
- 23 01 00 00 00 00 02 bd 00
- 29 01 00 00 00 00 03 c0 18 66
- 29 01 00 00 00 00 10 c1 23 31 99 21 20 00 30 28 0c 0c 00 00 00 21 01
- 29 01 00 00 00 00 07 c2 00 06 06 01 03 00
- 29 01 00 00 00 00 19 c8 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 19 c9 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 19 ca 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 11 d0 29 03 ce a6 00 43 20 10 01 00 01 01 00 03 01 00
- 29 01 00 00 00 00 08 d1 18 0C 23 03 75 02 50
- 23 01 00 00 00 00 02 d3 11
- 29 01 00 00 00 00 03 d5 2a 2a
- 29 01 00 00 00 00 03 de 01 51
- 23 01 00 00 00 00 02 e6 51
- 23 01 00 00 00 00 02 fa 03
- 23 01 00 00 64 00 02 d6 28
- 15 01 00 00 64 00 02 36 41
- 39 01 00 00 00 00 05 2a 00 00 01 df
- 39 01 00 00 00 00 05 2b 00 00 03 1f
- 15 01 00 00 00 00 02 35 00
- 39 01 00 00 00 00 03 44 00 50
- 05 01 00 00 7D 00 02 11 00
- 05 01 00 00 14 00 02 29 00];
+ qcom,mdss-dsi-on-command = [
+ 05 01 00 00 00 00 02
+ 01 00
+ 23 01 00 00 00 00 02
+ b0 04
+ 29 01 00 00 00 00 03
+ b3 02 00
+ 29 01 00 00 00 00 03
+ b6 51 83
+ 29 01 00 00 00 00 05
+ b7 00 80 15 25
+ 29 01 00 00 00 00 14
+ b8 00 07 07 ff c8 c8 01 18 10 10
+ 37 5a 87 de ff 00 00 00 00
+ 29 01 00 00 00 00 05
+ b9 00 00 00 00
+ 23 01 00 00 00 00 02
+ bd 00
+ 29 01 00 00 00 00 03
+ c0 02 43
+ 29 01 00 00 00 00 10
+ c1 43 31 99 21 20 00 10 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 00 07
+ c2 28 06 06 01 03 00
+ 29 01 00 00 00 00 04
+ c3 40 00 03
+ 29 01 00 00 00 00 03
+ 6f 03 00
+ 29 01 00 00 00 00 03
+ c4 00 01
+ 29 01 00 00 00 00 03
+ c6 00 00
+ 29 01 00 00 00 00 06
+ c7 11 8d a0 f5 27
+ 29 01 00 00 00 00 19
+ c8 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ c9 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ ca 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 11
+ d0 99 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 00 02
+ d3 33
+ 29 01 00 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 00 02
+ d6 28
+ 29 01 00 00 00 00 10
+ d7 01 00 aa c0 2a 2c 22 12 71 0a 12 00 a0
+ 00 03
+ 29 01 00 00 00 00 09
+ d8 44 44 22 44 21 46 42 40
+ 29 01 00 00 00 00 04
+ d9 cf 2d 51
+ 29 01 00 00 00 00 02
+ da 01
+ 29 01 00 00 00 00 03
+ de 01 4f
+ 29 01 00 00 00 00 07
+ e1 00 00 00 00 00 00
+ 23 01 00 00 00 00 02
+ e6 4f
+ 29 01 00 00 00 00 06
+ f3 06 00 00 24 00
+ 29 01 00 00 00 00 02
+ f8 00
+ 23 01 00 00 00 00 02
+ fa 03
+ 29 01 00 00 00 00 04
+ fb 00 00 00
+ 29 01 00 00 00 00 06
+ fc 00 00 00 00 00
+ 29 01 00 00 00 00 05
+ fd 00 00 70 00
+ 39 01 00 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 00 02
+ 35 00
+ 39 01 00 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 00 02
+ 36 41
+ 15 01 00 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 00 02
+ 11 00
+ 05 01 00 00 3c 00 02
+ 29 00
+ ];
qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
05 01 00 00 78 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
@@ -80,6 +154,7 @@
qcom,mdss-dsi-lane-1-state;
qcom,mdss-dsi-te-pin-select = <1>;
qcom,mdss-dsi-te-v-sync-rd-ptr-irq-line = <0x2c>;
+ qcom,mdss-dsi-te-v-sync-continues-lines = <0x3c>;
qcom,mdss-dsi-te-dcs-command = <1>;
qcom,mdss-dsi-te-check-enable;
qcom,mdss-dsi-te-using-te-pin;
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
index 32af837..fae4834 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -42,34 +42,111 @@
qcom,mdss-dsi-color-order = <0>;
qcom,mdss-dsi-underflow-color = <0xff>;
qcom,mdss-dsi-border-color = <0>;
- qcom,mdss-dsi-on-command = [05 01 00 00 00 00 02 01 00
- 23 01 00 00 00 00 02 b0 04
- 29 01 00 00 00 00 03 b3 02 00
- 23 01 00 00 00 00 02 bd 00
- 29 01 00 00 00 00 03 c0 18 66
- 29 01 00 00 00 00 10 c1 23 31 99 21 20 00 30 28 0c 0c 00 00 00 21 01
- 29 01 00 00 00 00 07 c2 00 06 06 01 03 00
- 29 01 00 00 00 00 19 c8 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 19 c9 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 19 ca 04 10 18 20 2e 46 3c 28 1f 18 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
- 29 01 00 00 00 00 11 d0 29 03 ce a6 00 43 20 10 01 00 01 01 00 03 01 00
- 29 01 00 00 00 00 08 d1 18 0C 23 03 75 02 50
- 23 01 00 00 00 00 02 d3 11
- 29 01 00 00 00 00 03 d5 2a 2a
- 29 01 00 00 00 00 03 de 01 51
- 23 01 00 00 00 00 02 e6 51
- 23 01 00 00 00 00 02 fa 03
- 23 01 00 00 64 00 02 d6 28
- 39 01 00 00 00 00 05 2a 00 00 01 df
- 39 01 00 00 00 00 05 2b 00 00 03 1f
- 15 01 00 00 00 00 02 35 00
- 39 01 00 00 00 00 03 44 00 50
- 15 01 00 00 00 00 02 36 c1
- 15 01 00 00 00 00 02 3a 77
- 05 01 00 00 00 00 02 11 00
- 05 01 00 00 00 00 02 29 00];
+ qcom,mdss-dsi-on-command = [
+ 05 01 00 00 00 00 02
+ 01 00
+ 23 01 00 00 00 00 02
+ b0 04
+ 29 01 00 00 00 00 03
+ b3 02 00
+ 29 01 00 00 00 00 03
+ b6 51 83
+ 29 01 00 00 00 00 05
+ b7 00 80 15 25
+ 29 01 00 00 00 00 14
+ b8 00 07 07 ff c8 c8 01 18 10 10
+ 37 5a 87 de ff 00 00 00 00
+ 29 01 00 00 00 00 05
+ b9 00 00 00 00
+ 23 01 00 00 00 00 02
+ bd 00
+ 29 01 00 00 00 00 03
+ c0 02 43
+ 29 01 00 00 00 00 10
+ c1 43 31 99 21 20 00 10 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 00 07
+ c2 28 06 06 01 03 00
+ 29 01 00 00 00 00 04
+ c3 40 00 03
+ 29 01 00 00 00 00 03
+ 6f 03 00
+ 29 01 00 00 00 00 03
+ c4 00 01
+ 29 01 00 00 00 00 03
+ c6 00 00
+ 29 01 00 00 00 00 06
+ c7 11 8d a0 f5 27
+ 29 01 00 00 00 00 19
+ c8 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ c9 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 19
+ ca 01 0a 12 1c 2b 45 3f 29 17 13
+ 0f 04 01 0a 12 1c 2b 45 3f 29 17 13 0f 04
+ 29 01 00 00 00 00 11
+ d0 99 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 00 02
+ d3 33
+ 29 01 00 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 00 02
+ d6 28
+ 29 01 00 00 00 00 10
+ d7 01 00 aa c0 2a 2c 22 12 71 0a 12 00 a0
+ 00 03
+ 29 01 00 00 00 00 09
+ d8 44 44 22 44 21 46 42 40
+ 29 01 00 00 00 00 04
+ d9 cf 2d 51
+ 29 01 00 00 00 00 02
+ da 01
+ 29 01 00 00 00 00 03
+ de 01 4f
+ 29 01 00 00 00 00 07
+ e1 00 00 00 00 00 00
+ 23 01 00 00 00 00 02
+ e6 4f
+ 29 01 00 00 00 00 06
+ f3 06 00 00 24 00
+ 29 01 00 00 00 00 02
+ f8 00
+ 23 01 00 00 00 00 02
+ fa 03
+ 29 01 00 00 00 00 04
+ fb 00 00 00
+ 29 01 00 00 00 00 06
+ fc 00 00 00 00 00
+ 29 01 00 00 00 00 05
+ fd 00 00 70 00
+ 39 01 00 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 00 02
+ 35 00
+ 39 01 00 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 00 02
+ 36 c1
+ 15 01 00 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 00 02
+ 11 00
+ 05 01 00 00 3c 00 02
+ 29 00
+ ];
qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
- 05 01 00 00 78 00 02 10 00];
+ 05 01 00 00 78 00 02 10 00
+ 23 01 00 00 10 00 02
+ b0 04
+ 23 01 00 00 20 00 02
+ b1 01];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-h-sync-pulse = <0>;
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 1820dc7..6969940 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -315,7 +315,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 5642d4d..5734b9c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -189,7 +189,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 583cd3c..98d2f5e 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -120,7 +120,7 @@
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
qcom,r-conn-mohm = <0>;
- qcom,shutdown-soc-valid-limit = <20>;
+ qcom,shutdown-soc-valid-limit = <100>;
qcom,adjust-soc-low-threshold = <15>;
qcom,ocv-voltage-high-threshold-uv = <3750000>;
qcom,ocv-voltage-low-threshold-uv = <3650000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index a574bb0..53e0578 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -114,10 +114,10 @@
"MIC BIAS1 External", "Handset Mic",
"AMIC2", "MIC BIAS2 External",
"MIC BIAS2 External", "Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCRight Headset Mic",
- "AMIC5", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic";
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Analog Mic3",
+ "AMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Analog Mic4";
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
@@ -238,7 +238,7 @@
qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
- qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,clk-rates = <400000 25000000 50000000>;
#address-cells = <0>;
interrupt-parent = <&sdhc_2>;
@@ -454,6 +454,7 @@
&slim_msm {
tapan_codec {
qcom,cdc-micbias1-ext-cap;
+ qcom,cdc-micbias3-ext-cap;
};
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 5b3da9b..838592c 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -41,9 +41,14 @@
qcom,pvs-fuse = <22 6 5>;
qcom,pvs-fuse-redun = <22 27 5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
+ qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+ 1275000 1260000 1245000 1230000 1215000
+ 1200000 1185000 1170000 1155000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1275000 1275000
+ 1275000 1275000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index c2ce546..a57adcd 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -33,28 +33,33 @@
&pm8226_l3 {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_l3_ao {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_l3_so {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1337500>;
};
&pm8226_s2 {
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1280000>;
+ regulator-max-microvolt = <1330000>;
};
&apc_vreg_corner {
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
- 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1280000>;
+ qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000 1310000
+ 1300000 1290000 1280000 1270000 1260000
+ 1250000 1240000 1230000 1220000 1210000
+ 1200000 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 22d6948..483aad1 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -33,7 +33,7 @@
adsp_mem: adsp_region {
linux,contiguous-region;
- reg = <0 0xc00000>;
+ reg = <0 0x2a00000>;
label = "adsp_mem";
};
@@ -201,6 +201,12 @@
};
};
+ qcom,vidc {
+ compatible = "qcom,msm-vidc";
+ qcom,hfi = "q6";
+ qcom,max-hw-load = <108000>; /* 720p @ 30 * 1 */
+ };
+
qcom,wfd {
compatible = "qcom,msm-wfd";
};
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
index 1b4a594..e133117 100644
--- a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -38,6 +38,78 @@
qcom,cci-master = <0>;
};
+ eeprom0: qcom,eeprom@6a {
+ cell-index = <0>;
+ reg = <0x6a 0x0>;
+ qcom,eeprom-name = "truly_cm7700";
+ compatible = "qcom,msm_eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,num-blocks = <9>;
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0 1 1>;
+ qcom,mem0 = <0 0x0 2 0 1 0>;
+ qcom,page1 = <1 0x3d84 2 0x8 1 1>;
+ qcom,pageen1 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <32 0x3d00 2 0 1 0>;
+ qcom,page2 = <1 0x3d84 2 0x9 1 1>;
+ qcom,pageen2 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <32 0x3d00 2 0 1 0>;
+ qcom,page3 = <1 0x3d84 2 0xa 1 1>;
+ qcom,pageen3 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <32 0x3d00 2 0 1 0>;
+ qcom,page4 = <1 0x3d84 2 0xb 1 1>;
+ qcom,pageen4 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll4 = <0 0x0 2 0 1 1>;
+ qcom,mem4 = <32 0x3d00 2 0 1 0>;
+ qcom,page5 = <1 0x3d84 2 0xc 1 1>;
+ qcom,pageen5 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll5 = <0 0x0 2 0 1 1>;
+ qcom,mem5 = <32 0x3d00 2 0 1 0>;
+ qcom,page6 = <1 0x3d84 2 0xd 1 1>;
+ qcom,pageen6 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll6 = <0 0x0 2 0 1 1>;
+ qcom,mem6 = <32 0x3d00 2 0 1 0>;
+ qcom,page7 = <1 0x3d84 2 0xe 1 1>;
+ qcom,pageen7 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll7 = <0 0x0 2 0 1 1>;
+ qcom,mem7 = <32 0x3d00 2 0 1 0>;
+ qcom,page8 = <1 0x3d84 2 0xf 1 1>;
+ qcom,pageen8 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll8 = <0 0x0 2 0 1 1>;
+ qcom,mem8 = <32 0x3d00 2 0 1 0>;
+
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vio-supply = <&pm8110_l14>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio";
+ qcom,cam-vreg-type = <0 0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000>;
+ qcom,cam-vreg-op-mode = <200000 8000>;
+ 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,cam-power-seq-type = "sensor_vreg",
+ "sensor_vreg", "sensor_clk",
+ "sensor_gpio", "sensor_gpio";
+ qcom,cam-power-seq-val = "cam_vdig",
+ "cam_vio", "sensor_cam_mclk",
+ "sensor_gpio_reset",
+ "sensor_gpio_standby";
+ qcom,cam-power-seq-cfg-val = <1 1 24000000 1 1>;
+ qcom,cam-power-seq-delay = <1 1 5 5 10>;
+ };
+
qcom,camera@6f {
compatible = "qcom,ov8825";
reg = <0x6f>;
@@ -46,6 +118,7 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov8825";
cam_vdig-supply = <&pm8110_l2>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 1929b50..eb69678 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -42,10 +42,15 @@
qcom,pvs-fuse = <23 6 5>;
qcom,pvs-fuse-redun = <61 47 5>;
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1>;
- qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
- qcom,pvs-corner-ceiling-nom = <1050000 1075000 1200000>;
+ qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000 1275000 1275000 1275000
+ 1275000 1275000>;
+ qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
+ qcom,pvs-corner-ceiling-nom = <1075000 1075000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
vdd-apc-supply = <&pm8110_s2>;
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 2a619db..4a2de1c 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -168,6 +168,7 @@
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<2 216>, /* tsens_upper_lower_int */
+ <41 63>, /* dino_gen_purpose_irq35 */
<0xff 18>, /* APC_qgicQTmrSecPhysIrptReq */
<0xff 19>, /* APC_qgicQTmrNonSecPhysIrptReq */
<0xff 35>, /* WDT_barkInt */
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 257d7a4..079f0b1 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -170,6 +170,7 @@
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
<2 216>, /* tsens_upper_lower_int */
+ <41 63>, /* dino_gen_purpose_irq35 */
<0xff 56>, /* q6_wdog_expired_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 5893a9b..2ab272a 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -48,28 +48,33 @@
&pm8226_l3 {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_l3_ao {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_l3_so {
regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1287500>;
+ regulator-max-microvolt = <1350000>;
};
&pm8226_s2 {
regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <1280000>;
+ regulator-max-microvolt = <1350000>;
};
&apc_vreg_corner {
- qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2
- 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3>;
- qcom,pvs-corner-ceiling-slow = <1050000 1160000 1280000>;
+ qcom,pvs-init-voltage = <1350000 1340000 1330000 1320000 1310000
+ 1300000 1290000 1280000 1270000 1260000
+ 1250000 1240000 1230000 1220000 1210000
+ 1200000 1190000 1180000 1170000 1160000
+ 1150000 1140000 1140000 1140000 1140000
+ 1140000 1140000 1140000 1140000 1140000
+ 1140000 1140000>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
qcom,pvs-corner-ceiling-nom = <1050000 1080000 1200000>;
qcom,pvs-corner-ceiling-fast = <1050000 1050000 1140000>;
qcom,cpr-step-quotient = <30>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 26c5b8f..9948833 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -36,8 +36,6 @@
qcom,actuator-src = <&actuator0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -79,8 +77,6 @@
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -122,8 +118,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -159,8 +153,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index f61b83a..9cbd45c 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -37,8 +37,6 @@
qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <270>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -80,8 +78,6 @@
qcom,mount-angle = <270>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -123,8 +119,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -160,8 +154,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index cf968d2..bf7f492 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -37,8 +37,6 @@
qcom,mount-angle = <0>;
qcom,actuator-src = <&actuator0>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs2>;
@@ -79,8 +77,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "imx135";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
@@ -123,8 +119,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <180>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs2>;
@@ -159,8 +153,6 @@
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,sensor-name = "mt9m114";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 6ad6213..68af4a6 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -37,8 +37,6 @@
qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "s5k3l1yx";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -79,8 +77,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
@@ -124,8 +120,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov2720";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -161,8 +155,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <0>;
qcom,sensor-name = "mt9m114";
- qcom,vdd-cx-supply = <&pm8841_s2>;
- qcom,vdd-cx-name = "qcom,vdd-cx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index af4030f..f2f73e9 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -184,3 +184,26 @@
status = "ok";
};
};
+
+&cci {
+
+ qcom,camera@6e {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@20 {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@6c {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+
+ qcom,camera@90 {
+ qcom,vdd-cx-supply = <&pm8841_s2>;
+ qcom,vdd-cx-name = "qcom,vdd-cx";
+ };
+};
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 970c03f..1a197a3 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -286,6 +286,7 @@
CONFIG_OV5648=y
CONFIG_MSM_CAMERA_SENSOR=y
# CONFIG_MSM_CPP is not set
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSI22_HEADER=y
CONFIG_MSM_CSIPHY=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 54b1c14..8238414 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -286,6 +286,7 @@
CONFIG_HI256=y
CONFIG_OV12830=y
CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_CCI=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 87e3e5b..696ddf9 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1761,6 +1761,16 @@
help
SMD Transport Layer for IPC Router
+config MSM_IPC_ROUTER_HSIC_XPRT
+ depends on USB_QCOM_IPC_BRIDGE
+ depends on MSM_IPC_ROUTER
+ bool "MSM HSIC XPRT Layer"
+ help
+ HSIC Transport Layer that enables off-chip communication of
+ IPC Router. When the HSIC endpoint becomes available, this layer
+ registers the transport with IPC Router and enable message
+ exchange.
+
config MSM_IPC_ROUTER_SECURITY
depends on MSM_IPC_ROUTER
bool "MSM IPC Router Security support"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 89eb589..dd533f4 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -130,6 +130,7 @@
obj-$(CONFIG_MSM_SMD_NMEA) += smd_nmea.o
obj-$(CONFIG_MSM_RESET_MODEM) += reset_modem.o
obj-$(CONFIG_MSM_IPC_ROUTER_SMD_XPRT) += ipc_router_smd_xprt.o
+obj-$(CONFIG_MSM_IPC_ROUTER_HSIC_XPRT) += ipc_router_hsic_xprt.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
obj-$(CONFIG_MSM_IPC_ROUTER) += ipc_router.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 59c682f..9ea00c1 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -106,7 +106,23 @@
{ 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
- /* No support for 1p5 GHz yet */
+ { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 0 }
+};
+
+static struct clkctl_acpu_speed acpu_freq_tbl_8226_1p6[] = {
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 0, 4 },
+ { 1, 384000, ACPUPLL, 5, 2, CPR_CORNER_SVS, 0, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 0, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 0, 7 },
+ { 1, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1094400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1305600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1344000, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1401600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1497600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
+ { 1, 1593600, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 0, 7 },
{ 0 }
};
@@ -125,8 +141,9 @@
[6] = acpu_freq_tbl_8226_1p2,
[2] = acpu_freq_tbl_8226_1p4,
[5] = acpu_freq_tbl_8226_1p4,
- [3] = acpu_freq_tbl_8226_1p5,
[4] = acpu_freq_tbl_8226_1p5,
+ [7] = acpu_freq_tbl_8226_1p5,
+ [1] = acpu_freq_tbl_8226_1p6,
};
static struct acpuclk_drv_data drv_data = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8410019..6d848d2 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -899,460 +899,38 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 915000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 985000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1000000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1015000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
+static struct acpu_level acpu_freq_tbl_pro_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 999 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 999 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 999 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 805000, 999 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 815000, 999 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 825000, 999 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 835000, 999 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 845000, 999 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 855000, 999 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 865000, 999 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 999 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 999 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 999 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 915000, 999 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 999 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 940000, 999 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 999 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 999 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 999 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 999 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 999 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 999 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 999 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 999 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 999 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 999 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 999 },
+ /* higher frequencies aren't available for bring up */
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 785000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 795000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 805000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 815000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 825000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 835000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 905000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 965000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 865000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 875000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 885000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 900000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 945000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 955000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 755000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 765000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 785000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 795000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 935000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 970000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 755000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 765000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 785000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 795000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 935000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 950000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 960000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 735000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 745000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 755000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 765000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 785000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 795000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 805000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 815000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 825000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 845000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 875000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 885000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 915000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 735000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 745000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 755000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 765000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 785000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 795000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 805000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 815000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 825000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 835000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 845000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 870000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 890000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 895000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 905000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 925000, 691},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 845000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 855000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 915000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 945000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1000000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1020000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1040000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1060000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1080000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1100000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 915000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 995000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1015000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1035000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1055000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1075000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 780000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 790000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 800000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 810000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 820000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 830000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 840000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 850000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 880000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 910000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 970000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 990000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1010000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1030000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1050000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 780000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 790000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 800000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 810000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 820000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 830000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 840000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 865000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 880000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 910000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 925000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 955000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 970000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 985000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1005000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1025000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 760000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 770000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 810000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 830000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 840000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 850000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 865000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 895000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 910000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 925000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 955000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 970000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 985000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1000000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 760000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 770000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 780000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 790000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 800000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 810000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 820000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 830000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 840000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 850000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 860000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 870000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 885000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 900000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 930000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 945000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 960000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 975000, 800},
- { 0, { 0 } }
-};
-
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 725000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 725000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 725000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 725000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 735000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 745000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 755000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 765000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 775000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 785000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 795000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 805000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 815000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 825000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 835000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 845000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 855000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 865000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 875000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 890000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 905000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 920000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 935000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 950000, 800},
- { 0, { 0 } }
-};
static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v1 1.7GHz Parts */
@@ -1396,45 +974,45 @@
};
static struct pvs_table pvs_pro[NUM_SPEED_BINS][NUM_PVS] __initdata = {
- /* 2.0 GHz is not used on 8974Pro */
- [0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
- [0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
- [0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
- [0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
- [0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
- [0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
- [0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ /* Not used by 8974Pro */
+ [0][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [0][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 8974Pro AB 2.3GHz */
- [1][0] = { acpu_ftbl_pro_2p3g_pvs0, sizeof(acpu_ftbl_pro_2p3g_pvs0) },
- [1][1] = { acpu_ftbl_pro_2p3g_pvs1, sizeof(acpu_ftbl_pro_2p3g_pvs1) },
- [1][2] = { acpu_ftbl_pro_2p3g_pvs2, sizeof(acpu_ftbl_pro_2p3g_pvs2) },
- [1][3] = { acpu_ftbl_pro_2p3g_pvs3, sizeof(acpu_ftbl_pro_2p3g_pvs3) },
- [1][4] = { acpu_ftbl_pro_2p3g_pvs4, sizeof(acpu_ftbl_pro_2p3g_pvs4) },
- [1][5] = { acpu_ftbl_pro_2p3g_pvs5, sizeof(acpu_ftbl_pro_2p3g_pvs5) },
- [1][6] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
- [1][7] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
+ /* 8974Pro AB Bringup */
+ [1][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [1][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 2.2GHz is not used on 8974Pro */
- [2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
- [2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
- [2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
- [2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
- [2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
- [2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
- [2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
- [2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ /* Not used by 8974Pro */
+ [2][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [2][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
- /* 8974Pro AC 2.5GHz */
- [3][0] = { acpu_ftbl_pro_2p5g_pvs0, sizeof(acpu_ftbl_pro_2p5g_pvs0) },
- [3][1] = { acpu_ftbl_pro_2p5g_pvs1, sizeof(acpu_ftbl_pro_2p5g_pvs1) },
- [3][2] = { acpu_ftbl_pro_2p5g_pvs2, sizeof(acpu_ftbl_pro_2p5g_pvs2) },
- [3][3] = { acpu_ftbl_pro_2p5g_pvs3, sizeof(acpu_ftbl_pro_2p5g_pvs3) },
- [3][4] = { acpu_ftbl_pro_2p5g_pvs4, sizeof(acpu_ftbl_pro_2p5g_pvs4) },
- [3][5] = { acpu_ftbl_pro_2p5g_pvs5, sizeof(acpu_ftbl_pro_2p5g_pvs5) },
- [3][6] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
- [3][7] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
+ /* 8974Pro Bringup */
+ [3][0] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][1] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][2] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][3] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][4] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][5] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][6] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
+ [3][7] = { acpu_freq_tbl_pro_pvs0, sizeof(acpu_freq_tbl_pro_pvs0) },
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 820bcf9..6281395 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -195,6 +195,7 @@
static struct sps_register_event rx_register_event;
static bool satellite_mode;
static uint32_t num_buffers;
+static unsigned long long last_rx_pkt_timestamp;
static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
static int bam_mux_initialized;
@@ -1117,6 +1118,29 @@
queue_work_on(0, bam_mux_rx_workqueue, &rx_timer_work);
}
+/**
+ * store_rx_timestamp() - store the current raw time as as a timestamp for when
+ * the last rx packet was processed
+ */
+static void store_rx_timestamp(void)
+{
+ last_rx_pkt_timestamp = sched_clock();
+}
+
+/**
+ * log_rx_timestamp() - Log the stored rx pkt timestamp in a human readable
+ * format
+ */
+static void log_rx_timestamp(void)
+{
+ unsigned long long t = last_rx_pkt_timestamp;
+ unsigned long nanosec_rem;
+
+ nanosec_rem = do_div(t, 1000000000U);
+ BAM_DMUX_LOG("Last rx pkt processed at [%6u.%09lu]\n", (unsigned)t,
+ nanosec_rem);
+}
+
static void rx_timer_work_func(struct work_struct *work)
{
struct sps_iovec iov;
@@ -1125,20 +1149,26 @@
int ret;
u32 buffs_unused, buffs_used;
+ BAM_DMUX_LOG("%s: polling start\n", __func__);
while (bam_connection_is_active) { /* timer loop */
++inactive_cycles;
while (bam_connection_is_active) { /* deplete queue loop */
- if (in_global_reset)
+ if (in_global_reset) {
+ BAM_DMUX_LOG(
+ "%s: polling exit, global reset detected\n",
+ __func__);
return;
+ }
ret = sps_get_iovec(bam_rx_pipe, &iov);
if (ret) {
- pr_err("%s: sps_get_iovec failed %d\n",
+ DMUX_LOG_KERR("%s: sps_get_iovec failed %d\n",
__func__, ret);
break;
}
if (iov.addr == 0)
break;
+ store_rx_timestamp();
inactive_cycles = 0;
mutex_lock(&bam_rx_pool_mutexlock);
if (unlikely(list_empty(&bam_rx_pool))) {
@@ -1171,6 +1201,7 @@
}
if (inactive_cycles >= POLLING_INACTIVITY) {
+ BAM_DMUX_LOG("%s: polling exit, no data\n", __func__);
rx_switch_to_interrupt_mode();
break;
}
@@ -1182,7 +1213,8 @@
&buffs_unused);
if (ret) {
- pr_err("%s: error getting num buffers unused after sleep\n",
+ DMUX_LOG_KERR(
+ "%s: error getting num buffers unused after sleep\n",
__func__);
break;
@@ -1768,6 +1800,7 @@
if (time_remaining == 0) {
DMUX_LOG_KERR("%s: shutdown completion timed out\n",
__func__);
+ log_rx_timestamp();
ssrestart_check();
}
}
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index dcce820..5dd9bab 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -73,17 +73,22 @@
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gpio_spi_config = {
+static struct gpiomux_setting gpio_spi_act_config = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gpio_spi_cs_config = {
+static struct gpiomux_setting gpio_spi_cs_act_config = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_6MA,
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting gpio_spi_susp_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
static struct gpiomux_setting gpio_spi_cs_eth_config = {
.func = GPIOMUX_FUNC_4,
@@ -160,25 +165,29 @@
{
.gpio = 0, /* BLSP1 QUP1 SPI_DATA_MOSI */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 1, /* BLSP1 QUP1 SPI_DATA_MISO */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 2, /* BLSP1 QUP1 SPI_CS1 */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_cs_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
.gpio = 3, /* BLSP1 QUP1 SPI_CLK */
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ [GPIOMUX_ACTIVE] = &gpio_spi_act_config,
+ [GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
},
},
{
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index ba792ab..1999379 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2829,6 +2829,8 @@
F_APCS_PLL(1305600000, 68, 0x0, 0x1, 0x0, 0x0, 0x0),
F_APCS_PLL(1344000000, 70, 0x0, 0x1, 0x0, 0x0, 0x0),
F_APCS_PLL(1401600000, 73, 0x0, 0x1, 0x0, 0x0, 0x0),
+ F_APCS_PLL(1497600000, 78, 0x0, 0x1, 0x0, 0x0, 0x0),
+ F_APCS_PLL(1593600000, 83, 0x0, 0x1, 0x0, 0x0, 0x0),
PLL_F_END
};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 92dab97..33dcd9f 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3026,11 +3026,13 @@
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006d"),
CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "6-0078"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-0020"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006a"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006f"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-007d"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006d"),
CLK_LOOKUP("cam_clk", mclk1_clk.c, "6-0078"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-0020"),
+ CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006a"),
/* CSIPHY clocks */
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 3b80374..654dbd3 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4897,10 +4897,29 @@
CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", oFF),
};
-static struct clk_lookup msm_clocks_8974ac_only[] __initdata = {
+static struct clk_lookup msm_clocks_8974pro_only[] __initdata = {
CLK_LOOKUP("gpll4", gpll4_clk_src.c, ""),
CLK_LOOKUP("sleep_clk", gcc_sdcc1_cdccal_sleep_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("cal_clk", gcc_sdcc1_cdccal_ff_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk2_clk_src.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+};
+
+static struct clk_lookup msm_clocks_8974_only[] __initdata = {
+ CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", gp1_clk_src.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mmss_gp1_clk_src.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "20.qcom,camera"),
+ CLK_LOOKUP("cam_clk", gcc_gp1_clk.c, "6c.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_gp1_clk.c, "90.qcom,camera"),
};
static struct clk_lookup msm_clocks_8974_common[] __initdata = {
@@ -5076,22 +5095,16 @@
CLK_LOOKUP("core_clk_src", mdp_clk_src.c, "mdp.0"),
CLK_LOOKUP("vsync_clk", mdss_vsync_clk.c, "mdp.0"),
- /* MM sensor clocks */
- CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "6e.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mmss_gp0_clk_src.c, "20.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", gp1_clk_src.c, "6c.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mmss_gp1_clk_src.c, "90.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "6e.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_gp0_clk.c, "20.qcom,camera"),
- CLK_LOOKUP("cam_clk", gcc_gp1_clk.c, "6c.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_gp1_clk.c, "90.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, ""),
- CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, ""),
- CLK_LOOKUP("cam_clk", camss_mclk3_clk.c, ""),
- CLK_LOOKUP("cam_gp0_src_clk", mmss_gp0_clk_src.c, ""),
- CLK_LOOKUP("cam_gp1_src_clk", mmss_gp1_clk_src.c, ""),
- CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
- CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
+ /* MM sensor clocks placeholder */
+ CLK_LOOKUP("", camss_mclk0_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk1_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk2_clk.c, ""),
+ CLK_LOOKUP("", camss_mclk3_clk.c, ""),
+ CLK_LOOKUP("", mmss_gp0_clk_src.c, ""),
+ CLK_LOOKUP("", mmss_gp1_clk_src.c, ""),
+ CLK_LOOKUP("", camss_gp0_clk.c, ""),
+ CLK_LOOKUP("", camss_gp1_clk.c, ""),
+
/* CCI clocks */
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
"fda0c000.qcom,cci"),
@@ -5450,7 +5463,8 @@
};
static struct clk_lookup msm_clocks_8974[ARRAY_SIZE(msm_clocks_8974_common)
- + ARRAY_SIZE(msm_clocks_8974ac_only)];
+ + ARRAY_SIZE(msm_clocks_8974_only)
+ + ARRAY_SIZE(msm_clocks_8974pro_only)];
static struct pll_config_regs mmpll0_regs __initdata = {
.l_reg = (void __iomem *)MMPLL0_L_REG,
@@ -5797,18 +5811,26 @@
memcpy(msm_clocks_8974, msm_clocks_8974_common,
sizeof(msm_clocks_8974_common));
- msm8974_clock_init_data.size -= ARRAY_SIZE(msm_clocks_8974ac_only);
- /* version specific changes */
+ /* version specific clock changes */
if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2
|| cpu_is_msm8974pro())
msm8974_v2_clock_override();
- if (cpu_is_msm8974pro()) {
+ if (cpu_is_msm8974pro())
msm8974_pro_clock_override();
+
+ /* version specific lookup table changes */
+ if (cpu_is_msm8974()) {
memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
- msm_clocks_8974ac_only, sizeof(msm_clocks_8974ac_only));
+ msm_clocks_8974_only, sizeof(msm_clocks_8974_only));
msm8974_clock_init_data.size +=
- ARRAY_SIZE(msm_clocks_8974ac_only);
+ ARRAY_SIZE(msm_clocks_8974_only);
+ } else if (cpu_is_msm8974pro()) {
+ memcpy(msm_clocks_8974 + ARRAY_SIZE(msm_clocks_8974_common),
+ msm_clocks_8974pro_only,
+ sizeof(msm_clocks_8974pro_only));
+ msm8974_clock_init_data.size +=
+ ARRAY_SIZE(msm_clocks_8974pro_only);
}
clk_ops_pixel_clock = clk_ops_pixel;
@@ -5841,7 +5863,7 @@
struct clock_init_data msm8974_clock_init_data __initdata = {
.table = msm_clocks_8974,
- .size = ARRAY_SIZE(msm_clocks_8974),
+ .size = ARRAY_SIZE(msm_clocks_8974_common),
.pre_init = msm8974_clock_pre_init,
.post_init = msm8974_clock_post_init,
};
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index b69b155..59e0e2a 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -148,7 +148,7 @@
void __iomem *efuse_base;
/* Process voltage parameters */
- u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
+ u32 pvs_init_v[CPR_PVS_EFUSE_BINS_MAX];
u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
/* Process voltage variables */
u32 pvs_bin;
@@ -999,6 +999,7 @@
u64 efuse_bits;
int rc, process;
u32 pvs_fuse[3], pvs_fuse_redun_sel[4];
+ u32 init_v;
bool redundant;
size_t pvs_bins;
@@ -1034,25 +1035,35 @@
((1 << pvs_fuse[2]) - 1);
pvs_bins = 1 << pvs_fuse[2];
- rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
- cpr_vreg->pvs_bin_process,
- pvs_bins);
+
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-init-voltage",
+ cpr_vreg->pvs_init_v, pvs_bins);
if (rc < 0) {
- pr_err("pvs-bin-process missing: rc=%d\n", rc);
+ pr_err("pvs-init-voltage missing: rc=%d\n", rc);
return rc;
}
- process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
- pr_info("[row:%d] = 0x%llX, n_bits=%d, bin=%d (%d)\n",
- pvs_fuse[0], efuse_bits, pvs_fuse[2],
- cpr_vreg->pvs_bin, process);
+ init_v = cpr_vreg->pvs_init_v[cpr_vreg->pvs_bin];
+ for (process = NUM_APC_PVS - 1; process > APC_PVS_NO; process--) {
+ if (init_v <= cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO])
+ break;
+ }
- if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
- pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
- cpr_vreg->pvs_bin, process);
+ if (process == APC_PVS_NO) {
+ process = APC_PVS_SLOW;
+ cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO] = init_v;
+ cpr_vreg->ceiling_max = init_v;
+ } else if (process == APC_PVS_FAST &&
+ init_v < cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_CORNER_SVS]) {
process = APC_PVS_SLOW;
}
+ pr_info("[row:%d] = 0x%llX, n_bits=%d, bin=%d (%d)",
+ pvs_fuse[0], efuse_bits, pvs_fuse[2],
+ cpr_vreg->pvs_bin, process);
+ pr_info("pvs initial turbo voltage_= from %u to %u\n",
+ init_v, cpr_vreg->pvs_corner_v[process][CPR_CORNER_TURBO]);
+
cpr_vreg->process = process;
return 0;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 6fe945c..ce66531 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -298,6 +298,8 @@
pr_err("%s: failure\n", __func__);
return NULL;
}
+ memcpy(&(cloned_pkt->hdr), &(pkt->hdr), sizeof(struct rr_header_v1));
+ /* TODO: Copy optional headers, if available */
pkt_fragment_q = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
if (!pkt_fragment_q) {
@@ -323,6 +325,7 @@
kfree_skb(temp_skb);
}
kfree(pkt_fragment_q);
+ /* TODO: Free optional headers, if present */
kfree(cloned_pkt);
return NULL;
}
@@ -361,6 +364,7 @@
kfree_skb(temp_skb);
}
kfree(pkt->pkt_fragment_q);
+ /* TODO: Free Optional headers, if present */
kfree(pkt);
return;
}
@@ -373,6 +377,8 @@
int first = 1, offset = 0;
int skb_size, data_size;
void *data;
+ int last = 1;
+ int align_size;
skb_head = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
if (!skb_head) {
@@ -382,10 +388,13 @@
skb_queue_head_init(skb_head);
data_size = buf_len;
+ align_size = ALIGN_SIZE(data_size);
while (offset != buf_len) {
skb_size = data_size;
if (first)
skb_size += IPC_ROUTER_HDR_SIZE;
+ if (last)
+ skb_size += align_size;
skb = alloc_skb(skb_size, GFP_KERNEL);
if (!skb) {
@@ -394,6 +403,7 @@
goto buf_to_skb_error;
}
data_size = data_size / 2;
+ last = 0;
continue;
}
@@ -407,6 +417,7 @@
skb_queue_tail(skb_head, skb);
offset += data_size;
data_size = buf_len - offset;
+ last = 1;
}
return skb_head;
@@ -447,7 +458,7 @@
return buf;
}
-static void msm_ipc_router_free_skb(struct sk_buff_head *skb_head)
+void msm_ipc_router_free_skb(struct sk_buff_head *skb_head)
{
struct sk_buff *temp_skb;
@@ -461,6 +472,328 @@
kfree(skb_head);
}
+/**
+ * extract_header_v1() - Extract IPC Router header of version 1
+ * @pkt: Packet structure into which the header has to be extraced.
+ * @skb: SKB from which the header has to be extracted.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ */
+static int extract_header_v1(struct rr_packet *pkt, struct sk_buff *skb)
+{
+ if (!pkt || !skb) {
+ pr_err("%s: Invalid pkt or skb\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(&pkt->hdr, skb->data, sizeof(struct rr_header_v1));
+ skb_pull(skb, sizeof(struct rr_header_v1));
+ pkt->length -= sizeof(struct rr_header_v1);
+ return 0;
+}
+
+/**
+ * extract_header_v2() - Extract IPC Router header of version 2
+ * @pkt: Packet structure into which the header has to be extraced.
+ * @skb: SKB from which the header has to be extracted.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ */
+static int extract_header_v2(struct rr_packet *pkt, struct sk_buff *skb)
+{
+ struct rr_header_v2 *hdr;
+
+ if (!pkt || !skb) {
+ pr_err("%s: Invalid pkt or skb\n", __func__);
+ return -EINVAL;
+ }
+
+ hdr = (struct rr_header_v2 *)skb->data;
+ pkt->hdr.version = (uint32_t)hdr->version;
+ pkt->hdr.type = (uint32_t)hdr->type;
+ pkt->hdr.src_node_id = (uint32_t)hdr->src_node_id;
+ pkt->hdr.src_port_id = (uint32_t)hdr->src_port_id;
+ pkt->hdr.size = (uint32_t)hdr->size;
+ pkt->hdr.control_flag = (uint32_t)hdr->control_flag;
+ pkt->hdr.dst_node_id = (uint32_t)hdr->dst_node_id;
+ pkt->hdr.dst_port_id = (uint32_t)hdr->dst_port_id;
+ skb_pull(skb, sizeof(struct rr_header_v2));
+ pkt->length -= sizeof(struct rr_header_v2);
+ return 0;
+}
+
+/**
+ * extract_header() - Extract IPC Router header
+ * @pkt: Packet from which the header has to be extraced.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ *
+ * This function will check if the header version is v1 or v2 and invoke
+ * the corresponding helper function to extract the IPC Router header.
+ */
+static int extract_header(struct rr_packet *pkt)
+{
+ struct sk_buff *temp_skb;
+ int ret;
+
+ if (!pkt) {
+ pr_err("%s: NULL PKT\n", __func__);
+ return -EINVAL;
+ }
+
+ temp_skb = skb_peek(pkt->pkt_fragment_q);
+ if (!temp_skb || !temp_skb->data) {
+ pr_err("%s: No SKBs in skb_queue\n", __func__);
+ return -EINVAL;
+ }
+
+ if (temp_skb->data[0] == IPC_ROUTER_V1) {
+ ret = extract_header_v1(pkt, temp_skb);
+ } else if (temp_skb->data[0] == IPC_ROUTER_V2) {
+ ret = extract_header_v2(pkt, temp_skb);
+ /* TODO: Extract optional headers if present */
+ } else {
+ pr_err("%s: Invalid Header version %02x\n",
+ __func__, temp_skb->data[0]);
+ print_hex_dump(KERN_ERR, "Header: ", DUMP_PREFIX_ADDRESS,
+ 16, 1, temp_skb->data, pkt->length, true);
+ return -EINVAL;
+ }
+ return ret;
+}
+
+/**
+ * calc_tx_header_size() - Calculate header size to be reserved in SKB
+ * @pkt: Packet in which the space for header has to be reserved.
+ * @dst_xprt_info: XPRT through which the destination is reachable.
+ *
+ * @return: required header size on success,
+ * starndard Linux error codes on failure.
+ *
+ * This function is used to calculate the header size that has to be reserved
+ * in a transmit SKB. The header size is calculated based on the XPRT through
+ * which the destination node is reachable.
+ */
+static int calc_tx_header_size(struct rr_packet *pkt,
+ struct msm_ipc_router_xprt_info *dst_xprt_info)
+{
+ int hdr_size = 0;
+ int xprt_version = 0;
+ struct msm_ipc_routing_table_entry *rt_entry;
+ struct msm_ipc_router_xprt_info *xprt_info = dst_xprt_info;
+
+ if (!pkt) {
+ pr_err("%s: NULL PKT\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!xprt_info) {
+ rt_entry = lookup_routing_table(pkt->hdr.dst_node_id);
+ if (!rt_entry || !(rt_entry->xprt_info)) {
+ pr_err("%s: Node %d is not up\n",
+ __func__, pkt->hdr.dst_node_id);
+ return -ENODEV;
+ }
+
+ xprt_info = rt_entry->xprt_info;
+ }
+ if (xprt_info)
+ xprt_version = xprt_info->xprt->get_version(xprt_info->xprt);
+
+ if (xprt_version == IPC_ROUTER_V1) {
+ pkt->hdr.version = IPC_ROUTER_V1;
+ hdr_size = sizeof(struct rr_header_v1);
+ } else if (xprt_version == IPC_ROUTER_V2) {
+ pkt->hdr.version = IPC_ROUTER_V2;
+ hdr_size = sizeof(struct rr_header_v2);
+ /* TODO: Calculate optional header length, if present */
+ } else {
+ pr_err("%s: Invalid xprt_version %d\n",
+ __func__, xprt_version);
+ hdr_size = -EINVAL;
+ }
+
+ return hdr_size;
+}
+
+/**
+ * prepend_header_v1() - Prepend IPC Router header of version 1
+ * @pkt: Packet structure which contains the header info to be prepended.
+ * @hdr_size: Size of the header
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ */
+static int prepend_header_v1(struct rr_packet *pkt, int hdr_size)
+{
+ struct sk_buff *temp_skb;
+ struct rr_header_v1 *hdr;
+
+ if (!pkt || hdr_size <= 0) {
+ pr_err("%s: Invalid input parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ temp_skb = skb_peek(pkt->pkt_fragment_q);
+ if (!temp_skb || !temp_skb->data) {
+ pr_err("%s: No SKBs in skb_queue\n", __func__);
+ return -EINVAL;
+ }
+
+ if (skb_headroom(temp_skb) < hdr_size) {
+ temp_skb = alloc_skb(hdr_size, GFP_KERNEL);
+ if (!temp_skb) {
+ pr_err("%s: Could not allocate SKB of size %d\n",
+ __func__, hdr_size);
+ return -ENOMEM;
+ }
+ }
+
+ hdr = (struct rr_header_v1 *)skb_push(temp_skb, hdr_size);
+ memcpy(hdr, &pkt->hdr, hdr_size);
+ if (temp_skb != skb_peek(pkt->pkt_fragment_q))
+ skb_queue_head(pkt->pkt_fragment_q, temp_skb);
+ pkt->length += hdr_size;
+ return 0;
+}
+
+/**
+ * prepend_header_v2() - Prepend IPC Router header of version 2
+ * @pkt: Packet structure which contains the header info to be prepended.
+ * @hdr_size: Size of the header
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ */
+static int prepend_header_v2(struct rr_packet *pkt, int hdr_size)
+{
+ struct sk_buff *temp_skb;
+ struct rr_header_v2 *hdr;
+
+ if (!pkt || hdr_size <= 0) {
+ pr_err("%s: Invalid input parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ temp_skb = skb_peek(pkt->pkt_fragment_q);
+ if (!temp_skb || !temp_skb->data) {
+ pr_err("%s: No SKBs in skb_queue\n", __func__);
+ return -EINVAL;
+ }
+
+ if (skb_headroom(temp_skb) < hdr_size) {
+ temp_skb = alloc_skb(hdr_size, GFP_KERNEL);
+ if (!temp_skb) {
+ pr_err("%s: Could not allocate SKB of size %d\n",
+ __func__, hdr_size);
+ return -ENOMEM;
+ }
+ }
+
+ hdr = (struct rr_header_v2 *)skb_push(temp_skb, hdr_size);
+ hdr->version = (uint8_t)pkt->hdr.version;
+ hdr->type = (uint8_t)pkt->hdr.type;
+ hdr->control_flag = (uint16_t)pkt->hdr.control_flag;
+ hdr->size = (uint32_t)pkt->hdr.size;
+ hdr->src_node_id = (uint16_t)pkt->hdr.src_node_id;
+ hdr->src_port_id = (uint16_t)pkt->hdr.src_port_id;
+ hdr->dst_node_id = (uint16_t)pkt->hdr.dst_node_id;
+ hdr->dst_port_id = (uint16_t)pkt->hdr.dst_port_id;
+ /* TODO: Add optional headers, if present */
+ if (temp_skb != skb_peek(pkt->pkt_fragment_q))
+ skb_queue_head(pkt->pkt_fragment_q, temp_skb);
+ pkt->length += hdr_size;
+ return 0;
+}
+
+/**
+ * prepend_header() - Prepend IPC Router header
+ * @pkt: Packet structure which contains the header info to be prepended.
+ * @xprt_info: XPRT through which the packet is transmitted.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ *
+ * This function prepends the header to the packet to be transmitted. The
+ * IPC Router header version to be prepended depends on the XPRT through
+ * which the destination is reachable.
+ */
+static int prepend_header(struct rr_packet *pkt,
+ struct msm_ipc_router_xprt_info *xprt_info)
+{
+ int hdr_size;
+ struct sk_buff *temp_skb;
+
+ if (!pkt) {
+ pr_err("%s: NULL PKT\n", __func__);
+ return -EINVAL;
+ }
+
+ temp_skb = skb_peek(pkt->pkt_fragment_q);
+ if (!temp_skb || !temp_skb->data) {
+ pr_err("%s: No SKBs in skb_queue\n", __func__);
+ return -EINVAL;
+ }
+
+ hdr_size = calc_tx_header_size(pkt, xprt_info);
+ if (hdr_size <= 0)
+ return hdr_size;
+
+ if (pkt->hdr.version == IPC_ROUTER_V1)
+ return prepend_header_v1(pkt, hdr_size);
+ else if (pkt->hdr.version == IPC_ROUTER_V2)
+ return prepend_header_v2(pkt, hdr_size);
+ else
+ return -EINVAL;
+}
+
+/**
+ * defragment_pkt() - Defragment and linearize the packet
+ * @pkt: Packet to be linearized.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ *
+ * Some packets contain fragments of data over multiple SKBs. If an XPRT
+ * does not supported fragmented writes, linearize multiple SKBs into one
+ * single SKB.
+ */
+static int defragment_pkt(struct rr_packet *pkt)
+{
+ struct sk_buff *dst_skb, *src_skb, *temp_skb;
+ int offset = 0, buf_len = 0, copy_len;
+ void *buf;
+ int align_size;
+
+ if (!pkt || pkt->length <= 0) {
+ pr_err("%s: Invalid PKT\n", __func__);
+ return -EINVAL;
+ }
+
+ if (skb_queue_len(pkt->pkt_fragment_q) == 1)
+ return 0;
+
+ align_size = ALIGN_SIZE(pkt->length);
+ dst_skb = alloc_skb(pkt->length + align_size, GFP_KERNEL);
+ if (!dst_skb) {
+ pr_err("%s: could not allocate one skb of size %d\n",
+ __func__, pkt->length);
+ return -ENOMEM;
+ }
+ buf = skb_put(dst_skb, pkt->length);
+ buf_len = pkt->length;
+
+ skb_queue_walk(pkt->pkt_fragment_q, src_skb) {
+ copy_len = buf_len < src_skb->len ? buf_len : src_skb->len;
+ memcpy(buf + offset, src_skb->data, copy_len);
+ offset += copy_len;
+ buf_len -= copy_len;
+ }
+
+ while (!skb_queue_empty(pkt->pkt_fragment_q)) {
+ temp_skb = skb_dequeue(pkt->pkt_fragment_q);
+ kfree_skb(temp_skb);
+ }
+ skb_queue_tail(pkt->pkt_fragment_q, dst_skb);
+ return 0;
+}
+
static int post_pkt_to_port(struct msm_ipc_port *port_ptr,
struct rr_packet *pkt, int clone)
{
@@ -515,7 +848,7 @@
down_read(&local_ports_lock_lha2);
do {
next_port_id++;
- if ((next_port_id & 0xFFFFFFFE) == 0xFFFFFFFE)
+ if ((next_port_id & IPC_ROUTER_ADDRESS) == IPC_ROUTER_ADDRESS)
next_port_id = 1;
key = (next_port_id & (LP_HASH_SIZE - 1));
@@ -932,7 +1265,7 @@
{
struct rr_packet *pkt;
struct sk_buff *ipc_rtr_pkt;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
int pkt_size;
void *data;
struct sk_buff_head *pkt_fragment_q;
@@ -973,32 +1306,33 @@
skb_reserve(ipc_rtr_pkt, IPC_ROUTER_HDR_SIZE);
data = skb_put(ipc_rtr_pkt, sizeof(*msg));
memcpy(data, msg, sizeof(*msg));
- hdr = (struct rr_header *)skb_push(ipc_rtr_pkt, IPC_ROUTER_HDR_SIZE);
- if (!hdr) {
- pr_err("%s: skb_push failed\n", __func__);
- kfree_skb(ipc_rtr_pkt);
- kfree(pkt_fragment_q);
- kfree(pkt);
- return -ENOMEM;
- }
+ skb_queue_tail(pkt_fragment_q, ipc_rtr_pkt);
+ pkt->pkt_fragment_q = pkt_fragment_q;
+ pkt->length = sizeof(*msg);
- hdr->version = IPC_ROUTER_VERSION;
+ hdr = &(pkt->hdr);
+ hdr->version = IPC_ROUTER_V1;
hdr->type = msg->cmd;
hdr->src_node_id = IPC_ROUTER_NID_LOCAL;
hdr->src_port_id = IPC_ROUTER_ADDRESS;
- hdr->confirm_rx = 0;
+ hdr->control_flag = 0;
hdr->size = sizeof(*msg);
if (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)
hdr->dst_node_id = dst_node_id;
else
hdr->dst_node_id = xprt_info->remote_node_id;
hdr->dst_port_id = IPC_ROUTER_ADDRESS;
- skb_queue_tail(pkt_fragment_q, ipc_rtr_pkt);
- pkt->pkt_fragment_q = pkt_fragment_q;
- pkt->length = pkt_size;
mutex_lock(&xprt_info->tx_lock_lhb2);
- ret = xprt_info->xprt->write(pkt, pkt_size, xprt_info->xprt);
+ ret = prepend_header(pkt, xprt_info);
+ if (ret < 0) {
+ mutex_unlock(&xprt_info->tx_lock_lhb2);
+ pr_err("%s: Prepend Header failed\n", __func__);
+ release_pkt(pkt);
+ return ret;
+ }
+
+ ret = xprt_info->xprt->write(pkt, pkt->length, xprt_info->xprt);
mutex_unlock(&xprt_info->tx_lock_lhb2);
release_pkt(pkt);
@@ -1074,7 +1408,7 @@
{
struct rr_packet *pkt;
struct sk_buff *ipc_rtr_pkt;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
int pkt_size;
void *data;
struct sk_buff_head *pkt_fragment_q;
@@ -1094,7 +1428,7 @@
}
skb_queue_head_init(pkt_fragment_q);
- pkt_size = IPC_ROUTER_HDR_SIZE + sizeof(*msg);
+ pkt_size = sizeof(*msg);
ipc_rtr_pkt = alloc_skb(pkt_size, GFP_KERNEL);
if (!ipc_rtr_pkt) {
pr_err("%s: ipc_rtr_pkt alloc failed\n", __func__);
@@ -1103,22 +1437,14 @@
return -ENOMEM;
}
- skb_reserve(ipc_rtr_pkt, IPC_ROUTER_HDR_SIZE);
data = skb_put(ipc_rtr_pkt, sizeof(*msg));
memcpy(data, msg, sizeof(*msg));
- hdr = (struct rr_header *)skb_push(ipc_rtr_pkt, IPC_ROUTER_HDR_SIZE);
- if (!hdr) {
- pr_err("%s: skb_push failed\n", __func__);
- kfree_skb(ipc_rtr_pkt);
- kfree(pkt_fragment_q);
- kfree(pkt);
- return -ENOMEM;
- }
- hdr->version = IPC_ROUTER_VERSION;
+ hdr = &(pkt->hdr);
+ hdr->version = IPC_ROUTER_V1;
hdr->type = msg->cmd;
hdr->src_node_id = IPC_ROUTER_NID_LOCAL;
hdr->src_port_id = IPC_ROUTER_ADDRESS;
- hdr->confirm_rx = 0;
+ hdr->control_flag = 0;
hdr->size = sizeof(*msg);
hdr->dst_node_id = IPC_ROUTER_NID_LOCAL;
hdr->dst_port_id = IPC_ROUTER_ADDRESS;
@@ -1164,70 +1490,60 @@
return 0;
}
-static int relay_msg(struct msm_ipc_router_xprt_info *xprt_info,
- struct rr_packet *pkt)
-{
- struct msm_ipc_router_xprt_info *fwd_xprt_info;
-
- if (!xprt_info || !pkt)
- return -EINVAL;
-
- down_read(&xprt_info_list_lock_lha5);
- list_for_each_entry(fwd_xprt_info, &xprt_info_list, list) {
- mutex_lock(&fwd_xprt_info->tx_lock_lhb2);
- if (xprt_info->xprt->link_id != fwd_xprt_info->xprt->link_id)
- fwd_xprt_info->xprt->write(pkt, pkt->length,
- fwd_xprt_info->xprt);
- mutex_unlock(&fwd_xprt_info->tx_lock_lhb2);
- }
- up_read(&xprt_info_list_lock_lha5);
- return 0;
-}
-
static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info,
struct rr_packet *pkt)
{
- uint32_t dst_node_id;
- struct sk_buff *head_pkt;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
struct msm_ipc_router_xprt_info *fwd_xprt_info;
struct msm_ipc_routing_table_entry *rt_entry;
int ret = 0;
+ int fwd_xprt_option;
if (!xprt_info || !pkt)
return -EINVAL;
- head_pkt = skb_peek(pkt->pkt_fragment_q);
- if (!head_pkt)
- return -EINVAL;
-
- hdr = (struct rr_header *)head_pkt->data;
- dst_node_id = hdr->dst_node_id;
+ hdr = &(pkt->hdr);
down_read(&routing_table_lock_lha3);
- rt_entry = lookup_routing_table(dst_node_id);
+ rt_entry = lookup_routing_table(hdr->dst_node_id);
if (!(rt_entry) || !(rt_entry->xprt_info)) {
- up_read(&routing_table_lock_lha3);
pr_err("%s: Routing table not initialized\n", __func__);
- return -ENODEV;
+ ret = -ENODEV;
+ goto fm_error1;
}
down_read(&rt_entry->lock_lha4);
fwd_xprt_info = rt_entry->xprt_info;
+ ret = prepend_header(pkt, fwd_xprt_info);
+ if (ret < 0) {
+ pr_err("%s: Prepend Header failed\n", __func__);
+ goto fm_error2;
+ }
+ fwd_xprt_option = fwd_xprt_info->xprt->get_option(fwd_xprt_info->xprt);
+ if (!(fwd_xprt_option & FRAG_PKT_WRITE_ENABLE)) {
+ ret = defragment_pkt(pkt);
+ if (ret < 0)
+ goto fm_error2;
+ }
+
+ mutex_lock(&fwd_xprt_info->tx_lock_lhb2);
if (xprt_info->remote_node_id == fwd_xprt_info->remote_node_id) {
pr_err("%s: Discarding Command to route back\n", __func__);
ret = -EINVAL;
- goto fwd_msg_out;
+ goto fm_error3;
}
if (xprt_info->xprt->link_id == fwd_xprt_info->xprt->link_id) {
pr_err("%s: DST in the same cluster\n", __func__);
- goto fwd_msg_out;
+ ret = 0;
+ goto fm_error3;
}
- mutex_lock(&fwd_xprt_info->tx_lock_lhb2);
fwd_xprt_info->xprt->write(pkt, pkt->length, fwd_xprt_info->xprt);
+
+fm_error3:
mutex_unlock(&fwd_xprt_info->tx_lock_lhb2);
-fwd_msg_out:
+fm_error2:
up_read(&rt_entry->lock_lha4);
+fm_error1:
up_read(&routing_table_lock_lha3);
return ret;
@@ -1470,7 +1786,7 @@
}
static int process_hello_msg(struct msm_ipc_router_xprt_info *xprt_info,
- struct rr_header *hdr)
+ struct rr_header_v1 *hdr)
{
int i, rc = 0;
union rr_control_msg ctl;
@@ -1508,7 +1824,7 @@
/* Send a reply HELLO message */
memset(&ctl, 0, sizeof(ctl));
- ctl.cmd = IPC_ROUTER_CTRL_CMD_HELLO;
+ ctl.hello.cmd = IPC_ROUTER_CTRL_CMD_HELLO;
rc = msm_ipc_router_send_control_msg(xprt_info, &ctl,
IPC_ROUTER_DUMMY_DEST_NODE);
if (rc < 0) {
@@ -1654,7 +1970,7 @@
* to the cluster from which this message is received. Notify the
* local clients waiting for this service.
*/
- relay_msg(xprt_info, pkt);
+ relay_ctl_msg(xprt_info, msg);
post_control_ports(pkt);
return 0;
}
@@ -1677,7 +1993,7 @@
* belong to the cluster from which this message is received.
* Notify the local clients communicating with the service.
*/
- relay_msg(xprt_info, pkt);
+ relay_ctl_msg(xprt_info, msg);
post_control_ports(pkt);
}
up_write(&server_list_lock_lha2);
@@ -1697,7 +2013,7 @@
msm_ipc_router_destroy_remote_port(rport_ptr);
up_write(&routing_table_lock_lha3);
- relay_msg(xprt_info, pkt);
+ relay_ctl_msg(xprt_info, msg);
post_control_ports(pkt);
return 0;
}
@@ -1707,26 +2023,20 @@
{
union rr_control_msg *msg;
int rc = 0;
- struct sk_buff *temp_ptr;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
- if (pkt->length != (IPC_ROUTER_HDR_SIZE + sizeof(*msg))) {
+ if (pkt->length != sizeof(*msg)) {
pr_err("%s: r2r msg size %d != %d\n", __func__, pkt->length,
- (IPC_ROUTER_HDR_SIZE + sizeof(*msg)));
+ sizeof(*msg));
return -EINVAL;
}
- temp_ptr = skb_peek(pkt->pkt_fragment_q);
- if (!temp_ptr) {
- pr_err("%s: pkt_fragment_q is empty\n", __func__);
- return -EINVAL;
+ hdr = &(pkt->hdr);
+ msg = msm_ipc_router_skb_to_buf(pkt->pkt_fragment_q, sizeof(*msg));
+ if (!msg) {
+ pr_err("%s: Error extracting control msg\n", __func__);
+ return -ENOMEM;
}
- hdr = (struct rr_header *)temp_ptr->data;
- if (!hdr) {
- pr_err("%s: No data inside the skb\n", __func__);
- return -EINVAL;
- }
- msg = (union rr_control_msg *)((char *)hdr + IPC_ROUTER_HDR_SIZE);
switch (msg->cmd) {
case IPC_ROUTER_CTRL_CMD_HELLO:
@@ -1752,17 +2062,17 @@
RR("o UNKNOWN(%08x)\n", msg->cmd);
rc = -ENOSYS;
}
-
+ kfree(msg);
return rc;
}
static void do_read_data(struct work_struct *work)
{
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
struct rr_packet *pkt = NULL;
struct msm_ipc_port *port_ptr;
- struct sk_buff *head_skb;
struct msm_ipc_router_remote_port *rport_ptr;
+ int ret;
struct msm_ipc_router_xprt_info *xprt_info =
container_of(work,
@@ -1777,24 +2087,15 @@
goto fail_data;
}
- head_skb = skb_peek(pkt->pkt_fragment_q);
- if (!head_skb) {
- pr_err("%s: head_skb is invalid\n", __func__);
+ ret = extract_header(pkt);
+ if (ret < 0)
goto fail_data;
- }
-
- hdr = (struct rr_header *)(head_skb->data);
+ hdr = &(pkt->hdr);
RAW("ver=%d type=%d src=%d:%08x crx=%d siz=%d dst=%d:%08x\n",
hdr->version, hdr->type, hdr->src_node_id,
- hdr->src_port_id, hdr->confirm_rx, hdr->size,
+ hdr->src_port_id, hdr->control_flag, hdr->size,
hdr->dst_node_id, hdr->dst_port_id);
- if (hdr->version != IPC_ROUTER_VERSION) {
- pr_err("version %d != %d\n",
- hdr->version, IPC_ROUTER_VERSION);
- goto fail_data;
- }
-
if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) &&
((hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX) ||
(hdr->type == IPC_ROUTER_CTRL_CMD_DATA))) {
@@ -1803,8 +2104,7 @@
continue;
}
- if ((hdr->dst_port_id == IPC_ROUTER_ADDRESS) ||
- (hdr->type == IPC_ROUTER_CTRL_CMD_HELLO)) {
+ if (hdr->type != IPC_ROUTER_CTRL_CMD_DATA) {
process_control_msg(xprt_info, pkt);
release_pkt(pkt);
continue;
@@ -1819,7 +2119,7 @@
(hdr->src_port_id & 0xffffff),
(hdr->dst_node_id << 24) |
(hdr->dst_port_id & 0xffffff),
- (hdr->type << 24) | (hdr->confirm_rx << 16) |
+ (hdr->type << 24) | (hdr->control_flag << 16) |
(hdr->size & 0xffff));
}
#endif
@@ -1906,6 +2206,7 @@
ctl.srv.port_id = port_ptr->this_port.port_id;
up_write(&server_list_lock_lha2);
broadcast_ctl_msg(&ctl);
+ broadcast_ctl_msg_locally(&ctl);
spin_lock_irqsave(&port_ptr->port_lock, flags);
port_ptr->type = SERVER_PORT;
port_ptr->mode_info.mode = MULTI_LINK_MODE;
@@ -1957,6 +2258,7 @@
port_ptr->this_port.port_id);
up_write(&server_list_lock_lha2);
broadcast_ctl_msg(&ctl);
+ broadcast_ctl_msg_locally(&ctl);
spin_lock_irqsave(&port_ptr->port_lock, flags);
port_ptr->type = CLIENT_PORT;
spin_unlock_irqrestore(&port_ptr->port_lock, flags);
@@ -1967,8 +2269,7 @@
uint32_t port_id,
struct sk_buff_head *data)
{
- struct sk_buff *head_skb;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
struct msm_ipc_port *port_ptr;
struct rr_packet *pkt;
int ret_len;
@@ -1983,34 +2284,22 @@
pr_err("%s: New pkt create failed\n", __func__);
return -ENOMEM;
}
-
- head_skb = skb_peek(pkt->pkt_fragment_q);
- if (!head_skb) {
- pr_err("%s: pkt_fragment_q is empty\n", __func__);
- release_pkt(pkt);
- return -EINVAL;
- }
- hdr = (struct rr_header *)skb_push(head_skb, IPC_ROUTER_HDR_SIZE);
- if (!hdr) {
- pr_err("%s: Prepend Header failed\n", __func__);
- release_pkt(pkt);
- return -ENOMEM;
- }
- hdr->version = IPC_ROUTER_VERSION;
+ hdr = &(pkt->hdr);
+ hdr->version = IPC_ROUTER_V1;
hdr->type = IPC_ROUTER_CTRL_CMD_DATA;
hdr->src_node_id = src->this_port.node_id;
hdr->src_port_id = src->this_port.port_id;
hdr->size = pkt->length;
- hdr->confirm_rx = 0;
+ hdr->control_flag = 0;
hdr->dst_node_id = IPC_ROUTER_NID_LOCAL;
hdr->dst_port_id = port_id;
- pkt->length += IPC_ROUTER_HDR_SIZE;
down_read(&local_ports_lock_lha2);
port_ptr = msm_ipc_router_lookup_local_port(port_id);
if (!port_ptr) {
pr_err("%s: Local port %d not present\n", __func__, port_id);
up_read(&local_ports_lock_lha2);
+ pkt->pkt_fragment_q = NULL;
release_pkt(pkt);
return -ENODEV;
}
@@ -2027,35 +2316,26 @@
struct msm_ipc_router_remote_port *rport_ptr,
struct rr_packet *pkt)
{
- struct sk_buff *head_skb;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
struct msm_ipc_router_xprt_info *xprt_info;
struct msm_ipc_routing_table_entry *rt_entry;
struct msm_ipc_resume_tx_port *resume_tx_port;
+ struct sk_buff *temp_skb;
+ int xprt_option;
int ret;
+ int align_size;
if (!rport_ptr || !src || !pkt)
return -EINVAL;
- head_skb = skb_peek(pkt->pkt_fragment_q);
- if (!head_skb) {
- pr_err("%s: pkt_fragment_q is empty\n", __func__);
- return -EINVAL;
- }
- hdr = (struct rr_header *)skb_push(head_skb, IPC_ROUTER_HDR_SIZE);
- if (!hdr) {
- pr_err("%s: Prepend Header failed\n", __func__);
- return -ENOMEM;
- }
- hdr->version = IPC_ROUTER_VERSION;
+ hdr = &(pkt->hdr);
hdr->type = IPC_ROUTER_CTRL_CMD_DATA;
hdr->src_node_id = src->this_port.node_id;
hdr->src_port_id = src->this_port.port_id;
hdr->size = pkt->length;
- hdr->confirm_rx = 0;
+ hdr->control_flag = 0;
hdr->dst_node_id = rport_ptr->node_id;
hdr->dst_port_id = rport_ptr->port_id;
- pkt->length += IPC_ROUTER_HDR_SIZE;
mutex_lock(&rport_ptr->quota_lock_lhb2);
if (rport_ptr->tx_quota_cnt == IPC_ROUTER_DEFAULT_RX_QUOTA) {
@@ -2083,7 +2363,7 @@
}
rport_ptr->tx_quota_cnt++;
if (rport_ptr->tx_quota_cnt == IPC_ROUTER_DEFAULT_RX_QUOTA)
- hdr->confirm_rx = 1;
+ hdr->control_flag |= CONTROL_FLAG_CONFIRM_RX;
mutex_unlock(&rport_ptr->quota_lock_lhb2);
rt_entry = lookup_routing_table(hdr->dst_node_id);
@@ -2094,6 +2374,25 @@
}
down_read(&rt_entry->lock_lha4);
xprt_info = rt_entry->xprt_info;
+ ret = prepend_header(pkt, xprt_info);
+ if (ret < 0) {
+ up_read(&rt_entry->lock_lha4);
+ pr_err("%s: Prepend Header failed\n", __func__);
+ return ret;
+ }
+ xprt_option = xprt_info->xprt->get_option(xprt_info->xprt);
+ if (!(xprt_option & FRAG_PKT_WRITE_ENABLE)) {
+ ret = defragment_pkt(pkt);
+ if (ret < 0) {
+ up_read(&rt_entry->lock_lha4);
+ return ret;
+ }
+ }
+
+ temp_skb = skb_peek_tail(pkt->pkt_fragment_q);
+ align_size = ALIGN_SIZE(pkt->length);
+ skb_put(temp_skb, align_size);
+ pkt->length += align_size;
mutex_lock(&xprt_info->tx_lock_lhb2);
ret = xprt_info->xprt->write(pkt, pkt->length, xprt_info->xprt);
mutex_unlock(&xprt_info->tx_lock_lhb2);
@@ -2107,10 +2406,10 @@
RAW_HDR("[w rr_h] "
"ver=%i,type=%s,src_nid=%08x,src_port_id=%08x,"
- "confirm_rx=%i,size=%3i,dst_pid=%08x,dst_cid=%08x\n",
+ "control_flag=%i,size=%3i,dst_pid=%08x,dst_cid=%08x\n",
hdr->version, type_to_str(hdr->type),
hdr->src_node_id, hdr->src_port_id,
- hdr->confirm_rx, hdr->size,
+ hdr->control_flag, hdr->size,
hdr->dst_node_id, hdr->dst_port_id);
#if defined(CONFIG_MSM_SMD_LOGGING)
@@ -2123,13 +2422,13 @@
(hdr->src_port_id & 0xffffff),
(hdr->dst_node_id << 24) |
(hdr->dst_port_id & 0xffffff),
- (hdr->type << 24) | (hdr->confirm_rx << 16) |
+ (hdr->type << 24) | (hdr->control_flag << 16) |
(hdr->size & 0xffff));
}
#endif
#endif
- return pkt->length;
+ return hdr->size;
}
int msm_ipc_router_send_to(struct msm_ipc_port *src,
@@ -2203,6 +2502,8 @@
ret = msm_ipc_router_write_pkt(src, rport_ptr, pkt);
up_read(&routing_table_lock_lha3);
+ if (ret < 0)
+ pkt->pkt_fragment_q = NULL;
release_pkt(pkt);
return ret;
@@ -2222,11 +2523,10 @@
}
ret = msm_ipc_router_send_to(src, out_skb_head, dest);
- if (ret == -EAGAIN)
- return ret;
if (ret < 0) {
- pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
- __func__, ret);
+ if (ret != -EAGAIN)
+ pr_err("%s: msm_ipc_router_send_to failed - ret: %d\n",
+ __func__, ret);
msm_ipc_router_free_skb(out_skb_head);
return ret;
}
@@ -2248,7 +2548,7 @@
static int msm_ipc_router_send_resume_tx(void *data)
{
union rr_control_msg msg;
- struct rr_header *hdr = (struct rr_header *)data;
+ struct rr_header_v1 *hdr = (struct rr_header_v1 *)data;
struct msm_ipc_routing_table_entry *rt_entry;
int ret;
@@ -2278,14 +2578,12 @@
}
int msm_ipc_router_read(struct msm_ipc_port *port_ptr,
- struct sk_buff_head **data,
+ struct rr_packet **read_pkt,
size_t buf_len)
{
struct rr_packet *pkt;
- struct sk_buff *head_skb;
- int ret;
- if (!port_ptr || !data)
+ if (!port_ptr || !read_pkt)
return -EINVAL;
mutex_lock(&port_ptr->port_rx_q_lock_lhb3);
@@ -2295,26 +2593,19 @@
}
pkt = list_first_entry(&port_ptr->port_rx_q, struct rr_packet, list);
- if ((buf_len) && ((pkt->length - IPC_ROUTER_HDR_SIZE) > buf_len)) {
+ if ((buf_len) && (pkt->hdr.size > buf_len)) {
mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
return -ETOOSMALL;
}
list_del(&pkt->list);
if (list_empty(&port_ptr->port_rx_q))
wake_unlock(&port_ptr->port_rx_wake_lock);
- *data = pkt->pkt_fragment_q;
- ret = pkt->length;
+ *read_pkt = pkt;
mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
- kfree(pkt);
- head_skb = skb_peek(*data);
- if (!head_skb) {
- pr_err("%s: Socket Buffer not found", __func__);
- return -EFAULT;
- }
- if (((struct rr_header *)(head_skb->data))->confirm_rx)
- msm_ipc_router_send_resume_tx((void *)(head_skb->data));
+ if (pkt->hdr.control_flag & CONTROL_FLAG_CONFIRM_RX)
+ msm_ipc_router_send_resume_tx(&pkt->hdr);
- return ret;
+ return pkt->length;
}
/**
@@ -2362,7 +2653,7 @@
/**
* msm_ipc_router_recv_from() - Recieve messages destined to a local port.
* @port_ptr: Pointer to the local port
- * @data : Pointer to the socket buffer head
+ * @pkt : Pointer to the router-to-router packet
* @src: Pointer to local port address
* @timeout: < 0 timeout indicates infinite wait till a message arrives.
* > 0 timeout indicates the wait time.
@@ -2383,31 +2674,30 @@
* of bytes that are read.
*/
int msm_ipc_router_recv_from(struct msm_ipc_port *port_ptr,
- struct sk_buff_head **data,
+ struct rr_packet **pkt,
struct msm_ipc_addr *src,
long timeout)
{
int ret, data_len, align_size;
struct sk_buff *temp_skb;
- struct rr_header *hdr = NULL;
+ struct rr_header_v1 *hdr = NULL;
- if (!port_ptr || !data) {
+ if (!port_ptr || !pkt) {
pr_err("%s: Invalid pointers being passed\n", __func__);
return -EINVAL;
}
- *data = NULL;
+ *pkt = NULL;
ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
if (ret)
return ret;
- ret = msm_ipc_router_read(port_ptr, data, 0);
- if (ret <= 0 || !(*data))
+ ret = msm_ipc_router_read(port_ptr, pkt, 0);
+ if (ret <= 0 || !(*pkt))
return ret;
- temp_skb = skb_peek(*data);
- hdr = (struct rr_header *)(temp_skb->data);
+ hdr = &((*pkt)->hdr);
if (src) {
src->addrtype = MSM_IPC_ADDR_ID;
src->addr.port_addr.node_id = hdr->src_node_id;
@@ -2415,10 +2705,9 @@
}
data_len = hdr->size;
- skb_pull(temp_skb, IPC_ROUTER_HDR_SIZE);
align_size = ALIGN_SIZE(data_len);
if (align_size) {
- temp_skb = skb_peek_tail(*data);
+ temp_skb = skb_peek_tail((*pkt)->pkt_fragment_q);
skb_trim(temp_skb, (temp_skb->len - align_size));
}
return data_len;
@@ -2429,11 +2718,10 @@
unsigned char **data,
unsigned int *len)
{
- struct sk_buff_head *in_skb_head;
+ struct rr_packet *pkt;
int ret;
- ret = msm_ipc_router_recv_from(port_ptr, &in_skb_head, src, 0);
-
+ ret = msm_ipc_router_recv_from(port_ptr, &pkt, src, 0);
if (ret < 0) {
if (ret != -ENOMSG)
pr_err("%s: msm_ipc_router_recv_from failed - ret: %d\n",
@@ -2441,12 +2729,12 @@
return ret;
}
- *data = msm_ipc_router_skb_to_buf(in_skb_head, ret);
+ *data = msm_ipc_router_skb_to_buf(pkt->pkt_fragment_q, ret);
if (!(*data))
pr_err("%s: Buf conversion failed\n", __func__);
*len = ret;
- msm_ipc_router_free_skb(in_skb_head);
+ release_pkt(pkt);
return 0;
}
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index 7bfc52b..8ffd661 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -24,12 +24,17 @@
#include <net/sock.h>
/* definitions for the R2R wire protcol */
-#define IPC_ROUTER_VERSION 1
+#define IPC_ROUTER_V1 1
+/*
+ * Ambiguous definition but will enable multiplexing IPC_ROUTER_V2 packets
+ * with an existing alternate transport in user-space, if needed.
+ */
+#define IPC_ROUTER_V2 3
-#define IPC_ROUTER_CLIENT_BCAST_ID 0xffffffff
-#define IPC_ROUTER_ADDRESS 0xfffffffe
+#define IPC_ROUTER_ADDRESS 0x0000FFFF
#define IPC_ROUTER_NID_LOCAL 1
+#define MAX_IPC_PKT_SIZE 66000
#define IPC_ROUTER_CTRL_CMD_DATA 1
#define IPC_ROUTER_CTRL_CMD_HELLO 2
@@ -55,6 +60,11 @@
#define ALL_SERVICE 0xFFFFFFFF
#define ALL_INSTANCE 0xFFFFFFFF
+#define CONTROL_FLAG_CONFIRM_RX 0x1
+#define CONTROL_FLAG_OPT_HDR 0x2
+
+#define FRAG_PKT_WRITE_ENABLE 0x1
+
enum {
CLIENT_PORT,
SERVER_PORT,
@@ -68,10 +78,22 @@
MULTI_LINK_MODE,
};
+/**
+ * rr_control_msg - Control message structure
+ * @cmd: Command identifier for HELLO message in Version 1.
+ * @hello: Message structure for HELLO message in Version 2.
+ * @srv: Message structure for NEW_SERVER/REMOVE_SERVER events.
+ * @cli: Message structure for REMOVE_CLIENT event.
+ */
union rr_control_msg {
uint32_t cmd;
struct {
uint32_t cmd;
+ uint32_t magic;
+ uint32_t capability;
+ } hello;
+ struct {
+ uint32_t cmd;
uint32_t service;
uint32_t instance;
uint32_t node_id;
@@ -84,22 +106,67 @@
} cli;
};
-struct rr_header {
+/**
+ * rr_header_v1 - IPC Router header version 1
+ * @version: Version information.
+ * @type: IPC Router Message Type.
+ * @src_node_id: Source Node ID of the message.
+ * @src_port_id: Source Port ID of the message.
+ * @control_flag: Flag to indicate flow control.
+ * @size: Size of the IPC Router payload.
+ * @dst_node_id: Destination Node ID of the message.
+ * @dst_port_id: Destination Port ID of the message.
+ */
+struct rr_header_v1 {
uint32_t version;
uint32_t type;
uint32_t src_node_id;
uint32_t src_port_id;
- uint32_t confirm_rx;
+ uint32_t control_flag;
uint32_t size;
uint32_t dst_node_id;
uint32_t dst_port_id;
};
-#define IPC_ROUTER_HDR_SIZE sizeof(struct rr_header)
-#define MAX_IPC_PKT_SIZE 66000
+/**
+ * rr_header_v2 - IPC Router header version 2
+ * @version: Version information.
+ * @type: IPC Router Message Type.
+ * @control_flag: Flags to indicate flow control, optional header etc.
+ * @size: Size of the IPC Router payload.
+ * @src_node_id: Source Node ID of the message.
+ * @src_port_id: Source Port ID of the message.
+ * @dst_node_id: Destination Node ID of the message.
+ * @dst_port_id: Destination Port ID of the message.
+ */
+struct rr_header_v2 {
+ uint8_t version;
+ uint8_t type;
+ uint16_t control_flag;
+ uint32_t size;
+ uint16_t src_node_id;
+ uint16_t src_port_id;
+ uint16_t dst_node_id;
+ uint16_t dst_port_id;
+} __attribute__((__packed__));
+union rr_header {
+ struct rr_header_v1 hdr_v1;
+ struct rr_header_v2 hdr_v2;
+};
+
+#define IPC_ROUTER_HDR_SIZE sizeof(union rr_header)
+
+/**
+ * rr_packet - Router to Router packet structure
+ * @list: Pointer to prev & next packets in a port's rx list.
+ * @hdr: Header information extracted from or prepended to a packet.
+ * @pkt_fragment_q: Queue of SKBs containing payload.
+ * @length: Length of data in the chain of SKBs
+ */
struct rr_packet {
struct list_head list;
+ struct rr_header_v1 hdr;
struct sk_buff_head *pkt_fragment_q;
uint32_t length;
};
@@ -110,11 +177,28 @@
void *default_pil;
};
+/**
+ * msm_ipc_router_xprt - Structure to hold XPRT specific information
+ * @name: Name of the XPRT.
+ * @link_id: Network cluster ID to which the XPRT belongs to.
+ * @priv: XPRT's private data.
+ * @get_version: Method to get header version supported by the XPRT.
+ * @get_option: Method to get XPRT specific options.
+ * @read_avail: Method to get data size available to be read from the XPRT.
+ * @read: Method to read data from the XPRT.
+ * @write_avail: Method to get write space available in the XPRT.
+ * @write: Method to write data to the XPRT.
+ * @close: Method to close the XPRT.
+ * @sft_close_done: Method to indicate to the XPRT that handling of reset
+ * event is complete.
+ */
struct msm_ipc_router_xprt {
char *name;
uint32_t link_id;
void *priv;
+ int (*get_version)(struct msm_ipc_router_xprt *xprt);
+ int (*get_option)(struct msm_ipc_router_xprt *xprt);
int (*read_avail)(struct msm_ipc_router_xprt *xprt);
int (*read)(void *data, uint32_t len,
struct msm_ipc_router_xprt *xprt);
@@ -141,12 +225,12 @@
struct sk_buff_head *data,
struct msm_ipc_addr *dest);
int msm_ipc_router_read(struct msm_ipc_port *port_ptr,
- struct sk_buff_head **data,
+ struct rr_packet **pkt,
size_t buf_len);
int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr);
int msm_ipc_router_recv_from(struct msm_ipc_port *port_ptr,
- struct sk_buff_head **data,
+ struct rr_packet **pkt,
struct msm_ipc_addr *src_addr,
long timeout);
int msm_ipc_router_register_server(struct msm_ipc_port *server_port,
@@ -173,4 +257,5 @@
static inline void msm_ipc_unload_default_node(void *pil) { }
#endif
+void msm_ipc_router_free_skb(struct sk_buff_head *skb_head);
#endif
diff --git a/arch/arm/mach-msm/ipc_router_hsic_xprt.c b/arch/arm/mach-msm/ipc_router_hsic_xprt.c
new file mode 100644
index 0000000..0427c1c
--- /dev/null
+++ b/arch/arm/mach-msm/ipc_router_hsic_xprt.c
@@ -0,0 +1,503 @@
+/* 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.
+ */
+
+/*
+ * IPC ROUTER HSIC XPRT module.
+ */
+#define DEBUG
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <mach/ipc_bridge.h>
+#include <mach/subsystem_restart.h>
+
+#include "ipc_router.h"
+
+static int msm_ipc_router_hsic_xprt_debug_mask;
+module_param_named(debug_mask, msm_ipc_router_hsic_xprt_debug_mask,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#if defined(DEBUG)
+#define D(x...) do { \
+if (msm_ipc_router_hsic_xprt_debug_mask) \
+ pr_info(x); \
+} while (0)
+#else
+#define D(x...) do { } while (0)
+#endif
+
+#define NUM_HSIC_XPRTS 1
+#define XPRT_NAME_LEN 32
+
+/**
+ * msm_ipc_router_hsic_xprt - IPC Router's HSIC XPRT strucutre
+ * @xprt: IPC Router XPRT structure to contain HSIC XPRT specific info.
+ * @pdev: Platform device registered by IPC Bridge function driver.
+ * @hsic_xprt_wq: Workqueue to queue read & other XPRT related works.
+ * @read_work: Read Work to perform read operation from HSIC's ipc_bridge.
+ * @in_pkt: Pointer to any partially read packet.
+ * @ss_reset_lock: Lock to protect access to the ss_reset flag.
+ * @sft_close_complete: Variable to indicate completion of SSR handling
+ * by IPC Router.
+ * @xprt_version: IPC Router header version supported by this XPRT.
+ * @xprt_option: XPRT specific options to be handled by IPC Router.
+ */
+struct msm_ipc_router_hsic_xprt {
+ struct msm_ipc_router_xprt xprt;
+ struct platform_device *pdev;
+ struct workqueue_struct *hsic_xprt_wq;
+ struct delayed_work read_work;
+ struct rr_packet *in_pkt;
+ struct mutex ss_reset_lock;
+ int ss_reset;
+ struct completion sft_close_complete;
+ unsigned xprt_version;
+ unsigned xprt_option;
+};
+
+struct msm_ipc_router_hsic_xprt_work {
+ struct msm_ipc_router_xprt *xprt;
+ struct work_struct work;
+};
+
+static void hsic_xprt_read_data(struct work_struct *work);
+
+/**
+ * msm_ipc_router_hsic_xprt_config - Config. Info. of each HSIC XPRT
+ * @ch_name: Name of the HSIC endpoint exported by ipc_bridge driver.
+ * @xprt_name: Name of the XPRT to be registered with IPC Router.
+ * @hsic_pdev_id: ID to differentiate among multiple ipc_bridge endpoints.
+ * @link_id: Network Cluster ID to which this XPRT belongs to.
+ * @xprt_version: IPC Router header version supported by this XPRT.
+ */
+struct msm_ipc_router_hsic_xprt_config {
+ char ch_name[XPRT_NAME_LEN];
+ char xprt_name[XPRT_NAME_LEN];
+ int hsic_pdev_id;
+ uint32_t link_id;
+ unsigned xprt_version;
+};
+
+struct msm_ipc_router_hsic_xprt_config hsic_xprt_cfg[] = {
+ {"ipc_bridge", "ipc_rtr_ipc_bridge1", 1, 1, 3},
+};
+
+static struct msm_ipc_router_hsic_xprt hsic_remote_xprt[NUM_HSIC_XPRTS];
+
+/**
+ * find_hsic_xprt_cfg() - Find the config info specific to an HSIC endpoint
+ * @pdev: Platform device registered by HSIC's ipc_bridge driver
+ *
+ * @return: Index to the entry in the hsic_remote_xprt table if matching
+ * endpoint is found, < 0 on error.
+ *
+ * This function is used to find the configuration information specific to
+ * an HSIC endpoint from the hsic_remote_xprt table.
+ */
+static int find_hsic_xprt_cfg(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < NUM_HSIC_XPRTS; i++) {
+ /* TODO: Update the condition for multiple hsic links */
+ if (!strncmp(pdev->name, hsic_xprt_cfg[i].ch_name, 32))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * msm_ipc_router_hsic_get_xprt_version() - Get IPC Router header version
+ * supported by the XPRT
+ * @xprt: XPRT for which the version information is required.
+ *
+ * @return: IPC Router header version supported by the XPRT.
+ */
+static int msm_ipc_router_hsic_get_xprt_version(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp;
+ if (!xprt)
+ return -EINVAL;
+ hsic_xprtp = container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+
+ return (int)hsic_xprtp->xprt_version;
+}
+
+/**
+ * msm_ipc_router_hsic_get_xprt_option() - Get XPRT options
+ * @xprt: XPRT for which the option information is required.
+ *
+ * @return: Options supported by the XPRT.
+ */
+static int msm_ipc_router_hsic_get_xprt_option(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp;
+ if (!xprt)
+ return -EINVAL;
+ hsic_xprtp = container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+
+ return (int)hsic_xprtp->xprt_option;
+}
+
+/**
+ * msm_ipc_router_hsic_remote_write_avail() - Get available write space
+ * @xprt: XPRT for which the available write space info. is required.
+ *
+ * @return: Write space in bytes on success, 0 on SSR.
+ */
+static int msm_ipc_router_hsic_remote_write_avail(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct ipc_bridge_platform_data *pdata;
+ int write_avail;
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp =
+ container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+
+ mutex_lock(&hsic_xprtp->ss_reset_lock);
+ if (hsic_xprtp->ss_reset || !hsic_xprtp->pdev) {
+ write_avail = 0;
+ } else {
+ pdata = hsic_xprtp->pdev->dev.platform_data;
+ write_avail = pdata->max_write_size;
+ }
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return write_avail;
+}
+
+/**
+ * msm_ipc_router_hsic_remote_write() - Write to XPRT
+ * @data: Data to be written to the XPRT.
+ * @len: Length of the data to be written.
+ * @xprt: XPRT to which the data has to be written.
+ *
+ * @return: Data Length on success, standard Linux error codes on failure.
+ */
+static int msm_ipc_router_hsic_remote_write(void *data,
+ uint32_t len, struct msm_ipc_router_xprt *xprt)
+{
+ struct rr_packet *pkt = (struct rr_packet *)data;
+ struct sk_buff *skb;
+ struct ipc_bridge_platform_data *pdata;
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp;
+ int ret;
+
+ if (!pkt || pkt->length != len || !xprt) {
+ pr_err("%s: Invalid input parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ hsic_xprtp = container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+ mutex_lock(&hsic_xprtp->ss_reset_lock);
+ if (hsic_xprtp->ss_reset) {
+ pr_err("%s: Trying to write on a reset link\n", __func__);
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return -ENETRESET;
+ }
+
+ if (!hsic_xprtp->pdev) {
+ pr_err("%s: Trying to write on a closed link\n", __func__);
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return -ENODEV;
+ }
+
+ pdata = hsic_xprtp->pdev->dev.platform_data;
+ if (!pdata || !pdata->write) {
+ pr_err("%s on a uninitialized link\n", __func__);
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return -EFAULT;
+ }
+
+ skb = skb_peek(pkt->pkt_fragment_q);
+ if (!skb) {
+ pr_err("%s SKB is NULL\n", __func__);
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return -EINVAL;
+ }
+ D("%s: About to write %d bytes\n", __func__, len);
+ ret = pdata->write(hsic_xprtp->pdev, skb->data, skb->len);
+ if (ret == skb->len)
+ ret = len;
+ D("%s: Finished writing %d bytes\n", __func__, len);
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ return ret;
+}
+
+/**
+ * msm_ipc_router_hsic_remote_close() - Close the XPRT
+ * @xprt: XPRT which needs to be closed.
+ *
+ * @return: 0 on success, standard Linux error codes on failure.
+ */
+static int msm_ipc_router_hsic_remote_close(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp;
+ struct ipc_bridge_platform_data *pdata;
+
+ if (!xprt)
+ return -EINVAL;
+ hsic_xprtp = container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+
+ mutex_lock(&hsic_xprtp->ss_reset_lock);
+ hsic_xprtp->ss_reset = 1;
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ flush_workqueue(hsic_xprtp->hsic_xprt_wq);
+ destroy_workqueue(hsic_xprtp->hsic_xprt_wq);
+ pdata = hsic_xprtp->pdev->dev.platform_data;
+ if (pdata && pdata->close)
+ pdata->close(hsic_xprtp->pdev);
+ hsic_xprtp->pdev = NULL;
+ return 0;
+}
+
+/**
+ * hsic_xprt_read_data() - Read work to read from the XPRT
+ * @work: Read work to be executed.
+ *
+ * This function is a read work item queued on a XPRT specific workqueue.
+ * The work parameter contains information regarding the XPRT on which this
+ * read work has to be performed. The work item keeps reading from the HSIC
+ * endpoint, until the endpoint returns an error.
+ */
+static void hsic_xprt_read_data(struct work_struct *work)
+{
+ int pkt_size;
+ struct sk_buff *skb = NULL;
+ void *data;
+ struct ipc_bridge_platform_data *pdata;
+ struct delayed_work *rwork = to_delayed_work(work);
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp =
+ container_of(rwork, struct msm_ipc_router_hsic_xprt, read_work);
+
+ while (1) {
+ mutex_lock(&hsic_xprtp->ss_reset_lock);
+ if (hsic_xprtp->ss_reset) {
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ break;
+ }
+ pdata = hsic_xprtp->pdev->dev.platform_data;
+ mutex_unlock(&hsic_xprtp->ss_reset_lock);
+ while (!hsic_xprtp->in_pkt) {
+ hsic_xprtp->in_pkt = kzalloc(sizeof(struct rr_packet),
+ GFP_KERNEL);
+ if (hsic_xprtp->in_pkt)
+ break;
+ pr_err("%s: packet allocation failure\n", __func__);
+ msleep(100);
+ }
+ while (!hsic_xprtp->in_pkt->pkt_fragment_q) {
+ hsic_xprtp->in_pkt->pkt_fragment_q =
+ kmalloc(sizeof(struct sk_buff_head),
+ GFP_KERNEL);
+ if (hsic_xprtp->in_pkt->pkt_fragment_q)
+ break;
+ pr_err("%s: Couldn't alloc pkt_fragment_q\n",
+ __func__);
+ msleep(100);
+ }
+ skb_queue_head_init(hsic_xprtp->in_pkt->pkt_fragment_q);
+ D("%s: Allocated rr_packet\n", __func__);
+
+ while (!skb) {
+ skb = alloc_skb(pdata->max_read_size, GFP_KERNEL);
+ if (skb)
+ break;
+ pr_err("%s: Couldn't alloc SKB\n", __func__);
+ msleep(100);
+ }
+ data = skb_put(skb, pdata->max_read_size);
+ pkt_size = pdata->read(hsic_xprtp->pdev, data,
+ pdata->max_read_size);
+ if (pkt_size < 0) {
+ pr_err("%s: Error %d @ read operation\n",
+ __func__, pkt_size);
+ kfree_skb(skb);
+ kfree(hsic_xprtp->in_pkt->pkt_fragment_q);
+ kfree(hsic_xprtp->in_pkt);
+ break;
+ }
+ skb_queue_tail(hsic_xprtp->in_pkt->pkt_fragment_q, skb);
+ hsic_xprtp->in_pkt->length = pkt_size;
+ D("%s: Packet size read %d\n", __func__, pkt_size);
+ msm_ipc_router_xprt_notify(&hsic_xprtp->xprt,
+ IPC_ROUTER_XPRT_EVENT_DATA, (void *)hsic_xprtp->in_pkt);
+ release_pkt(hsic_xprtp->in_pkt);
+ hsic_xprtp->in_pkt = NULL;
+ skb = NULL;
+ }
+}
+
+/**
+ * hsic_xprt_sft_close_done() - Completion of XPRT reset
+ * @xprt: XPRT on which the reset operation is complete.
+ *
+ * This function is used by IPC Router to signal this HSIC XPRT Abstraction
+ * Layer(XAL) that the reset of XPRT is completely handled by IPC Router.
+ */
+static void hsic_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_hsic_xprt *hsic_xprtp =
+ container_of(xprt, struct msm_ipc_router_hsic_xprt, xprt);
+
+ complete_all(&hsic_xprtp->sft_close_complete);
+}
+
+/**
+ * msm_ipc_router_hsic_remote_remove() - Remove an HSIC endpoint
+ * @pdev: Platform device corresponding to HSIC endpoint.
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called when the underlying ipc_bridge driver unregisters
+ * a platform device, mapped to an HSIC endpoint, during SSR.
+ */
+static int msm_ipc_router_hsic_remote_remove(struct platform_device *pdev)
+{
+ int id;
+ struct ipc_bridge_platform_data *pdata;
+
+ id = find_hsic_xprt_cfg(pdev);
+ if (id < 0) {
+ pr_err("%s: called for unknown ch %s\n",
+ __func__, pdev->name);
+ return id;
+ }
+
+ mutex_lock(&hsic_remote_xprt[id].ss_reset_lock);
+ hsic_remote_xprt[id].ss_reset = 1;
+ mutex_unlock(&hsic_remote_xprt[id].ss_reset_lock);
+ flush_workqueue(hsic_remote_xprt[id].hsic_xprt_wq);
+ destroy_workqueue(hsic_remote_xprt[id].hsic_xprt_wq);
+ init_completion(&hsic_remote_xprt[id].sft_close_complete);
+ msm_ipc_router_xprt_notify(&hsic_remote_xprt[id].xprt,
+ IPC_ROUTER_XPRT_EVENT_CLOSE, NULL);
+ D("%s: Notified IPC Router of %s CLOSE\n",
+ __func__, hsic_remote_xprt[id].xprt.name);
+ wait_for_completion(&hsic_remote_xprt[id].sft_close_complete);
+ hsic_remote_xprt[id].pdev = NULL;
+ pdata = pdev->dev.platform_data;
+ if (pdata && pdata->close)
+ pdata->close(pdev);
+ return 0;
+}
+
+/**
+ * msm_ipc_router_hsic_remote_probe() - Probe an HSIC endpoint
+ * @pdev: Platform device corresponding to HSIC endpoint.
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called when the underlying ipc_bridge driver registers
+ * a platform device, mapped to an HSIC endpoint.
+ */
+static int msm_ipc_router_hsic_remote_probe(struct platform_device *pdev)
+{
+ int rc;
+ int id; /*Index into the hsic_xprt_cfg table*/
+ struct ipc_bridge_platform_data *pdata;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata || !pdata->open || !pdata->read ||
+ !pdata->write || !pdata->close) {
+ pr_err("%s: pdata or pdata->operations is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ id = find_hsic_xprt_cfg(pdev);
+ if (id < 0) {
+ pr_err("%s: called for unknown ch %s\n",
+ __func__, pdev->name);
+ return id;
+ }
+
+ hsic_remote_xprt[id].hsic_xprt_wq =
+ create_singlethread_workqueue(pdev->name);
+ if (!hsic_remote_xprt[id].hsic_xprt_wq) {
+ pr_err("%s: WQ creation failed for %s\n",
+ __func__, pdev->name);
+ return -EFAULT;
+ }
+
+ hsic_remote_xprt[id].xprt.name = hsic_xprt_cfg[id].xprt_name;
+ hsic_remote_xprt[id].xprt.link_id = hsic_xprt_cfg[id].link_id;
+ hsic_remote_xprt[id].xprt.get_version =
+ msm_ipc_router_hsic_get_xprt_version;
+ hsic_remote_xprt[id].xprt.get_option =
+ msm_ipc_router_hsic_get_xprt_option;
+ hsic_remote_xprt[id].xprt.read_avail = NULL;
+ hsic_remote_xprt[id].xprt.read = NULL;
+ hsic_remote_xprt[id].xprt.write_avail =
+ msm_ipc_router_hsic_remote_write_avail;
+ hsic_remote_xprt[id].xprt.write = msm_ipc_router_hsic_remote_write;
+ hsic_remote_xprt[id].xprt.close = msm_ipc_router_hsic_remote_close;
+ hsic_remote_xprt[id].xprt.sft_close_done = hsic_xprt_sft_close_done;
+ hsic_remote_xprt[id].xprt.priv = NULL;
+
+ hsic_remote_xprt[id].in_pkt = NULL;
+ INIT_DELAYED_WORK(&hsic_remote_xprt[id].read_work, hsic_xprt_read_data);
+ mutex_init(&hsic_remote_xprt[id].ss_reset_lock);
+ hsic_remote_xprt[id].ss_reset = 0;
+ hsic_remote_xprt[id].xprt_version = hsic_xprt_cfg[id].xprt_version;
+ hsic_remote_xprt[id].xprt_option = 0;
+
+ rc = pdata->open(pdev);
+ if (rc < 0) {
+ pr_err("%s: Channel open failed for %s.%d\n",
+ __func__, pdev->name, pdev->id);
+ destroy_workqueue(hsic_remote_xprt[id].hsic_xprt_wq);
+ return rc;
+ }
+ hsic_remote_xprt[id].pdev = pdev;
+ msm_ipc_router_xprt_notify(&hsic_remote_xprt[id].xprt,
+ IPC_ROUTER_XPRT_EVENT_OPEN, NULL);
+ D("%s: Notified IPC Router of %s OPEN\n",
+ __func__, hsic_remote_xprt[id].xprt.name);
+ queue_delayed_work(hsic_remote_xprt[id].hsic_xprt_wq,
+ &hsic_remote_xprt[id].read_work, 0);
+ return 0;
+}
+
+static struct platform_driver msm_ipc_router_hsic_remote_driver[] = {
+ {
+ .probe = msm_ipc_router_hsic_remote_probe,
+ .remove = msm_ipc_router_hsic_remote_remove,
+ .driver = {
+ .name = "ipc_bridge",
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static int __init msm_ipc_router_hsic_init(void)
+{
+ int i, ret, rc = 0;
+ BUG_ON(ARRAY_SIZE(hsic_xprt_cfg) != NUM_HSIC_XPRTS);
+ for (i = 0; i < ARRAY_SIZE(msm_ipc_router_hsic_remote_driver); i++) {
+ ret = platform_driver_register(
+ &msm_ipc_router_hsic_remote_driver[i]);
+ if (ret) {
+ pr_err("%s: Failed to register platform driver for xprt%d. Continuing...\n",
+ __func__, i);
+ rc = ret;
+ }
+ }
+ return rc;
+}
+
+module_init(msm_ipc_router_hsic_init);
+MODULE_DESCRIPTION("IPC Router HSIC XPRT");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index d6a3e03..87880c2 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -55,6 +55,8 @@
int ss_reset;
void *pil;
struct completion sft_close_complete;
+ unsigned xprt_version;
+ unsigned xprt_option;
};
struct msm_ipc_router_smd_xprt_work {
@@ -71,13 +73,14 @@
char xprt_name[XPRT_NAME_LEN];
uint32_t edge;
uint32_t link_id;
+ unsigned xprt_version;
};
struct msm_ipc_router_smd_xprt_config smd_xprt_cfg[] = {
- {"RPCRPY_CNTL", "ipc_rtr_smd_rpcrpy_cntl", SMD_APPS_MODEM, 1},
- {"IPCRTR", "ipc_rtr_smd_ipcrtr", SMD_APPS_MODEM, 1},
- {"IPCRTR", "ipc_rtr_q6_ipcrtr", SMD_APPS_QDSP, 1},
- {"IPCRTR", "ipc_rtr_wcnss_ipcrtr", SMD_APPS_WCNSS, 1},
+ {"RPCRPY_CNTL", "ipc_rtr_smd_rpcrpy_cntl", SMD_APPS_MODEM, 1, 1},
+ {"IPCRTR", "ipc_rtr_smd_ipcrtr", SMD_APPS_MODEM, 1, 1},
+ {"IPCRTR", "ipc_rtr_q6_ipcrtr", SMD_APPS_QDSP, 1, 1},
+ {"IPCRTR", "ipc_rtr_wcnss_ipcrtr", SMD_APPS_WCNSS, 1, 1},
};
static struct msm_ipc_router_smd_xprt smd_remote_xprt[NUM_SMD_XPRTS];
@@ -95,6 +98,28 @@
return -ENODEV;
}
+static int msm_ipc_router_smd_get_xprt_version(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_smd_xprt *smd_xprtp;
+ if (!xprt)
+ return -EINVAL;
+ smd_xprtp = container_of(xprt, struct msm_ipc_router_smd_xprt, xprt);
+
+ return (int)smd_xprtp->xprt_version;
+}
+
+static int msm_ipc_router_smd_get_xprt_option(
+ struct msm_ipc_router_xprt *xprt)
+{
+ struct msm_ipc_router_smd_xprt *smd_xprtp;
+ if (!xprt)
+ return -EINVAL;
+ smd_xprtp = container_of(xprt, struct msm_ipc_router_smd_xprt, xprt);
+
+ return (int)smd_xprtp->xprt_option;
+}
+
static int msm_ipc_router_smd_remote_write_avail(
struct msm_ipc_router_xprt *xprt)
{
@@ -110,7 +135,6 @@
{
struct rr_packet *pkt = (struct rr_packet *)data;
struct sk_buff *ipc_rtr_pkt;
- int align_sz, align_data = 0;
int offset, sz_written = 0;
int ret, num_retries = 0;
unsigned long flags;
@@ -123,9 +147,7 @@
if (!len || pkt->length != len)
return -EINVAL;
- align_sz = ALIGN_SIZE(pkt->length);
- while ((ret = smd_write_start(smd_xprtp->channel,
- (len + align_sz))) < 0) {
+ while ((ret = smd_write_start(smd_xprtp->channel, len)) < 0) {
spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
if (smd_xprtp->ss_reset) {
spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock,
@@ -143,7 +165,7 @@
num_retries++;
}
- D("%s: Ready to write\n", __func__);
+ D("%s: Ready to write %d bytes\n", __func__, len);
skb_queue_walk(pkt->pkt_fragment_q, ipc_rtr_pkt) {
offset = 0;
while (offset < ipc_rtr_pkt->len) {
@@ -175,30 +197,6 @@
__func__, offset, xprt->name);
}
- if (align_sz) {
- if (smd_write_segment_avail(smd_xprtp->channel) < align_sz)
- smd_enable_read_intr(smd_xprtp->channel);
-
- wait_event(smd_xprtp->write_avail_wait_q,
- ((smd_write_segment_avail(smd_xprtp->channel) >=
- align_sz) || smd_xprtp->ss_reset));
- smd_disable_read_intr(smd_xprtp->channel);
- spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
- if (smd_xprtp->ss_reset) {
- spin_unlock_irqrestore(
- &smd_xprtp->ss_reset_lock, flags);
- pr_err("%s: %s chnl reset\n",
- __func__, xprt->name);
- return -ENETRESET;
- }
- spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock,
- flags);
-
- smd_write_segment(smd_xprtp->channel,
- &align_data, align_sz, 0);
- D("%s: Wrote %d align bytes over %s\n",
- __func__, align_sz, xprt->name);
- }
if (!smd_write_end(smd_xprtp->channel))
D("%s: Finished writing\n", __func__);
return len;
@@ -453,6 +451,10 @@
smd_remote_xprt[id].xprt.name = smd_xprt_cfg[id].xprt_name;
smd_remote_xprt[id].xprt.link_id = smd_xprt_cfg[id].link_id;
+ smd_remote_xprt[id].xprt.get_version =
+ msm_ipc_router_smd_get_xprt_version;
+ smd_remote_xprt[id].xprt.get_option =
+ msm_ipc_router_smd_get_xprt_option;
smd_remote_xprt[id].xprt.read_avail = NULL;
smd_remote_xprt[id].xprt.read = NULL;
smd_remote_xprt[id].xprt.write_avail =
@@ -468,6 +470,8 @@
INIT_DELAYED_WORK(&smd_remote_xprt[id].read_work, smd_xprt_read_data);
spin_lock_init(&smd_remote_xprt[id].ss_reset_lock);
smd_remote_xprt[id].ss_reset = 0;
+ smd_remote_xprt[id].xprt_version = smd_xprt_cfg[id].xprt_version;
+ smd_remote_xprt[id].xprt_option = FRAG_PKT_WRITE_ENABLE;
smd_remote_xprt[id].pil = msm_ipc_load_subsystem(
smd_xprt_cfg[id].edge);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index ea27c71..bdda546 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -131,12 +131,15 @@
int i, copied, first = 1;
int data_size = 0, request_size, offset;
void *data;
+ int last = 0;
+ int align_size;
for (i = 0; i < num_sect; i++)
data_size += msg_sect[i].iov_len;
if (!data_size)
return NULL;
+ align_size = ALIGN_SIZE(data_size);
msg_head = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
if (!msg_head) {
@@ -148,10 +151,14 @@
for (copied = 1, i = 0; copied && (i < num_sect); i++) {
data_size = msg_sect[i].iov_len;
offset = 0;
+ if (i == (num_sect - 1))
+ last = 1;
while (offset != msg_sect[i].iov_len) {
request_size = data_size;
if (first)
request_size += IPC_ROUTER_HDR_SIZE;
+ if (last)
+ request_size += align_size;
msg = alloc_skb(request_size, GFP_KERNEL);
if (!msg) {
@@ -161,6 +168,7 @@
goto msg_build_failure;
}
data_size = data_size / 2;
+ last = 0;
continue;
}
@@ -182,6 +190,8 @@
skb_queue_tail(msg_head, msg);
offset += data_size;
data_size = msg_sect[i].iov_len - offset;
+ if (i == (num_sect - 1))
+ last = 1;
}
}
return msg_head;
@@ -196,24 +206,23 @@
}
static int msm_ipc_router_extract_msg(struct msghdr *m,
- struct sk_buff_head *msg_head)
+ struct rr_packet *pkt)
{
struct sockaddr_msm_ipc *addr;
- struct rr_header *hdr;
+ struct rr_header_v1 *hdr;
struct sk_buff *temp;
union rr_control_msg *ctl_msg;
int offset = 0, data_len = 0, copy_len;
- if (!m || !msg_head) {
+ if (!m || !pkt) {
pr_err("%s: Invalid pointers passed\n", __func__);
return -EINVAL;
}
addr = (struct sockaddr_msm_ipc *)m->msg_name;
- temp = skb_peek(msg_head);
- hdr = (struct rr_header *)(temp->data);
+ hdr = &(pkt->hdr);
if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)) {
- skb_pull(temp, IPC_ROUTER_HDR_SIZE);
+ temp = skb_peek(pkt->pkt_fragment_q);
ctl_msg = (union rr_control_msg *)(temp->data);
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
@@ -222,7 +231,7 @@
m->msg_namelen = sizeof(struct sockaddr_msm_ipc);
return offset;
}
- if (addr && (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
+ if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) {
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
addr->address.addr.port_addr.node_id = hdr->src_node_id;
@@ -231,8 +240,7 @@
}
data_len = hdr->size;
- skb_pull(temp, IPC_ROUTER_HDR_SIZE);
- skb_queue_walk(msg_head, temp) {
+ skb_queue_walk(pkt->pkt_fragment_q, temp) {
copy_len = data_len < temp->len ? data_len : temp->len;
if (copy_to_user(m->msg_iov->iov_base + offset, temp->data,
copy_len)) {
@@ -245,22 +253,6 @@
return offset;
}
-static void msm_ipc_router_release_msg(struct sk_buff_head *msg_head)
-{
- struct sk_buff *temp;
-
- if (!msg_head) {
- pr_err("%s: Invalid msg pointer\n", __func__);
- return;
- }
-
- while (!skb_queue_empty(msg_head)) {
- temp = skb_dequeue(msg_head);
- kfree_skb(temp);
- }
- kfree(msg_head);
-}
-
static int msm_ipc_router_create(struct net *net,
struct socket *sock,
int protocol,
@@ -385,8 +377,16 @@
if (ipc_buf)
msm_ipc_router_ipc_log(IPC_SEND, ipc_buf, port_ptr);
ret = msm_ipc_router_send_to(port_ptr, msg, &dest->address);
- if (ret == (IPC_ROUTER_HDR_SIZE + total_len))
- ret = total_len;
+ if (ret != total_len) {
+ if (ret < 0) {
+ if (ret != -EAGAIN)
+ pr_err("%s: Send_to failure %d\n",
+ __func__, ret);
+ msm_ipc_router_free_skb(msg);
+ } else if (ret >= 0) {
+ ret = -EFAULT;
+ }
+ }
out_sendmsg:
release_sock(sk);
@@ -398,7 +398,7 @@
{
struct sock *sk = sock->sk;
struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
- struct sk_buff_head *msg;
+ struct rr_packet *pkt;
struct sk_buff *ipc_buf;
long timeout;
int ret;
@@ -420,18 +420,17 @@
return ret;
}
- ret = msm_ipc_router_read(port_ptr, &msg, buf_len);
- if (ret <= 0 || !msg) {
+ ret = msm_ipc_router_read(port_ptr, &pkt, buf_len);
+ if (ret <= 0 || !pkt) {
release_sock(sk);
return ret;
}
- ret = msm_ipc_router_extract_msg(m, msg);
- ipc_buf = skb_peek(msg);
+ ret = msm_ipc_router_extract_msg(m, pkt);
+ ipc_buf = skb_peek(pkt->pkt_fragment_q);
if (ipc_buf)
msm_ipc_router_ipc_log(IPC_RECV, ipc_buf, port_ptr);
- msm_ipc_router_release_msg(msg);
- msg = NULL;
+ release_pkt(pkt);
release_sock(sk);
return ret;
}
@@ -460,7 +459,7 @@
switch (cmd) {
case IPC_ROUTER_IOCTL_GET_VERSION:
- n = IPC_ROUTER_VERSION;
+ n = IPC_ROUTER_V1;
ret = put_user(n, (unsigned int *)arg);
break;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index bc15fe8..8b64653 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -1876,7 +1876,7 @@
struct msm_bus_bimc_info *binfo;
struct msm_bus_bimc_qos_bw qbw;
int i;
- long int bw;
+ int64_t bw;
int ports = info->node_info->num_mports;
struct msm_bus_bimc_commit *sel_cd =
(struct msm_bus_bimc_commit *)sel_cdata;
@@ -1912,11 +1912,11 @@
qbw.bw = sel_cd->mas[info->node_info->masterp[i]].bw;
qbw.ws = info->node_info->ws;
/* Threshold low = 90% of bw */
- qbw.thl = (90 * bw) / 100;
+ qbw.thl = div_s64((90 * bw), 100);
/* Threshold medium = bw */
qbw.thm = bw;
/* Threshold high = 10% more than bw */
- qbw.thh = (110 * bw) / 100;
+ qbw.thh = div_s64((110 * bw), 100);
/* Check if info is a shared master.
* If it is, mark it dirty
* If it isn't, then set QOS Bandwidth
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 87719e3..7e4a513 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -36,7 +36,8 @@
(((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0)
#define INTERLEAVED_BW(fab_pdata, bw, ports) \
- ((fab_pdata->il_flag) ? msm_bus_div64((ports), (bw)) : (bw))
+ ((fab_pdata->il_flag) ? ((bw < 0) \
+ ? -msm_bus_div64((ports), (-bw)) : msm_bus_div64((ports), (bw))) : (bw))
#define INTERLEAVED_VAL(fab_pdata, n) \
((fab_pdata->il_flag) ? (n) : 1)
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
index d33c340..8f7b7f2 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -511,7 +511,7 @@
struct msm_bus_noc_info *ninfo;
struct msm_bus_noc_qos_bw qos_bw;
int i, ports;
- long int bw;
+ int64_t bw;
struct msm_bus_noc_commit *sel_cd =
(struct msm_bus_noc_commit *)sel_cdata;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index deb1cc7..d34bdf2 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -144,7 +144,7 @@
SMSM_APPS_DEM_I = 3,
};
-int msm_smd_debug_mask = MSM_SMx_POWER_INFO;
+int msm_smd_debug_mask = MSM_SMx_POWER_INFO | MSM_SMD_INFO;
module_param_named(debug_mask, msm_smd_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
void *smd_log_ctx;
@@ -825,7 +825,7 @@
}
}
-static void smd_channel_reset_state(struct smd_alloc_elm *shared,
+static void smd_channel_reset_state(struct smd_alloc_elm *shared, int table_id,
unsigned new_state, unsigned pid)
{
unsigned n;
@@ -834,6 +834,19 @@
void *local_ch;
void *remote_ch;
int is_word_access;
+ unsigned base_id;
+
+ switch (table_id) {
+ case PRI_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID;
+ break;
+ case SEC_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID_2;
+ break;
+ default:
+ SMD_INFO("%s: invalid table_id:%d\n", __func__, table_id);
+ return;
+ }
for (n = 0; n < SMD_CHANNELS; n++) {
if (!shared[n].ref_count)
@@ -844,10 +857,10 @@
type = SMD_CHANNEL_TYPE(shared[n].type);
is_word_access = is_word_access_ch(type);
if (is_word_access)
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ shared2 = smem_alloc(base_id + n,
sizeof(struct smd_shared_v2_word_access));
else
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + n,
+ shared2 = smem_alloc(base_id + n,
sizeof(struct smd_shared_v2));
if (!shared2)
continue;
@@ -870,16 +883,19 @@
void smd_channel_reset(uint32_t restart_pid)
{
- struct smd_alloc_elm *shared;
+ struct smd_alloc_elm *shared_pri;
+ struct smd_alloc_elm *shared_sec;
unsigned long flags;
SMx_POWER_INFO("%s: starting reset\n", __func__);
- shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
- if (!shared) {
+ shared_pri = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared_pri) * 64);
+ if (!shared_pri) {
pr_err("%s: allocation table not initialized\n", __func__);
return;
}
+ shared_sec = smem_find(SMEM_CHANNEL_ALLOC_TBL_2,
+ sizeof(*shared_sec) * 64);
/* reset SMSM entry */
if (smsm_info.state) {
@@ -903,7 +919,11 @@
/* change all remote states to CLOSING */
mutex_lock(&smd_probe_lock);
spin_lock_irqsave(&smd_lock, flags);
- smd_channel_reset_state(shared, SMD_SS_CLOSING, restart_pid);
+ smd_channel_reset_state(shared_pri, PRI_ALLOC_TBL, SMD_SS_CLOSING,
+ restart_pid);
+ if (shared_sec)
+ smd_channel_reset_state(shared_sec, SEC_ALLOC_TBL,
+ SMD_SS_CLOSING, restart_pid);
spin_unlock_irqrestore(&smd_lock, flags);
mutex_unlock(&smd_probe_lock);
@@ -919,7 +939,11 @@
/* change all remote states to CLOSED */
mutex_lock(&smd_probe_lock);
spin_lock_irqsave(&smd_lock, flags);
- smd_channel_reset_state(shared, SMD_SS_CLOSED, restart_pid);
+ smd_channel_reset_state(shared_pri, PRI_ALLOC_TBL, SMD_SS_CLOSED,
+ restart_pid);
+ if (shared_sec)
+ smd_channel_reset_state(shared_sec, SEC_ALLOC_TBL,
+ SMD_SS_CLOSED, restart_pid);
spin_unlock_irqrestore(&smd_lock, flags);
mutex_unlock(&smd_probe_lock);
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index e91f28d..428d5b0 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -340,12 +340,16 @@
break;
case SMD_EVENT_OPEN:
+ tty = tty_port_tty_get(&info->port);
spin_lock_irqsave(&info->reset_lock_lha2, flags);
+ if (tty)
+ clear_bit(TTY_OTHER_CLOSED, &tty->flags);
info->in_reset = 0;
info->in_reset_updated = 1;
info->is_open = 1;
wake_up_interruptible(&info->ch_opened_wait_queue);
spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
+ tty_kref_put(tty);
break;
case SMD_EVENT_CLOSE:
@@ -355,13 +359,17 @@
info->is_open = 0;
wake_up_interruptible(&info->ch_opened_wait_queue);
spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
- /* schedule task to send TTY_BREAK */
- tasklet_hi_schedule(&info->tty_tsklt);
tty = tty_port_tty_get(&info->port);
- if (tty->index == LOOPBACK_IDX)
- schedule_delayed_work(&loopback_work,
- msecs_to_jiffies(1000));
+ if (tty) {
+ /* send TTY_BREAK through read tasklet */
+ set_bit(TTY_OTHER_CLOSED, &tty->flags);
+ tasklet_hi_schedule(&info->tty_tsklt);
+
+ if (tty->index == LOOPBACK_IDX)
+ schedule_delayed_work(&loopback_work,
+ msecs_to_jiffies(1000));
+ }
tty_kref_put(tty);
break;
}
@@ -772,7 +780,7 @@
return ret;
}
-static int __init smd_tty_core_init(void)
+static int smd_tty_core_init(void)
{
int ret;
int n;
@@ -846,7 +854,7 @@
return ret;
}
-static int __init smd_tty_devicetree_init(struct platform_device *pdev)
+static int smd_tty_devicetree_init(struct platform_device *pdev)
{
int ret;
int idx;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2781a34..7da0811 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -911,11 +911,7 @@
mutex_lock(&private->process_private_mutex);
- /*
- * If debug root initialized then it means the rest of the fields
- * are also initialized
- */
- if (private->debug_root)
+ if (test_bit(KGSL_PROCESS_INIT, &private->priv))
goto done;
private->mem_rb = RB_ROOT;
@@ -936,6 +932,8 @@
if (kgsl_process_init_debugfs(private))
goto error;
+ set_bit(KGSL_PROCESS_INIT, &private->priv);
+
done:
mutex_unlock(&private->process_private_mutex);
return private;
diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h
index b2f137c..fe9bc76 100644
--- a/drivers/gpu/msm/kgsl_debugfs.h
+++ b/drivers/gpu/msm/kgsl_debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2011,2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,7 +35,7 @@
static inline void kgsl_device_debugfs_init(struct kgsl_device *device) { }
static inline void kgsl_core_debugfs_close(void) { }
static inline struct dentry *kgsl_get_debugfs_dir(void) { return NULL; }
-static inline int kgsl_process_init_debugfs(struct kgsl_process_private *)
+static inline int kgsl_process_init_debugfs(struct kgsl_process_private *priv)
{
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 09a31c9..0b5fe52 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -315,8 +315,23 @@
unsigned int pagefault_ts;
};
+/**
+ * struct kgsl_process_private - Private structure for a KGSL process (across
+ * all devices)
+ * @priv: Internal flags, use KGSL_PROCESS_* values
+ * @pid: ID for the task owner of the process
+ * @mem_lock: Spinlock to protect the process memory lists
+ * @refcount: kref object for reference counting the process
+ * @process_private_mutex: Mutex to synchronize access to the process struct
+ * @mem_rb: RB tree node for the memory owned by this process
+ * @idr: Iterator for assigning IDs to memory allocations
+ * @pagetable: Pointer to the pagetable owned by this process
+ * @kobj: Pointer to a kobj for the sysfs directory for this process
+ * @debug_root: Pointer to the debugfs root for this process
+ * @stats: Memory allocation statistics for this process
+ */
struct kgsl_process_private {
- unsigned int refcnt;
+ unsigned long priv;
pid_t pid;
spinlock_t mem_lock;
@@ -338,6 +353,14 @@
} stats[KGSL_MEM_ENTRY_MAX];
};
+/**
+ * enum kgsl_process_priv_flags - Private flags for kgsl_process_private
+ * @KGSL_PROCESS_INIT: Set if the process structure has been set up
+ */
+enum kgsl_process_priv_flags {
+ KGSL_PROCESS_INIT = 0,
+};
+
struct kgsl_device_private {
struct kgsl_device *device;
struct kgsl_process_private *process_priv;
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 9f326f1..0a92d51 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -32,7 +32,6 @@
#define SHOW_PROGRESS
#define MAX_FIRMWARE_ID_LEN 10
#define FORCE_UPDATE false
-#define DO_LOCKDOWN false
#define INSIDE_FIRMWARE_UPDATE
#define FW_IMAGE_OFFSET 0x100
@@ -1115,7 +1114,11 @@
if (retval < 0)
return retval;
- if (f01_device_status.flash_prog) {
+ if (force) {
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Force to enter flash prog mode\n",
+ __func__);
+ } else if (f01_device_status.flash_prog) {
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s: Already in flash prog mode\n",
__func__);
@@ -1475,6 +1478,9 @@
"%s: Erase all command written\n",
__func__);
+ if (fwu->polling_mode)
+ msleep(100);
+
retval = fwu_wait_for_idle(ERASE_WAIT_MS);
if (retval < 0)
return retval;
@@ -1757,7 +1763,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -1800,7 +1806,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -1835,7 +1841,7 @@
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
return retval;
}
@@ -2166,7 +2172,7 @@
fwu->initialized = true;
fwu->force_update = FORCE_UPDATE;
- fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->do_lockdown = rmi4_data->board->do_lockdown;
fwu->initialized = true;
fwu->polling_mode = false;
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 2506e05..cf1c717 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -96,6 +96,8 @@
#define F12_FINGERS_TO_SUPPORT 10
#define MAX_F11_TOUCH_WIDTH 15
+#define RMI4_COORDS_ARR_SIZE 4
+
static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
unsigned short addr, unsigned char *data,
unsigned short length);
@@ -1053,9 +1055,9 @@
wy = finger_data->wy;
#endif
- if (rmi4_data->board->x_flip)
+ if (rmi4_data->flip_x)
x = rmi4_data->sensor_max_x - x;
- if (rmi4_data->board->y_flip)
+ if (rmi4_data->flip_y)
y = rmi4_data->sensor_max_y - y;
dev_dbg(&rmi4_data->i2c_client->dev,
@@ -1332,6 +1334,50 @@
}
#ifdef CONFIG_OF
+static int synaptics_rmi4_get_dt_coords(struct device *dev, char *name,
+ struct synaptics_rmi4_platform_data *pdata)
+{
+ u32 coords[RMI4_COORDS_ARR_SIZE];
+ struct property *prop;
+ struct device_node *np = dev->of_node;
+ int coords_size, rc;
+
+ prop = of_find_property(np, name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ coords_size = prop->length / sizeof(u32);
+ if (coords_size != RMI4_COORDS_ARR_SIZE) {
+ dev_err(dev, "invalid %s\n", name);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(np, name, coords, coords_size);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read %s\n", name);
+ return rc;
+ }
+
+ if (strcmp(name, "synaptics,panel-coords") == 0) {
+ pdata->panel_minx = coords[0];
+ pdata->panel_miny = coords[1];
+ pdata->panel_maxx = coords[2];
+ pdata->panel_maxy = coords[3];
+ } else if (strcmp(name, "synaptics,display-coords") == 0) {
+ pdata->disp_minx = coords[0];
+ pdata->disp_miny = coords[1];
+ pdata->disp_maxx = coords[2];
+ pdata->disp_maxy = coords[3];
+ } else {
+ dev_err(dev, "unsupported property %s\n", name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int synaptics_rmi4_parse_dt(struct device *dev,
struct synaptics_rmi4_platform_data *rmi4_pdata)
{
@@ -1349,21 +1395,26 @@
"synaptics,disable-gpios");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
+ rmi4_pdata->do_lockdown = of_property_read_bool(np,
+ "synaptics,do-lockdown");
- rc = of_property_read_u32(np, "synaptics,panel-x", &temp_val);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Unable to read panel X dimension\n");
+ rc = synaptics_rmi4_get_dt_coords(dev, "synaptics,display-coords",
+ rmi4_pdata);
+ if (rc && (rc != -EINVAL))
return rc;
- } else {
- rmi4_pdata->panel_x = temp_val;
- }
- rc = of_property_read_u32(np, "synaptics,panel-y", &temp_val);
- if (rc && (rc != -EINVAL)) {
- dev_err(dev, "Unable to read panel Y dimension\n");
+ rc = synaptics_rmi4_get_dt_coords(dev, "synaptics,panel-coords",
+ rmi4_pdata);
+ if (rc && (rc != -EINVAL))
return rc;
- } else {
- rmi4_pdata->panel_y = temp_val;
+
+ rmi4_pdata->reset_delay = RESET_DELAY;
+ rc = of_property_read_u32(np, "synaptics,reset-delay", &temp_val);
+ if (!rc)
+ rmi4_pdata->reset_delay = temp_val;
+ else if (rc != -EINVAL) {
+ dev_err(dev, "Unable to read reset delay\n");
+ return rc;
}
rc = of_property_read_string(np, "synaptics,fw-image-name",
@@ -1819,11 +1870,10 @@
const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
if (!pdata->capacitance_button_map) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: capacitance_button_map is" \
- "NULL in board file\n",
+ dev_info(&rmi4_data->i2c_client->dev,
+ "%s: capacitance_button_map not in use\n",
__func__);
- return -ENODEV;
+ return 0;
} else if (!pdata->capacitance_button_map->map) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: Button map is missing in board file\n",
@@ -2258,7 +2308,7 @@
return retval;
}
- msleep(RESET_DELAY);
+ msleep(rmi4_data->board->reset_delay);
return retval;
};
@@ -2603,7 +2653,7 @@
gpio_set_value(rmi4_data->board->reset_gpio, 0);
usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(rmi4_data->board->reset_gpio, 1);
- msleep(RESET_DELAY);
+ msleep(rmi4_data->board->reset_delay);
} else
synaptics_rmi4_reset_command(rmi4_data);
@@ -2776,12 +2826,32 @@
goto err_free_gpios;
}
+ if (rmi4_data->board->disp_maxx)
+ rmi4_data->disp_maxx = rmi4_data->board->disp_maxx;
+ else
+ rmi4_data->disp_maxx = rmi4_data->sensor_max_x;
+
+ if (rmi4_data->board->disp_maxy)
+ rmi4_data->disp_maxy = rmi4_data->board->disp_maxy;
+ else
+ rmi4_data->disp_maxy = rmi4_data->sensor_max_y;
+
+ if (rmi4_data->board->disp_minx)
+ rmi4_data->disp_minx = rmi4_data->board->disp_minx;
+ else
+ rmi4_data->disp_minx = 0;
+
+ if (rmi4_data->board->disp_miny)
+ rmi4_data->disp_miny = rmi4_data->board->disp_miny;
+ else
+ rmi4_data->disp_miny = 0;
+
input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_X, 0,
- rmi4_data->sensor_max_x, 0, 0);
+ ABS_MT_POSITION_X, rmi4_data->disp_minx,
+ rmi4_data->disp_maxx, 0, 0);
input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_Y, 0,
- rmi4_data->sensor_max_y, 0, 0);
+ ABS_MT_POSITION_Y, rmi4_data->disp_miny,
+ rmi4_data->disp_maxy, 0, 0);
input_set_abs_params(rmi4_data->input_dev,
ABS_PRESSURE, 0, 255, 0, 0);
#ifdef REPORT_2D_W
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 677a2fe..ef39bb7 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -186,6 +186,10 @@
* @irq: attention interrupt
* @sensor_max_x: sensor maximum x value
* @sensor_max_y: sensor maximum y value
+ * @disp_maxx: max x value of display
+ * @disp_maxy: max y value of display
+ * @disp_minx: min x value of display
+ * @disp_miny: min y value of display
* @irq_enabled: flag for indicating interrupt enable status
* @touch_stopped: flag to stop interrupt thread processing
* @fingers_on_2d: flag to indicate presence of fingers in 2d area
@@ -230,6 +234,10 @@
int irq;
int sensor_max_x;
int sensor_max_y;
+ int disp_maxx;
+ int disp_maxy;
+ int disp_minx;
+ int disp_miny;
bool irq_enabled;
bool touch_stopped;
bool fingers_on_2d;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 675110f..ecab061 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -59,7 +59,7 @@
#define WLED_CTL_DLY_MAX 1400
#define WLED_MAX_CURR 25
#define WLED_MSB_MASK 0x0F
-#define WLED_MAX_CURR_MASK 0x19
+#define WLED_MAX_CURR_MASK 0x1F
#define WLED_OP_FDBCK_MASK 0x07
#define WLED_OP_FDBCK_BIT_SHFT 0x00
#define WLED_OP_FDBCK_DEFAULT 0x00
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index c188105..32d74ba 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -816,6 +816,7 @@
cci_client = msm_actuator_t->i2c_client.cci_client;
cci_client->cci_subdev = msm_cci_get_subdev();
+ cci_client->cci_i2c_master = MASTER_MAX;
v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
msm_actuator_t->act_v4l2_subdev_ops);
v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
index 591c464..059633b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cam_cci_hwreg.h
@@ -15,7 +15,7 @@
#define CCI_HW_VERSION_ADDR 0x00000000
#define CCI_RESET_CMD_ADDR 0x00000004
-#define CCI_RESET_CMD_RMSK 0xcf73f3f7
+#define CCI_RESET_CMD_RMSK 0x0f73f3f7
#define CCI_M0_RESET_RMSK 0x3F1
#define CCI_M1_RESET_RMSK 0x3F001
#define CCI_QUEUE_START_ADDR 0x00000008
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 17c5a14..d11798e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -628,21 +628,46 @@
{"cci_clk", -1},
};
-static int32_t msm_cci_init(struct v4l2_subdev *sd)
+static int32_t msm_cci_init(struct v4l2_subdev *sd,
+ struct msm_camera_cci_ctrl *c_ctrl)
{
int rc = 0;
struct cci_device *cci_dev;
+ enum cci_i2c_master_t master;
cci_dev = v4l2_get_subdevdata(sd);
- CDBG("%s line %d\n", __func__, __LINE__);
- if (!cci_dev) {
- pr_err("%s cci device NULL\n", __func__);
+ if (!cci_dev || !c_ctrl) {
+ pr_err("%s:%d failed: invalid params %p %p\n", __func__,
+ __LINE__, cci_dev, c_ctrl);
rc = -ENOMEM;
return rc;
}
if (cci_dev->ref_count++) {
CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+ master = c_ctrl->cci_info->cci_i2c_master;
+ CDBG("%s:%d master %d\n", __func__, __LINE__, master);
+ if (master < MASTER_MAX) {
+ mutex_lock(&cci_dev->cci_master_info[master].mutex);
+ /* Set reset pending flag to TRUE */
+ cci_dev->cci_master_info[master].reset_pending = TRUE;
+ /* Set proper mask to RESET CMD address */
+ if (master == MASTER_0)
+ msm_camera_io_w(CCI_M0_RESET_RMSK,
+ cci_dev->base + CCI_RESET_CMD_ADDR);
+ else
+ msm_camera_io_w(CCI_M1_RESET_RMSK,
+ cci_dev->base + CCI_RESET_CMD_ADDR);
+ /* wait for reset done irq */
+ rc = wait_for_completion_interruptible_timeout(
+ &cci_dev->cci_master_info[master].
+ reset_complete,
+ CCI_TIMEOUT);
+ if (rc <= 0)
+ pr_err("%s:%d wait failed %d\n", __func__,
+ __LINE__, rc);
+ mutex_unlock(&cci_dev->cci_master_info[master].mutex);
+ }
return 0;
}
@@ -685,6 +710,7 @@
cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
msm_camera_io_w(0x1, cci_dev->base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
cci_dev->cci_state = CCI_STATE_ENABLED;
+
return 0;
reset_complete_failed:
@@ -695,6 +721,7 @@
msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
cci_dev->cci_gpio_tbl_size, 0);
request_gpio_failed:
+ cci_dev->ref_count--;
return rc;
}
@@ -710,7 +737,7 @@
}
if (--cci_dev->ref_count) {
- CDBG("%s ref_count %d\n", __func__, cci_dev->ref_count);
+ CDBG("%s ref_count Exit %d\n", __func__, cci_dev->ref_count);
return 0;
}
@@ -723,6 +750,7 @@
cci_dev->cci_gpio_tbl_size, 0);
cci_dev->cci_state = CCI_STATE_DISABLED;
+
return 0;
}
@@ -734,7 +762,7 @@
cci_ctrl->cmd);
switch (cci_ctrl->cmd) {
case MSM_CCI_INIT:
- rc = msm_cci_init(sd);
+ rc = msm_cci_init(sd, cci_ctrl);
break;
case MSM_CCI_RELEASE:
rc = msm_cci_release(sd);
@@ -837,10 +865,7 @@
rc = msm_cci_config(sd, arg);
break;
case MSM_SD_SHUTDOWN: {
- struct msm_camera_cci_ctrl ctrl_cmd;
- ctrl_cmd.cmd = MSM_CCI_RELEASE;
- rc = msm_cci_config(sd, &ctrl_cmd);
- break;
+ return rc;
}
default:
rc = -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index 1407f12..7f13568 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -229,6 +229,88 @@
return rc;
}
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc = 0, i = 0;
+ struct msm_eeprom_board_info *eb_info;
+ struct msm_camera_power_ctrl_t *power_info =
+ &e_ctrl->eboard_info->power_info;
+ struct device_node *of_node = NULL;
+ struct msm_camera_gpio_conf *gconf = NULL;
+ uint16_t gpio_array_size = 0;
+ uint16_t *gpio_array = NULL;
+
+ eb_info = e_ctrl->eboard_info;
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
+ of_node = e_ctrl->i2c_client.
+ spi_client->spi_master->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ of_node = e_ctrl->pdev->dev.of_node;
+ else if (e_ctrl->eeprom_device_type == MSM_CAMERA_I2C_DEVICE)
+ of_node = e_ctrl->i2c_client.client->dev.of_node;
+
+ rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+ &power_info->num_vreg);
+ if (rc < 0)
+ return rc;
+
+ rc = msm_camera_get_dt_power_setting_data(of_node,
+ power_info->cam_vreg, power_info->num_vreg,
+ &power_info->power_setting, &power_info->power_setting_size);
+ if (rc < 0)
+ goto error1;
+
+ power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+ GFP_KERNEL);
+ if (!power_info->gpio_conf) {
+ rc = -ENOMEM;
+ goto error2;
+ }
+ gconf = power_info->gpio_conf;
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+ if (gpio_array_size) {
+ gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+ GFP_KERNEL);
+ if (!gpio_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error3;
+ }
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+ gpio_array[i]);
+ }
+
+ rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error4;
+ }
+
+ rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto error4;
+ }
+ kfree(gpio_array);
+ }
+
+ return rc;
+error4:
+ kfree(gpio_array);
+error3:
+ kfree(power_info->gpio_conf);
+error2:
+ kfree(power_info->cam_vreg);
+error1:
+ kfree(power_info->power_setting);
+ return rc;
+}
+
static int msm_eeprom_alloc_memory_map(struct msm_eeprom_ctrl_t *e_ctrl,
struct device_node *of)
{
@@ -320,10 +402,19 @@
int32_t msm_eeprom_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id) {
int rc = 0;
+ int32_t j = 0;
+ uint32_t temp = 0;
struct msm_eeprom_ctrl_t *e_ctrl = NULL;
struct msm_camera_power_ctrl_t *power_info = NULL;
+ struct device_node *of_node = client->dev.of_node;
CDBG("%s E\n", __func__);
+
+ if (!of_node) {
+ pr_err("%s of_node NULL\n", __func__);
+ return -EINVAL;
+ }
+
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
pr_err("%s i2c_check_functionality failed\n", __func__);
goto probe_failure;
@@ -337,13 +428,23 @@
e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
CDBG("%s client = %x\n", __func__, (unsigned int)client);
- e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
+ e_ctrl->eboard_info = kzalloc(sizeof(
+ struct msm_eeprom_board_info), GFP_KERNEL);
if (!e_ctrl->eboard_info) {
pr_err("%s:%d board info NULL\n", __func__, __LINE__);
return -EINVAL;
}
+
+ rc = of_property_read_u32(of_node, "qcom,slave-addr", &temp);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ return rc;
+ }
+
power_info = &e_ctrl->eboard_info->power_info;
+ e_ctrl->eboard_info->i2c_slaveaddr = temp;
e_ctrl->i2c_client.client = client;
+ e_ctrl->is_supported = 0;
/* Set device type as I2C */
e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
@@ -356,6 +457,45 @@
power_info->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
power_info->dev = &client->dev;
+ rc = of_property_read_string(of_node, "qcom,eeprom-name",
+ &e_ctrl->eboard_info->eeprom_name);
+ CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+ e_ctrl->eboard_info->eeprom_name, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto board_free;
+ }
+
+ rc = msm_eeprom_get_dt_data(e_ctrl);
+ if (rc)
+ goto board_free;
+
+ rc = msm_eeprom_alloc_memory_map(e_ctrl, of_node);
+ if (rc)
+ goto board_free;
+
+ rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("%s failed power up %d\n", __func__, __LINE__);
+ goto memdata_free;
+ }
+ rc = read_eeprom_memory(e_ctrl);
+ if (rc < 0) {
+ pr_err("%s read_eeprom_memory failed\n", __func__);
+ goto power_down;
+ }
+
+ for (j = 0; j < e_ctrl->num_bytes; j++)
+ CDBG("memory_data[%d] = 0x%X\n", j, e_ctrl->memory_data[j]);
+
+ rc = msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto power_down;
+ }
+
/*IMPLEMENT READING PART*/
/* Initialize sub device */
v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
@@ -368,9 +508,18 @@
e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
msm_sd_register(&e_ctrl->msm_sd);
+ e_ctrl->is_supported = 1;
CDBG("%s success result=%d X\n", __func__, rc);
return rc;
+power_down:
+ msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+memdata_free:
+ kfree(e_ctrl->memory_data);
+ kfree(e_ctrl->eboard_info->eeprom_map);
+board_free:
+ kfree(e_ctrl->eboard_info);
probe_failure:
pr_err("%s failed! rc = %d\n", __func__, rc);
return rc;
@@ -454,86 +603,6 @@
return 0;
}
-static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
-{
- int rc = 0, i = 0;
- struct msm_eeprom_board_info *eb_info;
- struct msm_camera_power_ctrl_t *power_info =
- &e_ctrl->eboard_info->power_info;
- struct device_node *of_node = NULL;
- struct msm_camera_gpio_conf *gconf = NULL;
- uint16_t gpio_array_size = 0;
- uint16_t *gpio_array = NULL;
-
- eb_info = e_ctrl->eboard_info;
- if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
- of_node = e_ctrl->i2c_client.
- spi_client->spi_master->dev.of_node;
- else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
- of_node = e_ctrl->pdev->dev.of_node;
-
- rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
- &power_info->num_vreg);
- if (rc < 0)
- return rc;
-
- rc = msm_camera_get_dt_power_setting_data(of_node,
- power_info->cam_vreg, power_info->num_vreg,
- &power_info->power_setting, &power_info->power_setting_size);
- if (rc < 0)
- goto ERROR1;
-
- power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
- GFP_KERNEL);
- if (!power_info->gpio_conf) {
- rc = -ENOMEM;
- goto ERROR2;
- }
- gconf = power_info->gpio_conf;
- gpio_array_size = of_gpio_count(of_node);
- CDBG("%s gpio count %d\n", __func__, gpio_array_size);
-
- if (gpio_array_size) {
- gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
- GFP_KERNEL);
- if (!gpio_array) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR3;
- }
- for (i = 0; i < gpio_array_size; i++) {
- gpio_array[i] = of_get_gpio(of_node, i);
- CDBG("%s gpio_array[%d] = %d\n", __func__, i,
- gpio_array[i]);
- }
-
- rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
-
- rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
- gpio_array, gpio_array_size);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR4;
- }
- kfree(gpio_array);
- }
-
- return rc;
-ERROR4:
- kfree(gpio_array);
-ERROR3:
- kfree(power_info->gpio_conf);
-ERROR2:
- kfree(power_info->cam_vreg);
-ERROR1:
- kfree(power_info->power_setting);
- return rc;
-}
-
static int msm_eeprom_spi_setup(struct spi_device *spi)
{
struct msm_eeprom_ctrl_t *e_ctrl = NULL;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
index 62102cb..9fc3817 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_MSMB_CAMERA) += msm_led_trigger.o
obj-$(CONFIG_MSMB_CAMERA) += msm_led_i2c_trigger.o
obj-$(CONFIG_MSMB_CAMERA) += adp1660.o
+obj-$(CONFIG_MSMB_CAMERA) += msm_led_torch.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c
new file mode 100644
index 0000000..ff63696
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_torch.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include "msm_led_flash.h"
+
+static struct led_trigger *torch_trigger;
+
+static void msm_led_torch_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (!torch_trigger) {
+ pr_err("No torch trigger found, can't set brightness\n");
+ return;
+ }
+
+ led_trigger_event(torch_trigger, value);
+};
+
+static struct led_classdev msm_torch_led = {
+ .name = "torch-light",
+ .brightness_set = msm_led_torch_brightness_set,
+ .brightness = LED_OFF,
+};
+
+int32_t msm_led_torch_create_classdev(struct platform_device *pdev,
+ void *data)
+{
+ int rc;
+ struct msm_led_flash_ctrl_t *fctrl =
+ (struct msm_led_flash_ctrl_t *)data;
+
+ if (!fctrl || !fctrl->torch_trigger) {
+ pr_err("Invalid fctrl or torch trigger\n");
+ return -EINVAL;
+ }
+
+ torch_trigger = fctrl->torch_trigger;
+ msm_led_torch_brightness_set(&msm_torch_led, LED_OFF);
+
+ rc = led_classdev_register(&pdev->dev, &msm_torch_led);
+ if (rc) {
+ pr_err("Failed to register led dev. rc = %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+};
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 1b0ec44..20905c9 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -26,6 +26,9 @@
#define CDBG(fmt, args...) do { } while (0)
#endif
+extern int32_t msm_led_torch_create_classdev(
+ struct platform_device *pdev, void *data);
+
static struct msm_led_flash_ctrl_t fctrl;
static int32_t msm_led_trigger_get_subdev_id(struct msm_led_flash_ctrl_t *fctrl,
@@ -209,7 +212,11 @@
of_node_put(flash_src_node);
}
}
+
rc = msm_led_flash_create_v4lsubdev(pdev, &fctrl);
+ if (!rc)
+ msm_led_torch_create_classdev(pdev, &fctrl);
+
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index ddc168a..0083378 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1272,9 +1272,10 @@
case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
- case MSM_SD_SHUTDOWN:
msm_sensor_stop_stream(s_ctrl);
return 0;
+ case MSM_SD_SHUTDOWN:
+ return 0;
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index e335ff0..afd7200 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -514,6 +514,19 @@
b->m.planes[i].m.userptr = binfo->device_addr[i];
dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
binfo->device_addr[i]);
+
+ if ((vidc_inst->fmts[OUTPUT_PORT]->fourcc ==
+ V4L2_PIX_FMT_HEVC_HYBRID) && binfo->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+ rc = msm_smem_cache_operations(v4l2_inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_INVALIDATE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to INV caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
+ }
+
if (binfo->handle[i] &&
(b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
rc = msm_smem_cache_operations(v4l2_inst->mem_client,
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 73ff9fa..a3d88c5 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -363,6 +363,14 @@
.type = OUTPUT_PORT,
},
{
+ .name = "HEVC_HYBRID",
+ .description = "HEVC compressed format",
+ .fourcc = V4L2_PIX_FMT_HEVC_HYBRID,
+ .num_planes = 1,
+ .get_frame_size = get_frame_size_compressed,
+ .type = OUTPUT_PORT,
+ },
+ {
.name = "VP8",
.description = "VP8 compressed format",
.fourcc = V4L2_PIX_FMT_VP8,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 122f0e9..fdc851c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1337,7 +1337,9 @@
case V4L2_PIX_FMT_HEVC:
codec = HAL_VIDEO_CODEC_HEVC;
break;
-
+ case V4L2_PIX_FMT_HEVC_HYBRID:
+ codec = HAL_VIDEO_CODEC_HEVC_HYBRID;
+ break;
default:
dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
codec = HAL_UNUSED_CODEC;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 890a5be..b600d64 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -202,6 +202,7 @@
HAL_VIDEO_CODEC_VP7 = 0x00000800,
HAL_VIDEO_CODEC_VP8 = 0x00001000,
HAL_VIDEO_CODEC_HEVC = 0x00002000,
+ HAL_VIDEO_CODEC_HEVC_HYBRID = 0x00004000,
HAL_UNUSED_CODEC = 0x10000000,
};
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index de312f4..b5c431e 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -80,6 +80,7 @@
#define HFI_VIDEO_CODEC_SPARK 0x00000200
#define HFI_VIDEO_CODEC_VP8 0x00001000
#define HFI_VIDEO_CODEC_HEVC 0x00002000
+#define HFI_VIDEO_CODEC_HEVC_HYBRID 0x00004000
#define HFI_H264_PROFILE_BASELINE 0x00000001
#define HFI_H264_PROFILE_MAIN 0x00000002
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index c6d08d1..8090b95 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -44,6 +44,7 @@
struct timed_output_dev dev;
struct work_struct work;
struct mutex lock;
+ struct mutex lock_clk;
unsigned int enable;
unsigned int period_ns;
bool is_len_gpio_valid;
@@ -120,16 +121,19 @@
}
}
+ mutex_lock(&haptic->lock_clk);
/* vote for clock */
if (haptic->pdata->need_pwm_clk && !haptic->clk_on) {
rc = clk_prepare_enable(haptic->pwm_clk);
if (rc < 0) {
pr_err("%s: clk enable failed\n",
__func__);
+ mutex_unlock(&haptic->lock_clk);
goto dis_clk_cb;
}
haptic->clk_on = true;
}
+ mutex_unlock(&haptic->lock_clk);
rc = isa1200_write_reg(haptic->client,
ISA1200_HCTRL5,
@@ -162,11 +166,13 @@
if (rc < 0)
pr_err("%s: stop vibartion fail\n", __func__);
+ mutex_lock(&haptic->lock_clk);
/* de-vote clock */
if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
clk_disable_unprepare(haptic->pwm_clk);
haptic->clk_on = false;
}
+ mutex_unlock(&haptic->lock_clk);
/* check for board specific clk callback */
if (haptic->pdata->clk_enable) {
rc = haptic->pdata->clk_enable(false);
@@ -180,10 +186,12 @@
return;
dis_clk:
+ mutex_lock(&haptic->lock_clk);
if (haptic->pdata->need_pwm_clk && haptic->clk_on) {
clk_disable_unprepare(haptic->pwm_clk);
haptic->clk_on = false;
}
+ mutex_unlock(&haptic->lock_clk);
dis_clk_cb:
if (haptic->pdata->clk_enable) {
@@ -649,6 +657,7 @@
}
mutex_init(&haptic->lock);
+ mutex_init(&haptic->lock_clk);
INIT_WORK(&haptic->work, isa1200_chip_work);
haptic->clk_on = false;
@@ -787,6 +796,7 @@
/* destroy mutex */
mutex_destroy(&haptic->lock);
+ mutex_destroy(&haptic->lock_clk);
/* power-off the chip */
if (haptic->pdata->regulator_info) {
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index a4498d2..3648d88 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -26,6 +26,12 @@
#include "sd.h"
#include "sd_ops.h"
+#define UHS_SDR104_MIN_DTR (100 * 1000 * 1000)
+#define UHS_DDR50_MIN_DTR (50 * 1000 * 1000)
+#define UHS_SDR50_MIN_DTR (50 * 1000 * 1000)
+#define UHS_SDR25_MIN_DTR (25 * 1000 * 1000)
+#define UHS_SDR12_MIN_DTR (12.5 * 1000 * 1000)
+
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
@@ -486,18 +492,22 @@
}
if ((card->host->caps & MMC_CAP_UHS_SDR104) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR104) &&
+ (card->host->f_max > UHS_SDR104_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR104_BUS_SPEED;
} else if ((card->host->caps & MMC_CAP_UHS_DDR50) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_DDR50) &&
+ (card->host->f_max > UHS_DDR50_MIN_DTR)) {
card->sd_bus_speed = UHS_DDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50)) && (card->sw_caps.sd3_bus_mode &
- SD_MODE_UHS_SDR50)) {
+ SD_MODE_UHS_SDR50) &&
+ (card->host->f_max > UHS_SDR50_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR50_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25)) &&
- (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25)) {
+ (card->sw_caps.sd3_bus_mode & SD_MODE_UHS_SDR25) &&
+ (card->host->f_max > UHS_SDR25_MIN_DTR)) {
card->sd_bus_speed = UHS_SDR25_BUS_SPEED;
} else if ((card->host->caps & (MMC_CAP_UHS_SDR104 |
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR25 |
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 44f86dd..9f06258 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -42,6 +42,11 @@
module_param_named(debug_enable, msm_rmnet_bam_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+static unsigned long int msm_rmnet_bam_headroom_check_failure;
+module_param(msm_rmnet_bam_headroom_check_failure, ulong, S_IRUGO);
+MODULE_PARM_DESC(msm_rmnet_bam_headroom_check_failure,
+ "Number of packets with insufficient headroom");
+
#define DEBUG_MASK_LVL0 (1U << 0)
#define DEBUG_MASK_LVL1 (1U << 1)
#define DEBUG_MASK_LVL2 (1U << 2)
@@ -287,6 +292,23 @@
((struct net_device *)dev)->name, __func__);
}
+static struct sk_buff *_rmnet_add_headroom(struct sk_buff **skb,
+ struct net_device *dev)
+{
+ struct sk_buff *skbn;
+
+ if (skb_headroom(*skb) < dev->needed_headroom) {
+ msm_rmnet_bam_headroom_check_failure++;
+ skbn = skb_realloc_headroom(*skb, dev->needed_headroom);
+ kfree_skb(*skb);
+ *skb = skbn;
+ } else {
+ skbn = *skb;
+ }
+
+ return skbn;
+}
+
static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
@@ -295,6 +317,10 @@
u32 opmode;
unsigned long flags;
+ if (unlikely(!_rmnet_add_headroom(&skb, dev))) {
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
/* For QoS mode, prepend QMI header and assign flow ID from skb->mark */
spin_lock_irqsave(&p->lock, flags);
opmode = p->operation_mode;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index aa29748..7d6e345 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -1797,6 +1797,7 @@
if (IS_ERR(penv->pil)) {
dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
ret = PTR_ERR(penv->pil);
+ wcnss_pronto_log_debug_regs();
penv->pil = NULL;
goto fail_pil;
}
diff --git a/drivers/platform/msm/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index b77c826..7d26bef 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.c
@@ -199,8 +199,15 @@
#define qpnp_check_gpled_lpg_channel(id) \
(id >= QPNP_GPLED_LPG_CHANNEL_RANGE_START && \
id <= QPNP_GPLED_LPG_CHANNEL_RANGE_END)
+
#define QPNP_PWM_LUT_NOT_SUPPORTED 0x1
+/* Supported PWM sizes */
+#define QPNP_PWM_SIZE_6_BIT 6
+#define QPNP_PWM_SIZE_7_BIT 7
+#define QPNP_PWM_SIZE_8_BIT 8
+#define QPNP_PWM_SIZE_9_BIT 9
+
/* LPG revisions */
enum qpnp_lpg_revision {
QPNP_LPG_REVISION_0 = 0x0,
@@ -301,6 +308,7 @@
int pwm_period;
int pwm_duty;
struct pwm_period_config period;
+ int force_pwm_size;
};
/* Public facing structure */
@@ -418,14 +426,16 @@
* (PWM Period / N) = (Pre-divide * Clock Period) * 2^m
*/
static void qpnp_lpg_calc_period(unsigned int period_us,
- struct qpnp_pwm_config *pwm_conf)
+ struct pwm_device *pwm)
{
int n, m, clk, div;
int best_m, best_div, best_clk;
unsigned int last_err, cur_err, min_err;
unsigned int tmp_p, period_n;
- int id = pwm_conf->channel_id;
- struct pwm_period_config *period = &pwm_conf->period;
+ int id = pwm->pwm_config.channel_id;
+ int force_pwm_size = pwm->pwm_config.force_pwm_size;
+ struct qpnp_lpg_chip *chip = pwm->chip;
+ struct pwm_period_config *period = &pwm->pwm_config.period;
/* PWM Period / N */
if (qpnp_check_gpled_lpg_channel(id))
@@ -443,6 +453,15 @@
period_n = (period_us >> n) * NSEC_PER_USEC;
}
+ if (force_pwm_size != 0) {
+ if (n < force_pwm_size)
+ period_n = period_n >> (force_pwm_size - n);
+ else
+ period_n = period_n << (n - force_pwm_size);
+ n = force_pwm_size;
+ pr_info("LPG channel '%d' pwm size is forced to=%d\n", id, n);
+ }
+
min_err = last_err = (unsigned)(-1);
best_m = 0;
best_clk = 0;
@@ -476,19 +495,20 @@
}
/* Adapt to optimal pwm size, the higher the resolution the better */
- if (qpnp_check_gpled_lpg_channel(id)) {
- if (n == 7 && best_m >= 1) {
- n += 1;
- best_m -= 1;
- }
- } else {
- if (n == 6 && best_m >= 3) {
- n += 3;
- best_m -= 3;
- } else {
- if (n == 6) {
- n += best_m;
- best_m -= best_m;
+ if (!force_pwm_size) {
+ if (qpnp_check_gpled_lpg_channel(id)) {
+ if (n == 7 && best_m >= 1) {
+ n += 1;
+ best_m -= 1;
+ }
+ } else if (n == 6) {
+ if (best_m >= 3) {
+ n += 3;
+ best_m -= 3;
+ } else if (best_m >= 1 &&
+ chip->sub_type != QPNP_PWM_MODE_ONLY_SUB_TYPE) {
+ n += 1;
+ best_m -= 1;
}
}
}
@@ -1075,7 +1095,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, pwm_config);
+ qpnp_lpg_calc_period(period_us, pwm);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1131,7 +1151,7 @@
period = &pwm_config->period;
if (pwm_config->pwm_period != period_us) {
- qpnp_lpg_calc_period(period_us, pwm_config);
+ qpnp_lpg_calc_period(period_us, pwm);
qpnp_lpg_save_period(pwm);
pwm_config->pwm_period = period_us;
}
@@ -1715,6 +1735,7 @@
struct pwm_device *pwm_dev = &chip->pwm_dev;
struct qpnp_lpg_config *lpg_config = &chip->lpg_config;
struct qpnp_lut_config *lut_config = &lpg_config->lut_config;
+ int force_pwm_size = 0;
rc = of_property_read_u32(of_node, "qcom,channel-id",
&pwm_dev->pwm_config.channel_id);
@@ -1724,6 +1745,27 @@
goto out;
}
+ /*
+ * For cetrain LPG channels PWM size can be forced. So that
+ * for every requested pwm period closest pwm frequency is
+ * selected in qpnp_lpg_calc_period() for the forced pwm size.
+ */
+ rc = of_property_read_u32(of_node, "qcom,force-pwm-size",
+ &force_pwm_size);
+ if (qpnp_check_gpled_lpg_channel(pwm_dev->pwm_config.channel_id)) {
+ if (!(force_pwm_size == QPNP_PWM_SIZE_7_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_8_BIT))
+ force_pwm_size = 0;
+ } else if (chip->sub_type == QPNP_PWM_MODE_ONLY_SUB_TYPE) {
+ if (!(force_pwm_size == QPNP_PWM_SIZE_6_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_9_BIT))
+ force_pwm_size = 0;
+ } else if (!(force_pwm_size == QPNP_PWM_SIZE_6_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_7_BIT ||
+ force_pwm_size == QPNP_PWM_SIZE_9_BIT))
+ force_pwm_size = 0;
+
+ pwm_dev->pwm_config.force_pwm_size = force_pwm_size;
res = spmi_get_resource_byname(spmi, NULL, IORESOURCE_MEM,
QPNP_LPG_CHANNEL_BASE);
if (!res) {
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 6706e0d..49e57b9 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -190,6 +190,7 @@
struct mutex vbat_monitor_mutex;
struct mutex soc_invalidation_mutex;
struct mutex last_soc_mutex;
+ struct mutex status_lock;
bool use_external_rsense;
bool use_ocv_thresholds;
@@ -295,6 +296,7 @@
static enum power_supply_property msm_bms_power_props[] = {
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_RESISTANCE,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
@@ -3110,6 +3112,7 @@
{
int status = get_battery_status(chip);
+ mutex_lock(&chip->status_lock);
if (chip->battery_status != status) {
pr_debug("status = %d, shadow status = %d\n",
status, chip->battery_status);
@@ -3126,6 +3129,7 @@
pr_debug("battery full\n");
enable_bms_irq(&chip->ocv_thr_irq);
enable_bms_irq(&chip->sw_cc_thr_irq);
+ recalculate_soc(chip);
} else if (chip->battery_status
== POWER_SUPPLY_STATUS_FULL) {
pr_debug("battery not full any more\n");
@@ -3138,6 +3142,7 @@
* recalculation to update the SoC */
schedule_work(&chip->recalc_work);
}
+ mutex_unlock(&chip->status_lock);
}
#define CALIB_WRKARND_DIG_MAJOR_MAX 0x03
@@ -3212,6 +3217,9 @@
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = get_prop_bms_capacity(chip);
break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = chip->battery_status;
+ break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_bms_current_now(chip);
break;
@@ -3989,6 +3997,7 @@
mutex_init(&chip->vbat_monitor_mutex);
mutex_init(&chip->soc_invalidation_mutex);
mutex_init(&chip->last_soc_mutex);
+ mutex_init(&chip->status_lock);
init_waitqueue_head(&chip->bms_wait_queue);
warm_reset = qpnp_pon_is_warm_reset();
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index f9e05fc..6e9dc57 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1693,7 +1693,7 @@
get_prop_capacity(struct qpnp_chg_chip *chip)
{
union power_supply_propval ret = {0,};
- int battery_status, charger_in;
+ int battery_status, bms_status, soc, charger_in;
if (chip->use_default_batt_values || !get_prop_batt_present(chip))
return DEFAULT_CAPACITY;
@@ -1701,28 +1701,32 @@
if (chip->bms_psy) {
chip->bms_psy->get_property(chip->bms_psy,
POWER_SUPPLY_PROP_CAPACITY, &ret);
+ soc = ret.intval;
battery_status = get_prop_batt_status(chip);
+ chip->bms_psy->get_property(chip->bms_psy,
+ POWER_SUPPLY_PROP_STATUS, &ret);
+ bms_status = ret.intval;
charger_in = qpnp_chg_is_usb_chg_plugged_in(chip) ||
qpnp_chg_is_dc_chg_plugged_in(chip);
if (battery_status != POWER_SUPPLY_STATUS_CHARGING
+ && bms_status != POWER_SUPPLY_STATUS_CHARGING
&& charger_in
&& !chip->resuming_charging
&& !chip->charging_disabled
&& chip->soc_resume_limit
- && ret.intval <= chip->soc_resume_limit) {
- pr_debug("resuming charging at %d%% soc\n",
- ret.intval);
+ && soc <= chip->soc_resume_limit) {
+ pr_debug("resuming charging at %d%% soc\n", soc);
chip->resuming_charging = true;
qpnp_chg_set_appropriate_vbatdet(chip);
qpnp_chg_charge_en(chip, !chip->charging_disabled);
}
- if (ret.intval == 0) {
+ if (soc == 0) {
if (!qpnp_chg_is_usb_chg_plugged_in(chip)
&& !qpnp_chg_is_usb_chg_plugged_in(chip))
pr_warn_ratelimited("Battery 0, CHG absent\n");
}
- return ret.intval;
+ return soc;
} else {
pr_debug("No BMS supply registered return 50\n");
}
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 1f2f6f9..5264005 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -482,6 +482,8 @@
if (rc == 0) {
pr_err("DSI command transaction time out\n");
rc = -ETIME;
+ } else if (!IS_ERR_VALUE(rc)) {
+ rc = 0;
}
dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
@@ -524,7 +526,7 @@
{
struct dsi_cmd_desc *cm;
u32 dsi_ctrl, ctrl;
- int i, video_mode;
+ int i, video_mode, rc = 0;
unsigned char *ctrl_base = dsi_host_private->dsi_base;
/* turn on cmd mode
@@ -546,6 +548,11 @@
dsi_buf_init(tp);
dsi_cmd_dma_add(tp, cm);
msm_dsi_cmd_dma_tx(tp);
+ rc = msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("%s: failed to call cmd_dma_tx\n", __func__);
+ break;
+ }
if (cm->dchdr.wait)
msleep(cm->dchdr.wait);
cm++;
@@ -555,7 +562,7 @@
if (video_mode)
MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
- return 0;
+ return rc;
}
/* MDSS_DSI_MRPS, Maximum Return Packet Size */
@@ -582,7 +589,7 @@
struct dsi_buf *tp, struct dsi_buf *rp,
struct dsi_cmd_desc *cmds, int rlen)
{
- int cnt, len, diff, pkt_size;
+ int cnt, len, diff, pkt_size, rc = 0;
char cmd;
if (pdata->panel_info.mipi.no_max_pkt_size)
@@ -618,7 +625,13 @@
max_pktsize[0] = pkt_size;
dsi_buf_init(tp);
dsi_cmd_dma_add(tp, pkt_size_cmd);
- msm_dsi_cmd_dma_tx(tp);
+ rc = msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ msm_dsi_disable_irq();
+ pr_err("%s: dma_tx failed\n", __func__);
+ rp->len = 0;
+ goto end;
+ }
pr_debug("%s: Max packet size sent\n", __func__);
}
@@ -627,6 +640,12 @@
/* transmit read comamnd to client */
msm_dsi_cmd_dma_tx(tp);
+ if (IS_ERR_VALUE(rc)) {
+ msm_dsi_disable_irq();
+ pr_err("%s: dma_tx failed\n", __func__);
+ rp->len = 0;
+ goto end;
+ }
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
@@ -680,6 +699,7 @@
break;
}
+end:
return rp->len;
}
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f6c90f5..8a5f1ee 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
+#include <linux/dma-buf.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -120,8 +121,19 @@
};
struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = {
- [MDP3_IOMMU_DOMAIN] = {
- .domain_type = MDP3_IOMMU_DOMAIN,
+ [MDP3_PPP_IOMMU_DOMAIN] = {
+ .domain_type = MDP3_PPP_IOMMU_DOMAIN,
+ .client_name = "mdp_ppp",
+ .partitions = {
+ {
+ .start = SZ_128K,
+ .size = SZ_1G - SZ_128K,
+ },
+ },
+ .npartitions = 1,
+ },
+ [MDP3_DMA_IOMMU_DOMAIN] = {
+ .domain_type = MDP3_DMA_IOMMU_DOMAIN,
.client_name = "mdp_dma",
.partitions = {
{
@@ -136,27 +148,27 @@
struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = {
[MDP3_IOMMU_CTX_PPP_0] = {
.ctx_type = MDP3_IOMMU_CTX_PPP_0,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_PPP_IOMMU_DOMAIN],
.ctx_name = "mdpe_0",
.attached = 0,
},
[MDP3_IOMMU_CTX_PPP_1] = {
.ctx_type = MDP3_IOMMU_CTX_PPP_1,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_PPP_IOMMU_DOMAIN],
.ctx_name = "mdpe_1",
.attached = 0,
},
[MDP3_IOMMU_CTX_DMA_0] = {
.ctx_type = MDP3_IOMMU_CTX_DMA_0,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_DMA_IOMMU_DOMAIN],
.ctx_name = "mdps_0",
.attached = 0,
},
[MDP3_IOMMU_CTX_DMA_1] = {
.ctx_type = MDP3_IOMMU_CTX_DMA_1,
- .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .domain = &mdp3_iommu_domains[MDP3_DMA_IOMMU_DOMAIN],
.ctx_name = "mdps_1",
.attached = 0,
},
@@ -685,6 +697,8 @@
{
int ret;
+ mutex_init(&mdp3_res->iommu_lock);
+
ret = mdp3_iommu_domain_init();
if (ret) {
pr_err("mdp3 iommu domain init fails\n");
@@ -1032,17 +1046,335 @@
return 0;
}
-int mdp3_put_img(struct mdp3_img_data *data)
+static void mdp3_iommu_heap_unmap_iommu(struct mdp3_iommu_meta *meta)
+{
+ unsigned int domain_num;
+ unsigned int partition_num = 0;
+ struct iommu_domain *domain;
+
+ domain_num = (mdp3_res->domains + MDP3_PPP_IOMMU_DOMAIN)->domain_idx;
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ pr_err("Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ iommu_unmap_range(domain, meta->iova_addr, meta->mapped_size);
+ msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
+ meta->mapped_size);
+
+ return;
+}
+
+static void mdp3_iommu_meta_destroy(struct kref *kref)
+{
+ struct mdp3_iommu_meta *meta =
+ container_of(kref, struct mdp3_iommu_meta, ref);
+
+ rb_erase(&meta->node, &mdp3_res->iommu_root);
+ mdp3_iommu_heap_unmap_iommu(meta);
+ dma_buf_put(meta->dbuf);
+ kfree(meta);
+}
+
+
+static void mdp3_iommu_meta_put(struct mdp3_iommu_meta *meta)
+{
+ /* Need to lock here to prevent race against map/unmap */
+ mutex_lock(&mdp3_res->iommu_lock);
+ kref_put(&meta->ref, mdp3_iommu_meta_destroy);
+ mutex_unlock(&mdp3_res->iommu_lock);
+}
+
+static struct mdp3_iommu_meta *mdp3_iommu_meta_lookup(struct sg_table *table)
+{
+ struct rb_root *root = &mdp3_res->iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct mdp3_iommu_meta *entry = NULL;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct mdp3_iommu_meta, node);
+
+ if (table < entry->table)
+ p = &(*p)->rb_left;
+ else if (table > entry->table)
+ p = &(*p)->rb_right;
+ else
+ return entry;
+ }
+ return NULL;
+}
+
+void mdp3_unmap_iommu(struct ion_client *client, struct ion_handle *handle)
+{
+ struct mdp3_iommu_meta *meta;
+ struct sg_table *table;
+
+ table = ion_sg_table(client, handle);
+
+ mutex_lock(&mdp3_res->iommu_lock);
+ meta = mdp3_iommu_meta_lookup(table);
+ if (!meta) {
+ WARN(1, "%s: buffer was never mapped for %p\n", __func__,
+ handle);
+ mutex_unlock(&mdp3_res->iommu_lock);
+ goto out;
+ }
+ mutex_unlock(&mdp3_res->iommu_lock);
+
+ mdp3_iommu_meta_put(meta);
+out:
+ return;
+}
+
+static void mdp3_iommu_meta_add(struct mdp3_iommu_meta *meta)
+{
+ struct rb_root *root = &mdp3_res->iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct mdp3_iommu_meta *entry;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct mdp3_iommu_meta, node);
+
+ if (meta->table < entry->table) {
+ p = &(*p)->rb_left;
+ } else if (meta->table > entry->table) {
+ p = &(*p)->rb_right;
+ } else {
+ pr_err("%s: handle %p already exists\n", __func__,
+ entry->handle);
+ BUG();
+ }
+ }
+
+ rb_link_node(&meta->node, parent, p);
+ rb_insert_color(&meta->node, root);
+}
+
+static int mdp3_iommu_map_iommu(struct mdp3_iommu_meta *meta,
+ unsigned long align, unsigned long iova_length,
+ unsigned int padding, unsigned long flags)
+{
+ struct iommu_domain *domain;
+ int ret = 0;
+ unsigned long size;
+ unsigned long unmap_size;
+ struct sg_table *table;
+ int prot = IOMMU_WRITE | IOMMU_READ;
+ unsigned int domain_num = (mdp3_res->domains +
+ MDP3_PPP_IOMMU_DOMAIN)->domain_idx;
+ unsigned int partition_num = 0;
+
+ size = meta->size;
+ table = meta->table;
+
+ /* Use the biggest alignment to allow bigger IOMMU mappings.
+ * Use the first entry since the first entry will always be the
+ * biggest entry. To take advantage of bigger mapping sizes both the
+ * VA and PA addresses have to be aligned to the biggest size.
+ */
+ if (sg_dma_len(table->sgl) > align)
+ align = sg_dma_len(table->sgl);
+
+ ret = msm_allocate_iova_address(domain_num, partition_num,
+ meta->mapped_size, align, &meta->iova_addr);
+
+ if (ret)
+ goto out;
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Adding padding to before buffer */
+ if (padding) {
+ unsigned long phys_addr = sg_phys(table->sgl);
+ ret = msm_iommu_map_extra(domain, meta->iova_addr, phys_addr,
+ padding, SZ_4K, prot);
+ if (ret)
+ goto out1;
+ }
+
+ /* Mapping actual buffer */
+ ret = iommu_map_range(domain, meta->iova_addr + padding,
+ table->sgl, size, prot);
+ if (ret) {
+ pr_err("%s: could not map %lx in domain %p\n",
+ __func__, meta->iova_addr, domain);
+ unmap_size = padding;
+ goto out2;
+ }
+
+ /* Adding padding to end of buffer */
+ if (padding) {
+ unsigned long phys_addr = sg_phys(table->sgl);
+ unsigned long extra_iova_addr = meta->iova_addr +
+ padding + size;
+ ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+ padding, SZ_4K, prot);
+ if (ret) {
+ unmap_size = padding + size;
+ goto out2;
+ }
+ }
+ return ret;
+
+out2:
+ iommu_unmap_range(domain, meta->iova_addr, unmap_size);
+out1:
+ msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
+ iova_length);
+
+out:
+ return ret;
+}
+
+static struct mdp3_iommu_meta *mdp3_iommu_meta_create(struct ion_client *client,
+ struct ion_handle *handle, struct sg_table *table, unsigned long size,
+ unsigned long align, unsigned long iova_length, unsigned int padding,
+ unsigned long flags, unsigned long *iova)
+{
+ struct mdp3_iommu_meta *meta;
+ int ret;
+
+ meta = kzalloc(sizeof(*meta), GFP_KERNEL);
+
+ if (!meta)
+ return ERR_PTR(-ENOMEM);
+
+ meta->handle = handle;
+ meta->table = table;
+ meta->size = size;
+ meta->mapped_size = iova_length;
+ meta->dbuf = ion_share_dma_buf(client, handle);
+ kref_init(&meta->ref);
+
+ ret = mdp3_iommu_map_iommu(meta,
+ align, iova_length, padding, flags);
+ if (ret < 0) {
+ pr_err("%s: Unable to map buffer\n", __func__);
+ goto out;
+ }
+
+ *iova = meta->iova_addr;
+ mdp3_iommu_meta_add(meta);
+
+ return meta;
+out:
+ kfree(meta);
+ return ERR_PTR(ret);
+}
+
+/*
+ * PPP hw reads in tiles of 16 which might be outside mapped region
+ * need to map buffers ourseleve to add extra padding
+ */
+int mdp3_self_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ unsigned long align, unsigned long padding, unsigned long *iova,
+ unsigned long *buffer_size, unsigned long flags,
+ unsigned long iommu_flags)
+{
+ struct mdp3_iommu_meta *iommu_meta = NULL;
+ struct sg_table *table;
+ struct scatterlist *sg;
+ unsigned long size = 0, iova_length = 0;
+ int ret = 0;
+ int i;
+
+ table = ion_sg_table(client, handle);
+ if (IS_ERR_OR_NULL(table))
+ return PTR_ERR(table);
+
+ for_each_sg(table->sgl, sg, table->nents, i)
+ size += sg_dma_len(sg);
+
+ padding = PAGE_ALIGN(padding);
+
+ /* Adding 16 lines padding before and after buffer */
+ iova_length = size + 2 * padding;
+
+ if (size & ~PAGE_MASK) {
+ pr_debug("%s: buffer size %lx is not aligned to %lx", __func__,
+ size, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (iova_length & ~PAGE_MASK) {
+ pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
+ iova_length, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mutex_lock(&mdp3_res->iommu_lock);
+ iommu_meta = mdp3_iommu_meta_lookup(table);
+
+ if (!iommu_meta) {
+ iommu_meta = mdp3_iommu_meta_create(client, handle, table, size,
+ align, iova_length, padding, flags, iova);
+ if (!IS_ERR_OR_NULL(iommu_meta)) {
+ iommu_meta->flags = iommu_flags;
+ ret = 0;
+ } else {
+ ret = PTR_ERR(iommu_meta);
+ goto out_unlock;
+ }
+ } else {
+ if (iommu_meta->flags != iommu_flags) {
+ pr_err("%s: handle %p is already mapped with diff flag\n",
+ __func__, handle);
+ ret = -EINVAL;
+ goto out_unlock;
+ } else if (iommu_meta->mapped_size != iova_length) {
+ pr_err("%s: handle %p is already mapped with diff len\n",
+ __func__, handle);
+ ret = -EINVAL;
+ goto out_unlock;
+ } else {
+ kref_get(&iommu_meta->ref);
+ *iova = iommu_meta->iova_addr;
+ }
+ }
+ BUG_ON(iommu_meta->size != size);
+ mutex_unlock(&mdp3_res->iommu_lock);
+
+ *iova = *iova + padding;
+ *buffer_size = size;
+ return ret;
+
+out_unlock:
+ mutex_unlock(&mdp3_res->iommu_lock);
+out:
+ mdp3_iommu_meta_put(iommu_meta);
+ return ret;
+}
+
+int mdp3_put_img(struct mdp3_img_data *data, int client)
{
struct ion_client *iclient = mdp3_res->ion_client;
- int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+ int dom;
if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
pr_info("mdp3_put_img fb mem buf=0x%x\n", data->addr);
fput_light(data->srcp_file, data->p_need);
data->srcp_file = NULL;
} else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
- ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+ if (client == MDP3_CLIENT_DMA_P) {
+ dom = (mdp3_res->domains +
+ MDP3_DMA_IOMMU_DOMAIN)->domain_idx;
+ ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+ } else {
+ mdp3_unmap_iommu(iclient, data->srcp_ihdl);
+ }
ion_free(iclient, data->srcp_ihdl);
data->srcp_ihdl = NULL;
} else {
@@ -1051,14 +1383,15 @@
return 0;
}
-int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data)
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
+ int client)
{
struct file *file;
int ret = -EINVAL;
int fb_num;
unsigned long *start, *len;
struct ion_client *iclient = mdp3_res->ion_client;
- int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+ int dom;
start = (unsigned long *) &data->addr;
len = (unsigned long *) &data->len;
@@ -1100,10 +1433,15 @@
data->srcp_ihdl = NULL;
return ret;
}
-
- ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
- 0, SZ_4K, 0, start, len, 0, 0);
-
+ if (client == MDP3_CLIENT_DMA_P) {
+ dom = (mdp3_res->domains +
+ MDP3_DMA_IOMMU_DOMAIN)->domain_idx;
+ ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
+ 0, SZ_4K, 0, start, len, 0, 0);
+ } else {
+ ret = mdp3_self_map_iommu(iclient, data->srcp_ihdl,
+ SZ_4K, data->padding, start, len, 0, 0);
+ }
if (IS_ERR_VALUE(ret)) {
ion_free(iclient, data->srcp_ihdl);
pr_err("failed to map ion handle (%d)\n", ret);
@@ -1118,7 +1456,7 @@
pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
data->srcp_ihdl, data->addr, data->len);
} else {
- mdp3_put_img(data);
+ mdp3_put_img(data, client);
return -EINVAL;
}
@@ -1288,7 +1626,7 @@
{
if (!mdp3_res)
return -ENODEV;
- return mdp3_res->domains[MDP3_IOMMU_DOMAIN].domain_idx;
+ return mdp3_res->domains[MDP3_DMA_IOMMU_DOMAIN].domain_idx;
}
int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
@@ -1403,7 +1741,8 @@
return 0;
splash_on_err:
- mdp3_clk_enable(0);
+ if (mdp3_clk_enable(0))
+ pr_err("%s: Unable to disable mdp3 clocks\n", __func__);
return rc;
}
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 3f081ba..2f73c42 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -41,8 +41,9 @@
};
enum {
- MDP3_IOMMU_DOMAIN,
- MDP3_IOMMU_DOMAIN_MAX
+ MDP3_DMA_IOMMU_DOMAIN,
+ MDP3_PPP_IOMMU_DOMAIN,
+ MDP3_IOMMU_DOMAIN_MAX,
};
enum {
@@ -58,6 +59,12 @@
MDP3_CLIENT_PPP,
};
+enum {
+ DI_PARTITION_NUM = 0,
+ DI_DOMAIN_NUM = 1,
+ DI_MAX,
+};
+
struct mdp3_bus_handle_map {
struct msm_bus_vectors *bus_vector;
struct msm_bus_paths *usecases;
@@ -83,6 +90,19 @@
int attached;
};
+struct mdp3_iommu_meta {
+ struct rb_node node;
+ struct ion_handle *handle;
+ struct rb_root iommu_maps;
+ struct kref ref;
+ struct sg_table *table;
+ struct dma_buf *dbuf;
+ int mapped_size;
+ unsigned long size;
+ unsigned long iova_addr;
+ unsigned long flags;
+};
+
#define MDP3_MAX_INTR 28
struct mdp3_intr_cb {
@@ -111,6 +131,8 @@
struct mdp3_iommu_domain_map *domains;
struct mdp3_iommu_ctx_map *iommu_contexts;
struct ion_handle *ion_handle;
+ struct mutex iommu_lock;
+ struct rb_root iommu_root;
void *virt;
unsigned long phys;
size_t size;
@@ -132,6 +154,7 @@
struct mdp3_img_data {
u32 addr;
u32 len;
+ u32 padding;
u32 flags;
int p_need;
struct file *srcp_file;
@@ -151,8 +174,9 @@
int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
int mdp3_clk_enable(int enable);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
-int mdp3_put_img(struct mdp3_img_data *data);
-int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
+int mdp3_put_img(struct mdp3_img_data *data, int client);
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data,
+ int client);
int mdp3_iommu_enable(int client);
int mdp3_iommu_disable(int client);
int mdp3_iommu_is_attached(int client);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 341c98f..bf5b643 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -50,7 +50,7 @@
while (count--) {
struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
- mdp3_put_img(data);
+ mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
bufq->count = 0;
bufq->push_idx = 0;
@@ -706,7 +706,7 @@
struct msmfb_data *img = &req->data;
struct mdp3_img_data data;
- rc = mdp3_get_img(img, &data);
+ rc = mdp3_get_img(img, &data, MDP3_CLIENT_DMA_P);
if (rc) {
pr_err("fail to get overlay buffer\n");
return rc;
@@ -715,7 +715,7 @@
rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
if (rc) {
pr_err("fail to queue the overlay buffer, buffer drop\n");
- mdp3_put_img(&data);
+ mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
return rc;
}
return 0;
@@ -779,7 +779,7 @@
if (mdp3_bufq_count(&mdp3_session->bufq_out) > 2) {
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
- mdp3_put_img(data);
+ mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
mutex_unlock(&mdp3_session->lock);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 5ed89e4..5874286 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -292,12 +292,7 @@
MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
MDP3_REG_WRITE(MDP3_REG_DMA_P_OUT_XY, dma_p_out_xy);
- /*
- * NOTE: MDP_DMA_P_FETCH_CFG: max_burst_size need to use value 4, not
- * the default 16 for MDP hang issue workaround
- */
- MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x20);
-
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x40);
dma->source_config = *source_config;
dma->output_config = *output_config;
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 8e1dd66..e1f2d10 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -119,11 +119,22 @@
struct mdp3_img_data *data)
{
struct msmfb_data fb_data;
+ uint32_t stride;
+ int bpp = ppp_bpp(img->format);
+
+ if (bpp <= 0) {
+ pr_err("%s incorrect format %d\n", __func__, img->format);
+ return -EINVAL;
+ }
+
fb_data.flags = img->priv;
fb_data.memory_id = img->memory_id;
fb_data.offset = 0;
- return mdp3_get_img(&fb_data, data);
+ stride = img->width * bpp;
+ data->padding = 16 * stride;
+
+ return mdp3_get_img(&fb_data, data, MDP3_CLIENT_PPP);
}
/* Check format */
@@ -346,6 +357,7 @@
struct mdss_panel_info *panel_info = mfd->panel_info;
uint64_t ab = 0, ib = 0;
int rate = 0;
+ int rc;
if (on_off) {
rate = MDP_BLIT_CLK_RATE;
@@ -357,8 +369,17 @@
ib = (ab * 3) / 2;
}
mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
- mdp3_clk_enable(on_off);
- mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+ rc = mdp3_clk_enable(on_off);
+ if (rc < 0) {
+ pr_err("%s: mdp3_clk_enable failed\n", __func__);
+ return rc;
+ }
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+ if (rc < 0) {
+ mdp3_clk_enable(!on_off);
+ pr_err("%s: scale_set_quota failed\n", __func__);
+ return rc;
+ }
ppp_stat->bw_on = on_off;
return 0;
}
@@ -909,10 +930,14 @@
static void mdp3_free_bw_wq_handler(struct work_struct *work)
{
struct msm_fb_data_type *mfd = ppp_stat->mfd;
+ int rc;
+
mutex_lock(&ppp_stat->config_ppp_mutex);
if (ppp_stat->bw_on) {
mdp3_ppp_turnon(mfd, 0);
- mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ rc = mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ if (rc < 0)
+ WARN(1, "Unable to disable ppp iommu\n");
}
mutex_unlock(&ppp_stat->config_ppp_mutex);
}
@@ -931,8 +956,19 @@
}
if (!ppp_stat->bw_on) {
- mdp3_iommu_enable(MDP3_CLIENT_PPP);
+ rc = mdp3_iommu_enable(MDP3_CLIENT_PPP);
+ if (rc < 0) {
+ mutex_unlock(&ppp_stat->config_ppp_mutex);
+ pr_err("%s: mdp3_iommu_enable failed\n", __func__);
+ return;
+ }
mdp3_ppp_turnon(mfd, 1);
+ if (rc < 0) {
+ mdp3_iommu_disable(MDP3_CLIENT_PPP);
+ mutex_unlock(&ppp_stat->config_ppp_mutex);
+ pr_err("%s: Enable ppp resources failed\n", __func__);
+ return;
+ }
}
while (req) {
mdp3_ppp_wait_for_fence(req);
@@ -945,8 +981,10 @@
&req->src_data[i],
&req->dst_data[i]);
}
- mdp3_put_img(&req->src_data[i]);
- mdp3_put_img(&req->dst_data[i]);
+ mdp3_put_img(&req->src_data[i],
+ MDP3_CLIENT_PPP);
+ mdp3_put_img(&req->dst_data[i],
+ MDP3_CLIENT_PPP);
}
}
/* Signal to release fence */
@@ -1017,7 +1055,7 @@
rc = mdp3_ppp_get_img(&req->req_list[i].dst,
&req->req_list[i], &req->dst_data[i]);
if (rc < 0 || req->dst_data[i].len == 0) {
- mdp3_put_img(&req->src_data[i]);
+ mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
goto parse_err_1;
}
@@ -1060,8 +1098,8 @@
put_unused_fd(req->cur_rel_fen_fd);
parse_err_1:
for (i--; i >= 0; i--) {
- mdp3_put_img(&req->src_data[i]);
- mdp3_put_img(&req->dst_data[i]);
+ mdp3_put_img(&req->src_data[i], MDP3_CLIENT_PPP);
+ mdp3_put_img(&req->dst_data[i], MDP3_CLIENT_PPP);
}
mdp3_ppp_deinit_buf_sync(req);
mutex_unlock(&ppp_stat->req_mutex);
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index 199387f..a051037 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -361,38 +361,6 @@
return rgb;
}
-uint8_t *mdp_bg_adjust_rot_addr(struct ppp_blit_op *iBuf,
- uint8_t *addr, uint32_t bpp, uint32_t uv)
-{
- uint32_t dest_ystride = iBuf->bg.prop.width * bpp;
- uint32_t h_slice = 1, min_val;
-
- if (uv && ((iBuf->bg.color_fmt == MDP_Y_CBCR_H2V2) ||
- (iBuf->bg.color_fmt == MDP_Y_CRCB_H2V2)))
- h_slice = 2;
-
- if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
- ((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
- min_val = (iBuf->bg.roi.width + iBuf->bg.roi.x) % 16;
- if (!min_val)
- min_val = 16;
- addr +=
- (iBuf->bg.roi.width -
- MIN(min_val, iBuf->bg.roi.width)) * bpp;
- }
- if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
- min_val = (iBuf->bg.roi.height + iBuf->bg.roi.y) % 16;
- if (!min_val)
- min_val = 16;
- addr +=
- ((iBuf->bg.roi.height -
- MIN(min_val, iBuf->bg.roi.height))/h_slice) *
- dest_ystride;
- }
-
- return addr;
-}
-
uint8_t *mdp_dst_adjust_rot_addr(struct ppp_blit_op *iBuf,
uint8_t *addr, uint32_t bpp, uint32_t uv)
{
@@ -434,9 +402,7 @@
img->p0 += (x + y * ALIGN(width, 128)) * bpp;
else
img->p0 += (x + y * width) * bpp;
- if (layer == 1)
- img->p0 = mdp_bg_adjust_rot_addr(blit_op, img->p0, bpp, 0);
- else if (layer == 2)
+ if (layer != 0)
img->p0 = mdp_dst_adjust_rot_addr(blit_op, img->p0, bpp, 0);
if (img->p1) {
@@ -454,13 +420,9 @@
img->p1 += ((x / h_slice) * h_slice +
((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
- if (layer == 1) {
- img->p0 = mdp_bg_adjust_rot_addr(blit_op,
- img->p0, bpp, 0);
- } else if (layer == 2) {
+ if (layer != 0)
img->p0 = mdp_dst_adjust_rot_addr(blit_op,
img->p0, bpp, 0);
- }
}
}
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index ec21db2..2d63532 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -323,6 +323,7 @@
struct clk *esc_clk;
struct clk *pixel_clk;
u8 ctrl_state;
+ int panel_mode;
int irq_cnt;
int mdss_dsi_clk_on;
int rst_gpio;
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index e48d0d2..62bc7e6 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -25,6 +25,8 @@
#include "mdss.h"
#include "mdss_dsi.h"
+#define VSYNC_PERIOD 17
+
static struct mdss_dsi_ctrl_pdata *left_ctrl_pdata;
static struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
@@ -766,6 +768,8 @@
pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+ ctrl_pdata->panel_mode = pinfo->mode;
+
if (pinfo->mode == DSI_VIDEO_MODE) {
data = 0;
if (pinfo->pulse_mode_hsa_he)
@@ -1135,6 +1139,8 @@
return 4;
}
+static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl);
+
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_buf *tp);
@@ -1147,7 +1153,7 @@
struct dsi_buf *tp;
struct dsi_cmd_desc *cm;
struct dsi_ctrl_hdr *dchdr;
- int len, tot = 0;
+ int len, wait, tot = 0;
tp = &ctrl->tx_buf;
mdss_dsi_buf_init(tp);
@@ -1164,6 +1170,9 @@
tot += len;
if (dchdr->last) {
tp->data = tp->start; /* begin of buf */
+
+ wait = mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
len = mdss_dsi_cmd_dma_tx(ctrl, tp);
if (IS_ERR_VALUE(len)) {
@@ -1172,7 +1181,8 @@
__func__, cmds->payload[0]);
return -EINVAL;
}
- if (dchdr->wait)
+
+ if (!wait || dchdr->wait > VSYNC_PERIOD)
usleep(dchdr->wait * 1000);
mdss_dsi_buf_init(tp);
@@ -1357,6 +1367,9 @@
rp->len = 0;
goto end;
}
+
+ mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
if (IS_ERR_VALUE(ret)) {
@@ -1377,6 +1390,8 @@
goto end;
}
+ mdss_dsi_wait4video_eng_busy(ctrl);
+
mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
/* transmit read comamnd to client */
ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
@@ -1541,7 +1556,6 @@
return rlen;
}
-#define VSYNC_PERIOD 17
void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
{
@@ -1567,11 +1581,21 @@
MIPI_OUTP((ctrl->ctrl_base) + 0x0110, data);
}
-static void mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+static int mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
{
- mdss_dsi_wait4video_done(ctrl);
- /* delay 4 ms to skip BLLP */
- usleep(4000);
+ int ret = 0;
+
+ if (ctrl->panel_mode == DSI_CMD_MODE)
+ return ret;
+
+ if (ctrl->ctrl_state & CTRL_STATE_MDP_ACTIVE) {
+ mdss_dsi_wait4video_done(ctrl);
+ /* delay 4 ms to skip BLLP */
+ usleep(4000);
+ ret = 1;
+ }
+
+ return ret;
}
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl)
@@ -1638,7 +1662,6 @@
void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
{
struct dcs_cmd_req *req;
- u32 data;
mutex_lock(&ctrl->cmd_mutex);
req = mdss_dsi_cmdlist_get(ctrl);
@@ -1646,26 +1669,14 @@
/* make sure dsi_cmd_mdp is idle */
mdss_dsi_cmd_mdp_busy(ctrl);
+ pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
+
if (req == NULL)
goto need_lock;
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
mdss_dsi_clk_ctrl(ctrl, 1);
- data = MIPI_INP((ctrl->ctrl_base) + 0x0004);
- if (data & 0x02) {
- /* video mode, make sure video engine is busy
- * so dcs command will be sent at start of BLLP
- */
- mdss_dsi_wait4video_eng_busy(ctrl);
- } else {
- /* command mode */
- if (!from_mdp) { /* cmdlist_put */
- /* make sure dsi_cmd_mdp is idle */
- mdss_dsi_cmd_mdp_busy(ctrl);
- }
- }
-
if (req->flags & CMD_REQ_RX)
mdss_dsi_cmdlist_rx(ctrl, req);
else
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 9c0daa9..17280ed 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -242,12 +242,28 @@
return ret;
}
+static ssize_t mdss_mdp_show_blank_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ int ret;
+
+ pr_debug("fb%d panel_power_on = %d\n", mfd->index, mfd->panel_power_on);
+ ret = scnprintf(buf, PAGE_SIZE, "panel_power_on = %d\n",
+ mfd->panel_power_on);
+
+ return ret;
+}
+
static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, S_IRUGO, mdss_fb_get_split, NULL);
+static DEVICE_ATTR(show_blank_event, S_IRUGO, mdss_mdp_show_blank_event, NULL);
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
&dev_attr_msm_fb_split.attr,
+ &dev_attr_show_blank_event.attr,
NULL,
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c79b672..8e805da 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -2153,10 +2153,11 @@
mdp5_data->ctl = ctl;
}
- if (!mfd->panel_info->cont_splash_enabled) {
+ if (!mfd->panel_info->cont_splash_enabled &&
+ (mfd->panel_info->type != DTV_PANEL) &&
+ (mfd->panel_info->type != WRITEBACK_PANEL)) {
rc = mdss_mdp_overlay_start(mfd);
- if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL) &&
- (mfd->panel_info->type != WRITEBACK_PANEL))
+ if (!IS_ERR_VALUE(rc))
rc = mdss_mdp_overlay_kickoff(mfd);
} else {
rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 5df022e..6716ce3 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -43,6 +43,15 @@
* @reset_gpio: reset gpio
* @panel_x: panel maximum values on the x
* @panel_y: panel maximum values on the y
+ * @disp_maxx: display panel maximum values on the x
+ * @disp_maxy: display panel maximum values on the y
+ * @disp_minx: display panel minimum values on the x
+ * @disp_miny: display panel minimum values on the y
+ * @panel_maxx: touch panel maximum values on the x
+ * @panel_maxy: touch panel maximum values on the y
+ * @panel_minx: touch panel minimum values on the x
+ * @panel_miny: touch panel minimum values on the y
+ * @reset_delay: reset delay
* @gpio_config: pointer to gpio configuration function
* @capacitance_button_map: pointer to 0d button map
*/
@@ -52,12 +61,20 @@
bool i2c_pull_up;
bool power_down_enable;
bool disable_gpios;
+ bool do_lockdown;
unsigned irq_gpio;
u32 irq_flags;
u32 reset_flags;
unsigned reset_gpio;
- unsigned panel_x;
- unsigned panel_y;
+ unsigned panel_minx;
+ unsigned panel_miny;
+ unsigned panel_maxx;
+ unsigned panel_maxy;
+ unsigned disp_minx;
+ unsigned disp_miny;
+ unsigned disp_maxx;
+ unsigned disp_maxy;
+ unsigned reset_delay;
const char *fw_image_name;
int (*gpio_config)(unsigned gpio, bool configure);
struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index e8ca1cd..853899e 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -63,6 +63,10 @@
(AUDIO_MAX_COMMON_IOCTL_NUM+28), unsigned)
#define AUDIO_DEREGISTER_VOCPROC_VOL_TABLE _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+29), unsigned)
+#define AUDIO_SET_HW_DELAY_RX _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+30), struct hw_delay)
+#define AUDIO_SET_HW_DELAY_TX _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+31), struct hw_delay)
#define AUDIO_MAX_ACDB_IOCTL (AUDIO_MAX_COMMON_IOCTL_NUM+40)
/* ACDB structures */
@@ -96,6 +100,11 @@
int status;
};
+struct hw_delay {
+ uint32_t num_entries;
+ void *delay_info;
+};
+
/* For Real-Time Audio Calibration */
#define AUDIO_GET_RTAC_ADM_INFO _IOR(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_ACDB_IOCTL+1), unsigned)
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 38877cc..e1c096b 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -403,6 +403,7 @@
#define V4L2_PIX_FMT_DIVX v4l2_fourcc('D', 'I', 'V', 'X') /* DIVX */
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* ON2 VP8 stream */
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* for HEVC stream */
+#define V4L2_PIX_FMT_HEVC_HYBRID v4l2_fourcc('H', 'V', 'C', 'H')
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -705,6 +706,7 @@
#define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
#define V4L2_QCOM_BUF_DROP_FRAME 0x100000
#define V4L2_QCOM_BUF_INPUT_UNSUPPORTED 0x200000
+#define V4L2_QCOM_BUF_FLAG_EOS 0x2000
/*
* O V E R L A Y P R E V I E W
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index fb58d12..cadbe97 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1968,6 +1968,14 @@
*/
} __packed;
+#define AFE_PARAM_ID_DEVICE_HW_DELAY 0x00010243
+#define AFE_API_VERSION_DEVICE_HW_DELAY 0x1
+
+struct afe_param_id_device_hw_delay_cfg {
+ uint32_t device_hw_delay_minor_version;
+ uint32_t delay_in_us;
+} __packed;
+
union afe_port_config {
struct afe_param_id_pcm_cfg pcm;
struct afe_param_id_i2s_cfg i2s;
@@ -1976,6 +1984,7 @@
struct afe_param_id_rt_proxy_port_cfg rtproxy;
struct afe_param_id_internal_bt_fm_cfg int_bt_fm;
struct afe_param_id_pseudo_port_cfg pseudo_port;
+ struct afe_param_id_device_hw_delay_cfg hw_delay;
} __packed;
struct afe_audioif_config_command_no_payload {
@@ -2481,6 +2490,8 @@
#define ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT 0x00010BE4
+#define ASM_STREAM_POSTPROC_TOPO_ID_NONE 0x00010C68
+
#define ASM_MEDIA_FMT_EVRCB_FS 0x00010BEF
#define ASM_MEDIA_FMT_EVRCWB_FS 0x00010BF0
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 0131170..3db5820 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -154,7 +154,7 @@
* down, but we are still initializing the system. Pages are given directly
* to the page allocator, no bootmem metadata is updated because it is gone.
*/
-void __init free_bootmem_late(unsigned long addr, unsigned long size)
+void free_bootmem_late(unsigned long addr, unsigned long size)
{
unsigned long cursor, end;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 9cc2f45..46ccd2f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -745,7 +745,7 @@
local_irq_restore(flags);
}
-void __meminit __free_pages_bootmem(struct page *page, unsigned int order)
+void __free_pages_bootmem(struct page *page, unsigned int order)
{
unsigned int nr_pages = 1 << order;
unsigned int loop;
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index bd4f926..fb115e7 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1910,6 +1910,13 @@
{"EAR PA", NULL, "DAC1"},
{"DAC1", NULL, "CP"},
+ /* Clocks for playback path */
+ {"DAC1", NULL, "EAR CLK"},
+ {"HPHL DAC", NULL, "HPHL CLK"},
+ {"HPHR DAC", NULL, "HPHR CLK"},
+ {"SPK DAC", NULL, "SPK CLK"},
+ {"LINEOUT DAC", NULL, "LINEOUT CLK"},
+
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
{"HEADPHONE", NULL, "HPHR"},
@@ -2336,6 +2343,17 @@
SND_SOC_DAPM_MIXER("RX3 CHAIN", MSM8X10_WCD_A_CDC_RX3_B6_CTL,
5, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPHR CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("HPHL CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("EAR CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("LINEOUT CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SPK CLK", MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 4, 0, NULL, 0),
+
SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
&rx_mix1_inp1_mux),
SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index a6ef992..4e07d7f 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -48,6 +48,12 @@
/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
#define TAPAN_WG_TIME_FACTOR_US 240
+#define TAPAN_SB_PGD_PORT_RX_BASE 0x40
+#define TAPAN_SB_PGD_PORT_TX_BASE 0x50
+#define TAPAN_REGISTER_START_OFFSET 0x800
+
+#define CODEC_REG_CFG_MINOR_VER 1
+
static struct regulator *tapan_codec_find_regulator(
struct snd_soc_codec *codec,
const char *name);
@@ -106,6 +112,54 @@
*/
#define TAPAN_ZDET_MUL_FACTOR 1852
+static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_TX_BASE),
+ SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_TX_BASE),
+ SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_RX_BASE),
+ SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_SB_PGD_PORT_RX_BASE),
+ SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_IIR_B1_CTL),
+ AANC_FF_GAIN_ADAPTIVE, 0x4, 8, 0
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_IIR_B1_CTL),
+ AANC_FFGAIN_ADAPTIVE_EN, 0x8, 8, 0
+ },
+ {
+ CODEC_REG_CFG_MINOR_VER,
+ (TAPAN_REGISTER_START_OFFSET + TAPAN_A_CDC_ANC1_GAIN_CTL),
+ AANC_GAIN_CONTROL, 0xFF, 8, 0
+ },
+};
+
+static struct afe_param_cdc_reg_cfg_data tapan_audio_reg_cfg = {
+ .num_registers = ARRAY_SIZE(audio_reg_cfg),
+ .reg_data = audio_reg_cfg,
+};
+
+static struct afe_param_id_cdc_aanc_version tapan_cdc_aanc_version = {
+ .cdc_aanc_minor_version = AFE_API_VERSION_CDC_AANC_VERSION,
+ .aanc_hw_version = AANC_HW_BLOCK_VERSION_2,
+};
+
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -250,6 +304,8 @@
bool spkr_pa_widget_on;
+ struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
+
/* resmgr module */
struct wcd9xxx_resmgr resmgr;
/* mbhc module */
@@ -266,6 +322,9 @@
* end of impedance measurement
*/
struct list_head reg_save_restore;
+
+ int (*machine_codec_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event);
};
static const u32 comp_shift[] = {
@@ -2964,6 +3023,9 @@
static int tapan_volatile(struct snd_soc_codec *ssc, unsigned int reg)
{
+
+ int i = 0;
+
/* Registers lower than 0x100 are top level registers which can be
* written by the Tapan core driver.
*/
@@ -2997,6 +3059,11 @@
if (reg == TAPAN_A_MBHC_INSERT_DET_STATUS)
return 1;
+ for (i = 0; i < ARRAY_SIZE(audio_reg_cfg); i++)
+ if (audio_reg_cfg[i].reg_logical_addr -
+ TAPAN_REGISTER_START_OFFSET == reg)
+ return 1;
+
return 0;
}
@@ -4822,6 +4889,46 @@
{TAPAN_A_RX_HPH_CHOP_CTL, 0xFF, 0x24},
};
+void *tapan_get_afe_config(struct snd_soc_codec *codec,
+ enum afe_config_type config_type)
+{
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (config_type) {
+ case AFE_SLIMBUS_SLAVE_CONFIG:
+ return &priv->slimbus_slave_cfg;
+ case AFE_CDC_REGISTERS_CONFIG:
+ return &tapan_audio_reg_cfg;
+ case AFE_AANC_VERSION:
+ return &tapan_cdc_aanc_version;
+ default:
+ pr_err("%s: Unknown config_type 0x%x\n", __func__, config_type);
+ return NULL;
+ }
+}
+
+static void tapan_init_slim_slave_cfg(struct snd_soc_codec *codec)
+{
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+ struct afe_param_cdc_slimbus_slave_cfg *cfg;
+ struct wcd9xxx *wcd9xxx = codec->control_data;
+ uint64_t eaddr = 0;
+
+ pr_debug("%s\n", __func__);
+ cfg = &priv->slimbus_slave_cfg;
+ cfg->minor_version = 1;
+ cfg->tx_slave_port_offset = 0;
+ cfg->rx_slave_port_offset = 16;
+
+ memcpy(&eaddr, &wcd9xxx->slim->e_addr, sizeof(wcd9xxx->slim->e_addr));
+ /* e-addr is 6-byte elemental address of the device */
+ WARN_ON(sizeof(wcd9xxx->slim->e_addr) != 6);
+ cfg->device_enum_addr_lsw = eaddr & 0xFFFFFFFF;
+ cfg->device_enum_addr_msw = eaddr >> 32;
+
+ pr_debug("%s: slimbus logical address 0x%llx\n", __func__, eaddr);
+}
+
static void tapan_codec_init_reg(struct snd_soc_codec *codec)
{
u32 i;
@@ -5209,6 +5316,16 @@
}
EXPORT_SYMBOL(tapan_hs_detect_exit);
+void tapan_event_register(
+ int (*machine_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event),
+ struct snd_soc_codec *codec)
+{
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ tapan->machine_codec_event_cb = machine_event_cb;
+}
+EXPORT_SYMBOL(tapan_event_register);
+
static int tapan_device_down(struct wcd9xxx *wcd9xxx)
{
struct snd_soc_codec *codec;
@@ -5278,6 +5395,8 @@
if (ret)
pr_err("%s: Failed to setup irq: %d\n", __func__, ret);
+ tapan->machine_codec_event_cb(codec, WCD9XXX_CODEC_EVENT_CODEC_UP);
+
mutex_unlock(&codec->mutex);
return ret;
}
@@ -5523,6 +5642,7 @@
INIT_LIST_HEAD(&tapan->dai[i].wcd9xxx_ch_list);
init_waitqueue_head(&tapan->dai[i].dai_wait);
}
+ tapan_init_slim_slave_cfg(codec);
}
if (codec_ver == WCD9306) {
diff --git a/sound/soc/codecs/wcd9306.h b/sound/soc/codecs/wcd9306.h
index c4788cc..07b2175 100644
--- a/sound/soc/codecs/wcd9306.h
+++ b/sound/soc/codecs/wcd9306.h
@@ -14,9 +14,11 @@
#include <sound/soc.h>
#include <sound/jack.h>
+#include <sound/apr_audio-v2.h>
#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
#include "wcd9xxx-mbhc.h"
#include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
#define TAPAN_NUM_REGISTERS 0x400
#define TAPAN_MAX_REGISTER (TAPAN_NUM_REGISTERS-1)
@@ -77,5 +79,10 @@
bool dapm);
extern int tapan_hs_detect(struct snd_soc_codec *codec,
struct wcd9xxx_mbhc_config *mbhc_cfg);
-
+extern void *tapan_get_afe_config(struct snd_soc_codec *codec,
+ enum afe_config_type config_type);
+extern void tapan_event_register(
+ int (*machine_event_cb)(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event),
+ struct snd_soc_codec *codec);
#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index e52eb9d..4ce9b4a 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -72,63 +72,6 @@
.num_channels = 1
};
-enum {
- RESERVED = 0,
- AANC_LPF_FF_FB = 1,
- AANC_LPF_COEFF_MSB,
- AANC_LPF_COEFF_LSB,
- HW_MAD_AUDIO_ENABLE,
- HW_MAD_ULTR_ENABLE,
- HW_MAD_BEACON_ENABLE,
- HW_MAD_AUDIO_SLEEP_TIME,
- HW_MAD_ULTR_SLEEP_TIME,
- HW_MAD_BEACON_SLEEP_TIME,
- HW_MAD_TX_AUDIO_SWITCH_OFF,
- HW_MAD_TX_ULTR_SWITCH_OFF,
- HW_MAD_TX_BEACON_SWITCH_OFF,
- MAD_AUDIO_INT_DEST_SELECT_REG,
- MAD_ULT_INT_DEST_SELECT_REG,
- MAD_BEACON_INT_DEST_SELECT_REG,
- MAD_CLIP_INT_DEST_SELECT_REG,
- MAD_VBAT_INT_DEST_SELECT_REG,
- MAD_AUDIO_INT_MASK_REG,
- MAD_ULT_INT_MASK_REG,
- MAD_BEACON_INT_MASK_REG,
- MAD_CLIP_INT_MASK_REG,
- MAD_VBAT_INT_MASK_REG,
- MAD_AUDIO_INT_STATUS_REG,
- MAD_ULT_INT_STATUS_REG,
- MAD_BEACON_INT_STATUS_REG,
- MAD_CLIP_INT_STATUS_REG,
- MAD_VBAT_INT_STATUS_REG,
- MAD_AUDIO_INT_CLEAR_REG,
- MAD_ULT_INT_CLEAR_REG,
- MAD_BEACON_INT_CLEAR_REG,
- MAD_CLIP_INT_CLEAR_REG,
- MAD_VBAT_INT_CLEAR_REG,
- SB_PGD_PORT_TX_WATERMARK_n,
- SB_PGD_PORT_TX_ENABLE_n,
- SB_PGD_PORT_RX_WATERMARK_n,
- SB_PGD_PORT_RX_ENABLE_n,
- SB_PGD_TX_PORTn_MULTI_CHNL_0,
- SB_PGD_TX_PORTn_MULTI_CHNL_1,
- SB_PGD_RX_PORTn_MULTI_CHNL_0,
- SB_PGD_RX_PORTn_MULTI_CHNL_1,
- AANC_FF_GAIN_ADAPTIVE,
- AANC_FFGAIN_ADAPTIVE_EN,
- AANC_GAIN_CONTROL,
- SPKR_CLIP_PIPE_BANK_SEL,
- SPKR_CLIPDET_VAL0,
- SPKR_CLIPDET_VAL1,
- SPKR_CLIPDET_VAL2,
- SPKR_CLIPDET_VAL3,
- SPKR_CLIPDET_VAL4,
- SPKR_CLIPDET_VAL5,
- SPKR_CLIPDET_VAL6,
- SPKR_CLIPDET_VAL7,
- MAX_CFG_REGISTERS,
-};
-
static struct afe_param_cdc_reg_cfg audio_reg_cfg[] = {
{
1,
@@ -168,22 +111,22 @@
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
- SB_PGD_PORT_TX_WATERMARK_n, 0x1E, 8, 0x1
+ SB_PGD_PORT_TX_WATERMARK_N, 0x1E, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_TX_BASE),
- SB_PGD_PORT_TX_ENABLE_n, 0x1, 8, 0x1
+ SB_PGD_PORT_TX_ENABLE_N, 0x1, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
- SB_PGD_PORT_RX_WATERMARK_n, 0x1E, 8, 0x1
+ SB_PGD_PORT_RX_WATERMARK_N, 0x1E, 8, 0x1
},
{
1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_SB_PGD_PORT_RX_BASE),
- SB_PGD_PORT_RX_ENABLE_n, 0x1, 8, 0x1
+ SB_PGD_PORT_RX_ENABLE_N, 0x1, 8, 0x1
},
{ 1,
(TAIKO_REGISTER_START_OFFSET + TAIKO_A_CDC_ANC1_IIR_B1_CTL),
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index 9fba8e3..e63d36a 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -93,4 +93,61 @@
uint8_t value, int delay);
extern void wcd9xxx_restore_registers(struct snd_soc_codec *codec,
struct list_head *lh);
+enum {
+ RESERVED = 0,
+ AANC_LPF_FF_FB = 1,
+ AANC_LPF_COEFF_MSB,
+ AANC_LPF_COEFF_LSB,
+ HW_MAD_AUDIO_ENABLE,
+ HW_MAD_ULTR_ENABLE,
+ HW_MAD_BEACON_ENABLE,
+ HW_MAD_AUDIO_SLEEP_TIME,
+ HW_MAD_ULTR_SLEEP_TIME,
+ HW_MAD_BEACON_SLEEP_TIME,
+ HW_MAD_TX_AUDIO_SWITCH_OFF,
+ HW_MAD_TX_ULTR_SWITCH_OFF,
+ HW_MAD_TX_BEACON_SWITCH_OFF,
+ MAD_AUDIO_INT_DEST_SELECT_REG,
+ MAD_ULT_INT_DEST_SELECT_REG,
+ MAD_BEACON_INT_DEST_SELECT_REG,
+ MAD_CLIP_INT_DEST_SELECT_REG,
+ MAD_VBAT_INT_DEST_SELECT_REG,
+ MAD_AUDIO_INT_MASK_REG,
+ MAD_ULT_INT_MASK_REG,
+ MAD_BEACON_INT_MASK_REG,
+ MAD_CLIP_INT_MASK_REG,
+ MAD_VBAT_INT_MASK_REG,
+ MAD_AUDIO_INT_STATUS_REG,
+ MAD_ULT_INT_STATUS_REG,
+ MAD_BEACON_INT_STATUS_REG,
+ MAD_CLIP_INT_STATUS_REG,
+ MAD_VBAT_INT_STATUS_REG,
+ MAD_AUDIO_INT_CLEAR_REG,
+ MAD_ULT_INT_CLEAR_REG,
+ MAD_BEACON_INT_CLEAR_REG,
+ MAD_CLIP_INT_CLEAR_REG,
+ MAD_VBAT_INT_CLEAR_REG,
+ SB_PGD_PORT_TX_WATERMARK_N,
+ SB_PGD_PORT_TX_ENABLE_N,
+ SB_PGD_PORT_RX_WATERMARK_N,
+ SB_PGD_PORT_RX_ENABLE_N,
+ SB_PGD_TX_PORTn_MULTI_CHNL_0,
+ SB_PGD_TX_PORTn_MULTI_CHNL_1,
+ SB_PGD_RX_PORTn_MULTI_CHNL_0,
+ SB_PGD_RX_PORTn_MULTI_CHNL_1,
+ AANC_FF_GAIN_ADAPTIVE,
+ AANC_FFGAIN_ADAPTIVE_EN,
+ AANC_GAIN_CONTROL,
+ SPKR_CLIP_PIPE_BANK_SEL,
+ SPKR_CLIPDET_VAL0,
+ SPKR_CLIPDET_VAL1,
+ SPKR_CLIPDET_VAL2,
+ SPKR_CLIPDET_VAL3,
+ SPKR_CLIPDET_VAL4,
+ SPKR_CLIPDET_VAL5,
+ SPKR_CLIPDET_VAL6,
+ SPKR_CLIPDET_VAL7,
+ MAX_CFG_REGISTERS,
+};
+
#endif
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 40661ff..86dd840 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -215,6 +215,7 @@
select SND_SOC_MSM_HOSTLESS_PCM
select SND_SOC_WCD9306
select SND_DYNAMIC_MINORS
+ select DOLBY_DAP
help
To add support for SoC audio on MSM8226.
This will enable sound soc drivers which
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 57cd525..9460ec0 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -17,16 +17,20 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/io.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/jack.h>
+#include <sound/q6afe-v2.h>
#include <asm/mach-types.h>
#include <mach/socinfo.h>
+#include <mach/subsystem_notif.h>
#include <qdsp6v2/msm-pcm-routing-v2.h>
+#include "qdsp6v2/q6core.h"
+#include "../codecs/wcd9xxx-common.h"
#include "../codecs/wcd9306.h"
-#include <linux/io.h>
#define DRV_NAME "msm8226-asoc-tapan"
@@ -50,6 +54,10 @@
#define LO_1_SPK_AMP 0x1
#define LO_2_SPK_AMP 0x2
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
+static void *adsp_state_notifier;
+
static int msm8226_auxpcm_rate = 8000;
static atomic_t auxpcm_rsc_ref;
static const char *const auxpcm_rate_text[] = {"rate_8000", "rate_16000"};
@@ -336,6 +344,9 @@
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic3", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+
SND_SOC_DAPM_SPK("Lineout_1 amp", msm8226_ext_spkramp_event),
SND_SOC_DAPM_SPK("Lineout_2 amp", msm8226_ext_spkramp_event),
@@ -696,6 +707,107 @@
msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
};
+static int msm_afe_set_config(struct snd_soc_codec *codec)
+{
+ int rc;
+ void *config_data;
+
+ pr_debug("%s: enter\n", __func__);
+ config_data = tapan_get_afe_config(codec, AFE_CDC_REGISTERS_CONFIG);
+ rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set codec registers config %d\n",
+ __func__, rc);
+ return rc;
+ }
+ config_data = tapan_get_afe_config(codec, AFE_SLIMBUS_SLAVE_CONFIG);
+ rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set slimbus slave config %d\n", __func__,
+ rc);
+ return rc;
+ }
+ config_data = tapan_get_afe_config(codec, AFE_AANC_VERSION);
+ rc = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set AANC version %d\n", __func__,
+ rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void msm_afe_clear_config(void)
+{
+ afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
+ afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
+ afe_clear_config(AFE_AANC_VERSION);
+}
+
+static int msm8226_adsp_state_callback(struct notifier_block *nb,
+ unsigned long value, void *priv)
+{
+ if (value == SUBSYS_BEFORE_SHUTDOWN) {
+ pr_debug("%s: ADSP is about to shutdown. Clearing AFE config\n",
+ __func__);
+ msm_afe_clear_config();
+ } else if (value == SUBSYS_AFTER_POWERUP) {
+ pr_debug("%s: ADSP is up\n", __func__);
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block adsp_state_notifier_block = {
+ .notifier_call = msm8226_adsp_state_callback,
+ .priority = -INT_MAX,
+};
+
+static int msm8226_tapan_codec_up(struct snd_soc_codec *codec)
+{
+ int err;
+ unsigned long timeout;
+ int adsp_ready = 0;
+
+ pr_debug("%s\n", __func__);
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+
+ do {
+ if (!q6core_is_adsp_ready()) {
+ pr_err("%s: ADSP Audio isn't ready\n", __func__);
+ } else {
+ pr_debug("%s: ADSP Audio is ready\n", __func__);
+ adsp_ready = 1;
+ break;
+ }
+ } while (time_after(timeout, jiffies));
+
+ if (!adsp_ready) {
+ pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ err = msm_afe_set_config(codec);
+ if (err)
+ pr_err("%s: Failed to set AFE config. err %d\n",
+ __func__, err);
+ return err;
+}
+
+static int msm8226_tapan_event_cb(struct snd_soc_codec *codec,
+ enum wcd9xxx_codec_event codec_event)
+{
+ switch (codec_event) {
+ case WCD9XXX_CODEC_EVENT_CODEC_UP:
+ return msm8226_tapan_codec_up(codec);
+ default:
+ pr_err("%s: UnSupported codec event %d\n",
+ __func__, codec_event);
+ return -EINVAL;
+ }
+}
+
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -736,13 +848,37 @@
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+ err = msm_afe_set_config(codec);
+ if (err) {
+ pr_err("%s: Failed to set AFE config %d\n",
+ __func__, err);
+ return err;
+ }
+
/* start mbhc */
mbhc_cfg.calibration = def_tapan_mbhc_cal();
- if (mbhc_cfg.calibration)
+ if (mbhc_cfg.calibration) {
err = tapan_hs_detect(codec, &mbhc_cfg);
- else
+ } else {
err = -ENOMEM;
+ goto out;
+ }
+ adsp_state_notifier =
+ subsys_notif_register_notifier("adsp",
+ &adsp_state_notifier_block);
+
+ if (!adsp_state_notifier) {
+ pr_err("%s: Failed to register adsp state notifier\n",
+ __func__);
+ err = -EFAULT;
+ goto out;
+ }
+
+ tapan_event_register(msm8226_tapan_event_cb, rtd->codec);
+ return 0;
+
+out:
return err;
}
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index c9e38e0..9a2d4d3 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -36,6 +36,7 @@
#define NUM_VOCPROC_BLOCKS (6 * MAX_NETWORKS)
#define ACDB_TOTAL_VOICE_ALLOCATION (ACDB_BLOCK_SIZE * NUM_VOCPROC_BLOCKS)
+#define MAX_HW_DELAY_ENTRIES 25
struct sidetone_atomic_cal {
atomic_t enable;
@@ -98,6 +99,10 @@
/* Speaker protection */
struct msm_spk_prot_cfg spk_prot_cfg;
+
+ /* Av sync delay info */
+ struct hw_delay hw_delay_rx;
+ struct hw_delay hw_delay_tx;
};
static struct acdb_data acdb_data;
@@ -371,6 +376,122 @@
return result;
}
+int get_hw_delay(int32_t path, struct hw_delay_entry *entry)
+{
+ int i, result = 0;
+ struct hw_delay *delay = NULL;
+ struct hw_delay_entry *info = NULL;
+ pr_debug("%s,\n", __func__);
+
+ if (entry == NULL) {
+ pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+ result = -EINVAL;
+ goto ret;
+ }
+ if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+ pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+ __func__, path);
+ result = -EINVAL;
+ goto ret;
+ }
+ mutex_lock(&acdb_data.acdb_mutex);
+ if (path == RX_CAL)
+ delay = &acdb_data.hw_delay_rx;
+ else if (path == TX_CAL)
+ delay = &acdb_data.hw_delay_tx;
+
+ if ((delay == NULL) || ((delay != NULL) && delay->num_entries == 0)) {
+ pr_err("ACDB=> %s Invalid delay/ delay entries\n", __func__);
+ result = -EINVAL;
+ goto done;
+ }
+
+ info = (struct hw_delay_entry *)(delay->delay_info);
+ if (info == NULL) {
+ pr_err("ACDB=> %s Delay entries info is NULL\n", __func__);
+ result = -EFAULT;
+ goto done;
+ }
+ for (i = 0; i < delay->num_entries; i++) {
+ if (info[i].sample_rate == entry->sample_rate) {
+ entry->delay_usec = info[i].delay_usec;
+ break;
+ }
+ }
+ if (i == delay->num_entries) {
+ pr_err("ACDB=> %s: Unable to find delay for sample rate %d\n",
+ __func__, entry->sample_rate);
+ result = -EFAULT;
+ }
+
+done:
+ mutex_unlock(&acdb_data.acdb_mutex);
+ret:
+ pr_debug("ACDB=> %s: Path = %d samplerate = %u usec = %u status %d\n",
+ __func__, path, entry->sample_rate, entry->delay_usec, result);
+ return result;
+}
+
+int store_hw_delay(int32_t path, void *arg)
+{
+ int result = 0;
+ struct hw_delay delay;
+ struct hw_delay *delay_dest = NULL;
+ pr_debug("%s,\n", __func__);
+
+ if ((path >= MAX_AUDPROC_TYPES) || (path < 0) || (arg == NULL)) {
+ pr_err("ACDB=> Bad path/ pointer sent to %s, path: %d\n",
+ __func__, path);
+ result = -EINVAL;
+ goto done;
+ }
+ result = copy_from_user((void *)&delay, (void *)arg,
+ sizeof(struct hw_delay));
+ if (result) {
+ pr_err("ACDB=> %s failed to copy hw delay: result=%d path=%d\n",
+ __func__, result, path);
+ result = -EFAULT;
+ goto done;
+ }
+ if ((delay.num_entries <= 0) ||
+ (delay.num_entries > MAX_HW_DELAY_ENTRIES)) {
+ pr_err("ACDB=> %s incorrect no of hw delay entries: %d\n",
+ __func__, delay.num_entries);
+ result = -EINVAL;
+ goto done;
+ }
+ if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+ pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+ __func__, path);
+ result = -EINVAL;
+ goto done;
+ }
+
+ pr_debug("ACDB=> %s : Path = %d num_entries = %d\n",
+ __func__, path, delay.num_entries);
+
+ mutex_lock(&acdb_data.acdb_mutex);
+ if (path == RX_CAL)
+ delay_dest = &acdb_data.hw_delay_rx;
+ else if (path == TX_CAL)
+ delay_dest = &acdb_data.hw_delay_tx;
+
+ delay_dest->num_entries = delay.num_entries;
+
+ result = copy_from_user(delay_dest->delay_info,
+ delay.delay_info,
+ (sizeof(struct hw_delay_entry)*
+ delay.num_entries));
+ if (result) {
+ pr_err("ACDB=> %s failed to copy hw delay info res=%d path=%d",
+ __func__, result, path);
+ result = -EFAULT;
+ }
+ mutex_unlock(&acdb_data.acdb_mutex);
+done:
+ return result;
+}
+
int get_anc_cal(struct acdb_cal_block *cal_block)
{
int result = 0;
@@ -998,6 +1119,29 @@
atomic_set(&acdb_data.valid_adm_custom_top, 1);
atomic_set(&acdb_data.valid_asm_custom_top, 1);
atomic_inc(&usage_count);
+
+ /* Allocate memory for hw delay entries */
+ mutex_lock(&acdb_data.acdb_mutex);
+ acdb_data.hw_delay_rx.num_entries = 0;
+ acdb_data.hw_delay_tx.num_entries = 0;
+ acdb_data.hw_delay_rx.delay_info =
+ kmalloc(sizeof(struct hw_delay_entry)*
+ MAX_HW_DELAY_ENTRIES,
+ GFP_KERNEL);
+ if (acdb_data.hw_delay_rx.delay_info == NULL) {
+ pr_err("%s : Failed to allocate av sync delay entries rx\n",
+ __func__);
+ }
+ acdb_data.hw_delay_tx.delay_info =
+ kmalloc(sizeof(struct hw_delay_entry)*
+ MAX_HW_DELAY_ENTRIES,
+ GFP_KERNEL);
+ if (acdb_data.hw_delay_tx.delay_info == NULL) {
+ pr_err("%s : Failed to allocate av sync delay entries tx\n",
+ __func__);
+ }
+ mutex_unlock(&acdb_data.acdb_mutex);
+
return result;
}
@@ -1238,6 +1382,12 @@
case AUDIO_DEREGISTER_VOCPROC_VOL_TABLE:
result = deregister_vocvol_table();
goto done;
+ case AUDIO_SET_HW_DELAY_RX:
+ result = store_hw_delay(RX_CAL, (void *)arg);
+ goto done;
+ case AUDIO_SET_HW_DELAY_TX:
+ result = store_hw_delay(TX_CAL, (void *)arg);
+ goto done;
}
if (copy_from_user(&size, (void *) arg, sizeof(size))) {
@@ -1393,6 +1543,9 @@
else
result = deregister_memory();
+ kfree(acdb_data.hw_delay_rx.delay_info);
+ kfree(acdb_data.hw_delay_tx.delay_info);
+
return result;
}
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index d9c1210..e2ca395 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -41,6 +41,11 @@
atomic_t cal_paddr;
};
+struct hw_delay_entry {
+ uint32_t sample_rate;
+ uint32_t delay_usec;
+};
+
uint32_t get_voice_rx_topology(void);
uint32_t get_voice_tx_topology(void);
uint32_t get_adm_rx_topology(void);
@@ -65,5 +70,6 @@
int get_sidetone_cal(struct sidetone_cal *cal_data);
int get_spk_protection_cfg(struct msm_spk_prot_cfg *prot_cfg);
int get_aanc_cal(struct acdb_cal_block *cal_block);
+int get_hw_delay(int32_t path, struct hw_delay_entry *delay_info);
#endif
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 62cc5db..9d4257f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -192,7 +192,7 @@
topology_id = get_adm_tx_topology();
if (topology_id == 0)
- topology_id = DEFAULT_COPP_TOPOLOGY;
+ topology_id = NULL_COPP_TOPOLOGY;
return topology_id;
}
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index f7be34c..59113fe 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -632,6 +632,71 @@
}
}
+static int afe_send_hw_delay(u16 port_id, u32 rate)
+{
+ struct hw_delay_entry delay_entry;
+ struct afe_audioif_config_command config;
+ int index = 0;
+ int ret = -EINVAL;
+
+ pr_debug("%s\n", __func__);
+
+ delay_entry.sample_rate = rate;
+ if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
+ ret = get_hw_delay(TX_CAL, &delay_entry);
+ else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
+ ret = get_hw_delay(RX_CAL, &delay_entry);
+
+ if (ret != 0) {
+ pr_warn("%s: Failed to get hw delay info\n", __func__);
+ goto fail_cmd;
+ }
+ index = q6audio_get_port_index(port_id);
+ if (index < 0) {
+ pr_debug("%s: AFE port index invalid!\n", __func__);
+ goto fail_cmd;
+ }
+
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = sizeof(config);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = index;
+
+ config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ config.param.port_id = q6audio_get_port_id(port_id);
+ config.param.payload_size = sizeof(config) - sizeof(struct apr_hdr) -
+ sizeof(config.param);
+ config.param.payload_address_lsw = 0x00;
+ config.param.payload_address_msw = 0x00;
+ config.param.mem_map_handle = 0x00;
+ config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+ config.pdata.param_id = AFE_PARAM_ID_DEVICE_HW_DELAY;
+ config.pdata.param_size = sizeof(config.port);
+
+ config.port.hw_delay.delay_in_us = delay_entry.delay_usec;
+ config.port.hw_delay.device_hw_delay_minor_version =
+ AFE_API_VERSION_DEVICE_HW_DELAY;
+
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: AFE hw delay for port %#x failed\n",
+ __func__, port_id);
+ goto fail_cmd;
+ } else if (atomic_read(&this_afe.status) != 0) {
+ pr_err("%s: config cmd failed\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+fail_cmd:
+ pr_debug("%s port_id %u rate %u delay_usec %d status %d\n",
+ __func__, port_id, rate, delay_entry.delay_usec, ret);
+ return ret;
+
+}
+
void afe_send_cal(u16 port_id)
{
pr_debug("%s\n", __func__);
@@ -1248,6 +1313,7 @@
return ret;
afe_send_cal(port_id);
+ afe_send_hw_delay(port_id, rate);
/* Start SW MAD module */
mad_type = afe_port_get_mad_type(port_id);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 76812f1..9b74eea 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1607,7 +1607,7 @@
open.preprocopo_id = get_asm_topology();
if (open.preprocopo_id == 0)
- open.preprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT;
+ open.preprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE;
open.bits_per_sample = bits_per_sample;
open.mode_flags = 0x0;
@@ -1706,7 +1706,7 @@
open.postprocopo_id = get_asm_topology();
if (open.postprocopo_id == 0)
- open.postprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT;
+ open.postprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE;
switch (format) {
case FORMAT_LINEAR_PCM:
@@ -1790,7 +1790,7 @@
/* source endpoint : matrix */
open.postprocopo_id = get_asm_topology();
if (open.postprocopo_id == 0)
- open.postprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_DEFAULT;
+ open.postprocopo_id = ASM_STREAM_POSTPROC_TOPO_ID_NONE;
switch (wr_format) {
case FORMAT_LINEAR_PCM: