Merge "msm: mdss: Update screen resolution for Assertive Display"
diff --git a/Documentation/arm/msm/msm_smp2p.txt b/Documentation/arm/msm/msm_smp2p.txt
index 4f77614..77bfb50 100644
--- a/Documentation/arm/msm/msm_smp2p.txt
+++ b/Documentation/arm/msm/msm_smp2p.txt
@@ -128,8 +128,10 @@
| section. |
---------------------------------------------------------------------------
| Feature 3 Bytes Refer to Version |
- | flags and Feature Negotiation Must be set to zero. |
- | section. |
+ | flags and Feature Negotiation |
+ | section for details. |
+ | bit 0 SSR_ACK Feature Supported when set to 1 |
+ | bits 1:31 Reserved Must be set to 0. |
---------------------------------------------------------------------------
| Entries 2 Bytes Total number of Must be 0 or greater. |
| Total entries. |
@@ -137,7 +139,11 @@
| Entries 2 Bytes Number of valid Must be between 0 |
| Valid entries. and Entries Total. |
---------------------------------------------------------------------------
- | Reserved 4 Bytes Reserved Must be set to 0. |
+ | Flags 4 Bytes |
+ | bit 0 RESTART_DONE Toggle for every restart |
+ | bit 1 RESTART_ACK Toggle to ACK remote |
+ | RESTART_DONE |
+ | bits 2:31 Reserved Must be set to 0. |
---------------------------------------------------------------------------
Table 1 - SMEM Item Header
@@ -299,6 +305,12 @@
has changed.
2) Compare Entries Valid to cached value. If changed, initialize new entries.
+Security
+========
+Since the implementation resides in the kernel and does not expose interfaces
+to userspace, no security issues are anticipated. The usage of separate SMEM
+items allows for future security enhancements in SMEM.
+
Performance
===========
No performance issues are anticipated as the signaling rate is expected to be
@@ -311,19 +323,18 @@
To map an entry to the client, the client must add two nodes to the Device
Tree:
- 1) A node that matches "qcom,smp2pgpio" to create the entry
- 2) A node that matches the client driver to provide the GPIO pin mapping
+ 1) A node that matches "qcom,smp2pgpio" to create the entry
+ 2) A node that matches the client driver to provide the GPIO pin mapping
-The details of the device tree entries are contained in the file
-Documentionat/devicetree/bindings/arm/msm/smp2p.txt.
-
+The details of the device tree entries for the GPIO interface are contained in
+the file Documentation/devicetree/bindings/gpio/gpio-smp2p.txt.
/* SMP2P Test Driver for inbound entry. */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
qcom,remote-pid = <7>;
- qcom,is_inbound;
+ qcom,is-inbound;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
@@ -374,6 +385,48 @@
Please reference the unit test code for example usage.
+Subsystem Restart
+=================
+SMP2P is unaffected by SubSystem Restart (SSR) on the high-level OS side and is
+actually used as an underlying communication mechanism for SSR. On the
+peripheral system that is being restarted, SMP2P will zero out all existing
+state entries upon reboot as part of the SMP2P initialization process and if the
+SSR_ACK feature is enabled, then it waits for an acknowledgement as outlined in
+the following subsections.
+
+SSR_ACK Feature - Reboot Use Case (Non-HLOS Only)
+-------------------------------------------------
+If a remote system boots up after an SSR and sees that the remote and local
+version numbers and feature flags are equal, then it zeros out entry values. If
+the SSR_ACK feature is enabled, it will wait for an acknowledgement from the other
+processor that it has seen the zero entry before completing the negotiation
+sequence.
+
+ if remote and local version numbers and feature flags are equal
+ Zero out all entry values
+ if SSR_ACK feature is enabled
+ Set local RESTART_DONE flag to inverse of the remote RESTART_ACK
+ Send interrupt to remote system
+ Wait for interrupt and for remote RESTART_ACK to be equal to local
+ RESTART_DONE
+ Continue with normal negotiation sequence
+
+Interrupt Use Case
+------------------
+For every interrupt triggered by a remote change, SMP2P will notify the client
+of a change in state. In addition, if the SSR_ACK feature is enabled, the SSR
+handshaking will also be handled.
+
+ if SSR_ACK feature is enabled
+ if remote RESTART_DONE != local RESTART_ACK
+ Notify client of entry change (will be * -> 0 transition)
+ Toggle local RESTART_ACK
+ Send interrupt to remote system
+ else
+ Notify client of entry change as usual
+ else
+ Notify client of entry change as usual
+
Debug
=====
The state values and names for all entries accessible by the Apps are
@@ -395,12 +448,13 @@
Config options
==============
-Configuration of interrupts will be done using Device Tree. By default, the
-testing components will be enabled since it does not affect performance and has
-a minimal impact on kernel size. However, customers can disable the testing
-components for size optimization.
+Configuration of interrupts will be done using Device Tree per the format in
+Documentation/devicetree/bindings/arm/msm/smp2p.txt. By default, the testing
+components will be enabled since it does not affect performance and has a
+minimal impact on kernel size. However, customers can disable the testing
+component for size optimization.
- CONFIG_MSM_SMP2P - enables SMP2P core functionality
+ CONFIG_MSM_SMP2P - enables SMP2P
CONFIG_MSM_SMP2P_TEST - enables unit test support
Dependencies
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/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 7ca741c..24f21b4 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -7,7 +7,8 @@
- interrupt-names : Required interrupt resource entries are:
"core_irq" : Interrupt for HSIC core
- <supply-name>-supply: handle to the regulator device tree node
- Required "supply-name" is "HSIC_VDDCX" and optionally - "HSIC_GDSC".
+ Required "supply-name" is either "hsic_vdd_dig" or "HSIC_VDDCX" and
+ optionally - "HSIC_GDSC".
Optional properties :
- interrupt-parent - This must provide reference to the current
@@ -81,6 +82,9 @@
the reset and enumeration. Since some devices might take more than 100ms
for initialization when receiving the bus reset, add delay to avoid the
problem that enmueration is before device initialization done.
+- hsic,vdd-voltage-level: This property must be a list of three integer
+ values (no, min, max) where each value represents either a voltage in
+ microvolts or a value corresponding to voltage corner
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
below optional properties:
@@ -104,7 +108,7 @@
1 &intc 0 148 0
2 &msmgpio 144 0x8>;
interrupt-names = "core_irq", "async_irq", "wakeup";
- HSIC_VDDCX-supply = <&pm8019_l12>;
+ hsic_vdd_dig-supply = <&pm8841_s2_corner>;
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
@@ -113,6 +117,7 @@
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
hsic,consider-ipa-handshake;
+ hsic,vdd-voltage-level = <1 5 7>;
qcom,msm-bus,name = "hsic";
qcom,msm-bus,num-cases = <2>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 44ed2dc..e7eae76 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -130,7 +130,8 @@
- interrupt-names : Required interrupt resource entries are:
HSUSB EHCI expects "core_irq" and optionally "async_irq".
- <supply-name>-supply: handle to the regulator device tree node
- Required "supply-name" is "HSUSB_VDDCX" "HSUSB_1p8-supply" "HSUSB_3p3-supply".
+ Required "supply-name" is either "hsusb_vdd_dig" or "HSUSB_VDDCX"
+ "HSUSB_1p8-supply" "HSUSB_3p3-supply".
- qcom,usb2-power-budget: maximum vbus power (in mA) that can be provided.
Optional properties :
@@ -138,6 +139,15 @@
- qcom,resume-gpio: if present then peripheral connected to usb controller
cannot wakeup from XO shutdown using in-band usb bus resume. Use resume
gpio to wakeup peripheral.
+- qcom,vdd-voltage-level: This property must be a list of five integer
+ values (no, 0.5vsuspend, 0.75suspend, min, max) where each value respresents
+ either a voltage in microvolts or a value corresponding to voltage corner.
+ First value represents value to vote when USB is not at all active, second
+ value represents value to vote when target is not connected to dock during low
+ power mode, third value represents vlaue to vote when target is connected to dock
+ and no peripheral connected over dock during low power mode, fourth value represents
+ minimum value to vote when USB is operational, fifth item represents maximum value
+ to vote for USB is operational.
Example MSM HSUSB EHCI controller device node :
ehci: qcom,ehci-host@f9a55000 {
@@ -145,11 +155,12 @@
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>, <0 140 0>;
interrupt-names = "core_irq", "async_irq";
- HSUSB_VDDCX-supply = <&pm8841_s2>;
+ hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
HSUSB_1p8-supply = <&pm8941_l6>;
HSUSB_3p3-supply = <&pm8941_l24>;
qcom,usb2-enable-hsphy2;
qcom,usb2-power-budget = <500>;
+ qcom,vdd-voltage-level = <1 2 3 5 7>;
};
ANDROID USB:
diff --git a/arch/arm/boot/dts/apq8026-v1-cdp.dts b/arch/arm/boot/dts/apq8026-v1-cdp.dts
index 7b40738..d7e283b 100644
--- a/arch/arm/boot/dts/apq8026-v1-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-cdp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026 CDP";
compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
- qcom,msm-id = <199 1 0>,
- <219 1 0>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v1-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
index ccf1741..d24875c 100644
--- a/arch/arm/boot/dts/apq8026-v1-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -18,8 +18,7 @@
/ {
model = "Qualcomm APQ 8026 MTP";
compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
- qcom,msm-id = <199 8 0>,
- <219 8 0>;
+ qcom,board-id = <8 0>;
};
&cci {
diff --git a/arch/arm/boot/dts/apq8026-v1-xpm.dts b/arch/arm/boot/dts/apq8026-v1-xpm.dts
index 78ae609..f69511b 100644
--- a/arch/arm/boot/dts/apq8026-v1-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v1-xpm.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026 XPM";
compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
- qcom,msm-id = <199 14 0>,
- <219 14 0>;
+ qcom,board-id = <14 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v1.dtsi b/arch/arm/boot/dts/apq8026-v1.dtsi
index 7fbfcb5..eaea002 100644
--- a/arch/arm/boot/dts/apq8026-v1.dtsi
+++ b/arch/arm/boot/dts/apq8026-v1.dtsi
@@ -21,6 +21,8 @@
/ {
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
+ qcom,msm-id = <199 0>,
+ <219 0x20000>;
};
&tsens {
diff --git a/arch/arm/boot/dts/apq8026-v2-cdp.dts b/arch/arm/boot/dts/apq8026-v2-cdp.dts
index 3fb3c29..cb68779 100644
--- a/arch/arm/boot/dts/apq8026-v2-cdp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-cdp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 CDP";
compatible = "qcom,apq8026-cdp", "qcom,apq8026", "qcom,cdp";
- qcom,msm-id = <199 1 0x20000>,
- <219 1 0x20000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2-mtp.dts b/arch/arm/boot/dts/apq8026-v2-mtp.dts
index e620859..40856c8 100644
--- a/arch/arm/boot/dts/apq8026-v2-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v2-mtp.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 MTP";
compatible = "qcom,apq8026-mtp", "qcom,apq8026", "qcom,mtp";
- qcom,msm-id = <199 8 0x20000>,
- <219 8 0x20000>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2-xpm.dts b/arch/arm/boot/dts/apq8026-v2-xpm.dts
index 2848b2e..324516d 100644
--- a/arch/arm/boot/dts/apq8026-v2-xpm.dts
+++ b/arch/arm/boot/dts/apq8026-v2-xpm.dts
@@ -18,6 +18,5 @@
/ {
model = "Qualcomm APQ 8026v2 XPM";
compatible = "qcom,apq8026-xpm", "qcom,apq8026", "qcom,xpm";
- qcom,msm-id = <199 14 0x20000>,
- <219 14 0x20000>;
+ qcom,board-id = <14 0>;
};
diff --git a/arch/arm/boot/dts/apq8026-v2.dtsi b/arch/arm/boot/dts/apq8026-v2.dtsi
index 4c0d3ce..3ee8d94 100644
--- a/arch/arm/boot/dts/apq8026-v2.dtsi
+++ b/arch/arm/boot/dts/apq8026-v2.dtsi
@@ -21,6 +21,8 @@
/ {
model = "Qualcomm APQ 8026";
compatible = "qcom,apq8026";
+ qcom,msm-id = <199 0x20000>,
+ <219 0x20000>;
};
&tsens {
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 46f5f22..60bb518 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -84,7 +84,7 @@
1 &intc 0 148 0
2 &msmgpio 144 0x8>;
interrupt-names = "core_irq", "async_irq", "wakeup";
- HSIC_VDDCX-supply = <&pm8841_s2>;
+ hsic_vdd_dig-supply = <&pm8841_s2_corner>;
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
@@ -92,6 +92,7 @@
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
qcom,phy-susp-sof-workaround;
+ hsic,vdd-voltage-level = <1 5 7>;
qcom,msm-bus,name = "hsic";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/apq8074-v2.0-1.dtsi b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
index 8314fab..2b75fa2 100644
--- a/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
@@ -55,3 +55,8 @@
status = "ok";
};
+&ehci {
+ hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
+ qcom,vdd-voltage-level = <1 2 3 5 7>;
+};
+
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-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 357b024..829197a 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -242,13 +242,13 @@
29 01 00 00 00 00 03 E6 34 34
23 01 00 00 00 00 02 E7 05
29 01 00 00 00 00 06 F0 55 AA 52 00 00
- 05 01 00 00 32 00 02 11 00
- 05 01 00 00 96 00 02 29 00
+ 05 01 00 00 00 00 02 11 00
+ 05 01 00 00 14 00 02 29 00
29 01 00 00 00 00 06 F0 55 AA 52 08 01
29 01 00 00 00 00 06 F0 55 AA 52 00 00
29 01 00 00 00 00 02 53 2C];
- 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-off-command = [05 01 00 00 00 00 02 28 00
+ 05 01 00 00 00 00 02 10 00];
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
qcom,mdss-dsi-h-sync-pulse = <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-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
new file mode 100644
index 0000000..7bb414a
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -0,0 +1,119 @@
+/* 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.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_ssd2080m_720_vid: qcom,mdss_dsi_ssd2080m_720p_video {
+ qcom,mdss-dsi-panel-name = "ssd2080m 720p video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <720>;
+ qcom,mdss-dsi-panel-height = <1280>;
+ qcom,mdss-dsi-h-front-porch = <80>;
+ qcom,mdss-dsi-h-back-porch = <24>;
+ qcom,mdss-dsi-h-pulse-width = <14>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <15>;
+ qcom,mdss-dsi-v-front-porch = <12>;
+ qcom,mdss-dsi-v-pulse-width = <10>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = <0>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 FF 01
+ 29 01 00 00 00 00 05 C6 63 00 81 31
+ 29 01 00 00 00 00 05 CB E7 80 73 33
+ 29 01 00 00 00 00 02 EC D2
+ 29 01 00 00 00 00 03 B3 04 9F
+ 29 01 00 00 00 00 04 B2 16 1E 10
+ 29 01 00 00 00 00 02 B4 00
+ 29 01 00 00 00 00 02 C1 04
+ 29 01 00 00 00 00 04 C2 BE 00 58
+ 29 01 00 00 00 00 09 C3 01 22 11 21 0E 80 80 24
+ 29 01 00 00 00 00 08 B6 09 16 42 01 13 00 00
+ 29 01 00 00 00 00 04 B7 24 26 43
+ 29 01 00 00 00 00 06 B8 16 08 25 44 08
+ 29 01 00 00 00 00 09 B9 06 08 07 09 00 00 00 00
+ 29 01 00 00 00 00 09 BA 0E 10 0A 0C 16 05 00 00
+ 29 01 00 00 00 00 09 BB A1 A1 A1 A1 00 00 00 00
+ 29 01 00 00 00 00 09 BC 0F 11 0B 0D 16 05 00 00
+ 29 01 00 00 00 00 09 BD A1 A1 A1 A1 00 00 00 00
+ 29 01 00 00 00 00 04 E6 FF FF 0F
+ 29 01 00 00 00 00 02 C7 3F
+ 29 01 00 00 00 00 07 B5 47 00 00 08 00 01
+ 29 01 00 00 00 00 08 C4 DF 72 12 12 66 E3 99
+ 29 01 00 00 00 00 07 D0 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D1 28 27 14 02 01
+ 29 01 00 00 00 00 07 D2 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D3 28 27 14 02 01
+ 29 01 00 00 00 00 07 D4 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D5 28 27 14 02 01
+ 29 01 00 00 00 00 07 D6 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D7 28 27 14 02 01
+ 29 01 00 00 00 00 07 D8 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 D9 28 27 14 02 01
+ 29 01 00 00 00 00 07 DA 0A 00 0D 15 1F 2E
+ 29 01 00 00 00 00 06 DB 28 27 14 02 01
+ 29 01 00 00 00 00 03 CC 10 00
+ 29 01 00 00 00 00 04 CE 4E 55 A5
+ 29 01 00 00 00 00 04 E0 01 02 02
+ 29 01 00 00 00 00 05 F6 00 00 00 00
+ 29 01 00 00 00 00 05 F7 00 00 00 00
+ 29 01 00 00 00 00 03 E1 90 00
+ 29 01 00 00 00 00 03 DE 95 CF
+ 29 01 00 00 00 00 02 CF 46
+ 29 01 00 00 00 00 03 C5 77 47
+ 29 01 00 00 00 00 03 ED 00 20
+ 05 01 00 00 B4 00 02 11 00
+ 05 01 00 00 82 00 02 29 00
+ 15 01 00 00 00 00 02 53 2c];
+
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 10 00
+ 05 01 00 00 32 00 02 53 00
+ 05 01 00 00 00 00 02 c2 00
+ 39 01 00 00 00 00 02 cf 40
+ 05 01 00 00 50 00 03 de 84 00
+ 39 01 00 00 00 00 02 cb 22
+ 05 01 00 00 00 00 02 c3 00];
+
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-lane-map = <0>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [a8 1f 17 00 2f 2d 1c 21 29 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x20>;
+ qcom,mdss-dsi-t-clk-pre = <0x2f>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ };
+};
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-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index 5d7a7ec..fa5c739 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -31,6 +31,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6f {
compatible = "qcom,ov8825";
reg = <0x6f>;
@@ -75,6 +82,7 @@
qcom,slave-id = <0x20 0x0016 0x0135>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator1>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
cam_vdig-supply = <&pm8226_l5>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index 066d6c2..d377bf0 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -29,6 +29,8 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
+ synaptics,disable-gpios;
};
};
diff --git a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
index 8194bf6..eeec175 100644
--- a/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss-panels.dtsi
@@ -15,3 +15,4 @@
/include/ "dsi-panel-nt35521-720p-video.dtsi"
/include/ "dsi-panel-nt35596-1080p-video.dtsi"
/include/ "dsi-panel-nt35590-720p-cmd.dtsi"
+/include/ "dsi-panel-ssd2080m-720p-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index f4f7442..318d4fc 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -29,6 +29,8 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
+ synaptics,disable-gpios;
};
};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index a574bb0..18a1aea 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -29,7 +29,10 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
+ synaptics,power-down;
+ synaptics,disable-gpios;
};
+
focaltech@38 {
compatible = "focaltech,5x06";
reg = <0x38>;
@@ -114,10 +117,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 +241,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 +457,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-v1-cdp.dts b/arch/arm/boot/dts/msm8226-v1-cdp.dts
index c721df2..e426a97 100644
--- a/arch/arm/boot/dts/msm8226-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-cdp.dts
@@ -17,13 +17,5 @@
/ {
model = "Qualcomm MSM 8226 CDP";
compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
- qcom,msm-id = <145 1 0>,
- <158 1 0>,
- <159 1 0>,
- <198 1 0>,
- <205 1 0>,
- <220 1 0>,
- <221 1 0>,
- <222 1 0>,
- <223 1 0>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v1-mtp.dts b/arch/arm/boot/dts/msm8226-v1-mtp.dts
index 95d88a7..08d7cec 100644
--- a/arch/arm/boot/dts/msm8226-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-mtp.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 MTP";
compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
- qcom,msm-id = <145 8 0>,
- <158 8 0>,
- <159 8 0>,
- <198 8 0>,
- <205 8 0>,
- <220 8 0>,
- <221 8 0>,
- <222 8 0>,
- <223 8 0>;
+ qcom,board-id = <8 0>;
};
&cci {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
index f8fd0c2..7e9f91b 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-dvt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 0x2000b 0>,
- <158 0x2000b 0>,
- <159 0x2000b 0>,
- <198 0x2000b 0>,
- <205 0x2000b 0>,
- <220 0x2000b 0>,
- <221 0x2000b 0>,
- <222 0x2000b 0>,
- <223 0x2000b 0>;
+ qcom,board-id = <0x2000b 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
index bc5d8e7..c93d9db 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-evt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 11 0>,
- <158 11 0>,
- <159 11 0>,
- <198 11 0>,
- <205 11 0>,
- <220 11 0>,
- <221 11 0>,
- <222 11 0>,
- <223 11 0>;
+ qcom,board-id = <11 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-cdp.dts
index 7c955dd..3d40180 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-cdp.dts
@@ -18,13 +18,5 @@
/ {
model = "Qualcomm MSM 8226v2 CDP";
compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
- qcom,msm-id = <145 1 0x20000>,
- <158 1 0x20000>,
- <159 1 0x20000>,
- <198 1 0x20000>,
- <205 1 0x20000>,
- <220 1 0x20000>,
- <221 1 0x20000>,
- <222 1 0x20000>,
- <223 1 0x20000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2-mtp.dts b/arch/arm/boot/dts/msm8226-v2-mtp.dts
index dfdc5db..6034107 100644
--- a/arch/arm/boot/dts/msm8226-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-mtp.dts
@@ -18,13 +18,5 @@
/ {
model = "Qualcomm MSM 8226v2 MTP";
compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
- qcom,msm-id = <145 8 0x20000>,
- <158 8 0x20000>,
- <159 8 0x20000>,
- <198 8 0x20000>,
- <205 8 0x20000>,
- <220 8 0x20000>,
- <221 8 0x20000>,
- <222 8 0x20000>,
- <223 8 0x20000>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index e492720..13402af 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226v2 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 0x2000b 0x20000>,
- <158 0x2000b 0x20000>,
- <159 0x2000b 0x20000>,
- <198 0x2000b 0x20000>,
- <205 0x2000b 0x20000>,
- <220 0x2000b 0x20000>,
- <221 0x2000b 0x20000>,
- <222 0x2000b 0x20000>,
- <223 0x2000b 0x20000>;
+ qcom,board-id = <0x2000b 0>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
index 83c7034..b707d1c 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-evt.dts
@@ -17,15 +17,7 @@
/ {
model = "Qualcomm MSM 8226v2 QRD";
compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
- qcom,msm-id = <145 11 0x20000>,
- <158 11 0x20000>,
- <159 11 0x20000>,
- <198 11 0x20000>,
- <205 11 0x20000>,
- <220 11 0x20000>,
- <221 11 0x20000>,
- <222 11 0x20000>,
- <223 11 0x20000>;
+ qcom,board-id = <11 0>;
};
&mdss_dsi0 {
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 7b944fc..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";
};
@@ -438,6 +444,10 @@
qcom,msm-dai-q6-dev-id = <8>;
};
+ qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
qcom,msm-dai-q6 {
compatible = "qcom,msm-dai-q6";
qcom,msm-dai-q6-sb-0-rx {
@@ -480,6 +490,11 @@
qcom,msm-dai-q6-dev-id = <16393>;
};
+ qcom,msm-dai-q6-sb-5-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <16395>;
+ };
+
qcom,msm-dai-q6-bt-sco-rx {
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <12288>;
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-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index df61ca6..3fb33e9 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -364,4 +364,5 @@
&android_usb {
qcom,android-usb-cdrom;
+ qcom,android-usb-internal-ums;
};
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-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 500c7d8..7d8d6cf 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -19,10 +19,7 @@
/ {
model = "Qualcomm MSM 8926 CDP";
compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
- qcom,msm-id = <200 1 0>,
- <224 1 0>,
- <200 1 0x10001>,
- <224 1 0x10001>;
+ qcom,board-id = <1 0>;
};
&pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8926-mtp.dts b/arch/arm/boot/dts/msm8926-mtp.dts
index 73635bc..624781b 100644
--- a/arch/arm/boot/dts/msm8926-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-mtp.dts
@@ -19,8 +19,5 @@
/ {
model = "Qualcomm MSM 8926 MTP";
compatible = "qcom,msm8926-mtp", "qcom,msm8926", "qcom,mtp";
- qcom,msm-id = <200 8 0>,
- <224 8 0>,
- <200 8 0x10001>,
- <224 8 0x10001>;
+ qcom,board-id = <8 0>;
};
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dts
index 8fb0878..b7826e5 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dts
@@ -34,3 +34,11 @@
&pm8226_chg {
qcom,battery-data = <&qrd_batterydata>;
};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_ssd2080m_720_vid>;
+};
+
+&dsi_ssd2080m_720_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-qrd.dts
index 5cae698..8ee8828 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-qrd.dts
@@ -17,8 +17,5 @@
/ {
model = "Qualcomm MSM 8926 QRD";
compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
- qcom,msm-id = <200 11 0>,
- <224 11 0>,
- <200 11 0x10001>,
- <224 11 0x10001>;
+ qcom,board-id = <11 0>;
};
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-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index d200100..d6c7272 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -227,7 +227,7 @@
1 &intc 0 148 0
2 &msmgpio 144 0x8>;
interrupt-names = "core_irq", "async_irq", "wakeup";
- HSIC_VDDCX-supply = <&pm8841_s2>;
+ hsic_vdd_dig-supply = <&pm8841_s2_corner>;
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
@@ -236,6 +236,7 @@
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
qcom,phy-susp-sof-workaround;
+ hsic,vdd-voltage-level = <1 5 7>;
qcom,msm-bus,name = "hsic";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 73aba8f..67e1802 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -397,7 +397,7 @@
1 &intc 0 148 0
2 &msmgpio 144 0x8>;
interrupt-names = "core_irq", "async_irq", "wakeup";
- HSIC_VDDCX-supply = <&pm8841_s2>;
+ hsic_vdd_dig-supply = <&pm8841_s2_corner>;
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
@@ -405,6 +405,7 @@
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
qcom,phy-susp-sof-workaround;
+ hsic,vdd-voltage-level = <1 5 7>;
qcom,msm-bus,name = "hsic";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index c3fd98d..071c7c9 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -26,6 +26,8 @@
&ehci {
status = "ok";
vbus-supply = <&usb2_otg_sw>;
+ hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
+ qcom,vdd-voltage-level = <1 2 3 5 7>;
};
&hsic_host {
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/kernel/smp.c b/arch/arm/kernel/smp.c
index 32b5b26..5bca467 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -555,7 +555,7 @@
static DEFINE_RAW_SPINLOCK(stop_lock);
-static struct pt_regs __percpu regs_before_stop;
+DEFINE_PER_CPU(struct pt_regs, regs_before_stop);
/*
* ipi_cpu_stop - handle IPI from smp_send_stop()
*/
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/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index db66d27..0479844 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -55,8 +55,12 @@
return drv.scalable[cpu].cur_speed->khz;
}
-/* Select a source on the primary MUX. */
-static void set_pri_clk_src(struct scalable *sc, u32 pri_src_sel)
+struct set_clk_src_args {
+ struct scalable *sc;
+ u32 src_sel;
+};
+
+static void __set_pri_clk_src(struct scalable *sc, u32 pri_src_sel)
{
u32 regval;
@@ -73,6 +77,27 @@
udelay(1);
}
+static void __set_cpu_pri_clk_src(void *data)
+{
+ struct set_clk_src_args *args = data;
+ __set_pri_clk_src(args->sc, args->src_sel);
+}
+
+/* Select a source on the primary MUX. */
+static void set_pri_clk_src(struct scalable *sc, u32 pri_src_sel)
+{
+ int cpu = sc - drv.scalable;
+ if (sc != &drv.scalable[L2] && cpu_online(cpu)) {
+ struct set_clk_src_args args = {
+ .sc = sc,
+ .src_sel = pri_src_sel,
+ };
+ smp_call_function_single(cpu, __set_cpu_pri_clk_src, &args, 1);
+ } else {
+ __set_pri_clk_src(sc, pri_src_sel);
+ }
+}
+
/* Select a source on the secondary MUX. */
static void __cpuinit set_sec_clk_src(struct scalable *sc, u32 sec_src_sel)
{
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/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index a9a6942..de15be5 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -378,9 +378,7 @@
{
struct lpass_data *drv = subsys_to_drv(dev_id);
- disable_irq_nosync(drv->subsys_desc.wdog_bite_irq);
schedule_work(&drv->work);
-
return IRQ_HANDLED;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
index 0c71659..0a50bcc 100644
--- a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -53,7 +53,11 @@
pr_debug("%s:probe is not done, deferred\n", __func__);
return -EPROBE_DEFER;
}
-
+ if (!name || !client || !handle || !paddr || !vaddr
+ || !bufsz || !pa_len) {
+ pr_err("%s: Invalid params\n", __func__);
+ return -EINVAL;
+ }
*client = msm_audio_ion_client_create(UINT_MAX, name);
if (IS_ERR_OR_NULL((void *)(*client))) {
pr_err("%s: ION create client for AUDIO failed\n", __func__);
@@ -102,9 +106,9 @@
err_ion_handle:
ion_free(*client, *handle);
- *handle = NULL;
err_ion_client:
msm_audio_ion_client_destroy(*client);
+ *handle = NULL;
*client = NULL;
err:
return -EINVAL;
@@ -116,10 +120,16 @@
ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
{
int rc = 0;
+ if (!name || !client || !handle || !paddr || !vaddr || !pa_len) {
+ pr_err("%s: Invalid params\n", __func__);
+ rc = -EINVAL;
+ goto err;
+ }
*client = msm_audio_ion_client_create(UINT_MAX, name);
if (IS_ERR_OR_NULL((void *)(*client))) {
pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ rc = -EINVAL;
goto err;
}
@@ -132,8 +142,9 @@
if (IS_ERR_OR_NULL((void *) (*handle))) {
pr_err("%s: ion import dma buffer failed\n",
__func__);
- goto err_ion_handle;
- }
+ rc = -EINVAL;
+ goto err_destroy_client;
+ }
if (ionflag != NULL) {
rc = ion_handle_get_flags(*client, *handle, ionflag);
@@ -154,6 +165,7 @@
*vaddr = ion_map_kernel(*client, *handle);
if (IS_ERR_OR_NULL((void *)*vaddr)) {
pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ rc = -ENOMEM;
goto err_ion_handle;
}
pr_debug("%s: mapped address = %p, size=%d\n", __func__, *vaddr, bufsz);
@@ -162,13 +174,20 @@
err_ion_handle:
ion_free(*client, *handle);
+err_destroy_client:
msm_audio_ion_client_destroy(*client);
+ *client = NULL;
+ *handle = NULL;
err:
- return -EINVAL;
+ return rc;
}
int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
{
+ if (!client || !handle) {
+ pr_err("%s Invalid params\n", __func__);
+ return -EINVAL;
+ }
if (msm_audio_ion_data.smmu_enabled) {
/* Need to populate book kept infomation */
pr_debug("client=%p, domain=%p, domain_id=%d, group=%p",
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 2bae37a..ccab6e2 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -284,8 +284,10 @@
struct kvp *e, *n;
for_each_kvp(buf, n) {
+ bool found = false;
for_each_kvp(s->buf, e) {
if (n->k == e->k) {
+ found = true;
if (n->s == e->s) {
void *e_data = get_data(e);
void *n_data = get_data(n);
@@ -300,6 +302,11 @@
}
break;
}
+
+ }
+ if (!found) {
+ add_kvp(s->buf, n);
+ s->valid = true;
}
}
}
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 6df1da4..428d5b0 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -21,7 +21,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
-#include <linux/wakelock.h>
+#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
@@ -39,6 +39,7 @@
#define MODULE_NAME "msm_smdtty"
#define MAX_SMD_TTYS 37
#define MAX_TTY_BUF_SIZE 2048
+#define TTY_PUSH_WS_DELAY 500
#define MAX_RA_WAKE_LOCK_NAME_LEN 32
#define SMD_TTY_PROBE_WAIT_TIMEOUT 3000
#define SMD_TTY_LOG_PAGES 2
@@ -58,34 +59,65 @@
} while (0)
static void *smd_tty_log_ctx;
-static DEFINE_MUTEX(smd_tty_lock);
static struct delayed_work smd_tty_probe_work;
static int smd_tty_probe_done;
+/**
+ * struct smd_tty_info - context for an individual SMD TTY device
+ *
+ * @ch: SMD channel handle
+ * @port: TTY port context structure
+ * @device_ptr: TTY device pointer
+ * @pending_ws: pending-data wakeup source
+ * @tty_tsklt: read tasklet
+ * @buf_req_timer: RX buffer retry timer
+ * @ch_allocated: completion set when SMD channel is allocated
+ * @driver: SMD channel platform driver context structure
+ * @pil: Peripheral Image Loader handle
+ * @edge: SMD edge associated with port
+ * @ch_name: SMD channel name associated with port
+ * @dev_name: SMD platform device name associated with port
+ *
+ * @open_lock_lha1: open/close lock - used to serialize open/close operations
+ * @open_wait: Timeout in seconds to wait for SMD port to be created / opened
+ *
+ * @reset_lock_lha2: lock for reset and open state
+ * @in_reset: True if SMD channel is closed / in SSR
+ * @in_reset_updated: reset state changed
+ * @is_open: True if SMD port is open
+ * @ch_opened_wait_queue: SMD port open/close wait queue
+ *
+ * @ra_lock_lha3: Read-available lock - used to synchronize reads from SMD
+ * @ra_wakeup_source_name: Name of the read-available wakeup source
+ * @ra_wakeup_source: Read-available wakeup source
+ */
struct smd_tty_info {
smd_channel_t *ch;
struct tty_port port;
struct device *device_ptr;
- struct wake_lock wake_lock;
+ struct wakeup_source pending_ws;
struct tasklet_struct tty_tsklt;
struct timer_list buf_req_timer;
struct completion ch_allocated;
struct platform_driver driver;
void *pil;
- int in_reset;
- int in_reset_updated;
- int is_open;
- unsigned int open_wait;
- wait_queue_head_t ch_opened_wait_queue;
- spinlock_t reset_lock;
- spinlock_t ra_lock; /* Read Available Lock*/
- char ra_wake_lock_name[MAX_RA_WAKE_LOCK_NAME_LEN];
- struct wake_lock ra_wake_lock; /* Read Available Wakelock */
-
uint32_t edge;
char ch_name[SMD_MAX_CH_NAME_LEN];
char dev_name[SMD_MAX_CH_NAME_LEN];
+
+ struct mutex open_lock_lha1;
+ unsigned int open_wait;
+
+ spinlock_t reset_lock_lha2;
+ int in_reset;
+ int in_reset_updated;
+ int is_open;
+ wait_queue_head_t ch_opened_wait_queue;
+
+ spinlock_t ra_lock_lha3;
+ char ra_wakeup_source_name[MAX_RA_WAKE_LOCK_NAME_LEN];
+ struct wakeup_source ra_wakeup_source;
};
/**
@@ -140,13 +172,13 @@
struct smd_tty_info *info = (struct smd_tty_info *)param;
unsigned long flags;
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_hi_schedule(&info->tty_tsklt);
return;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
}
static ssize_t open_timeout_store(struct device *dev,
@@ -168,7 +200,9 @@
return -EINVAL;
}
if (!kstrtoul(buf, 10, &wait)) {
+ mutex_lock(&smd_tty[num_dev].open_lock_lha1);
smd_tty[num_dev].open_wait = wait;
+ mutex_unlock(&smd_tty[num_dev].open_lock_lha1);
return n;
} else {
SMD_TTY_INFO("[%s]: Unable to convert %s to an int",
@@ -181,6 +215,7 @@
struct device_attribute *attr, char *buf)
{
unsigned int num_dev;
+ unsigned int open_wait;
if (dev == NULL) {
SMD_TTY_INFO("%s: Invalid Device passed", __func__);
@@ -195,8 +230,11 @@
return -EINVAL;
}
- return snprintf(buf, PAGE_SIZE, "%d\n",
- smd_tty[num_dev].open_wait);
+ mutex_lock(&smd_tty[num_dev].open_lock_lha1);
+ open_wait = smd_tty[num_dev].open_wait;
+ mutex_unlock(&smd_tty[num_dev].open_lock_lha1);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", open_wait);
}
static DEVICE_ATTR
@@ -222,14 +260,14 @@
}
if (test_bit(TTY_THROTTLED, &tty->flags)) break;
- spin_lock_irqsave(&info->ra_lock, flags);
+ spin_lock_irqsave(&info->ra_lock_lha3, flags);
avail = smd_read_avail(info->ch);
if (avail == 0) {
- wake_unlock(&info->ra_wake_lock);
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ __pm_relax(&info->ra_wakeup_source);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
break;
}
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
if (avail > MAX_TTY_BUF_SIZE)
avail = MAX_TTY_BUF_SIZE;
@@ -252,7 +290,13 @@
__func__, info->ch->name);
}
- wake_lock_timeout(&info->wake_lock, HZ / 2);
+ /*
+ * Keep system awake long enough to allow the TTY
+ * framework to pass the flip buffer to any waiting
+ * userspace clients.
+ */
+ __pm_wakeup_event(&info->pending_ws, TTY_PUSH_WS_DELAY);
+
tty_flip_buffer_push(tty);
}
@@ -269,12 +313,12 @@
switch (event) {
case SMD_EVENT_DATA:
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (!info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
break;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
/* There may be clients (tty framework) that are blocked
* waiting for space to write data, so if a possible read
* interrupt came in wake anyone waiting and disable the
@@ -287,37 +331,45 @@
wake_up_interruptible(&tty->write_wait);
tty_kref_put(tty);
}
- spin_lock_irqsave(&info->ra_lock, flags);
+ spin_lock_irqsave(&info->ra_lock_lha3, flags);
if (smd_read_avail(info->ch)) {
- wake_lock(&info->ra_wake_lock);
+ __pm_stay_awake(&info->ra_wakeup_source);
tasklet_hi_schedule(&info->tty_tsklt);
}
- spin_unlock_irqrestore(&info->ra_lock, flags);
+ spin_unlock_irqrestore(&info->ra_lock_lha3, flags);
break;
case SMD_EVENT_OPEN:
- spin_lock_irqsave(&info->reset_lock, flags);
+ 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, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
+ tty_kref_put(tty);
break;
case SMD_EVENT_CLOSE:
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
info->in_reset = 1;
info->in_reset_updated = 1;
info->is_open = 0;
wake_up_interruptible(&info->ch_opened_wait_queue);
- spin_unlock_irqrestore(&info->reset_lock, flags);
- /* schedule task to send TTY_BREAK */
- tasklet_hi_schedule(&info->tty_tsklt);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
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;
}
@@ -346,7 +398,7 @@
info = smd_tty + n;
- mutex_lock(&smd_tty_lock);
+ mutex_lock(&info->open_lock_lha1);
tty->driver_data = info;
peripheral = smd_edge_to_subsystem(smd_tty[n].edge);
@@ -407,12 +459,11 @@
}
tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
- wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
- info->ch_name);
- scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
+ wakeup_source_init(&info->pending_ws, info->ch_name);
+ scnprintf(info->ra_wakeup_source_name, MAX_RA_WAKE_LOCK_NAME_LEN,
"SMD_TTY_%s_RA", info->ch_name);
- wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
- info->ra_wake_lock_name);
+ wakeup_source_init(&info->ra_wakeup_source,
+ info->ra_wakeup_source_name);
res = smd_named_open_on_edge(info->ch_name,
smd_tty[n].edge, &info->ch, info,
@@ -435,7 +486,7 @@
SMD_TTY_INFO("%s with PID %u opened port %s",
current->comm, current->pid, info->ch_name);
smd_disable_read_intr(info->ch);
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
return 0;
close_ch:
@@ -444,13 +495,13 @@
release_wl_tl:
tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
+ wakeup_source_trash(&info->pending_ws);
+ wakeup_source_trash(&info->ra_wakeup_source);
release_pil:
subsystem_put(info->pil);
out:
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
return res;
}
@@ -467,15 +518,15 @@
return;
}
- mutex_lock(&smd_tty_lock);
+ mutex_lock(&info->open_lock_lha1);
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
info->is_open = 0;
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
+ wakeup_source_trash(&info->pending_ws);
+ wakeup_source_trash(&info->ra_wakeup_source);
SMD_TTY_INFO("%s with PID %u closed port %s",
current->comm, current->pid,
@@ -487,7 +538,7 @@
info->ch = NULL;
subsystem_put(info->pil);
- mutex_unlock(&smd_tty_lock);
+ mutex_unlock(&info->open_lock_lha1);
tty_kref_put(tty);
}
@@ -550,13 +601,13 @@
struct smd_tty_info *info = tty->driver_data;
unsigned long flags;
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
if (info->is_open) {
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
tasklet_hi_schedule(&info->tty_tsklt);
return;
}
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
}
/*
@@ -573,7 +624,7 @@
tiocm = smd_tiocmget(info->ch);
- spin_lock_irqsave(&info->reset_lock, flags);
+ spin_lock_irqsave(&info->reset_lock_lha2, flags);
tiocm |= (info->in_reset ? TIOCM_OUT1 : 0);
if (info->in_reset_updated) {
tiocm |= TIOCM_OUT2;
@@ -581,7 +632,7 @@
}
SMD_TTY_INFO("PID %u --> %s TIOCM is %x ",
current->pid, __func__, tiocm);
- spin_unlock_irqrestore(&info->reset_lock, flags);
+ spin_unlock_irqrestore(&info->reset_lock_lha2, flags);
return tiocm;
}
@@ -707,23 +758,29 @@
/* TODO: For kernel >= 3.7 use tty_port_register_device */
smd_tty[idx].device_ptr = tty_register_device(smd_tty_driver, idx, 0);
init_completion(&smd_tty[idx].ch_allocated);
+ mutex_init(&smd_tty[idx].open_lock_lha1);
/* register platform device */
smd_tty[idx].driver.probe = smd_tty_dummy_probe;
smd_tty[idx].driver.driver.name = smd_tty[idx].dev_name;
smd_tty[idx].driver.driver.owner = THIS_MODULE;
- spin_lock_init(&smd_tty[idx].reset_lock);
- spin_lock_init(&smd_tty[idx].ra_lock);
+ spin_lock_init(&smd_tty[idx].reset_lock_lha2);
+ spin_lock_init(&smd_tty[idx].ra_lock_lha3);
smd_tty[idx].is_open = 0;
setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
(unsigned long)&smd_tty[idx]);
init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
ret = platform_driver_register(&smd_tty[idx].driver);
+ if (ret)
+ return ret;
+ if (device_create_file(smd_tty[idx].device_ptr, &dev_attr_open_timeout))
+ SMD_TTY_ERR("%s: Unable to create device attributes for %s",
+ __func__, smd_configs[idx].port_name);
return ret;
}
-static int __init smd_tty_core_init(void)
+static int smd_tty_core_init(void)
{
int ret;
int n;
@@ -771,12 +828,6 @@
}
ret = smd_tty_device_init(idx);
- if (device_create_file(smd_tty[idx].device_ptr,
- &dev_attr_open_timeout))
- SMD_TTY_ERR(
- "%s: Unable to create device attributes for %s",
- __func__, smd_configs[n].port_name);
-
if (ret) {
SMD_TTY_ERR(
"%s: init failed %d (%d)", __func__, idx, ret);
@@ -803,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/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index 4b69cf0..df241f8 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -53,6 +53,9 @@
* @smem_edge_out: Pointer to outbound smem item.
* @smem_edge_state: State of the outbound edge.
* @ops_ptr: Pointer to internal version-specific SMEM item access functions.
+ *
+ * @feature_ssr_ack_enabled: SSR ACK Support Enabled
+ * @restart_ack: Current cached state of the local ack bit
*/
struct smp2p_out_list_item {
spinlock_t out_item_lock_lha1;
@@ -61,11 +64,14 @@
struct smp2p_smem __iomem *smem_edge_out;
enum msm_smp2p_edge_state smem_edge_state;
struct smp2p_version_if *ops_ptr;
+
+ bool feature_ssr_ack_enabled;
+ bool restart_ack;
};
static struct smp2p_out_list_item out_list[SMP2P_NUM_PROCS];
static void *log_ctx;
-static int smp2p_debug_mask = MSM_SMP2P_INFO;
+static int smp2p_debug_mask = MSM_SMP2P_INFO | MSM_SMP2P_DEBUG;
module_param_named(debug_mask, smp2p_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
@@ -115,6 +121,7 @@
*
* @is_supported: True if this version is supported by SMP2P
* @negotiate_features: Returns (sub)set of supported features
+ * @negotiation_complete: Called when negotiation has been completed
* @find_entry: Finds existing / next empty entry
* @create_entry: Creates a new entry
* @read_entry: Reads the value of an entry
@@ -128,6 +135,7 @@
/* common functions */
bool is_supported;
uint32_t (*negotiate_features)(uint32_t features);
+ void (*negotiation_complete)(struct smp2p_out_list_item *);
void (*find_entry)(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name,
uint32_t **entry_ptr, int *empty_spot);
@@ -148,6 +156,7 @@
/* v0 (uninitialized SMEM item) interface functions */
static uint32_t smp2p_negotiate_features_v0(uint32_t features);
+static void smp2p_negotiation_complete_v0(struct smp2p_out_list_item *out_item);
static void smp2p_find_entry_v0(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name, uint32_t **entry_ptr,
int *empty_spot);
@@ -160,6 +169,7 @@
/* v1 interface functions */
static uint32_t smp2p_negotiate_features_v1(uint32_t features);
+static void smp2p_negotiation_complete_v1(struct smp2p_out_list_item *out_item);
static void smp2p_find_entry_v1(struct smp2p_smem __iomem *item,
uint32_t entries_total, char *name, uint32_t **entry_ptr,
int *empty_spot);
@@ -174,6 +184,7 @@
static struct smp2p_version_if version_if[] = {
[0] = {
.negotiate_features = smp2p_negotiate_features_v0,
+ .negotiation_complete = smp2p_negotiation_complete_v0,
.find_entry = smp2p_find_entry_v0,
.create_entry = smp2p_out_create_v0,
.read_entry = smp2p_out_read_v0,
@@ -184,6 +195,7 @@
[1] = {
.is_supported = true,
.negotiate_features = smp2p_negotiate_features_v1,
+ .negotiation_complete = smp2p_negotiation_complete_v1,
.find_entry = smp2p_find_entry_v1,
.create_entry = smp2p_out_create_v1,
.read_entry = smp2p_out_read_v1,
@@ -399,15 +411,76 @@
}
/**
- * smp2p_negotiate_features_v0 - Initial feature negotiation.
+ * smp2p_ssr_ack_needed - Returns true if SSR ACK required
+ *
+ * @rpid: Remote processor ID
+ *
+ * Must be called with out_item_lock_lha1 and in_item_lock_lhb1 locked.
+ */
+static bool smp2p_ssr_ack_needed(uint32_t rpid)
+{
+ bool ssr_done;
+
+ if (!out_list[rpid].feature_ssr_ack_enabled)
+ return false;
+
+ ssr_done = SMP2P_GET_RESTART_DONE(in_list[rpid].smem_edge_in->flags);
+ if (ssr_done != out_list[rpid].restart_ack)
+ return true;
+
+ return false;
+}
+
+/**
+ * smp2p_do_ssr_ack - Handles SSR ACK
+ *
+ * @rpid: Remote processor ID
+ *
+ * Must be called with out_item_lock_lha1 and in_item_lock_lhb1 locked.
+ */
+static void smp2p_do_ssr_ack(uint32_t rpid)
+{
+ bool ack;
+
+ if (!smp2p_ssr_ack_needed(rpid))
+ return;
+
+ ack = !out_list[rpid].restart_ack;
+ SMP2P_INFO("%s: ssr ack pid %d: %d -> %d\n", __func__, rpid,
+ out_list[rpid].restart_ack, ack);
+ out_list[rpid].restart_ack = ack;
+ SMP2P_SET_RESTART_ACK(out_list[rpid].smem_edge_out->flags, ack);
+ smp2p_send_interrupt(rpid);
+}
+
+/**
+ * smp2p_negotiate_features_v1 - Initial feature negotiation.
*
* @features: Inbound feature set.
* @returns: Supported features (will be a same/subset of @features).
*/
static uint32_t smp2p_negotiate_features_v1(uint32_t features)
{
- /* no supported features */
- return 0;
+ return SMP2P_FEATURE_SSR_ACK;
+}
+
+/**
+ * smp2p_negotiation_complete_v1 - Negotiation completed
+ *
+ * @out_item: Pointer to the output item structure
+ *
+ * Can be used to do final configuration based upon the negotiated feature set.
+ *
+ * Must be called with out_item_lock_lha1 locked.
+ */
+static void smp2p_negotiation_complete_v1(struct smp2p_out_list_item *out_item)
+{
+ uint32_t features;
+
+ features = SMP2P_GET_FEATURES(out_item->smem_edge_out->feature_version);
+
+ if (features & SMP2P_FEATURE_SSR_ACK)
+ out_item->feature_ssr_ack_enabled = true;
}
/**
@@ -707,6 +780,20 @@
}
/**
+ * smp2p_negotiation_complete_v0 - Negotiation completed
+ *
+ * @out_item: Pointer to the output item structure
+ *
+ * Can be used to do final configuration based upon the negotiated feature set.
+ */
+static void smp2p_negotiation_complete_v0(struct smp2p_out_list_item *out_item)
+{
+ SMP2P_ERR("%s: invalid negotiation complete for v0 pid %d\n",
+ __func__,
+ SMP2P_GET_REMOTE_PID(out_item->smem_edge_out->rem_loc_proc_id));
+}
+
+/**
* smp2p_find_entry_v0 - Stub function.
*
* @item: Pointer to the smem item.
@@ -885,7 +972,7 @@
SMP2P_SET_FEATURES(header_ptr->feature_version, features);
SMP2P_SET_ENT_TOTAL(header_ptr->valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(header_ptr->valid_total_ent, 0);
- header_ptr->reserved = 0;
+ header_ptr->flags = 0;
/* ensure that all fields are valid before version is written */
wmb();
@@ -992,8 +1079,9 @@
struct msm_smp2p_out *pos;
/* negotiation complete */
- out_item->smem_edge_state = SMP2P_EDGE_STATE_OPENED;
out_item->ops_ptr = &version_if[l_version];
+ out_item->ops_ptr->negotiation_complete(out_item);
+ out_item->smem_edge_state = SMP2P_EDGE_STATE_OPENED;
SMP2P_INFO(
"%s: negotiation complete pid %d: State %d->%d F0x%08x\n",
__func__, remote_pid, prev_state,
@@ -1528,9 +1616,41 @@
smp2p_do_negotiation(remote_pid, &out_list[remote_pid]);
if (out_list[remote_pid].smem_edge_state == SMP2P_EDGE_STATE_OPENED) {
+ bool do_restart_ack;
+
+ /*
+ * Follow double-check pattern for restart ack since:
+ * 1) we must notify clients of the X->0 transition
+ * that is part of the restart
+ * 2) lock cannot be held during the
+ * smp2p_in_edge_notify() call because clients may do
+ * re-entrant calls into our APIs.
+ *
+ * smp2p_do_ssr_ack() will only do the ack if it is
+ * necessary to handle the race condition exposed by
+ * unlocking the spinlocks.
+ */
+ spin_lock(&in_list[remote_pid].in_item_lock_lhb1);
+ do_restart_ack = smp2p_ssr_ack_needed(remote_pid);
+ spin_unlock(&in_list[remote_pid].in_item_lock_lhb1);
spin_unlock_irqrestore(&out_list[remote_pid].out_item_lock_lha1,
flags);
+
smp2p_in_edge_notify(remote_pid);
+
+ if (do_restart_ack) {
+ spin_lock_irqsave(
+ &out_list[remote_pid].out_item_lock_lha1,
+ flags);
+ spin_lock(&in_list[remote_pid].in_item_lock_lhb1);
+
+ smp2p_do_ssr_ack(remote_pid);
+
+ spin_unlock(&in_list[remote_pid].in_item_lock_lhb1);
+ spin_unlock_irqrestore(
+ &out_list[remote_pid].out_item_lock_lha1,
+ flags);
+ }
} else {
spin_unlock_irqrestore(&out_list[remote_pid].out_item_lock_lha1,
flags);
@@ -1565,6 +1685,8 @@
out_list[rpid].smem_edge_out = NULL;
out_list[rpid].ops_ptr = &version_if[0];
out_list[rpid].smem_edge_state = SMP2P_EDGE_STATE_CLOSED;
+ out_list[rpid].feature_ssr_ack_enabled = false;
+ out_list[rpid].restart_ack = false;
in_list[rpid].smem_edge_in = NULL;
in_list[rpid].item_size = 0;
@@ -1699,6 +1821,8 @@
out_list[i].smem_edge_out = NULL;
out_list[i].smem_edge_state = SMP2P_EDGE_STATE_CLOSED;
out_list[i].ops_ptr = &version_if[0];
+ out_list[i].feature_ssr_ack_enabled = false;
+ out_list[i].restart_ack = false;
spin_lock_init(&in_list[i].in_item_lock_lhb1);
INIT_LIST_HEAD(&in_list[i].list);
diff --git a/arch/arm/mach-msm/smp2p_debug.c b/arch/arm/mach-msm/smp2p_debug.c
index a493cbe..f4ff42d 100644
--- a/arch/arm/mach-msm/smp2p_debug.c
+++ b/arch/arm/mach-msm/smp2p_debug.c
@@ -141,9 +141,11 @@
}
i += scnprintf(buf + i, max - i,
- "Entries Valid/Max: %d/%d",
+ "Entries #/Max: %d/%d Flags: %c%c",
SMP2P_GET_ENT_VALID(item_ptr->valid_total_ent),
- SMP2P_GET_ENT_TOTAL(item_ptr->valid_total_ent)
+ SMP2P_GET_ENT_TOTAL(item_ptr->valid_total_ent),
+ item_ptr->flags & SMP2P_FLAGS_RESTART_ACK_MASK ? 'A' : 'a',
+ item_ptr->flags & SMP2P_FLAGS_RESTART_DONE_MASK ? 'D' : 'd'
);
return i;
diff --git a/arch/arm/mach-msm/smp2p_gpio.c b/arch/arm/mach-msm/smp2p_gpio.c
index 2a85e5f..5f70e0c 100644
--- a/arch/arm/mach-msm/smp2p_gpio.c
+++ b/arch/arm/mach-msm/smp2p_gpio.c
@@ -420,7 +420,7 @@
spin_unlock_irqrestore(&chip->irq_lock, flags);
if (trigger_interrrupt) {
- SMP2P_GPIO(
+ SMP2P_INFO(
"'%s':%d GPIO bit %d virq %d (%s,%s) - edge %s triggering\n",
chip->name, chip->remote_pid, i,
chip->irq_base + i,
diff --git a/arch/arm/mach-msm/smp2p_private.h b/arch/arm/mach-msm/smp2p_private.h
index b9a5cfe..8e0d7a3 100644
--- a/arch/arm/mach-msm/smp2p_private.h
+++ b/arch/arm/mach-msm/smp2p_private.h
@@ -20,8 +20,7 @@
#include "smp2p_private_api.h"
#define SMP2P_MAX_ENTRY 16
-#define SMP2P_LOCAL_VERSION 1
-#define SMP2P_LOCAL_FEATURE 0x0
+#define SMP2P_FEATURE_SSR_ACK 0x1
/* SMEM Item Header Macros */
#define SMP2P_MAGIC 0x504D5324
@@ -37,6 +36,10 @@
#define SMP2P_ENT_TOTAL_BIT 0
#define SMP2P_ENT_VALID_MASK 0xffff0000
#define SMP2P_ENT_VALID_BIT 16
+#define SMP2P_FLAGS_RESTART_DONE_BIT 0
+#define SMP2P_FLAGS_RESTART_DONE_MASK 0x1
+#define SMP2P_FLAGS_RESTART_ACK_BIT 1
+#define SMP2P_FLAGS_RESTART_ACK_MASK 0x2
#define SMP2P_GET_BITS(hdr_val, mask, bit) \
(((hdr_val) & (mask)) >> (bit))
@@ -77,6 +80,20 @@
SMP2P_SET_BITS(hdr, SMP2P_ENT_VALID_MASK, SMP2P_ENT_VALID_BIT,\
entries)
+#define SMP2P_GET_RESTART_DONE(hdr) \
+ SMP2P_GET_BITS(hdr, SMP2P_FLAGS_RESTART_DONE_MASK, \
+ SMP2P_FLAGS_RESTART_DONE_BIT)
+#define SMP2P_SET_RESTART_DONE(hdr, value) \
+ SMP2P_SET_BITS(hdr, SMP2P_FLAGS_RESTART_DONE_MASK, \
+ SMP2P_FLAGS_RESTART_DONE_BIT, value)
+
+#define SMP2P_GET_RESTART_ACK(hdr) \
+ SMP2P_GET_BITS(hdr, SMP2P_FLAGS_RESTART_ACK_MASK, \
+ SMP2P_FLAGS_RESTART_ACK_BIT)
+#define SMP2P_SET_RESTART_ACK(hdr, value) \
+ SMP2P_SET_BITS(hdr, SMP2P_FLAGS_RESTART_ACK_MASK, \
+ SMP2P_FLAGS_RESTART_ACK_BIT, value)
+
/* Loopback Command Macros */
#define SMP2P_RMT_CMD_TYPE_MASK 0x80000000
#define SMP2P_RMT_CMD_TYPE_BIT 31
@@ -162,12 +179,21 @@
SMP2P_EDGE_STATE_FAILED = 0xff,
};
+/**
+ * struct smp2p_smem - SMP2P SMEM Item Header
+ *
+ * @magic: Set to "$SMP" -- used for identification / debug purposes
+ * @feature_version: Feature and version fields
+ * @rem_loc_proc_id: Remote (31:16) and Local (15:0) processor IDs
+ * @valid_total_ent: Valid (31:16) and total (15:0) entries
+ * @flags: Flags (bits 31:2 reserved)
+ */
struct smp2p_smem {
uint32_t magic;
uint32_t feature_version;
uint32_t rem_loc_proc_id;
uint32_t valid_total_ent;
- uint32_t reserved;
+ uint32_t flags;
};
struct smp2p_entry_v1 {
diff --git a/arch/arm/mach-msm/smp2p_test.c b/arch/arm/mach-msm/smp2p_test.c
index 18c9bfd..2f86df4 100644
--- a/arch/arm/mach-msm/smp2p_test.c
+++ b/arch/arm/mach-msm/smp2p_test.c
@@ -16,6 +16,7 @@
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/completion.h>
+#include <mach/subsystem_restart.h>
#include "smp2p_private.h"
#include "smp2p_test_common.h"
@@ -77,7 +78,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
rmp->tx_interrupt();
@@ -161,7 +162,7 @@
SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
@@ -251,7 +252,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(false);
UT_ASSERT_PTR(NULL, ==,
@@ -369,7 +370,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 1);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create test entry and attach loopback server */
@@ -794,7 +795,7 @@
rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create Max Entries in the remote mock object */
@@ -892,7 +893,7 @@
rmp->remote_item.header.valid_total_ent, 1);
SMP2P_SET_ENT_VALID(
rmp->remote_item.header.valid_total_ent, 0);
- rmp->remote_item.header.reserved = 0x0;
+ rmp->remote_item.header.flags = 0x0;
msm_smp2p_set_remote_mock_exists(true);
/* Create an Entry in the remote mock object */
@@ -953,6 +954,217 @@
}
}
+/**
+ * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ */
+static void smp2p_ut_local_ssr_ack(struct seq_file *s)
+{
+ int failed = 0;
+ struct msm_smp2p_remote_mock *rmp = NULL;
+ int ret;
+
+ seq_printf(s, "Running %s\n", __func__);
+ do {
+ struct smp2p_smem *rhdr;
+ struct smp2p_smem *lhdr;
+ int negotiation_state;
+
+ /* initialize v1 without SMP2P_FEATURE_SSR_ACK enabled */
+ ret = smp2p_reset_mock_edge();
+ UT_ASSERT_INT(ret, ==, 0);
+ rmp = msm_smp2p_get_remote_mock();
+ UT_ASSERT_PTR(rmp, !=, NULL);
+ rhdr = &rmp->remote_item.header;
+
+ rmp->rx_interrupt_count = 0;
+ memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
+ rhdr->magic = SMP2P_MAGIC;
+ SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
+ SMP2P_REMOTE_MOCK_PROC);
+ SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
+ SMP2P_SET_VERSION(rhdr->feature_version, 1);
+ SMP2P_SET_FEATURES(rhdr->feature_version, 0);
+ SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
+ SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
+ rhdr->flags = 0x0;
+ msm_smp2p_set_remote_mock_exists(true);
+ rmp->tx_interrupt();
+
+ /* verify edge is open */
+ lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
+ &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ /* verify no response to ack feature */
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0);
+
+ /* initialize v1 with SMP2P_FEATURE_SSR_ACK enabled */
+ ret = smp2p_reset_mock_edge();
+ UT_ASSERT_INT(ret, ==, 0);
+ rmp = msm_smp2p_get_remote_mock();
+ UT_ASSERT_PTR(rmp, !=, NULL);
+ rhdr = &rmp->remote_item.header;
+
+ rmp->rx_interrupt_count = 0;
+ memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
+ rhdr->magic = SMP2P_MAGIC;
+ SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
+ SMP2P_REMOTE_MOCK_PROC);
+ SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
+ SMP2P_SET_VERSION(rhdr->feature_version, 1);
+ SMP2P_SET_FEATURES(rhdr->feature_version,
+ SMP2P_FEATURE_SSR_ACK);
+ SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
+ SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
+ rmp->rx_interrupt_count = 0;
+ rhdr->flags = 0x0;
+ msm_smp2p_set_remote_mock_exists(true);
+ rmp->tx_interrupt();
+
+ /* verify edge is open */
+ lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
+ &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ /* verify response to ack feature */
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(1, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ rmp->rx_interrupt_count = 0;
+ SMP2P_SET_RESTART_DONE(rhdr->flags, 0);
+ rmp->tx_interrupt();
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);
+
+ seq_puts(s, "\tOK\n");
+ } while (0);
+
+ if (failed) {
+ pr_err("%s: Failed\n", __func__);
+ seq_puts(s, "\tFailed\n");
+ }
+}
+
+/**
+ * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ * @rpid: Remote processor ID
+ * @int_cfg: Interrupt config
+ */
+static void smp2p_ut_remotesubsys_ssr_ack(struct seq_file *s, uint32_t rpid,
+ struct smp2p_interrupt_config *int_cfg)
+{
+ int failed = 0;
+
+ seq_printf(s, "Running %s\n", __func__);
+ do {
+ struct smp2p_smem *rhdr;
+ struct smp2p_smem *lhdr;
+ int negotiation_state;
+ bool ssr_ack_enabled;
+ uint32_t ssr_done_start;
+
+ lhdr = smp2p_get_out_item(rpid, &negotiation_state);
+ UT_ASSERT_PTR(NULL, !=, lhdr);
+ UT_ASSERT_INT(SMP2P_EDGE_STATE_OPENED, ==, negotiation_state);
+
+ rhdr = smp2p_get_in_item(rpid);
+ UT_ASSERT_PTR(NULL, !=, rhdr);
+
+ /* get initial state of SSR flags */
+ if (SMP2P_GET_FEATURES(rhdr->feature_version)
+ & SMP2P_FEATURE_SSR_ACK)
+ ssr_ack_enabled = true;
+ else
+ ssr_ack_enabled = false;
+
+ ssr_done_start = SMP2P_GET_RESTART_DONE(rhdr->flags);
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+
+ /* trigger restart */
+ seq_printf(s, "Restarting '%s'\n", int_cfg->name);
+ subsystem_restart(int_cfg->name);
+ msleep(10*1000);
+
+ /* verify ack signaling */
+ if (ssr_ack_enabled) {
+ ssr_done_start ^= 1;
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+ UT_ASSERT_INT(ssr_done_start, ==,
+ SMP2P_GET_RESTART_DONE(rhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(lhdr->flags));
+ seq_puts(s, "\tSSR ACK Enabled and Toggled\n");
+ } else {
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(lhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_ACK(lhdr->flags));
+
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_DONE(rhdr->flags));
+ UT_ASSERT_INT(0, ==,
+ SMP2P_GET_RESTART_ACK(rhdr->flags));
+ seq_puts(s, "\tSSR ACK Disabled\n");
+ }
+
+ seq_puts(s, "\tOK\n");
+ } while (0);
+
+ if (failed) {
+ pr_err("%s: Failed\n", __func__);
+ seq_puts(s, "\tFailed\n");
+ }
+}
+
+/**
+ * smp2p_ut_remote_ssr_ack - Verify SSR Done/ACK Feature
+ *
+ * @s: pointer to output file
+ *
+ * Triggers SSR for each subsystem.
+ */
+static void smp2p_ut_remote_ssr_ack(struct seq_file *s)
+{
+ struct smp2p_interrupt_config *int_cfg;
+ int pid;
+
+ int_cfg = smp2p_get_interrupt_config();
+ if (!int_cfg) {
+ seq_puts(s,
+ "Remote processor config unavailable\n");
+ return;
+ }
+
+ for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) {
+ if (!int_cfg[pid].is_configured)
+ continue;
+
+ msm_smp2p_deinit_rmt_lpb_proc(pid);
+ smp2p_ut_remotesubsys_ssr_ack(s, pid, &int_cfg[pid]);
+ msm_smp2p_init_rmt_lpb_proc(pid);
+ }
+}
+
static struct dentry *dent;
static int debugfs_show(struct seq_file *s, void *data)
@@ -1019,6 +1231,10 @@
smp2p_ut_remote_out_max_entries);
smp2p_debug_create("ut_local_in_multiple",
smp2p_ut_local_in_multiple);
+ smp2p_debug_create("ut_local_ssr_ack",
+ smp2p_ut_local_ssr_ack);
+ smp2p_debug_create("ut_remote_ssr_ack",
+ smp2p_ut_remote_ssr_ack);
return 0;
}
diff --git a/drivers/bif/bif-core.c b/drivers/bif/bif-core.c
index e11e6ba4..7bc9af2 100644
--- a/drivers/bif/bif-core.c
+++ b/drivers/bif/bif-core.c
@@ -2827,6 +2827,7 @@
struct bif_ctrl_dev *bdev = ERR_PTR(-EINVAL);
struct bif_slave_dev *sdev;
bool battery_present = false;
+ bool slaves_present = false;
int rc, rid_ohm;
if (!bif_desc) {
@@ -2901,12 +2902,21 @@
list_for_each_entry(sdev, &bif_sdev_list, list) {
if (sdev->present) {
battery_present = true;
+ slaves_present = true;
break;
}
}
BLOCKING_INIT_NOTIFIER_HEAD(&bdev->bus_change_notifier);
+ /* Disable the BIF bus master if no slaves are found. */
+ if (!slaves_present) {
+ rc = bdev->desc->ops->set_bus_state(bdev,
+ BIF_BUS_STATE_MASTER_DISABLED);
+ if (rc < 0)
+ pr_err("Could not disble BIF master, rc=%d\n", rc);
+ }
+
if (battery_present) {
bdev->battery_present = true;
rc = blocking_notifier_call_chain(&bdev->bus_change_notifier,
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index 9d0abd2..19a560a 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -1162,6 +1162,7 @@
+ QPNP_BSI_POWER_UP_LOW_DELAY_US);
break;
case BIF_BUS_STATE_POWER_DOWN:
+ case BIF_BUS_STATE_MASTER_DISABLED:
msleep(QPNP_BSI_MAX_SLAVE_POWER_UP_DELAY_MS);
break;
}
@@ -1180,13 +1181,34 @@
{
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
int rc = 0;
+ u8 reg;
if (state == chip->state)
return 0;
+ if (chip->state == BIF_BUS_STATE_MASTER_DISABLED) {
+ /*
+ * Enable the BSI peripheral when transitioning from a disabled
+ * bus state to any of the active bus states so that BIF
+ * transactions can take place.
+ */
+ reg = QPNP_BSI_ENABLE;
+ rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
+ if (rc) {
+ dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
switch (state) {
case BIF_BUS_STATE_MASTER_DISABLED:
- pr_info("master disable not yet supported.\n");
+ /* Disable the BSI peripheral. */
+ reg = QPNP_BSI_DISABLE;
+ rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
+ if (rc)
+ dev_err(&chip->spmi_dev->dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
+ __func__, rc);
break;
case BIF_BUS_STATE_POWER_DOWN:
rc = qpnp_bsi_bus_transaction(bdev, BIF_TRANS_BC, BIF_CMD_PDWN);
@@ -1624,7 +1646,7 @@
struct device *dev = &spmi->dev;
struct qpnp_bsi_chip *chip;
int rc;
- u8 type[2], reg;
+ u8 type[2];
if (!spmi->dev.of_node) {
dev_err(dev, "%s: device node missing\n", __func__);
@@ -1655,7 +1677,7 @@
chip->spmi_dev = spmi;
chip->bdesc.ops = &qpnp_bsi_ops;
- chip->state = BIF_BUS_STATE_POWER_DOWN;
+ chip->state = BIF_BUS_STATE_MASTER_DISABLED;
chip->com_mode = QPNP_BSI_COM_MODE_IRQ;
rc = qpnp_bsi_read(chip, QPNP_BSI_REG_TYPE, type, 2);
@@ -1691,15 +1713,6 @@
goto cleanup_irqs;
}
- /* Enable the BSI module. */
- reg = QPNP_BSI_ENABLE;
- rc = qpnp_bsi_write(chip, QPNP_BSI_REG_ENABLE, ®, 1);
- if (rc) {
- dev_err(dev, "%s: qpnp_bsi_write() failed, rc=%d\n",
- __func__, rc);
- goto cleanup_irqs;
- }
-
chip->bdev = bif_ctrl_register(&chip->bdesc, dev, chip,
spmi->dev.of_node);
if (IS_ERR(chip->bdev)) {
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index dcaa4e1..cdf711c 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -805,6 +805,8 @@
int i;
unsigned int ttbr0, tlbiall, tlbstatus, tlbsync, mmu_ctrl;
+ cmds += adreno_add_idle_cmds(adreno_dev, cmds);
+
for (i = 0; i < num_iommu_units; i++) {
ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu,
i, KGSL_IOMMU_CONTEXT_USER);
@@ -892,8 +894,14 @@
KGSL_IOMMU_CTX_TLBSTATUS) >> 2;
cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0,
KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF);
+ /* release all commands with wait_for_me */
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
+ *cmds++ = 0;
}
}
+
+ cmds += adreno_add_idle_cmds(adreno_dev, cmds);
+
return cmds - cmds_orig;
}
@@ -3107,6 +3115,7 @@
adreno_dev->fast_hang_detect = 1;
kgsl_pwrscale_enable(device);
} else {
+ kgsl_pwrctrl_wake(device);
device->pwrctrl.ctrl_flags = KGSL_PWR_ON;
adreno_dev->fast_hang_detect = 0;
kgsl_pwrscale_disable(device);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9a070a6..6507852 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -658,9 +658,7 @@
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmds++ = 0;
- if ((adreno_dev->gpurev == ADRENO_REV_A305) ||
- (adreno_dev->gpurev == ADRENO_REV_A305C) ||
- (adreno_dev->gpurev == ADRENO_REV_A320)) {
+ if (adreno_is_a3xx(adreno_dev)) {
*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
*cmds++ = 0;
}
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/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index 8fc1753..7f8a6b1 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -159,11 +159,13 @@
(priv->bin.total_time < FLOOR))
return;
- /* If there is an extended block of busy processing,
- * increase frequency. Otherwise run the normal algorithm.
+ /* If there is an extended block of busy processing, set
+ * frequency to turbo. Otherwise run the normal algorithm.
*/
if (priv->bin.busy_time > CEILING) {
- val = -1;
+ val = 0;
+ kgsl_pwrctrl_pwrlevel_change(device,
+ KGSL_PWRLEVEL_TURBO);
} else if (priv->idle_dcvs) {
idle = priv->bin.total_time - priv->bin.busy_time;
idle = (idle > 0) ? idle : 0;
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 1537866..642975d 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -734,7 +734,6 @@
idev->name = "MPU3050";
idev->id.bustype = BUS_I2C;
- idev->dev.parent = &client->dev;
idev->open = mpu3050_input_open;
idev->close = mpu3050_input_close;
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 f8ab5f4..aec655c 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);
@@ -820,6 +822,32 @@
return retval;
}
+/**
+ * synaptics_rmi4_release_all()
+ *
+ * Called by synaptics_rmi4_suspend()
+ *
+ * Release all touch data during the touch device switch to suspend state.
+ */
+
+static void synaptics_rmi4_release_all(struct synaptics_rmi4_data *rmi4_data)
+{
+ int finger;
+ int max_num_fingers = rmi4_data->num_of_fingers;
+
+ for (finger = 0; finger < max_num_fingers; finger++) {
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, 0);
+ }
+
+ input_report_key(rmi4_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 0);
+
+ input_sync(rmi4_data->input_dev);
+}
+
/**
* synaptics_rmi4_f11_abs_report()
*
@@ -1027,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,
@@ -1306,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)
{
@@ -1323,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",
@@ -1793,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",
@@ -2232,7 +2308,7 @@
return retval;
}
- msleep(RESET_DELAY);
+ msleep(rmi4_data->board->reset_delay);
return retval;
};
@@ -2577,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);
@@ -2750,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
@@ -3299,6 +3395,8 @@
synaptics_rmi4_sensor_sleep(rmi4_data);
}
+ synaptics_rmi4_release_all(rmi4_data);
+
retval = synaptics_rmi4_regulator_lpm(rmi4_data, true);
if (retval < 0) {
dev_err(dev, "failed to enter low power mode\n");
@@ -3363,17 +3461,6 @@
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
- if (rmi4_data->board->power_down_enable ||
- rmi4_data->board->disable_gpios) {
- retval = synaptics_rmi4_reset_device(rmi4_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to issue reset command, " \
- "rc = %d\n", __func__, retval);
- return retval;
- }
- }
-
rmi4_data->suspended = false;
return 0;
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 5a405be..bf59d03 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -23,6 +23,7 @@
#include <linux/spmi.h>
#include <linux/qpnp/pwm.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
@@ -43,6 +44,7 @@
#define WLED_HIGH_POLE_CAP_REG(base) (base + 0x58)
#define WLED_CURR_SINK_MASK 0xE0
#define WLED_CURR_SINK_SHFT 0x05
+#define WLED_DISABLE_ALL_SINKS 0x00
#define WLED_SWITCH_FREQ_MASK 0x0F
#define WLED_OVP_VAL_MASK 0x03
#define WLED_OVP_VAL_BIT_SHFT 0x00
@@ -58,8 +60,10 @@
#define WLED_CTL_DLY_STEP 200
#define WLED_CTL_DLY_MAX 1400
#define WLED_MAX_CURR 25
+#define WLED_NO_CURRENT 0x00
+#define WLED_OVP_DELAY 1000
#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
@@ -73,6 +77,9 @@
#define WLED_SYNC_VAL 0x07
#define WLED_SYNC_RESET_VAL 0x00
+#define PMIC_VER_8026 0x04
+#define PMIC_VERSION_REG 0x0105
+
#define WLED_DEFAULT_STRINGS 0x01
#define WLED_DEFAULT_OVP_VAL 0x02
#define WLED_BOOST_LIM_DEFAULT 0x03
@@ -173,7 +180,8 @@
#define LED_MPP_EN_CTRL(base) (base + 0x46)
#define LED_MPP_SINK_CTRL(base) (base + 0x4C)
-#define LED_MPP_CURRENT_DEFAULT 5
+#define LED_MPP_CURRENT_MIN 5
+#define LED_MPP_CURRENT_MAX 40
#define LED_MPP_VIN_CTRL_DEFAULT 0
#define LED_MPP_CURRENT_PER_SETTING 5
#define LED_MPP_SOURCE_SEL_DEFAULT LED_MPP_MODE_ENABLE
@@ -336,6 +344,7 @@
u8 ctrl_delay_us;
u8 switch_freq;
u8 op_fdbck;
+ u8 pmic_version;
bool dig_mod_gen_en;
bool cs_out_en;
};
@@ -510,16 +519,86 @@
pr_debug("===== %s LED register dump end =====\n", led->cdev.name);
}
+static int qpnp_wled_sync(struct qpnp_led_data *led)
+{
+ int rc;
+ u8 val;
+
+ /* sync */
+ val = WLED_SYNC_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set sync reg failed(%d)\n", rc);
+ return rc;
+ }
+
+ val = WLED_SYNC_RESET_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED reset sync reg failed(%d)\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
static int qpnp_wled_set(struct qpnp_led_data *led)
{
int rc, duty, level;
- u8 val, i, num_wled_strings;
+ u8 val, i, num_wled_strings, sink_val;
+
+ num_wled_strings = led->wled_cfg->num_strings;
level = led->cdev.brightness;
if (level > WLED_MAX_LEVEL)
level = WLED_MAX_LEVEL;
if (level == 0) {
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led,
+ WLED_FULL_SCALE_REG(led->base, i),
+ WLED_MAX_CURR_MASK, WLED_NO_CURRENT);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Write max current failure (%d)\n",
+ rc);
+ return rc;
+ }
+ }
+
+ rc = qpnp_wled_sync(led);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED sync failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_CURR_SINK_REG(led->base),
+ &sink_val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED read sink reg failed(%d)\n", rc);
+ return rc;
+ }
+
+ if (led->wled_cfg->pmic_version == PMIC_VER_8026) {
+ val = WLED_DISABLE_ALL_SINKS;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid,
+ WLED_CURR_SINK_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write sink reg failed(%d)\n", rc);
+ return rc;
+ }
+
+ usleep(WLED_OVP_DELAY);
+ }
+
val = WLED_BOOST_OFF;
rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
@@ -529,6 +608,35 @@
"WLED write ctrl reg failed(%d)\n", rc);
return rc;
}
+
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led,
+ WLED_FULL_SCALE_REG(led->base, i),
+ WLED_MAX_CURR_MASK, led->max_current);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Write max current failure (%d)\n",
+ rc);
+ return rc;
+ }
+ }
+
+ rc = qpnp_wled_sync(led);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED sync failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_CURR_SINK_REG(led->base),
+ &sink_val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write sink reg failed(%d)\n", rc);
+ return rc;
+ }
+
} else {
val = WLED_BOOST_ON;
rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
@@ -543,8 +651,6 @@
duty = (WLED_MAX_DUTY_CYCLE * level) / WLED_MAX_LEVEL;
- num_wled_strings = led->wled_cfg->num_strings;
-
/* program brightness control registers */
for (i = 0; i < num_wled_strings; i++) {
rc = qpnp_led_masked_write(led,
@@ -566,22 +672,9 @@
}
}
- /* sync */
- val = WLED_SYNC_VAL;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- WLED_SYNC_REG(led->base), &val, 1);
+ rc = qpnp_wled_sync(led);
if (rc) {
- dev_err(&led->spmi_dev->dev,
- "WLED set sync reg failed(%d)\n", rc);
- return rc;
- }
-
- val = WLED_SYNC_RESET_VAL;
- rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
- WLED_SYNC_REG(led->base), &val, 1);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "WLED reset sync reg failed(%d)\n", rc);
+ dev_err(&led->spmi_dev->dev, "WLED sync failed(%d)\n", rc);
return rc;
}
return 0;
@@ -625,6 +718,21 @@
if (led->mpp_cfg->pwm_mode != MANUAL_MODE)
pwm_enable(led->mpp_cfg->pwm_cfg->pwm_dev);
+ else {
+ if (led->cdev.brightness < LED_MPP_CURRENT_MIN)
+ led->cdev.brightness = LED_MPP_CURRENT_MIN;
+
+ val = (led->cdev.brightness / LED_MPP_CURRENT_MIN) - 1;
+
+ rc = qpnp_led_masked_write(led,
+ LED_MPP_SINK_CTRL(led->base),
+ LED_MPP_SINK_MASK, val);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Failed to write sink control reg\n");
+ return rc;
+ }
+ }
val = (led->mpp_cfg->source_sel & LED_MPP_SRC_MASK) |
(led->mpp_cfg->mode_ctrl & LED_MPP_MODE_CTRL_MASK);
@@ -1351,7 +1459,10 @@
led->cdev.max_brightness = RGB_MAX_LEVEL;
break;
case QPNP_ID_LED_MPP:
- led->cdev.max_brightness = MPP_MAX_LEVEL;
+ if (led->mpp_cfg->pwm_mode == MANUAL_MODE)
+ led->cdev.max_brightness = led->max_current;
+ else
+ led->cdev.max_brightness = MPP_MAX_LEVEL;
break;
case QPNP_ID_KPDBL:
led->cdev.max_brightness = KPDBL_MAX_LEVEL;
@@ -2332,6 +2443,14 @@
{
int rc, val;
+
+ if (led->max_current < LED_MPP_CURRENT_MIN ||
+ led->max_current > LED_MPP_CURRENT_MAX) {
+ dev_err(&led->spmi_dev->dev,
+ "max current for mpp is not valid\n");
+ return -EINVAL;
+ }
+
val = (led->mpp_cfg->current_setting / LED_MPP_CURRENT_PER_SETTING) - 1;
if (val < 0)
@@ -2349,7 +2468,7 @@
LED_MPP_SINK_MASK, val);
if (rc) {
dev_err(&led->spmi_dev->dev,
- "Failed to write led enable reg\n");
+ "Failed to write sink control reg\n");
return rc;
}
@@ -2462,6 +2581,13 @@
return -ENOMEM;
}
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ PMIC_VERSION_REG, &led->wled_cfg->pmic_version, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read pmic ver, rc(%d)\n", rc);
+ }
+
led->wled_cfg->num_strings = WLED_DEFAULT_STRINGS;
rc = of_property_read_u32(node, "qcom,num-strings", &val);
if (!rc)
@@ -2954,11 +3080,16 @@
return -ENOMEM;
}
- led->mpp_cfg->current_setting = LED_MPP_CURRENT_DEFAULT;
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MIN;
rc = of_property_read_u32(node, "qcom,current-setting", &val);
- if (!rc)
- led->mpp_cfg->current_setting = (u8) val;
- else if (rc != -EINVAL)
+ if (!rc) {
+ if (led->mpp_cfg->current_setting < LED_MPP_CURRENT_MIN)
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MIN;
+ else if (led->mpp_cfg->current_setting > LED_MPP_CURRENT_MAX)
+ led->mpp_cfg->current_setting = LED_MPP_CURRENT_MAX;
+ else
+ led->mpp_cfg->current_setting = (u8) val;
+ } else if (rc != -EINVAL)
return rc;
led->mpp_cfg->source_sel = LED_MPP_SOURCE_SEL_DEFAULT;
diff --git a/drivers/media/platform/msm/camera_v1/server/msm_cam_server.c b/drivers/media/platform/msm/camera_v1/server/msm_cam_server.c
index 78d15d9..d9fba33 100644
--- a/drivers/media/platform/msm/camera_v1/server/msm_cam_server.c
+++ b/drivers/media/platform/msm/camera_v1/server/msm_cam_server.c
@@ -2777,40 +2777,6 @@
return rc;
}
-static int msm_mmap_config(struct file *fp, struct vm_area_struct *vma)
-{
- struct msm_cam_config_dev *config_cam = fp->private_data;
- int rc = 0;
- int phyaddr;
- int retval;
- unsigned long size;
-
- D("%s: phy_addr=0x%x", __func__, config_cam->mem_map.cookie);
- phyaddr = (int)config_cam->mem_map.cookie;
- if (!phyaddr) {
- pr_err("%s: no physical memory to map", __func__);
- return -EFAULT;
- }
- memset(&config_cam->mem_map, 0,
- sizeof(struct msm_mem_map_info));
- size = vma->vm_end - vma->vm_start;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- retval = remap_pfn_range(vma, vma->vm_start,
- phyaddr >> PAGE_SHIFT,
- size, vma->vm_page_prot);
- if (retval) {
- pr_err("%s: remap failed, rc = %d",
- __func__, retval);
- rc = -ENOMEM;
- goto end;
- }
- D("%s: phy_addr=0x%x: %08lx-%08lx, pgoff %08lx\n",
- __func__, (uint32_t)phyaddr,
- vma->vm_start, vma->vm_end, vma->vm_pgoff);
-end:
- return rc;
-}
-
static int msm_open_config(struct inode *inode, struct file *fp)
{
int rc;
@@ -3081,12 +3047,6 @@
rc = msm_v4l2_evt_notify(config_cam->p_mctl, cmd, arg);
break;
- case MSM_CAM_IOCTL_SET_MEM_MAP_INFO:
- if (copy_from_user(&config_cam->mem_map, (void __user *)arg,
- sizeof(struct msm_mem_map_info)))
- rc = -EINVAL;
- break;
-
case MSM_CAM_IOCTL_SET_MCTL_SDEV:{
struct msm_mctl_set_sdev_data set_data;
if (copy_from_user(&set_data, (void __user *)arg,
@@ -3148,7 +3108,6 @@
.open = msm_open_config,
.poll = msm_poll_config,
.unlocked_ioctl = msm_ioctl_config,
- .mmap = msm_mmap_config,
.release = msm_close_config,
};
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/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a4cf18e..5e056be 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -4122,6 +4122,7 @@
radio = video_get_drvdata(video_devdata(file));
strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+ capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
radio->g_cap = capability;
return 0;
}
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/regulator/core.c b/drivers/regulator/core.c
index 0ebb944..450c4fb 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3357,14 +3357,6 @@
ret = set_supply(rdev, r);
if (ret < 0)
goto scrub;
-
- /* Enable supply if rail is enabled */
- if (rdev->desc->ops->is_enabled &&
- rdev->desc->ops->is_enabled(rdev)) {
- ret = regulator_enable(rdev->supply);
- if (ret < 0)
- goto scrub;
- }
}
/* add consumers devices */
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 3abc3b9..b7bf74e 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -33,6 +33,7 @@
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/security.h>
#include "binder.h"
@@ -1488,6 +1489,10 @@
return_error = BR_DEAD_REPLY;
goto err_dead_binder;
}
+ if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) {
+ return_error = BR_FAILED_REPLY;
+ goto err_invalid_target_handle;
+ }
if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
struct binder_transaction *tmp;
tmp = thread->transaction_stack;
@@ -1633,6 +1638,10 @@
fp->cookie, node->cookie);
goto err_binder_get_ref_for_node_failed;
}
+ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_for_node_failed;
+ }
ref = binder_get_ref_for_node(target_proc, node);
if (ref == NULL) {
return_error = BR_FAILED_REPLY;
@@ -1662,6 +1671,10 @@
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_failed;
}
+ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_failed;
+ }
if (ref->node->proc == target_proc) {
if (fp->type == BINDER_TYPE_HANDLE)
fp->type = BINDER_TYPE_BINDER;
@@ -1715,6 +1728,11 @@
return_error = BR_FAILED_REPLY;
goto err_fget_failed;
}
+ if (security_binder_transfer_file(proc->tsk, target_proc->tsk, file) < 0) {
+ fput(file);
+ return_error = BR_FAILED_REPLY;
+ goto err_get_unused_fd_failed;
+ }
target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
if (target_fd < 0) {
fput(file);
@@ -2748,6 +2766,9 @@
ret = -EBUSY;
goto err;
}
+ ret = security_binder_set_context_mgr(proc->tsk);
+ if (ret < 0)
+ goto err;
if (binder_context_mgr_uid != -1) {
if (binder_context_mgr_uid != current->cred->euid) {
binder_debug(BINDER_DEBUG_TOP_ERRORS,
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 94b6eda..8eb5573 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -81,20 +81,31 @@
}
/**
- * n_tty_set__room - receive space
+ * n_tty_set_room - receive space
* @tty: terminal
*
- * Called by the driver to find out how much data it is
- * permitted to feed to the line discipline without any being lost
- * and thus to manage flow control. Not serialized. Answers for the
- * "instant".
+ * Sets tty->receive_room to reflect the currently available space
+ * in the input buffer, and re-schedules the flip buffer work if space
+ * just became available.
+ *
+ * Locks: Concurrent update is protected with read_lock
*/
static void n_tty_set_room(struct tty_struct *tty)
{
- /* tty->read_cnt is not read locked ? */
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ int left;
int old_left;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->read_lock, flags);
+
+ if (I_PARMRK(tty)) {
+ /* Multiply read_cnt by 3, since each byte might take up to
+ * three times as many spaces when PARMRK is set (depending on
+ * its flags, e.g. parity error). */
+ left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ } else
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
/*
* If we are doing input canonicalization, and there are no
@@ -107,6 +118,8 @@
old_left = tty->receive_room;
tty->receive_room = left;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+
/* Did this open up the receive buffer? We may need to flip */
if (left && !old_left)
schedule_work(&tty->buf.work);
@@ -1811,7 +1824,6 @@
retval = -ERESTARTSYS;
break;
}
- /* FIXME: does n_tty_set_room need locking ? */
n_tty_set_room(tty);
timeout = schedule_timeout(timeout);
BUG_ON(!tty->read_buf);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 81bc0f0..24b18cb 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -463,8 +463,6 @@
int count;
char *char_buf;
unsigned char *flag_buf;
- unsigned int left = 0;
- unsigned int max_space;
count = head->commit - head->read;
if (!count) {
@@ -475,32 +473,10 @@
continue;
}
- /* update receive room */
- spin_lock(&tty->read_lock);
- if (tty->update_room_in_ldisc) {
- if ((tty->read_cnt == N_TTY_BUF_SIZE - 1) &&
- (tty->receive_room ==
- N_TTY_BUF_SIZE - 1))
- tty->rr_bug++;
- left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
- }
- spin_unlock(&tty->read_lock);
-
if (!tty->receive_room)
break;
-
- if (tty->update_room_in_ldisc && !left) {
- schedule_work(&tty->buf.work);
- break;
- }
-
- if (tty->update_room_in_ldisc)
- max_space = min(left, tty->receive_room);
- else
- max_space = tty->receive_room;
-
- if (count > max_space)
- count = max_space;
+ if (count > tty->receive_room)
+ count = tty->receive_room;
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
head->read += count;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f43affb..60d7119 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -201,6 +201,7 @@
bool lpm_irq_seen;
struct delayed_work resume_work;
struct work_struct restart_usb_work;
+ struct work_struct usb_block_reset_work;
struct dwc3_charger charger;
struct usb_phy *otg_xceiv;
struct delayed_work chg_work;
@@ -1495,6 +1496,11 @@
case DWC3_CONTROLLER_ERROR_EVENT:
dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n");
dwc3_msm_dump_phy_info(mdwc);
+ /*
+ * schedule work for doing block reset for recovery from erratic
+ * error event.
+ */
+ queue_work(system_nrt_wq, &mdwc->usb_block_reset_work);
break;
case DWC3_CONTROLLER_RESET_EVENT:
dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n");
@@ -1537,6 +1543,16 @@
dwc3_msm_dbm_soft_reset(mdwc, 0);
}
+static void dwc3_block_reset_usb_work(struct work_struct *w)
+{
+ struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
+ usb_block_reset_work);
+
+ dev_dbg(mdwc->dev, "%s\n", __func__);
+
+ dwc3_msm_block_reset(&mdwc->ext_xceiv, true);
+}
+
static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
{
u32 chg_ctrl;
@@ -2692,6 +2708,7 @@
INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work);
INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work);
INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
+ INIT_WORK(&mdwc->usb_block_reset_work, dwc3_block_reset_usb_work);
INIT_WORK(&mdwc->id_work, dwc3_id_work);
INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work);
init_completion(&mdwc->ext_chg_wait);
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index e912e86..5348eb5 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -24,6 +24,7 @@
#include "io.h"
#include "xhci.h"
+#define VBUS_REG_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
#define MAX_INVALID_CHRGR_RETRY 3
static int max_chgr_retry_count = MAX_INVALID_CHRGR_RETRY;
module_param(max_chgr_retry_count, int, S_IRUGO | S_IWUSR);
@@ -336,13 +337,13 @@
dev_dbg(otg->phy->dev, "%s: set gadget %s\n",
__func__, gadget->name);
otg->gadget = gadget;
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
} else {
if (otg->phy->state == OTG_STATE_B_PERIPHERAL) {
dwc3_otg_start_peripheral(otg, 0);
otg->gadget = NULL;
otg->phy->state = OTG_STATE_UNDEFINED;
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
} else {
otg->gadget = NULL;
}
@@ -367,7 +368,7 @@
* STOP chg_det as part of !BSV handling would reset the chg_det flags
*/
if (test_bit(B_SESS_VLD, &dotg->inputs))
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
}
/**
@@ -406,7 +407,7 @@
/* Flush processing any pending events before handling new ones */
if (init)
- flush_work(&dotg->sm_work);
+ flush_delayed_work(&dotg->sm_work);
if (event == DWC3_EVENT_PHY_RESUME) {
if (!pm_runtime_status_suspended(phy->dev)) {
@@ -453,15 +454,16 @@
if (!init) {
init = true;
- if (!work_busy(&dotg->sm_work))
- schedule_work(&dotg->sm_work);
+ if (!work_busy(&dotg->sm_work.work))
+ queue_delayed_work(system_nrt_wq,
+ &dotg->sm_work, 0);
complete(&dotg->dwc3_xcvr_vbus_init);
dev_dbg(phy->dev, "XCVR: BSV init complete\n");
return;
}
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
}
}
@@ -610,7 +612,7 @@
handled_irqs |= DWC3_OEVTEN_OTGBDEVVBUSCHNGEVNT;
}
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
ret = IRQ_HANDLED;
@@ -671,10 +673,12 @@
*/
static void dwc3_otg_sm_work(struct work_struct *w)
{
- struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work);
+ struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work.work);
struct usb_phy *phy = dotg->otg.phy;
struct dwc3_charger *charger = dotg->charger;
bool work = 0;
+ int ret = 0;
+ int delay = 0;
pm_runtime_resume(phy->dev);
dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));
@@ -817,10 +821,23 @@
if (test_bit(ID, &dotg->inputs)) {
dev_dbg(phy->dev, "id\n");
phy->state = OTG_STATE_B_IDLE;
+ dotg->vbus_retry_count = 0;
work = 1;
} else {
phy->state = OTG_STATE_A_HOST;
- if (dwc3_otg_start_host(&dotg->otg, 1)) {
+ ret = dwc3_otg_start_host(&dotg->otg, 1);
+ if ((ret == -EPROBE_DEFER) &&
+ dotg->vbus_retry_count < 3) {
+ /*
+ * Get regulator failed as regulator driver is
+ * not up yet. Will try to start host after 1sec
+ */
+ phy->state = OTG_STATE_A_IDLE;
+ dev_dbg(phy->dev, "Unable to get vbus regulator. Retrying...\n");
+ delay = VBUS_REG_CHECK_DELAY;
+ work = 1;
+ dotg->vbus_retry_count++;
+ } else if (ret) {
/*
* Probably set_host was not called yet.
* We will re-try as soon as it will be called
@@ -839,6 +856,7 @@
dev_dbg(phy->dev, "id\n");
dwc3_otg_start_host(&dotg->otg, 0);
phy->state = OTG_STATE_B_IDLE;
+ dotg->vbus_retry_count = 0;
work = 1;
}
break;
@@ -849,7 +867,7 @@
}
if (work)
- schedule_work(&dotg->sm_work);
+ queue_delayed_work(system_nrt_wq, &dotg->sm_work, delay);
}
@@ -973,7 +991,7 @@
dotg->otg.phy->state = OTG_STATE_UNDEFINED;
init_completion(&dotg->dwc3_xcvr_vbus_init);
- INIT_WORK(&dotg->sm_work, dwc3_otg_sm_work);
+ INIT_DELAYED_WORK(&dotg->sm_work, dwc3_otg_sm_work);
ret = request_irq(dotg->irq, dwc3_otg_interrupt, IRQF_SHARED,
"dwc3_otg", dotg);
@@ -988,7 +1006,7 @@
return 0;
err3:
- cancel_work_sync(&dotg->sm_work);
+ cancel_delayed_work_sync(&dotg->sm_work);
usb_set_transceiver(NULL);
err2:
kfree(dotg->otg.phy);
@@ -1013,7 +1031,7 @@
if (dotg) {
if (dotg->charger)
dotg->charger->start_detection(dotg->charger, false);
- cancel_work_sync(&dotg->sm_work);
+ cancel_delayed_work_sync(&dotg->sm_work);
usb_set_transceiver(NULL);
pm_runtime_put(dwc->dev);
free_irq(dotg->irq, dotg);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index 7adf874..3a75b0a 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -41,7 +41,7 @@
struct dwc3 *dwc;
void __iomem *regs;
struct regulator *vbus_otg;
- struct work_struct sm_work;
+ struct delayed_work sm_work;
struct dwc3_charger *charger;
struct dwc3_ext_xceiv *ext_xceiv;
#define ID 0
@@ -51,6 +51,7 @@
struct completion dwc3_xcvr_vbus_init;
int host_bus_suspend;
int charger_retry_count;
+ int vbus_retry_count;
};
/**
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index aaa22f3..8fa4774 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2656,9 +2656,6 @@
dbg_print_reg("OSTS", dwc3_readl(dwc->regs, DWC3_OSTS));
dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT);
-
- panic("DWC3 Erratic error\n");
-
}
static void dwc3_gadget_interrupt(struct dwc3 *dwc,
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index d102c22..5d58f16 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -342,7 +342,7 @@
#define HSIC_DBG1_REG 0x38
-static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+static int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
{ /* VDD_CX CORNER Voting */
[VDD_NONE] = RPM_VREG_CORNER_NONE,
[VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
@@ -359,6 +359,8 @@
{
int ret = 0;
int none_vol, min_vol, max_vol;
+ u32 tmp[3];
+ int len = 0;
if (!mehci->hsic_vddcx) {
mehci->vdd_type = VDDCX_CORNER;
@@ -373,6 +375,22 @@
}
mehci->vdd_type = VDDCX;
}
+
+ if (mehci->dev->of_node) {
+ of_get_property(mehci->dev->of_node,
+ "hsic,vdd-voltage-level",
+ &len);
+ if (len == sizeof(tmp)) {
+ of_property_read_u32_array(mehci->dev->of_node,
+ "hsic,vdd-voltage-level",
+ tmp, len/sizeof(*tmp));
+ vdd_val[mehci->vdd_type][VDD_NONE] = tmp[0];
+ vdd_val[mehci->vdd_type][VDD_MIN] = tmp[1];
+ vdd_val[mehci->vdd_type][VDD_MAX] = tmp[2];
+ } else {
+ dev_dbg(mehci->dev, "Use default vdd config\n");
+ }
+ }
}
none_vol = vdd_val[mehci->vdd_type][VDD_NONE];
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 0aecaad..dd04f49 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -40,6 +40,7 @@
#include <mach/msm_xo.h>
#include <mach/msm_iomap.h>
#include <linux/debugfs.h>
+#include <mach/rpm-regulator.h>
#define MSM_USB_BASE (hcd->regs)
@@ -76,6 +77,7 @@
int wakeup_int_cnt;
bool wakeup_irq_enabled;
int wakeup_irq;
+ enum usb_vdd_type vdd_type;
};
static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
@@ -96,26 +98,87 @@
#define HSUSB_PHY_1P8_VOL_MAX 1800000 /* uV */
#define HSUSB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define HSUSB_PHY_VDD_DIG_VOL_NONE 0 /* uV */
#define HSUSB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
#define HSUSB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
#define HSUSB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define HSUSB_PHY_SUSP_DIG_VOL_P50 500000
+#define HSUSB_PHY_SUSP_DIG_VOL_P75 750000
+enum hsusb_vdd_value {
+ VDD_MIN_NONE = 0,
+ VDD_MIN_P50,
+ VDD_MIN_P75,
+ VDD_MIN_OP,
+ VDD_MAX_OP,
+ VDD_VAL_MAX_OP,
+};
+
+static int hsusb_vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX_OP] = {
+ { /* VDD_CX CORNER Voting */
+ [VDD_MIN_NONE] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_P50] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_P75] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_OP] = RPM_VREG_CORNER_NOMINAL,
+ [VDD_MAX_OP] = RPM_VREG_CORNER_HIGH,
+ },
+ { /* VDD_CX Voltage Voting */
+ [VDD_MIN_NONE] = HSUSB_PHY_VDD_DIG_VOL_NONE,
+ [VDD_MIN_P50] = HSUSB_PHY_SUSP_DIG_VOL_P50,
+ [VDD_MIN_P75] = HSUSB_PHY_SUSP_DIG_VOL_P75,
+ [VDD_MIN_OP] = HSUSB_PHY_VDD_DIG_VOL_MIN,
+ [VDD_MAX_OP] = HSUSB_PHY_VDD_DIG_VOL_MAX,
+ },
+};
+
static int msm_ehci_init_vddcx(struct msm_hcd *mhcd, int init)
{
int ret = 0;
+ int none_vol, min_vol, max_vol;
+ u32 tmp[5];
+ int len = 0;
- if (!init)
+ if (!init) {
+ none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
+ max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
goto disable_reg;
-
- mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev, "HSUSB_VDDCX");
- if (IS_ERR(mhcd->hsusb_vddcx)) {
- dev_err(mhcd->dev, "unable to get ehci vddcx\n");
- return PTR_ERR(mhcd->hsusb_vddcx);
}
- ret = regulator_set_voltage(mhcd->hsusb_vddcx,
- HSUSB_PHY_VDD_DIG_VOL_MIN,
- HSUSB_PHY_VDD_DIG_VOL_MAX);
+ mhcd->vdd_type = VDDCX_CORNER;
+ mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev, "hsusb_vdd_dig");
+ if (IS_ERR(mhcd->hsusb_vddcx)) {
+ mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev,
+ "HSUSB_VDDCX");
+ if (IS_ERR(mhcd->hsusb_vddcx)) {
+ dev_err(mhcd->dev, "unable to get ehci vddcx\n");
+ return PTR_ERR(mhcd->hsusb_vddcx);
+ }
+ mhcd->vdd_type = VDDCX;
+ }
+
+ if (mhcd->dev->of_node) {
+ of_get_property(mhcd->dev->of_node,
+ "qcom,vdd-voltage-level",
+ &len);
+ if (len == sizeof(tmp)) {
+ of_property_read_u32_array(mhcd->dev->of_node,
+ "qcom,vdd-voltage-level",
+ tmp, len/sizeof(*tmp));
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE] = tmp[0];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50] = tmp[1];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75] = tmp[2];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP] = tmp[3];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP] = tmp[4];
+ } else {
+ dev_dbg(mhcd->dev, "Use default vdd config\n");
+ }
+ }
+
+ none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
+ max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
+
+ ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
if (ret) {
dev_err(mhcd->dev, "unable to set the voltage"
"for ehci vddcx\n");
@@ -143,8 +206,7 @@
reg_enable_err:
regulator_set_optimum_mode(mhcd->hsusb_vddcx, 0);
reg_optimum_mode_err:
- regulator_set_voltage(mhcd->hsusb_vddcx, 0,
- HSUSB_PHY_VDD_DIG_VOL_MIN);
+ regulator_set_voltage(mhcd->hsusb_vddcx, none_vol, max_vol);
return ret;
}
@@ -194,24 +256,22 @@
}
#ifdef CONFIG_PM_SLEEP
-#define HSUSB_PHY_SUSP_DIG_VOL_P50 500000
-#define HSUSB_PHY_SUSP_DIG_VOL_P75 750000
static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
{
struct msm_usb_host_platform_data *pdata;
- int max_vol = HSUSB_PHY_VDD_DIG_VOL_MAX;
+ int max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
int min_vol;
int ret;
pdata = mhcd->dev->platform_data;
if (high)
- min_vol = HSUSB_PHY_VDD_DIG_VOL_MIN;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
else if (pdata && pdata->dock_connect_irq &&
!irq_read_line(pdata->dock_connect_irq))
- min_vol = HSUSB_PHY_SUSP_DIG_VOL_P75;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75];
else
- min_vol = HSUSB_PHY_SUSP_DIG_VOL_P50;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50];
ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
if (ret) {
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 1c8664c..ebe8c6e 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -516,7 +516,6 @@
/* explicitly set the driver mode to raw */
tty->raw = 1;
tty->real_raw = 1;
- tty->update_room_in_ldisc = 1;
set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
dbg("%s", __func__);
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 3177efa..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,
},
@@ -383,7 +395,7 @@
static int mdp3_clk_update(u32 clk_idx, u32 enable)
{
- int ret = -EINVAL;
+ int ret = 0;
struct clk *clk;
int count = 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 bb53f33..ac3fd3a 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;
@@ -557,6 +557,88 @@
return 0;
}
+static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session;
+ struct mdp3_dma *mdp3_dma;
+ struct mdss_panel_data *panel;
+ struct mdp3_vsync_notification vsync_client;
+
+ pr_debug("mdp3_ctrl_reset\n");
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf) {
+ pr_err("mdp3_ctrl_reset no device");
+ return -ENODEV;
+ }
+
+ panel = mdp3_session->panel;
+ mdp3_dma = mdp3_session->dma;
+ mutex_lock(&mdp3_session->lock);
+
+ vsync_client = mdp3_dma->vsync_client;
+
+ rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to stop the MDP3 dma\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
+ if (rc)
+ pr_err("fail to turn off panel\n");
+
+ rc = mdp3_ctrl_res_req_clk(mfd, 0);
+ if (rc) {
+ pr_err("fail to release mdp clocks\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
+ if (rc) {
+ pr_err("fail to blank the panel\n");
+ goto reset_error;
+ }
+
+ rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+ if (rc) {
+ pr_err("fail to attach dma iommu\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_UNBLANK, NULL);
+ if (rc) {
+ pr_err("fail to unblank the panel\n");
+ goto reset_error;
+ }
+
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ if (rc) {
+ pr_err("fail to turn on the panel\n");
+ goto reset_error;
+ }
+
+ rc = mdp3_ctrl_res_req_clk(mfd, 1);
+ if (rc) {
+ pr_err("fail to turn on mdp clks\n");
+ goto reset_error;
+ }
+
+ mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+ mdp3_ctrl_dma_init(mfd, mdp3_dma);
+
+ if (vsync_client.handler)
+ mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
+
+ if (mfd->fbi->screen_base)
+ rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+
+reset_error:
+ mutex_unlock(&mdp3_session->lock);
+ return rc;
+}
+
static int mdp3_overlay_get(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
{
@@ -583,15 +665,15 @@
mutex_lock(&mdp3_session->lock);
- if (mdp3_session->overlay.id == req->id) {
- mdp3_session->overlay = *req;
- if (req->id == MSMFB_NEW_REQUEST) {
- mdp3_session->overlay.id = 1;
- req->id = 1;
- }
- } else {
- rc = -EINVAL;
+ if (mdp3_session->overlay.id != req->id)
+ pr_err("overlay was not released, continue to recover\n");
+
+ mdp3_session->overlay = *req;
+ if (req->id == MSMFB_NEW_REQUEST) {
+ mdp3_session->overlay.id = 1;
+ req->id = 1;
}
+
mutex_unlock(&mdp3_session->lock);
return rc;
@@ -624,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;
@@ -633,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;
@@ -673,20 +755,20 @@
if (!mdp3_session || !mdp3_session->dma)
return -EINVAL;
- if (!mdp3_session->status) {
- pr_err("%s, display off!\n", __func__);
- return -EPERM;
- }
-
if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
pr_debug("continuous splash screen, IOMMU not attached\n");
- mdp3_ctrl_off(mfd);
- mdp3_ctrl_on(mfd);
+ mdp3_ctrl_reset(mfd);
mdp3_free();
}
mutex_lock(&mdp3_session->lock);
+ if (!mdp3_session->status) {
+ pr_err("%s, display off!\n", __func__);
+ mutex_unlock(&mdp3_session->lock);
+ return -EPERM;
+ }
+
data = mdp3_bufq_pop(&mdp3_session->bufq_in);
if (data) {
mdp3_session->dma->update(mdp3_session->dma,
@@ -697,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);
@@ -721,11 +803,6 @@
if (!mdp3_session || !mdp3_session->dma)
return;
- if (!mdp3_session->status) {
- pr_err("mdp3_ctrl_pan_display, display off!\n");
- return;
- }
-
if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
pr_debug("continuous splash screen, IOMMU not attached\n");
mdp3_ctrl_off(mfd);
@@ -733,6 +810,12 @@
}
mutex_lock(&mdp3_session->lock);
+
+ if (!mdp3_session->status) {
+ pr_err("mdp3_ctrl_pan_display, display off!\n");
+ goto pan_error;
+ }
+
fbi = mfd->fbi;
bpp = fbi->var.bits_per_pixel / 8;
@@ -1136,7 +1219,8 @@
if (!mdp3_session->dma->config_lut)
return -EINVAL;
- if (cmap->start + cmap->len > MDP_LUT_SIZE) {
+ if (cmap->start > MDP_LUT_SIZE || cmap->len > MDP_LUT_SIZE ||
+ (cmap->start + cmap->len > MDP_LUT_SIZE)) {
pr_err("mdp3_ctrl_lut_update invalid arguments\n");
return -EINVAL;
}
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 31b9deb..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;
@@ -831,6 +826,7 @@
MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
init_completion(&dma->dma_comp);
+ dma->vsync_client.handler = NULL;
return ret;
}
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.h b/drivers/video/msm/mdss/mdss.h
index 99cb2cc..dd1a95b 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -121,6 +121,7 @@
void *video_intf;
u32 nintf;
+ u32 pp_bus_hdl;
struct mdss_ad_info *ad_cfgs;
u32 nad_cfgs;
struct workqueue_struct *ad_calc_wq;
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 e18b709..793cbd7 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.c b/drivers/video/msm/mdss/mdss_mdp.c
index 6d094f3..3107e38 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1105,8 +1105,8 @@
probe_done:
if (IS_ERR_VALUE(rc)) {
mdss_mdp_hw.ptr = NULL;
- mdss_res = NULL;
mdss_mdp_pp_term(&pdev->dev);
+ mdss_res = NULL;
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 6cfdde9..fcc87f6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -25,6 +25,7 @@
#include <mach/iommu_domains.h>
#include <mach/event_timer.h>
+#include <mach/msm_bus.h>
#include "mdss.h"
#include "mdss_debug.h"
@@ -37,6 +38,9 @@
#define CHECK_BOUNDS(offset, size, max_size) \
(((size) > (max_size)) || ((offset) > ((max_size) - (size))))
+#define PP_CLK_CFG_OFF 0
+#define PP_CLK_CFG_ON 1
+
static atomic_t ov_active_panels = ATOMIC_INIT(0);
static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
@@ -823,7 +827,7 @@
int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdss_mdp_pipe *pipe, *next;
+ struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_ctl *tmp;
int ret;
@@ -843,8 +847,7 @@
return ret;
}
- list_for_each_entry_safe(pipe, next, &mdp5_data->pipes_used,
- used_list) {
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
struct mdss_mdp_data *buf;
/*
* When external is connected and no dedicated wfd is present,
@@ -882,12 +885,6 @@
pipe->params_changed++;
buf = &pipe->front_buf;
} else if (!pipe->params_changed) {
- if (pipe->mixer && !mdss_mdp_pipe_is_staged(pipe) &&
- !list_empty(&pipe->used_list)) {
- list_del_init(&pipe->used_list);
- list_add(&pipe->cleanup_list,
- &mdp5_data->pipes_cleanup);
- }
continue;
} else if (pipe->front_buf.num_planes) {
buf = &pipe->front_buf;
@@ -1450,14 +1447,9 @@
if (!ctl->add_vsync_handler || !ctl->remove_vsync_handler)
return -EOPNOTSUPP;
- rc = mutex_lock_interruptible(&ctl->lock);
- if (rc)
- return rc;
-
if (!ctl->power_on) {
pr_debug("fb%d vsync pending first update en=%d\n",
mfd->index, en);
- mutex_unlock(&ctl->lock);
return -EPERM;
}
@@ -1470,8 +1462,6 @@
rc = ctl->remove_vsync_handler(ctl, &ctl->vsync_handler);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- mutex_unlock(&ctl->lock);
-
return rc;
}
@@ -1845,12 +1835,20 @@
struct mdp_histogram_start_req hist_req;
u32 block;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ u32 pp_bus_handle;
+ static int req = -1;
switch (cmd) {
case MSMFB_HISTOGRAM_START:
if (!mfd->panel_power_on)
return -EPERM;
+ pp_bus_handle = mdss_mdp_get_mdata()->pp_bus_hdl;
+ req = msm_bus_scale_client_update_request(pp_bus_handle,
+ PP_CLK_CFG_ON);
+ if (req)
+ pr_err("Updated pp_bus_scale failed, ret = %d", req);
+
ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
if (ret)
return ret;
@@ -1864,6 +1862,17 @@
return ret;
ret = mdss_mdp_histogram_stop(mdp5_data->ctl, block);
+ if (ret)
+ return ret;
+
+ if (!req) {
+ pp_bus_handle = mdss_mdp_get_mdata()->pp_bus_hdl;
+ req = msm_bus_scale_client_update_request(pp_bus_handle,
+ PP_CLK_CFG_OFF);
+ if (req)
+ pr_err("Updated pp_bus_scale failed, ret = %d",
+ req);
+ }
break;
case MSMFB_HISTOGRAM:
@@ -2130,10 +2139,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/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index d9af777..09b789b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -19,6 +19,8 @@
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
struct mdp_csc_cfg mdp_csc_convert[MDSS_MDP_MAX_CSC] = {
[MDSS_MDP_CSC_RGB2RGB] = {
@@ -226,6 +228,27 @@
#define SHARP_SMOOTH_THR_DEFAULT 8
#define SHARP_NOISE_THR_DEFAULT 2
+#define MDP_PP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
+ { \
+ .src = MSM_BUS_MASTER_SPDM, \
+ .dst = MSM_BUS_SLAVE_IMEM_CFG, \
+ .ab = (ab_val), \
+ .ib = (ib_val), \
+ }
+
+#define SZ_37_5M (37500000 * 8)
+
+static struct msm_bus_vectors mdp_pp_bus_vectors[] = {
+ MDP_PP_BUS_VECTOR_ENTRY(0, 0),
+ MDP_PP_BUS_VECTOR_ENTRY(0, SZ_37_5M),
+};
+static struct msm_bus_paths mdp_pp_bus_usecases[ARRAY_SIZE(mdp_pp_bus_vectors)];
+static struct msm_bus_scale_pdata mdp_pp_bus_scale_table = {
+ .usecase = mdp_pp_bus_usecases,
+ .num_usecases = ARRAY_SIZE(mdp_pp_bus_usecases),
+ .name = "mdss_pp",
+};
+
struct mdss_pp_res_type {
/* logical info */
u32 pp_disp_flags[MDSS_BLOCK_DISP_NUM];
@@ -1268,6 +1291,7 @@
int i, ret = 0;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct mdss_mdp_pipe *vig;
+ struct msm_bus_scale_pdata *pp_bus_pdata;
mutex_lock(&mdss_pp_mutex);
if (!mdss_pp_res) {
@@ -1289,12 +1313,34 @@
mutex_init(&vig[i].pp_res.hist.hist_mutex);
spin_lock_init(&vig[i].pp_res.hist.hist_lock);
}
+ if (!mdata->pp_bus_hdl) {
+ pp_bus_pdata = &mdp_pp_bus_scale_table;
+ for (i = 0; i < pp_bus_pdata->num_usecases; i++) {
+ mdp_pp_bus_usecases[i].num_paths = 1;
+ mdp_pp_bus_usecases[i].vectors =
+ &mdp_pp_bus_vectors[i];
+ }
+
+ mdata->pp_bus_hdl =
+ msm_bus_scale_register_client(pp_bus_pdata);
+ if (!mdata->pp_bus_hdl) {
+ pr_err("not able to register pp_bus_scale\n");
+ ret = -ENOMEM;
+ }
+ pr_debug("register pp_bus_hdl=%x\n", mdata->pp_bus_hdl);
+ }
+
}
mutex_unlock(&mdss_pp_mutex);
return ret;
}
void mdss_mdp_pp_term(struct device *dev)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ if (mdata->pp_bus_hdl) {
+ msm_bus_scale_unregister_client(mdata->pp_bus_hdl);
+ mdata->pp_bus_hdl = 0;
+ }
if (!mdss_pp_res) {
mutex_lock(&mdss_pp_mutex);
devm_kfree(dev, mdss_pp_res);
@@ -2567,13 +2613,13 @@
if (ret)
goto hist_collect_exit;
}
+ if (hist->bin_cnt != HIST_V_SIZE) {
+ pr_err("User not expecting size %d output",
+ HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
if (hist_cnt > 1) {
- if (hist->bin_cnt != HIST_V_SIZE) {
- pr_err("User not expecting size %d output",
- HIST_V_SIZE);
- ret = -EINVAL;
- goto hist_collect_exit;
- }
hist_concat = kmalloc(HIST_V_SIZE * sizeof(u32),
GFP_KERNEL);
if (!hist_concat) {
@@ -2637,13 +2683,14 @@
if (ret)
goto hist_collect_exit;
}
+ if (pipe_cnt != 0 &&
+ (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt))) {
+ pr_err("User not expecting size %d output",
+ pipe_cnt * HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
if (pipe_cnt > 1) {
- if (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt)) {
- pr_err("User not expecting size %d output",
- pipe_cnt * HIST_V_SIZE);
- ret = -EINVAL;
- goto hist_collect_exit;
- }
hist_concat = kmalloc(HIST_V_SIZE * pipe_cnt *
sizeof(u32), GFP_KERNEL);
if (!hist_concat) {
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index a01ae09..d05ca66 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -74,7 +74,6 @@
#define MDSS_INTF_MAX_NAME_LEN 5
struct mdss_panel_intf {
char name[MDSS_INTF_MAX_NAME_LEN];
- u8 len;
int type;
};
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/security.h b/include/linux/security.h
index 673afbb..b62f396 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1381,6 +1381,11 @@
struct security_operations {
char name[SECURITY_NAME_MAX + 1];
+ int (*binder_set_context_mgr) (struct task_struct *mgr);
+ int (*binder_transaction) (struct task_struct *from, struct task_struct *to);
+ int (*binder_transfer_binder) (struct task_struct *from, struct task_struct *to);
+ int (*binder_transfer_file) (struct task_struct *from, struct task_struct *to, struct file *file);
+
int (*ptrace_access_check) (struct task_struct *child, unsigned int mode);
int (*ptrace_traceme) (struct task_struct *parent);
int (*capget) (struct task_struct *target,
@@ -1664,6 +1669,10 @@
/* Security operations */
+int security_binder_set_context_mgr(struct task_struct *mgr);
+int security_binder_transaction(struct task_struct *from, struct task_struct *to);
+int security_binder_transfer_binder(struct task_struct *from, struct task_struct *to);
+int security_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file);
int security_ptrace_access_check(struct task_struct *child, unsigned int mode);
int security_ptrace_traceme(struct task_struct *parent);
int security_capget(struct task_struct *target,
@@ -1842,6 +1851,26 @@
return 0;
}
+static inline int security_binder_set_context_mgr(struct task_struct *mgr)
+{
+ return 0;
+}
+
+static inline int security_binder_transaction(struct task_struct *from, struct task_struct *to)
+{
+ return 0;
+}
+
+static inline int security_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
+{
+ return 0;
+}
+
+static inline int security_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
+{
+ return 0;
+}
+
static inline int security_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6fcafa8..6a0259d 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -282,10 +282,8 @@
struct winsize winsize; /* termios mutex */
unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
unsigned char low_latency:1, warned:1;
- unsigned char update_room_in_ldisc:1;
unsigned char ctrl_status; /* ctrl_lock */
unsigned int receive_room; /* Bytes free for queue */
- unsigned int rr_bug;
struct tty_struct *link;
struct fasync_struct *fasync;
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..bbda72e 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
@@ -4298,7 +4309,6 @@
struct asm_aac_dual_mono_mapping_param {
struct apr_hdr hdr;
struct asm_stream_cmd_set_encdec_param encdec;
- struct asm_enc_cfg_blk_param_v2 encblk;
u16 left_channel_sce;
u16 right_channel_sce;
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 594d750..3fc85b2 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -92,7 +92,8 @@
MAD_HW_NONE = 0x00,
MAD_HW_AUDIO = 0x01,
MAD_HW_BEACON = 0x02,
- MAD_HW_ULTRASOUND = 0x04
+ MAD_HW_ULTRASOUND = 0x04,
+ MAD_SW_AUDIO = 0x05,
};
struct afe_audio_buffer {
diff --git a/kernel/smp.c b/kernel/smp.c
index 2f8b10e..3cbd828 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -310,20 +310,20 @@
*/
this_cpu = get_cpu();
- /*
- * Can deadlock when called with interrupts disabled.
- * We allow cpu's that are not yet online though, as no one else can
- * send smp call function interrupt to this cpu and as such deadlocks
- * can't happen.
- */
- WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
- && !oops_in_progress);
-
if (cpu == this_cpu) {
local_irq_save(flags);
func(info);
local_irq_restore(flags);
} else {
+ /*
+ * Can deadlock when called with interrupts disabled.
+ * We allow cpu's that are not yet online though, as no one else
+ * can send smp call function interrupt to this cpu and as such
+ * deadlocks can't happen.
+ */
+ WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
+ && !oops_in_progress);
+
if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {
struct call_single_data *data = &d;
@@ -408,20 +408,21 @@
unsigned long flags;
this_cpu = get_cpu();
- /*
- * Can deadlock when called with interrupts disabled.
- * We allow cpu's that are not yet online though, as no one else can
- * send smp call function interrupt to this cpu and as such deadlocks
- * can't happen.
- */
- WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled()
- && !oops_in_progress);
if (cpu == this_cpu) {
local_irq_save(flags);
data->func(data->info);
local_irq_restore(flags);
} else {
+ /*
+ * Can deadlock when called with interrupts disabled.
+ * We allow cpu's that are not yet online though, as no one else
+ * can send smp call function interrupt to this cpu and as such
+ * deadlocks can't happen.
+ */
+ WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait
+ && irqs_disabled() && !oops_in_progress);
+
csd_lock(data);
generic_exec_single(cpu, data, wait);
}
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index df30ee0..818920f 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -127,7 +127,7 @@
/* Commands for resetting the watchdog */
static void __touch_watchdog(void)
{
- int this_cpu = smp_processor_id();
+ int this_cpu = raw_smp_processor_id();
__this_cpu_write(watchdog_touch_ts, get_timestamp(this_cpu));
}
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/security/capability.c b/security/capability.c
index 5bb21b1..fc991bc 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -12,6 +12,26 @@
#include <linux/security.h>
+static int cap_binder_set_context_mgr(struct task_struct *mgr)
+{
+ return 0;
+}
+
+static int cap_binder_transaction(struct task_struct *from, struct task_struct *to)
+{
+ return 0;
+}
+
+static int cap_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
+{
+ return 0;
+}
+
+static int cap_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
+{
+ return 0;
+}
+
static int cap_syslog(int type)
{
return 0;
@@ -877,6 +897,10 @@
void __init security_fixup_ops(struct security_operations *ops)
{
+ set_to_cap_if_null(ops, binder_set_context_mgr);
+ set_to_cap_if_null(ops, binder_transaction);
+ set_to_cap_if_null(ops, binder_transfer_binder);
+ set_to_cap_if_null(ops, binder_transfer_file);
set_to_cap_if_null(ops, ptrace_access_check);
set_to_cap_if_null(ops, ptrace_traceme);
set_to_cap_if_null(ops, capget);
diff --git a/security/security.c b/security/security.c
index bf619ff..cecd55e 100644
--- a/security/security.c
+++ b/security/security.c
@@ -130,6 +130,26 @@
/* Security operations */
+int security_binder_set_context_mgr(struct task_struct *mgr)
+{
+ return security_ops->binder_set_context_mgr(mgr);
+}
+
+int security_binder_transaction(struct task_struct *from, struct task_struct *to)
+{
+ return security_ops->binder_transaction(from, to);
+}
+
+int security_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
+{
+ return security_ops->binder_transfer_binder(from, to);
+}
+
+int security_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
+{
+ return security_ops->binder_transfer_file(from, to, file);
+}
+
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
return security_ops->ptrace_access_check(child, mode);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d85b793..b28b7eb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1818,6 +1818,67 @@
/* Hook functions begin here. */
+static int selinux_binder_set_context_mgr(struct task_struct *mgr)
+{
+ u32 mysid = current_sid();
+ u32 mgrsid = task_sid(mgr);
+
+ return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL);
+}
+
+static int selinux_binder_transaction(struct task_struct *from, struct task_struct *to)
+{
+ u32 mysid = current_sid();
+ u32 fromsid = task_sid(from);
+ u32 tosid = task_sid(to);
+ int rc;
+
+ if (mysid != fromsid) {
+ rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL);
+ if (rc)
+ return rc;
+ }
+
+ return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL);
+}
+
+static int selinux_binder_transfer_binder(struct task_struct *from, struct task_struct *to)
+{
+ u32 fromsid = task_sid(from);
+ u32 tosid = task_sid(to);
+ return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER, NULL);
+}
+
+static int selinux_binder_transfer_file(struct task_struct *from, struct task_struct *to, struct file *file)
+{
+ u32 sid = task_sid(to);
+ struct file_security_struct *fsec = file->f_security;
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode_security_struct *isec = inode->i_security;
+ struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ int rc;
+
+ COMMON_AUDIT_DATA_INIT(&ad, PATH);
+ ad.u.path = file->f_path;
+ ad.selinux_audit_data = &sad;
+
+ if (sid != fsec->sid) {
+ rc = avc_has_perm(sid, fsec->sid,
+ SECCLASS_FD,
+ FD__USE,
+ &ad);
+ if (rc)
+ return rc;
+ }
+
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+ return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
+ &ad);
+}
+
static int selinux_ptrace_access_check(struct task_struct *child,
unsigned int mode)
{
@@ -5523,6 +5584,11 @@
static struct security_operations selinux_ops = {
.name = "selinux",
+ .binder_set_context_mgr = selinux_binder_set_context_mgr,
+ .binder_transaction = selinux_binder_transaction,
+ .binder_transfer_binder = selinux_binder_transfer_binder,
+ .binder_transfer_file = selinux_binder_transfer_file,
+
.ptrace_access_check = selinux_ptrace_access_check,
.ptrace_traceme = selinux_ptrace_traceme,
.capget = selinux_capget,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index b8c5372..4a4a9ae 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -149,5 +149,6 @@
{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
{ "tun_socket",
{ COMMON_SOCK_PERMS, NULL } },
+ { "binder", { "impersonate", "call", "set_context_mgr", "transfer", NULL } },
{ NULL }
};
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/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 4e95fa9..a9e0c43 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1900,7 +1900,7 @@
0);
}
- if (mbhc->resmgr->reg_addr->micb_4_mbhc)
+ if (mbhc->resmgr->reg_addr && mbhc->resmgr->reg_addr->micb_4_mbhc)
snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
0x3, mbhc->mbhc_cfg->micbias);
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 55a5e57..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;
}
@@ -1165,6 +1301,38 @@
.codec_name = "snd-soc-dummy",
.be_id = MSM_FRONTEND_DAI_VOLTE,
},
+ {
+ .name = "QCHAT",
+ .stream_name = "QCHAT",
+ .cpu_dai_name = "QCHAT",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_QCHAT,
+ },
+ /* LSM FE */
+ {
+ .name = "Listen Audio Service",
+ .stream_name = "Listen Audio Service",
+ .cpu_dai_name = "LSM",
+ .platform_name = "msm-lsm-client",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_LSM1,
+ },
/* Backend BT/FM DAI Links */
{
.name = LPASS_BE_INT_BT_SCO_RX,
@@ -1457,6 +1625,19 @@
.ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm8226_9302_dai[] = {
@@ -1573,6 +1754,19 @@
.ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm8226_9306_dai_links[
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index dfde85c..23577ed 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -817,6 +817,22 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ {/* hw:x,14 */
+ .name = "QCHAT",
+ .stream_name = "QCHAT",
+ .cpu_dai_name = "QCHAT",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .be_id = MSM_FRONTEND_DAI_QCHAT,
+ },
/* Backend I2S DAI Links */
{
.name = LPASS_BE_SEC_MI2S_RX,
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 3e93b6e..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;
}
@@ -1066,6 +1210,8 @@
acdb_data.col_data[i] = NULL;
}
msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+ acdb_data.ion_client = NULL;
+ acdb_data.ion_handle = NULL;
mutex_unlock(&acdb_data.acdb_mutex);
}
return result;
@@ -1114,8 +1260,6 @@
return result;
err_ion_handle:
- msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-
atomic64_set(&acdb_data.mem_len, 0);
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 42a24fc..9d4257f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -68,7 +68,8 @@
MADNONE,
MADAUDIO,
MADBEACON,
- MADULTRASOUND
+ MADULTRASOUND,
+ MADSWAUDIO,
};
#define SLIMBUS_0_TX_TEXT "SLIMBUS_0_TX"
@@ -191,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;
}
@@ -882,6 +883,9 @@
case MAD_HW_ULTRASOUND:
ucontrol->value.integer.value[0] = MADULTRASOUND;
break;
+ case MAD_SW_AUDIO:
+ ucontrol->value.integer.value[0] = MADSWAUDIO;
+ break;
default:
WARN(1, "Unknown\n");
return -EINVAL;
@@ -921,6 +925,9 @@
case MADULTRASOUND:
mad_type = MAD_HW_ULTRASOUND;
break;
+ case MADSWAUDIO:
+ mad_type = MAD_SW_AUDIO;
+ break;
default:
WARN(1, "Unknown\n");
return -EINVAL;
@@ -2427,7 +2434,7 @@
msm_routing_lsm_mux_put);
static const char * const lsm_func_text[] = {
- "None", "AUDIO", "BEACON", "ULTRASOUND"
+ "None", "AUDIO", "BEACON", "ULTRASOUND", "SWAUDIO",
};
static const struct soc_enum lsm_func_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_func_text), lsm_func_text);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 158009f..6cfc2ef 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -46,6 +46,7 @@
#define MODE_AMR 0x5
#define MODE_AMR_WB 0xD
#define MODE_PCM 0xC
+#define MODE_4GV_NW 0xE
enum format {
FORMAT_S16_LE = 2,
@@ -140,6 +141,9 @@
unsigned int pcm_capture_count;
unsigned int pcm_capture_irq_pos; /* IRQ position */
unsigned int pcm_capture_buf_pos; /* position in buffer */
+
+ uint32_t evrc_min_rate;
+ uint32_t evrc_max_rate;
};
static int voip_get_media_type(uint32_t mode,
@@ -148,10 +152,15 @@
static int voip_get_rate_type(uint32_t mode,
uint32_t rate,
uint32_t *rate_type);
+static int voip_config_vocoder(struct snd_pcm_substream *substream);
static int msm_voip_mode_rate_config_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int msm_voip_mode_rate_config_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
+static int msm_voip_evrc_min_max_rate_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
static struct voip_drv_info voip_info;
@@ -261,6 +270,9 @@
SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
0, 2, msm_voip_mode_rate_config_get,
msm_voip_mode_rate_config_put),
+ SOC_SINGLE_MULTI_EXT("Voip Evrc Min Max Rate Config", SND_SOC_NOPM,
+ 0, 4, 0, 2, msm_voip_evrc_min_max_rate_config_get,
+ msm_voip_evrc_min_max_rate_config_put),
SOC_SINGLE_EXT("Voip Dtx Mode", SND_SOC_NOPM, 0, 1, 0,
msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
};
@@ -318,7 +330,8 @@
}
case MODE_IS127:
case MODE_4GV_NB:
- case MODE_4GV_WB: {
+ case MODE_4GV_WB:
+ case MODE_4GV_NW: {
/* Remove the DSP frame info header.
* Header format:
* Bits 0-3: frame rate
@@ -397,7 +410,8 @@
}
case MODE_IS127:
case MODE_4GV_NB:
- case MODE_4GV_WB: {
+ case MODE_4GV_WB:
+ case MODE_4GV_NW: {
*((uint32_t *)voc_pkt) = buf_node->frame.pktlen +
DSP_FRAME_HDR_LEN;
/* Advance to the header of voip packet */
@@ -769,13 +783,137 @@
return ret;
}
-static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+
+static int voip_config_vocoder(struct snd_pcm_substream *substream)
{
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
uint32_t media_type = 0;
uint32_t rate_type = 0;
+ uint32_t evrc_min_rate_type = 0;
+ uint32_t evrc_max_rate_type = 0;
+
+ if ((runtime->format != FORMAT_SPECIAL) &&
+ ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
+ (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB) || (prtd->mode == MODE_4GV_NW))) {
+ pr_err("%s(): mode:%d and format:%u are not mached\n",
+ __func__, prtd->mode, (uint32_t)runtime->format);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((runtime->format != FORMAT_S16_LE) &&
+ (prtd->mode == MODE_PCM)) {
+ pr_err("%s(): mode:%d and format:%u are not mached\n",
+ __func__, prtd->mode, (uint32_t)runtime->format);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = voip_get_media_type(prtd->mode,
+ prtd->play_samp_rate,
+ &media_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting media_type, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ pr_debug("%s(): media_type=%d\n", __func__, media_type);
+
+ if ((prtd->mode == MODE_PCM) ||
+ (prtd->mode == MODE_AMR) ||
+ (prtd->mode == MODE_AMR_WB)) {
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->rate,
+ &rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting rate_type, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ prtd->rate_type = rate_type;
+ pr_debug("rate_type=%d\n", rate_type);
+
+ } else if ((prtd->mode == MODE_IS127) ||
+ (prtd->mode == MODE_4GV_NB) ||
+ (prtd->mode == MODE_4GV_WB) ||
+ (prtd->mode == MODE_4GV_NW)) {
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->evrc_min_rate,
+ &evrc_min_rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting min rate, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ if (evrc_min_rate_type == VOC_0_RATE)
+ evrc_min_rate_type = VOC_8_RATE;
+
+ ret = voip_get_rate_type(prtd->mode,
+ prtd->evrc_max_rate,
+ &evrc_max_rate_type);
+ if (ret < 0) {
+ pr_err("%s(): fail at getting max rate, ret=%d\n",
+ __func__, ret);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ if (evrc_max_rate_type == VOC_0_RATE)
+ evrc_max_rate_type = VOC_1_RATE;
+
+ if (evrc_max_rate_type < evrc_min_rate_type) {
+ pr_err("%s(): Invalid EVRC min max rates: %d, %d\n",
+ __func__, evrc_min_rate_type,
+ evrc_max_rate_type);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ pr_debug("%s(): min rate=%d, max rate=%d\n",
+ __func__, evrc_min_rate_type, evrc_max_rate_type);
+ }
+ if ((prtd->play_samp_rate == 8000) &&
+ (prtd->cap_samp_rate == 8000))
+ voc_config_vocoder(media_type, rate_type,
+ VSS_NETWORK_ID_VOIP_NB,
+ voip_info.dtx_mode,
+ evrc_min_rate_type,
+ evrc_max_rate_type);
+ else if ((prtd->play_samp_rate == 16000) &&
+ (prtd->cap_samp_rate == 16000))
+ voc_config_vocoder(media_type, rate_type,
+ VSS_NETWORK_ID_VOIP_WB,
+ voip_info.dtx_mode,
+ evrc_min_rate_type,
+ evrc_max_rate_type);
+ else {
+ pr_debug("%s: Invalid rate playback %d, capture %d\n",
+ __func__, prtd->play_samp_rate,
+ prtd->cap_samp_rate);
+
+ ret = -EINVAL;
+ }
+done:
+
+ return ret;
+}
+
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct voip_drv_info *prtd = runtime->private_data;
mutex_lock(&prtd->lock);
@@ -784,63 +922,19 @@
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
ret = msm_pcm_capture_prepare(substream);
- if ((runtime->format != FORMAT_SPECIAL) &&
- ((prtd->mode == MODE_AMR) || (prtd->mode == MODE_AMR_WB) ||
- (prtd->mode == MODE_IS127) || (prtd->mode == MODE_4GV_NB) ||
- (prtd->mode == MODE_4GV_WB))) {
- pr_err("mode:%d and format:%u are not mached\n",
- prtd->mode, (uint32_t)runtime->format);
- ret = -EINVAL;
- goto done;
- }
-
- if ((runtime->format != FORMAT_S16_LE) &&
- (prtd->mode == MODE_PCM)) {
- pr_err("mode:%d and format:%u are not mached\n",
- prtd->mode, (uint32_t)runtime->format);
- ret = -EINVAL;
- goto done;
- }
-
if (prtd->playback_instance && prtd->capture_instance
- && (prtd->state != VOIP_STARTED)) {
+ && (prtd->state != VOIP_STARTED)) {
+ ret = voip_config_vocoder(substream);
+ if (ret < 0) {
+ pr_err("%s(): fail at configuring vocoder for voip, ret=%d\n",
+ __func__, ret);
- ret = voip_get_rate_type(prtd->mode,
- prtd->rate,
- &rate_type);
- if (ret < 0) {
- pr_err("fail at getting rate_type\n");
- ret = -EINVAL;
goto done;
}
- prtd->rate_type = rate_type;
- ret = voip_get_media_type(prtd->mode,
- prtd->play_samp_rate,
- &media_type);
- if (ret < 0) {
- pr_err("fail at getting media_type\n");
- goto done;
- }
- pr_debug(" media_type=%d, rate_type=%d\n", media_type,
- rate_type);
- if ((prtd->play_samp_rate == 8000) &&
- (prtd->cap_samp_rate == 8000))
- voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_NB,
- voip_info.dtx_mode);
- else if ((prtd->play_samp_rate == 16000) &&
- (prtd->cap_samp_rate == 16000))
- voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_WB,
- voip_info.dtx_mode);
- else {
- pr_debug("%s: Invalid rate playback %d, capture %d\n",
- __func__, prtd->play_samp_rate,
- prtd->cap_samp_rate);
- goto done;
- }
+
voc_register_mvs_cb(voip_process_ul_pkt,
- voip_process_dl_pkt, prtd);
+ voip_process_dl_pkt, prtd);
+
ret = voc_start_voice_call(
voc_get_session_id(VOIP_SESSION_NAME));
@@ -986,6 +1080,35 @@
return 0;
}
+static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ ucontrol->value.integer.value[0] = voip_info.evrc_min_rate;
+ ucontrol->value.integer.value[1] = voip_info.evrc_max_rate;
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+
+static int msm_voip_evrc_min_max_rate_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ voip_info.evrc_min_rate = ucontrol->value.integer.value[0];
+ voip_info.evrc_max_rate = ucontrol->value.integer.value[1];
+
+ pr_debug("%s(): evrc_min_rate=%d,evrc_max_rate=%d\n", __func__,
+ voip_info.evrc_min_rate, voip_info.evrc_max_rate);
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+
static int voip_get_rate_type(uint32_t mode, uint32_t rate,
uint32_t *rate_type)
{
@@ -1083,6 +1206,23 @@
}
break;
}
+ case MODE_4GV_NW: {
+ switch (rate) {
+ case VOC_0_RATE:
+ case VOC_8_RATE:
+ case VOC_4_RATE:
+ case VOC_2_RATE:
+ case VOC_1_RATE:
+ case VOC_8_RATE_NC:
+ *rate_type = rate;
+ break;
+ default:
+ pr_err("wrong rate for 4GV_NW.\n");
+ ret = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
pr_err("wrong mode type.\n");
ret = -EINVAL;
@@ -1122,6 +1262,9 @@
case MODE_4GV_WB: /* EVRC-WB */
*media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
break;
+ case MODE_4GV_NW: /* EVRC-NW */
+ *media_type = VSS_MEDIA_ID_4GV_NW_MODEM;
+ break;
default:
pr_debug(" input mode is not supported\n");
ret = -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 297a386..bba4c14 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -35,6 +35,7 @@
/* 2 is to account for module & param ID in payload */
#define ADM_GET_PARAMETER_LENGTH (4096 - APR_HDR_SIZE - 2 * sizeof(uint32_t))
+#define ULL_SUPPORTED_SAMPLE_RATE 48000
enum {
ADM_RX_AUDPROC_CAL,
@@ -1124,11 +1125,14 @@
(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- if (perf_mode)
+ if (perf_mode) {
open.topology_id = NULL_COPP_TOPOLOGY;
+ rate = ULL_SUPPORTED_SAMPLE_RATE;
+ }
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
+ WARN_ON(perf_mode && (rate != 48000));
open.sample_rate = rate;
memset(open.dev_channel_mapping, 0, 8);
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 2108f6b..59113fe 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -357,7 +357,8 @@
{
int ret;
- atomic_set(&this_afe.state, 1);
+ if (wait)
+ atomic_set(&this_afe.state, 1);
atomic_set(&this_afe.status, 0);
ret = apr_send_pkt(this_afe.apr, data);
if (ret > 0) {
@@ -631,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__);
@@ -1247,12 +1313,19 @@
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);
pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
mad_type);
- if (mad_type != MAD_HW_NONE) {
+ if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
+ if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
+ !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
+ pr_err("%s: AFE isn't configured yet for HW MAD\n",
+ __func__);
+ return -EINVAL;
+ }
ret = afe_turn_onoff_hw_mad(mad_type, true);
if (ret) {
pr_err("%s: afe_turn_onoff_hw_mad failed %d\n",
@@ -2118,7 +2191,6 @@
cnt = port->max_buf_cnt - 1;
if (port->buf[0].data) {
- msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -2126,6 +2198,9 @@
(void *)&port->buf[0].phys,
(void *)port->buf[0].client,
(void *)port->buf[0].handle);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
+ port->buf[0].client = NULL;
+ port->buf[0].handle = NULL;
}
while (cnt >= 0) {
@@ -2845,7 +2920,7 @@
mad_type = afe_port_get_mad_type(port_id);
pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
mad_type);
- if (mad_type != MAD_HW_NONE) {
+ if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) {
pr_debug("%s: Turn off MAD\n", __func__);
ret = afe_turn_onoff_hw_mad(mad_type, false);
if (ret) {
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c153d10..9c0c362 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -650,6 +650,8 @@
if (port->buf[cnt].data) {
msm_audio_ion_free(port->buf[cnt].client,
port->buf[cnt].handle);
+ port->buf[cnt].client = NULL;
+ port->buf[cnt].handle = NULL;
port->buf[cnt].data = NULL;
port->buf[cnt].phys = 0;
--(port->max_buf_cnt);
@@ -686,7 +688,6 @@
}
if (port->buf[0].data) {
- msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -694,6 +695,9 @@
(void *)&port->buf[0].phys,
(void *)port->buf[0].client,
(void *)port->buf[0].handle);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
+ port->buf[0].client = NULL;
+ port->buf[0].handle = NULL;
}
while (cnt >= 0) {
@@ -1603,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;
@@ -1702,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:
@@ -1786,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:
@@ -2233,7 +2237,6 @@
uint16_t sce_left, uint16_t sce_right)
{
struct asm_aac_dual_mono_mapping_param dual_mono;
- u32 frames_per_buf = 0;
int rc = 0;
@@ -2244,11 +2247,8 @@
dual_mono.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
dual_mono.encdec.param_id = ASM_PARAM_ID_AAC_DUAL_MONO_MAPPING;
- dual_mono.encdec.param_size = sizeof(struct asm_aac_enc_cfg_v2) -
- sizeof(struct asm_stream_cmd_set_encdec_param);
- dual_mono.encblk.frames_per_buf = frames_per_buf;
- dual_mono.encblk.enc_cfg_blk_size = dual_mono.encdec.param_size -
- sizeof(struct asm_enc_cfg_blk_param_v2);
+ dual_mono.encdec.param_size = sizeof(dual_mono.left_channel_sce) +
+ sizeof(dual_mono.right_channel_sce);
dual_mono.left_channel_sce = sce_left;
dual_mono.right_channel_sce = sce_right;
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index e8880d1..9227b23 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -320,13 +320,6 @@
int rc;
struct lsm_stream_cmd_open_tx open;
- if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) ||
- !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) {
- pr_err("%s: AFE isn't configured yet\n", __func__);
- rc = -EAGAIN;
- goto exit;
- }
-
memset(&open, 0, sizeof(open));
q6lsm_add_hdr(client, &open.hdr, sizeof(open), true);
@@ -339,8 +332,6 @@
pr_err("%s: Open failed opcode 0x%x, rc %d\n",
__func__, open.hdr.opcode, rc);
-exit:
- pr_debug("%s: leave %d\n", __func__, rc);
return rc;
}
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index ae5bbbf..c16b14c 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1544,7 +1544,8 @@
switch (common.mvs_info.media_type) {
case VSS_MEDIA_ID_EVRC_MODEM:
case VSS_MEDIA_ID_4GV_NB_MODEM:
- case VSS_MEDIA_ID_4GV_WB_MODEM: {
+ case VSS_MEDIA_ID_4GV_WB_MODEM:
+ case VSS_MEDIA_ID_4GV_NW_MODEM: {
struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
pr_debug("Setting EVRC min-max rate\n");
@@ -1561,8 +1562,10 @@
cvs_set_cdma_rate.hdr.token = 0;
cvs_set_cdma_rate.hdr.opcode =
VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE;
- cvs_set_cdma_rate.cdma_rate.min_rate = common.mvs_info.rate;
- cvs_set_cdma_rate.cdma_rate.max_rate = common.mvs_info.rate;
+ cvs_set_cdma_rate.cdma_rate.min_rate =
+ common.mvs_info.evrc_min_rate;
+ cvs_set_cdma_rate.cdma_rate.max_rate =
+ common.mvs_info.evrc_max_rate;
v->cvs_state = CMD_STATUS_FAIL;
@@ -1580,6 +1583,13 @@
goto fail;
}
+
+ if (common.mvs_info.media_type != VSS_MEDIA_ID_EVRC_MODEM) {
+ ret = voice_set_dtx(v);
+ if (ret < 0)
+ goto fail;
+ }
+
break;
}
case VSS_MEDIA_ID_AMR_NB_MODEM: {
@@ -3622,7 +3632,8 @@
return -EINVAL;
}
-static int voice_send_stream_mute_cmd(struct voice_data *v)
+static int voice_send_stream_mute_cmd(struct voice_data *v, uint16_t direction,
+ uint16_t mute_flag, uint32_t ramp_duration)
{
struct cvs_set_mute_cmd cvs_mute_cmd;
int ret = 0;
@@ -3650,10 +3661,9 @@
cvs_mute_cmd.hdr.dest_port = voice_get_cvs_handle(v);
cvs_mute_cmd.hdr.token = 0;
cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
- cvs_mute_cmd.cvs_set_mute.direction = VSS_IVOLUME_DIRECTION_TX;
- cvs_mute_cmd.cvs_set_mute.mute_flag = v->stream_tx.stream_mute;
- cvs_mute_cmd.cvs_set_mute.ramp_duration_ms =
- v->stream_tx.stream_mute_ramp_duration_ms;
+ cvs_mute_cmd.cvs_set_mute.direction = direction;
+ cvs_mute_cmd.cvs_set_mute.mute_flag = mute_flag;
+ cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = ramp_duration;
v->cvs_state = CMD_STATUS_FAIL;
ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_mute_cmd);
@@ -4309,6 +4319,13 @@
VSS_IVOLUME_DIRECTION_RX,
VSS_IVOLUME_MUTE_ON,
DEFAULT_MUTE_RAMP_DURATION);
+ /* Send unmute cmd as the TX stream
+ * might be muted previously
+ */
+ voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ VSS_IVOLUME_MUTE_OFF,
+ DEFAULT_MUTE_RAMP_DURATION);
} else if (v->lch_mode == VOICE_LCH_STOP) {
pr_debug("%s: TX and RX mute OFF\n", __func__);
@@ -4323,7 +4340,10 @@
/* Reset lch mode when VOICE_LCH_STOP is recieved */
v->lch_mode = 0;
/* Apply cached mute setting */
- voice_send_stream_mute_cmd(v);
+ voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
} else {
pr_debug("%s: Mute commands not sent for lch_mode=%d\n",
__func__, v->lch_mode);
@@ -4403,7 +4423,10 @@
ramp_duration;
if (is_voc_state_active(v->voc_state) &&
(v->lch_mode == 0))
- ret = voice_send_stream_mute_cmd(v);
+ ret = voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
mutex_unlock(&v->lock);
} else {
pr_err("%s: invalid session_id 0x%x\n", __func__,
@@ -4889,7 +4912,10 @@
if (ret < 0)
pr_err("voice volume failed\n");
- ret = voice_send_stream_mute_cmd(v);
+ ret = voice_send_stream_mute_cmd(v,
+ VSS_IVOLUME_DIRECTION_TX,
+ v->stream_tx.stream_mute,
+ v->stream_tx.stream_mute_ramp_duration_ms);
if (ret < 0)
pr_err("voice mute failed\n");
@@ -4929,14 +4955,18 @@
}
void voc_config_vocoder(uint32_t media_type,
- uint32_t rate,
- uint32_t network_type,
- uint32_t dtx_mode)
+ uint32_t rate,
+ uint32_t network_type,
+ uint32_t dtx_mode,
+ uint32_t evrc_min_rate,
+ uint32_t evrc_max_rate)
{
common.mvs_info.media_type = media_type;
common.mvs_info.rate = rate;
common.mvs_info.network_type = network_type;
common.mvs_info.dtx_mode = dtx_mode;
+ common.mvs_info.evrc_min_rate = evrc_min_rate;
+ common.mvs_info.evrc_max_rate = evrc_max_rate;
}
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
@@ -5487,6 +5517,8 @@
rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
v->shmem_info.sh_buf.handle);
+ v->shmem_info.sh_buf.client = NULL;
+ v->shmem_info.sh_buf.handle = NULL;
if (rc < 0) {
pr_err("%s: Error:%d freeing memory\n", __func__, rc);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 798391d..39f0986 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -217,7 +217,8 @@
VOC_8_RATE, /* 1/8 rate */
VOC_4_RATE, /* 1/4 rate */
VOC_2_RATE, /* 1/2 rate */
- VOC_1_RATE /* Full rate */
+ VOC_1_RATE, /* Full rate */
+ VOC_8_RATE_NC /* Noncritical 1/8 rate */
};
struct vss_istream_cmd_set_tty_mode_t {
@@ -981,6 +982,8 @@
/*CDMA EVRC-B vocoder modem format */
#define VSS_MEDIA_ID_4GV_WB_MODEM 0x00010FC4
/*CDMA EVRC-WB vocoder modem format */
+#define VSS_MEDIA_ID_4GV_NW_MODEM 0x00010FC5
+/*CDMA EVRC-NW vocoder modem format */
#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2 0x000112BF
@@ -1231,6 +1234,8 @@
ul_cb_fn ul_cb;
dl_cb_fn dl_cb;
void *private_data;
+ uint32_t evrc_min_rate;
+ uint32_t evrc_max_rate;
};
struct dtmf_driver_info {
@@ -1366,7 +1371,9 @@
void voc_config_vocoder(uint32_t media_type,
uint32_t rate,
uint32_t network_type,
- uint32_t dtx_mode);
+ uint32_t dtx_mode,
+ uint32_t evrc_min_rate,
+ uint32_t evrc_max_rate);
enum {
DEV_RX = 0,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index de98feb..55f8dc8 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3231,8 +3231,11 @@
mutex_init(&card->dapm_power_mutex);
ret = snd_soc_instantiate_card(card);
- if (ret != 0)
+ if (ret != 0) {
soc_cleanup_card_debugfs(card);
+ if (card->rtd)
+ kfree(card->rtd);
+ }
return ret;