Merge "USB: gadget: mtp: Add module parameter for Rx transfer length"
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 2f2ea22..6af445b 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -3,6 +3,11 @@
Required properties:
- compatible : one of:
- "qcom,msm-vidc"
+- hfi : supported Host-Firmware Interface, one of:
+ - "venus"
+ - "q6"
+
+Optional properties:
- reg : offset and length of the register set for the device.
- interrupts : should contain the vidc interrupt.
- vidc-cp-map : start and size of device virtual address range for secure buffers.
@@ -13,9 +18,6 @@
or non-secure.
- load-freq-tbl : load (in macroblocks/sec) and corresponding vcodec clock
required for optimal performance in descending order.
-- hfi : supported Host-Firmware Interface, one of:
- - "venus"
- - "q6"
Example:
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 5bef9b8..22e43ab 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -20,6 +20,8 @@
images and self-authentication is not desired;
<1> if the hardware requires self-authenticating images.
- qcom,is-loadable: if PIL is required to load the modem image
+- qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
+- qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
Example:
qcom,mss@fc880000 {
@@ -38,4 +40,10 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth = <1>;
+
+ /* GPIO inputs from mss */
+ gpio_err_fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ gpio_force_stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 3d022a3..925c8eb 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -85,9 +85,11 @@
- qcom,msm-dai-q6-dev-id : The slimbus multi channel port ID
Value is from 16384 to 16393
BT SCO port ID value from 12288 to 12289
- RT Proxy port ID values from 224 to 225 and 240 to 241
+ RT Proxy port ID values from 224 to 225 and 240 to
+ 241
FM Rx and TX port ID values from 12292 to 12293
- incall record Rx and TX port ID values from 32771 to 32772
+ incall record Rx and TX port ID values from 32771 to
+ 32772
* msm-auxpcm
@@ -161,22 +163,24 @@
- qcom,msm_bus,num_cases: Total number of use cases
- - qcom,msm_bus,active_only: Context flag for requests in active or
- dual (active & sleep) contex
+ - qcom,msm_bus,active_only: Context flag for requests in active
+ or dual (active & sleep) contex
- qcom,msm_bus,num_paths: Total number of master-slave pairs
- - qcom,msm_bus,vectors: Arrays of unsigned integers representing:
- master-id, slave-id, arbitrated bandwidth,
- instantaneous bandwidth
+ - qcom,msm_bus,vectors: Arrays of unsigned integers
+ representing:
+ master-id, slave-id, arbitrated
+ bandwidth,
+ instantaneous bandwidth
* wcd9xxx_intc
Required properties:
- compatible : "qcom,wcd9xxx-irq"
- - interrupt-controller : Mark this device node as an interrupt
- controller
+ - interrupt-controller : Mark this device node as an
+ interrupt controller
- #interrupt-cells : Should be 1
@@ -442,25 +446,34 @@
Required properties:
- compatible : "qcom,msm-dai-q6-mi2s"
- - qcom,msm-dai-q6-mi2s-dev-id: MSM or MDM can use Slimbus or I2S interface to transfer data
- to (WCD9XXX) codec. If slimbus interface is used then
- "msm-dai-q6" needs to be filled with correct data for slimbus
- interface. The sections "msm-dai-mi2s" is used by MDM or MSM
- to use I2S interface with codec. This section is used by CPU
- driver in ASOC MSM to configure MI2S interface. MSM internally
- has multiple MI2S namely Primary, Secondary, Tertiary and
- Quaternary MI2S. They are represented with id 0, 1, 2, 3
- respectively. The field "qcom,msm-dai-q6-mi2s-dev-id" represents
- which of the MI2S block is used. These MI2S are connected to I2S
- interface.
+ - qcom,msm-dai-q6-mi2s-dev-id: MSM or MDM can use Slimbus or I2S interface to
+ transfer data to (WCD9XXX) codec.
+ If slimbus interface is used then "msm-dai-q6"
+ needs to be filled with correct data for
+ slimbus interface.
+ The sections "msm-dai-mi2s" is used by MDM or
+ MSM to use I2S interface with codec.
+ This section is used by CPU driver in ASOC MSM
+ to configure MI2S interface. MSM internally
+ has multiple MI2S namely Primary, Secondary,
+ Tertiary and Quaternary MI2S.
+ They are represented with id 0, 1, 2, 3
+ respectively.
+ The field "qcom,msm-dai-q6-mi2s-dev-id"
+ represents which of the MI2S block is used.
+ These MI2S are connected to I2S interface.
- - qcom,msm-mi2s-rx-lines: Each MI2S interface in MSM has one or more SD lines. These lines
- are used for data transfer between codec and MSM. This element in
- indicates which output RX lines are used in the MI2S interface.
+ - qcom,msm-mi2s-rx-lines: Each MI2S interface in MSM has one or more SD
+ lines. These lines are used for data transfer
+ between codec and MSM.
+ This element in indicates which output RX lines
+ are used in the MI2S interface.
- - qcom,msm-mi2s-tx-lines: Each MI2S interface in MSM has one or more SD lines. These lines
- are used for data transfer between codec and MSM. This element in
- indicates which input TX lines are used in the MI2S interface.
+ - qcom,msm-mi2s-tx-lines: Each MI2S interface in MSM has one or more SD
+ lines. These lines are used for data transfer
+ between codec and MSM.
+ This element in indicates which input TX lines
+ are used in the MI2S interface.
Example:
@@ -540,9 +553,9 @@
It is possible that some MSM use PIL to load the ADSP image. While
other MSM may use SBL to load the ADSP image at boot. Audio APR needs
state of ADSP to register and enable APR to be used for sending commands
- to ADSP. so adsp-state represents the state of ADSP to ADSP loader. Value
- of 0 indicates ADSP loader needs to use PIL and value of 2 means ADSP
- image is already loaded by SBL.
+ to ADSP. so adsp-state represents the state of ADSP to ADSP loader.
+ Value of 0 indicates ADSP loader needs to use PIL and value of 2 means
+ ADSP image is already loaded by SBL.
Example:
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index 74c25a0..989bea8 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -8,33 +8,39 @@
- qcom,cdc-reset-gpio: gpio used for codec SOC reset.
- <supply-name>-supply: phandle to the regulator device tree node
- - qcom,<supply-name>-voltage - specifies voltage levels for supply. Should be
- specified in pairs (min, max), units mV.
+ - qcom,<supply-name>-voltage - specifies voltage levels for supply.
+ Should be specified in pairs (min, max), units mV.
- qcom,<supply-name>-current - specifies max current in mA that can drawn
- from the <supply-name>.
+ from the <supply-name>.
- above three properties with "supply-name" set to "qcom,cdc-vdd-buck", "qcom,cdc-vdd-tx-h",
- "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1", "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1",
- "qcom,cdc-vddcx-2" should be present.
+ above three properties with "supply-name" set to "qcom,cdc-vdd-buck",
+ "qcom,cdc-vdd-tx-h", "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1",
+ "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1", "qcom,cdc-vddcx-2"
+ should be present.
- - qcom,cdc-micbias-ldoh-v - LDOH output in volts ( should be 1.95 V and 3.00 V).
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
- qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
- qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
- qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
- - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1 (should be from 1 to 3).
- - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2 (should be from 1 to 3).
- - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3 (should be from 1 to 3).
- - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4 (should be from 1 to 3).
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1
+ (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2
+ (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3
+ (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4
+ (should be from 1 to 3).
This value represents the connected CFLIT to MIC Bias.
- qcom,cdc-micbias1-ext-cap: Boolean. Enable micbias 1 external capacitor mode.
- qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
- qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
- qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
- - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for codec.
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
+ codec.
- qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
- qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
enumeration address.
@@ -97,33 +103,39 @@
- reg: represents the slave address provided to the I2C driver.
- qcom,cdc-reset-gpio: gpio used for codec SOC reset.
- <supply-name>-supply: phandle to the regulator device tree node.
- - qcom,<supply-name>-voltage - specifies voltage levels for supply. Should be
- specified in pairs (min, max), units mV.
+ - qcom,<supply-name>-voltage - specifies voltage levels for supply.
+ Should be specified in pairs (min, max), units mV.
- qcom,<supply-name>-current - specifies max current in mA that can drawn
- from the <supply-name>.
+ from the <supply-name>.
- above three properties with "supply-name" set to "qcom,cdc-vdd-buck", "qcom,cdc-vdd-tx-h",
- "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1", "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1",
- "qcom,cdc-vddcx-2" should be present.
+ above three properties with "supply-name" set to "qcom,cdc-vdd-buck",
+ "qcom,cdc-vdd-tx-h", "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1",
+ "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1", "qcom,cdc-vddcx-2"
+ should be present.
- - qcom,cdc-micbias-ldoh-v - LDOH output in volts ( should be 1.95 V and 3.00 V).
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
- qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
- qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
- qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
- - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1 (should be from 1 to 3).
- - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2 (should be from 1 to 3).
- - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3 (should be from 1 to 3).
- - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4 (should be from 1 to 3).
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1
+ (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2
+ (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3
+ (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4
+ (should be from 1 to 3).
This value represents the connected CFLIT to MIC Bias.
- qcom,cdc-micbias1-ext-cap: Boolean. Enable micbias 1 external capacitor mode.
- qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
- qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
- qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
- - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for codec.
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
+ codec.
Example:
i2c@f9925000 {
@@ -143,7 +155,8 @@
reg = <0x0d>;
qcom,cdc-reset-gpio = <&msmgpio 22 0>;
interrupt-parent = <&wcd9xxx_intc>;
- interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28>;
cdc-vdd-buck-supply = <&pm8019_l11>;
qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 8b7b31b..cc64765 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -75,6 +75,34 @@
<87 512 60000000 960000000>;
};
+MSM HSUSB EHCI controller
+
+Required properties :
+- compatible : should be "qcom,ehci-host"
+- reg : offset and length of the register set in the memory map
+- interrupts: IRQ lines used by this controller
+- 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".
+- qcom,usb2-power-budget: maximum vbus power (in mA) that can be provided.
+
+Optional properties :
+- qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
+
+Example MSM HSUSB EHCI controller device node :
+ ehci: qcom,ehci-host@f9a55000 {
+ compatible = "qcom,ehci-host";
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0>, <0 140 0>;
+ interrupt-names = "core_irq", "async_irq";
+ HSUSB_VDDCX-supply = <&pm8841_s2>;
+ HSUSB_1p8-supply = <&pm8941_l6>;
+ HSUSB_3p3-supply = <&pm8941_l24>;
+ qcom,usb2-enable-hsphy2;
+ qcom,usb2-power-budget = <500>;
+ };
+
ANDROID USB:
Required properties:
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
new file mode 100644
index 0000000..e107b36
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -0,0 +1,402 @@
+/* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ qcom,spm@f9089000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9089000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-spm-dly= <0x20000400>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ };
+
+ qcom,spm@f9099000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9099000 0x1000>;
+ qcom,core-id = <1>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-spm-dly= <0x20000400>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ };
+
+ qcom,spm@f90a9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90a9000 0x1000>;
+ qcom,core-id = <2>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-spm-dly= <0x20000400>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ };
+
+ qcom,spm@f90b9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90b9000 0x1000>;
+ qcom,core-id = <3>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-spm-dly= <0x20000400>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
+ 5b 80 10 2b 30 06 26 30 0f];
+ };
+
+ qcom,spm@f9012000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9012000 0x1000>;
+ qcom,core-id = <0xffff>; /* L2/APCS SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x20000400>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-pmic-data0 = <0x02030080>;
+ qcom,saw2-pmic-data1 = <0x00030000>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,pfm-port = <0x2>;
+ qcom,saw2-spm-cmd-ret = [0b 00 03 00 7b 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 0b 6b c0 e0 d0 42 07
+ 78 1f 80 4e d0 e0 c0 22 6b 50 4b 60 02 32 50 7b
+ 0f];
+ qcom,saw2-spm-cmd-pc = [00 32 60 70 80 b0 0b 10 e0 d0 6b c0
+ 42 f0 11 07 01 b0 78 1f 80 4e c0 d0 12 e0 6b 50 4b
+ 60 02 32 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ };
+
+ qcom,lpm-resources {
+ compatible = "qcom,lpm-resources";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-resources@0 {
+ reg = <0x0>;
+ qcom,name = "vdd-dig";
+ qcom,resource-type = <0>;
+ qcom,type = <0x62706d73>; /* "smpb" */
+ qcom,id = <0x02>;
+ qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value = <5>; /* Super Turbo */
+ };
+
+ qcom,lpm-resources@1 {
+ reg = <0x1>;
+ qcom,name = "vdd-mem";
+ qcom,resource-type = <0>;
+ qcom,type = <0x62706d73>; /* "smpb" */
+ qcom,id = <0x01>;
+ qcom,key = <0x7675>; /* "uv" */
+ qcom,init-value = <1050000>; /* Super Turbo */
+ };
+
+ qcom,lpm-resources@2 {
+ reg = <0x2>;
+ qcom,name = "pxo";
+ qcom,resource-type = <0>;
+ qcom,type = <0x306b6c63>; /* "clk0" */
+ qcom,id = <0x00>;
+ qcom,key = <0x62616e45>; /* "Enab" */
+ qcom,init-value = <1>; /* On */
+ };
+
+ qcom,lpm-resources@3 {
+ reg = <0x3>;
+ qcom,name = "l2";
+ qcom,resource-type = <1>;
+ qcom,init-value = <2>; /* Retention */
+ };
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = <0>; /* MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <1>;
+ qcom,ss-power = <784>;
+ qcom,energy-overhead = <190000>;
+ qcom,time-overhead = <100>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = <4>; /* MSM_PM_SLEEP_MODE_RETENTION*/
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <75>;
+ qcom,ss-power = <735>;
+ qcom,energy-overhead = <77341>;
+ qcom,time-overhead = <105>;
+ };
+
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = <2>; /* MSM_PM_SLEEP_MODE_STANDALONE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <95>;
+ qcom,ss-power = <725>;
+ qcom,energy-overhead = <99500>;
+ qcom,time-overhead = <130>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <1>; /* GDHS */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <2000>;
+ qcom,ss-power = <138>;
+ qcom,energy-overhead = <1208400>;
+ qcom,time-overhead = <3200>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <1>; /* ON */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
+ qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
+ qcom,vdd-dig-lower-bound = <2>; /* RETENTION HIGH */
+ qcom,latency-us = <3000>;
+ qcom,ss-power = <110>;
+ qcom,energy-overhead = <1250300>;
+ qcom,time-overhead = <3500>;
+ };
+
+ qcom,lpm-level@5 {
+ reg = <0x5>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <1>; /* GDHS */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <3000>;
+ qcom,ss-power = <68>;
+ qcom,energy-overhead = <1350200>;
+ qcom,time-overhead = <4000>;
+ };
+
+ qcom,lpm-level@6 {
+ reg = <0x6>;
+ qcom,mode = <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
+ qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-dig-upper-bound = <5>; /* MAX */
+ qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,latency-us = <10300>;
+ qcom,ss-power = <63>;
+ qcom,energy-overhead = <2128000>;
+ qcom,time-overhead = <18200>;
+ };
+
+ qcom,lpm-level@7 {
+ reg = <0x7>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
+ qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
+ qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
+ qcom,vdd-dig-lower-bound = <2>; /* RETIONTION HIGH */
+ qcom,latency-us = <18000>;
+ qcom,ss-power = <10>;
+ qcom,energy-overhead = <3202600>;
+ qcom,time-overhead = <27000>;
+ };
+
+ qcom,lpm-level@8 {
+ reg = <0x8>;
+ qcom,mode= <3>; /* MSM_PM_SLEEP_MODE_POWER_COLLAPSE */
+ qcom,xo = <0>; /* OFF */
+ qcom,l2 = <0>; /* OFF */
+ qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
+ qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
+ qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
+ qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
+ qcom,latency-us = <20000>;
+ qcom,ss-power = <2>;
+ qcom,energy-overhead = <4252000>;
+ qcom,time-overhead = <32000>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = <0>; /* MSM_PM_BOOT_CONFIG_TZ */
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 173>, /* o_wcss_apss_smd_hi */
+ <0xff 174>, /* o_wcss_apss_smd_med */
+ <0xff 175>, /* o_wcss_apss_smd_low */
+ <0xff 176>, /* o_wcss_apss_smsm_irq */
+ <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+ <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+ <0xff 179>, /* o_wcss_apss_asic_intr
+
+ <0xff 188>, /* lpass_irq_out_apcs(0) */
+ <0xff 189>, /* lpass_irq_out_apcs(1) */
+ <0xff 190>, /* lpass_irq_out_apcs(2) */
+ <0xff 191>, /* lpass_irq_out_apcs(3) */
+ <0xff 192>, /* lpass_irq_out_apcs(4) */
+ <0xff 193>, /* lpass_irq_out_apcs(5) */
+ <0xff 194>, /* lpass_irq_out_apcs(6) */
+ <0xff 195>, /* lpass_irq_out_apcs(7) */
+ <0xff 196>, /* lpass_irq_out_apcs(8) */
+ <0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 240>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <3 102>,
+ <4 1 >,
+ <5 5 >,
+ <6 9 >,
+ <7 18>,
+ <8 20>,
+ <9 24>,
+ <10 27>,
+ <11 28>,
+ <12 34>,
+ <13 35>,
+ <14 37>,
+ <15 42>,
+ <16 44>,
+ <17 46>,
+ <18 50>,
+ <19 54>,
+ <20 59>,
+ <21 61>,
+ <22 62>,
+ <23 64>,
+ <24 65>,
+ <25 66>,
+ <26 67>,
+ <27 68>,
+ <28 71>,
+ <29 72>,
+ <30 73>,
+ <31 74>,
+ <32 75>,
+ <33 77>,
+ <34 79>,
+ <35 80>,
+ <36 82>,
+ <37 86>,
+ <38 92>,
+ <39 93>,
+ <40 95>;
+ };
+
+ qcom,pc-cntr@fe805664 {
+ compatible = "qcom,pc-cntr";
+ reg = <0xfe805664 0x40>;
+ };
+
+ qcom,pm-8x60 {
+ compatible = "qcom,pm-8x60";
+ qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
+ qcom,use-sync-timer;
+ };
+
+ qcom,rpm-stats@0xfc19dbd0{
+ compatible = "qcom,rpm-stats";
+ reg = <0xfc19dbd0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 854a708..9f0ff92 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -14,6 +14,7 @@
/include/ "msm8226-ion.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8226-iommu.dtsi"
+/include/ "msm8226-pm.dtsi"
/ {
model = "Qualcomm MSM 8226";
@@ -388,6 +389,13 @@
};
};
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-smd";
+ rpm-channel-name = "rpm_requests";
+ rpm-channel-type = <15>; /* SMD_APPS_RPM */
+ rpm-standalone;
+ };
+
sdcc1: qcom,sdcc@f9824000 {
cell-index = <1>; /* SDC1 eMMC slot */
compatible = "qcom,msm-sdcc";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 4d00d2b..b80a1c5 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -46,6 +46,11 @@
clock-frequency = <19200000>;
};
+ qcom,msm-adsp-loader {
+ compatible = "qcom,adsp-loader";
+ qcom,adsp-state = <0>;
+ };
+
serial@f991f000 {
compatible = "qcom,msm-lsuart-v14";
reg = <0xf991f000 0x1000>;
@@ -53,6 +58,11 @@
status = "disabled";
};
+ qcom,vidc@fdc00000 {
+ compatible = "qcom,msm-vidc";
+ hfi = "q6";
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
@@ -308,6 +318,15 @@
<0x155000cf>; /* LDO_22 */
};
+ qcom,lpass@fe200000 {
+ compatible = "qcom,pil-q6v5-lpass";
+ reg = <0xfe200000 0x00100>,
+ <0xfd485100 0x00010>;
+ reg-names = "qdsp6_base", "halt_base";
+ interrupts = <0 162 1>;
+
+ qcom,firmware-name = "adsp";
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
new file mode 100644
index 0000000..60f63a8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -0,0 +1,194 @@
+/* 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.
+ */
+/ {
+ qcom,smp2p-modem {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-adsp {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 158 1>;
+ };
+
+ qcom,smp2p-wcnss {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <4>;
+ qcom,irq-bitmask = <0x40000>;
+ interrupts = <0 143 1>;
+ };
+
+ /* SMP2P Test Driver for inbound entries */
+ smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+ gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+ };
+
+ /* SMP2P Test Driver for outbound entries */
+ smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+ gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+ };
+
+ /* SMP2P Test Driver for modem inbound */
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ /* SMP2P Test Driver for modem output */
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ /* SMP2P SSR Driver for inbound entry from modem. */
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* SMP2P SSR Driver for outbound entry to modem */
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* SMP2P Test Driver for adsp inbound */
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ /* SMP2P Test Driver for adsp output */
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ /* SMP2P Test Driver for wcnss inbound */
+ smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+ gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+ };
+
+ /* SMP2P Test Driver for wcnss output */
+ smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+ gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index ca2b3a2..ac869f2 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -19,6 +19,7 @@
/include/ "msm8974-ion.dtsi"
/include/ "msm8974-gpu.dtsi"
/include/ "msm8974-mdss.dtsi"
+/include/ "msm8974-smp2p.dtsi"
/ {
model = "Qualcomm MSM 8974";
@@ -896,6 +897,12 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth = <1>;
+
+ /* GPIO input from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
qcom,pronto@fb21b000 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index d374b59..7e32126 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -81,7 +81,7 @@
vbus_otg-supply = <&usb_vbus>;
qcom,hsusb-otg-phy-type = <2>;
- qcom,hsusb-otg-mode = <3>;
+ qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-disable-reset;
};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 463ce85..6793a65 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -47,6 +47,9 @@
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y
# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_LPASS_QDSP6V5=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_ADSP_LOADER=m
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 53c97ce..94009bc 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -339,6 +339,7 @@
CONFIG_MFD_PM8XXX_BATT_ALARM=y
CONFIG_WCD9304_CODEC=y
CONFIG_WCD9310_CODEC=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_MSM_GPIO=y
CONFIG_MEDIA_SUPPORT=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 2d97769..6efdafa 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -344,6 +344,7 @@
CONFIG_MFD_PM8XXX_BATT_ALARM=y
CONFIG_WCD9304_CODEC=y
CONFIG_WCD9310_CODEC=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_MSM_GPIO=y
CONFIG_MEDIA_SUPPORT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 7476e12..76a13f9 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -45,6 +45,8 @@
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
CONFIG_MSM_IPC_LOGGING=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
@@ -343,6 +345,7 @@
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_MSM=y
CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 4176e68..f025ab3 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -44,6 +44,8 @@
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
CONFIG_MSM_IPC_LOGGING=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
@@ -346,6 +348,7 @@
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_MSM=y
CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0cf684d..baaa09d 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -393,6 +393,9 @@
select MSM_NATIVE_RESTART
select MSM_RESTART_V2
select QMI_ENCDEC
+ select MSM_QDSP6_APRV2
+ select MSM_QDSP6V2_CODECS
+ select MSM_AUDIO_QDSP6V2 if SND_SOC
config ARCH_MSM8226
bool "MSM8226"
@@ -412,6 +415,10 @@
select MSM_QDSP6V2_CODECS
select MSM_AUDIO_QDSP6V2 if SND_SOC
select QMI_ENCDEC
+ select MSM_RPM_SMD
+ select MSM_SPM_V2
+ select MSM_L2_SPM
+ select MSM_PM8X60 if PM
endmenu
choice
@@ -529,7 +536,7 @@
config MSM_LPM_TEST
bool "Low Power Mode test framework"
- depends on MSM_RPM
+ depends on MSM_RPM || MSM_RPM_SMD
depends on MSM_PM8X60
help
LPM_TEST is a test framework that assists in exercising the low
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 16b53fb..57ecc27 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -458,6 +458,16 @@
.active_low = _active_low, \
}
+#define FIXED_VREG_INIT(_id, _supply_regulator) \
+ { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ }, \
+ .num_consumer_supplies = ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }
+
#define SAW_VREG_INIT(_id, _name, _min_uV, _max_uV) \
{ \
.constraints = { \
@@ -597,6 +607,17 @@
SX150X_GPIO(4, 15), "avc_5v", 0),
};
+/* Fixed regulator constraints */
+static struct regulator_init_data mpq8064_3p3_regulator_init =
+ /* ID supply */
+ FIXED_VREG_INIT(EXT_3P3V, NULL);
+
+struct fixed_voltage_config mpq8064_3p3_regulator_pdata = {
+ .supply_name = "ext_3p3v",
+ .gpio = -EINVAL,
+ .init_data = &mpq8064_3p3_regulator_init,
+};
+
/* SAW regulator constraints */
struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
/* ID vreg_name min_uV max_uV */
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 4898525..476a191 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2493,6 +2493,13 @@
}
}
+static struct platform_device mpq8064_device_ext_3p3v_vreg = {
+ .name = "reg-fixed-voltage",
+ .dev = {
+ .platform_data = &mpq8064_3p3_regulator_pdata,
+ },
+};
+
static struct platform_device apq8064_device_ext_5v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = PM8921_MPP_PM_TO_SYS(7),
@@ -2604,6 +2611,7 @@
static struct platform_device *pm8921_mpq_hrd_common_devices[] __initdata = {
&apq8064_device_ext_5v_vreg,
&apq8064_device_ext_mpp8_vreg,
+ &mpq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
};
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 4cdf939..adc037b 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -14,6 +14,7 @@
#define __ARCH_ARM_MACH_MSM_BOARD_APQ8064_H
#include <linux/regulator/msm-gpio-regulator.h>
+#include <linux/regulator/fixed.h>
#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/mfd/pm8xxx/pm8821.h>
#include <mach/msm_memtypes.h>
@@ -65,6 +66,8 @@
extern struct gpio_regulator_platform_data
mpq8064_gpio_regulator_pdata[] __devinitdata;
+extern struct fixed_voltage_config mpq8064_3p3_regulator_pdata;
+
extern struct rpm_regulator_platform_data
apq8064_rpm_regulator_pdata __devinitdata;
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index a83387f..3a6eb7f 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -42,9 +42,14 @@
#include <mach/socinfo.h>
#include <mach/board.h>
#include <mach/clk-provider.h>
+#include <mach/msm_smd.h>
+#include <mach/rpm-smd.h>
+#include <linux/msm_thermal.h>
#include "board-dt.h"
#include "clock.h"
#include "platsmp.h"
+#include "spm.h"
+#include "lpm_resources.h"
static struct memtype_reserve msm8226_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
@@ -121,6 +126,15 @@
msm_reserve();
}
+
+void __init msm8226_add_drivers(void)
+{
+ msm_rpm_driver_init();
+ msm_lpmrs_module_init();
+ msm_spm_device_init();
+ msm_thermal_device_init();
+}
+
void __init msm8226_init(void)
{
struct of_dev_auxdata *adata = msm8226_auxdata_lookup;
@@ -129,8 +143,10 @@
pr_err("%s: socinfo_init() failed\n", __func__);
msm8226_init_gpiomux();
+ msm8226_add_drivers();
msm_clock_init(&msm_dummy_clock_init_data);
of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+
}
static const char *msm8226_dt_match[] __initconst = {
@@ -140,7 +156,7 @@
DT_MACHINE_START(MSM8226_DT, "Qualcomm MSM 8226 (Flattened Device Tree)")
.map_io = msm_map_msm8226_io,
- .init_irq = msm_dt_init_irq_nompm,
+ .init_irq = msm_dt_init_irq,
.init_machine = msm8226_init,
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index b1e107d..ac93b00 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index ed7d43f..2fdceae 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -300,6 +300,8 @@
static struct of_dev_auxdata msm8974_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
"msm_otg", NULL),
+ OF_DEV_AUXDATA("qcom,ehci-host", 0xF9A55000, \
+ "msm_ehci_host", NULL),
OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
"msm_dwc3", NULL),
OF_DEV_AUXDATA("qcom,usb-bam-msm", 0xF9304000, \
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 30229e1..159f151 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -1272,6 +1272,8 @@
.cbcr_reg = LPASS_Q6_AXI_CBCR,
.has_sibling = 1,
.base = &virt_bases[GCC_BASE],
+ /* FIXME: Remove this once simulation is fixed. */
+ .halt_check = DELAY,
.c = {
.dbg_name = "gcc_lpass_q6_axi_clk",
.ops = &clk_ops_branch,
@@ -1735,6 +1737,8 @@
.cbcr_reg = BIMC_GFX_CBCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
+ /* FIXME: Remove this once simulation is fixed. */
+ .halt_check = DELAY,
.c = {
.dbg_name = "bimc_gfx_clk",
.ops = &clk_ops_branch,
@@ -1843,7 +1847,7 @@
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
- .parent = &csi0_clk_src.c,
+ .parent = &csi1_clk_src.c,
.dbg_name = "csi1pix_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi1pix_clk.c),
@@ -1855,7 +1859,7 @@
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
- .parent = &csi0_clk_src.c,
+ .parent = &csi1_clk_src.c,
.dbg_name = "csi1rdi_clk",
.ops = &clk_ops_branch,
CLK_INIT(csi1rdi_clk.c),
@@ -1995,6 +1999,8 @@
.cbcr_reg = MDP_AXI_CBCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
+ /* FIXME: Remove this once simulation is fixed. */
+ .halt_check = DELAY,
.c = {
.parent = &axi_clk_src.c,
.dbg_name = "mdp_axi_clk",
@@ -2148,6 +2154,8 @@
.cbcr_reg = VFE_AXI_CBCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
+ /* FIXME: Remove this once simulation is fixed. */
+ .halt_check = DELAY,
.c = {
.parent = &axi_clk_src.c,
.dbg_name = "vfe_axi_clk",
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index eb16eae..a48bf94 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5174,6 +5174,9 @@
CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
CLK_LOOKUP("ref_clk", div_clk2.c, "msm_smsc_hub"),
+ CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_ehci_host"),
+ CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "msm_ehci_host"),
+ CLK_LOOKUP("sleep_clk", gcc_usb2b_phy_sleep_clk.c, "msm_ehci_host"),
CLK_LOOKUP("pwm_clk", div_clk2.c, "0-0048"),
/* Multimedia clocks */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index c7a0238..5b4f00e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -105,6 +105,7 @@
MSM_CPU_7X25AB,
MSM_CPU_8064,
MSM_CPU_8064AB,
+ MSM_CPU_8064AA,
MSM_CPU_8930,
MSM_CPU_8930AA,
MSM_CPU_8930AB,
@@ -332,6 +333,15 @@
#endif
}
+static inline int cpu_is_apq8064aa(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+ return read_msm_cpu_type() == MSM_CPU_8064AA;
+#else
+ return 0;
+#endif
+}
+
static inline int cpu_is_msm8930(void)
{
#ifdef CONFIG_ARCH_MSM8930
@@ -473,7 +483,7 @@
static inline int soc_class_is_apq8064(void)
{
- return cpu_is_apq8064() || cpu_is_apq8064ab();
+ return cpu_is_apq8064() || cpu_is_apq8064ab() || cpu_is_apq8064aa();
}
static inline int soc_class_is_msm8930(void)
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 61c2aa8..b84d345 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -37,6 +37,10 @@
static struct msm_rpmrs_level *msm_lpm_levels;
static int msm_lpm_level_count;
+static DEFINE_PER_CPU(uint32_t , msm_lpm_sleep_time);
+static DEFINE_PER_CPU(int , lpm_permitted_level);
+static DEFINE_PER_CPU(struct atomic_notifier_head, lpm_notify_head);
+
static void msm_lpm_level_update(void)
{
unsigned int lpm_level;
@@ -55,6 +59,12 @@
int ret = 0;
int debug_mask;
struct msm_rpmrs_limits *l = (struct msm_rpmrs_limits *)limits;
+ struct msm_lpm_sleep_data sleep_data;
+
+ sleep_data.limits = limits;
+ sleep_data.kernel_sleep = __get_cpu_var(msm_lpm_sleep_time);
+ atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+ MSM_LPM_STATE_ENTER, &sleep_data);
ret = msm_rpm_enter_sleep();
if (ret) {
@@ -88,6 +98,8 @@
msm_rpm_exit_sleep();
msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
from_idle, notify_rpm, collapsed);
+ atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
+ MSM_LPM_STATE_EXIT, NULL);
}
void msm_lpm_show_resources(void)
@@ -96,6 +108,48 @@
return;
}
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits)
+{
+ return limits->pxo;
+}
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits)
+{
+ return limits->l2_cache;
+}
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits)
+{
+ return limits->vdd_mem_upper_bound;
+}
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits)
+{
+ return limits->vdd_dig_upper_bound;
+}
+
+static bool lpm_level_permitted(int cur_level_count)
+{
+ if (__get_cpu_var(lpm_permitted_level) == msm_lpm_level_count + 1)
+ return true;
+ return (__get_cpu_var(lpm_permitted_level) == cur_level_count);
+}
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+ struct notifier_block *nb, bool is_latency_measure)
+{
+ per_cpu(lpm_permitted_level, cpu) = level_iter;
+ return atomic_notifier_chain_register(&per_cpu(lpm_notify_head,
+ cpu), nb);
+}
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb)
+{
+ per_cpu(lpm_permitted_level, cpu) = msm_lpm_level_count + 1;
+ return atomic_notifier_chain_unregister(&per_cpu(lpm_notify_head, cpu),
+ nb);
+}
+
s32 msm_cpuidle_get_deep_idle_latency(void)
{
int i;
@@ -127,7 +181,7 @@
struct msm_rpmrs_level *best_level = NULL;
uint32_t pwr;
int i;
-
+ int best_level_iter = msm_lpm_level_count + 1;
if (!msm_lpm_levels)
return NULL;
@@ -170,14 +224,31 @@
level->rs_limits.latency_us[cpu] = level->latency_us;
level->rs_limits.power[cpu] = pwr;
best_level = level;
-
+ best_level_iter = i;
if (power)
*power = pwr;
}
}
+ if (best_level && !lpm_level_permitted(best_level_iter))
+ best_level = NULL;
+ else
+ per_cpu(msm_lpm_sleep_time, cpu) =
+ time_param->modified_time_us ?
+ time_param->modified_time_us : time_param->sleep_us;
return best_level ? &best_level->rs_limits : NULL;
}
+
+static struct lpm_test_platform_data lpm_test_pdata;
+
+static struct platform_device msm_lpm_test_device = {
+ .name = "lpm_test",
+ .id = -1,
+ .dev = {
+ .platform_data = &lpm_test_pdata,
+ },
+};
+
static struct msm_pm_sleep_ops msm_lpm_ops = {
.lowest_limits = msm_lpm_lowest_limits,
.enter_sleep = msm_lpm_enter_sleep,
@@ -194,6 +265,7 @@
int ret = 0;
uint32_t num_levels = 0;
int idx = 0;
+ unsigned int m_cpu = 0;
for_each_child_of_node(pdev->dev.of_node, node)
num_levels++;
@@ -279,6 +351,14 @@
msm_lpm_levels = levels;
msm_lpm_level_count = idx;
+ lpm_test_pdata.msm_lpm_test_levels = msm_lpm_levels;
+ lpm_test_pdata.msm_lpm_test_level_count = msm_lpm_level_count;
+
+ for_each_possible_cpu(m_cpu)
+ per_cpu(lpm_permitted_level, m_cpu) =
+ msm_lpm_level_count + 1;
+
+ platform_device_register(&msm_lpm_test_device);
msm_pm_set_sleep_ops(&msm_lpm_ops);
return 0;
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 120832f..42e43c2 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
#define __ARCH_ARM_MACH_MSM_LPM_RESOURCES_H
#include "pm.h"
+#include "test-lpm.h"
enum {
MSM_LPM_PXO_OFF = 0,
@@ -50,6 +51,93 @@
uint32_t time_overhead_us;
};
+enum {
+ MSM_LPM_STATE_ENTER = 0,
+ MSM_LPM_STATE_EXIT = 1,
+};
+
+#define MSM_PM(field) MSM_LPM_##field
+
+/**
+ * msm_pm_get_pxo() - get the limits for pxo
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource pxo on
+ * 8974
+ */
+
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_l2_cache() - get the limits for l2 cache
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource l2 cache
+ * on 8974
+ */
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_mem() - get the limits for pxo
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd mem
+ * on 8974
+ */
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_dig() - get the limits for vdd dig
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource on 8974
+ */
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
+
+/**
+ * struct msm_lpm_sleep_data - abstraction to get sleep data
+ * @limits: pointer to the msm_rpmrs_limits structure
+ * @kernel_sleep: kernel sleep time as decided by the power calculation
+ * algorithm
+ *
+ * This structure is an abstraction to get the limits and kernel sleep time
+ * during enter sleep.
+ */
+
+struct msm_lpm_sleep_data {
+ struct msm_rpmrs_limits *limits;
+ uint32_t kernel_sleep;
+};
+
+/**
+ * msm_lpm_register_notifier() - register for notifications
+ * @cpu: cpu to debug
+ * @level_iter: low power level index to debug
+ * @nb: notifier block to callback on notifications
+ * @is_latency_measure: is it latency measure
+ *
+ * This function sets the permitted level to the index of the
+ * level under test and registers notifier for callback.
+ */
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+ struct notifier_block *nb, bool is_latency_measure);
+
+/**
+ * msm_lpm_unregister_notifier() - unregister from notifications
+ * @cpu: cpu to debug
+ * @nb: notifier block to callback on notifications
+ *
+ * This function sets the permitted level to a value one more than
+ * available levels count which indicates that all levels are
+ * permitted and it also unregisters notifier for callback.
+ */
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
+
#ifdef CONFIG_MSM_RPM_SMD
/**
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index ed85c95..7cf61ab 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
#include <mach/subsystem_restart.h>
#include <mach/clk.h>
@@ -87,6 +88,8 @@
bool crash_shutdown;
bool ignore_errors;
int is_loadable;
+ int err_fatal_irq;
+ int force_stop_gpio;
};
static int pbl_mba_boot_timeout_ms = 100;
@@ -442,18 +445,17 @@
subsystem_restart_dev(drv->subsys);
}
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
{
- struct mba_data *drv = data;
+ struct mba_data *drv = dev_id;
- /* Ignore if we're the one that set SMSM_RESET */
+ /* Ignore if we're the one that set the force stop GPIO */
if (drv->crash_shutdown)
- return;
+ return IRQ_HANDLED;
- if (new_state & SMSM_RESET) {
- pr_err("Probable fatal error on the modem.\n");
- restart_modem(drv);
- }
+ pr_err("Fatal error on the modem.\n");
+ restart_modem(drv);
+ return IRQ_HANDLED;
}
static int modem_shutdown(const struct subsys_desc *subsys)
@@ -493,7 +495,7 @@
{
struct mba_data *drv = subsys_to_drv(subsys);
drv->crash_shutdown = true;
- smsm_reset_modem(SMSM_RESET);
+ gpio_set_value(drv->force_stop_gpio, 1);
}
static struct ramdump_segment smem_segments[] = {
@@ -630,10 +632,11 @@
goto err_irq;
}
- ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, drv);
+ ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
+ modem_err_fatal_intr_handler,
+ IRQF_TRIGGER_RISING, "pil-mss", drv);
if (ret < 0) {
- dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
+ dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
goto err_irq;
}
@@ -643,14 +646,11 @@
ret = PTR_ERR(drv->adsp_state_notifier);
dev_err(&pdev->dev, "%s: Registration with the SSR notification driver failed (%d)",
__func__, ret);
- goto err_smsm;
+ goto err_irq;
}
return 0;
-err_smsm:
- smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET, smsm_state_cb,
- drv);
err_irq:
destroy_ramdump_device(drv->smem_ramdump_dev);
err_ramdump_smem:
@@ -759,7 +759,7 @@
static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
{
struct mba_data *drv;
- int ret;
+ int ret, err_fatal_gpio;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -774,6 +774,22 @@
return ret;
}
+ /* Get the IRQ from the GPIO for registering inbound handler */
+ err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-err-fatal", 0);
+ if (err_fatal_gpio < 0)
+ return err_fatal_gpio;
+
+ drv->err_fatal_irq = gpio_to_irq(err_fatal_gpio);
+ if (drv->err_fatal_irq < 0)
+ return drv->err_fatal_irq;
+
+ /* Get the GPIO pin for writing the outbound bits: add more as needed */
+ drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-force-stop", 0);
+ if (drv->force_stop_gpio < 0)
+ return drv->force_stop_gpio;
+
return pil_subsys_init(drv, pdev);
}
@@ -783,8 +799,6 @@
subsys_notif_unregister_notifier(drv->adsp_state_notifier,
&adsp_state_notifier_block);
- smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, drv);
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->smem_ramdump_dev);
destroy_ramdump_device(drv->ramdump_dev);
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_tal.c b/arch/arm/mach-msm/qdsp6v2/apr_tal.c
index 03f0513..d734739 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_tal.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_tal.c
@@ -133,12 +133,12 @@
spin_unlock_irqrestore(&apr_ch->lock, flags);
break;
case SMD_EVENT_OPEN:
- pr_info("apr_tal: SMD_EVENT_OPEN\n");
+ pr_debug("apr_tal: SMD_EVENT_OPEN\n");
apr_ch->smd_state = 1;
wake_up(&apr_ch->wait);
break;
case SMD_EVENT_CLOSE:
- pr_info("apr_tal: SMD_EVENT_CLOSE\n");
+ pr_debug("apr_tal: SMD_EVENT_CLOSE\n");
break;
}
}
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_v2.c b/arch/arm/mach-msm/qdsp6v2/apr_v2.c
index ed494e4..f554cf3 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_v2.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_v2.c
@@ -50,16 +50,16 @@
pr_err("%s: adsp not up\n", __func__);
return NULL;
}
- pr_info("%s: adsp Up\n", __func__);
+ pr_debug("%s: adsp Up\n", __func__);
} else if ((dest_id == APR_DEST_MODEM) &&
(apr_get_modem_state() == APR_SUBSYS_DOWN)) {
- pr_info("%s: Wait for modem to bootup\n", __func__);
+ pr_debug("%s: Wait for modem to bootup\n", __func__);
rc = apr_wait_for_device_up(dest_id);
if (rc == 0) {
pr_err("%s: Modem is not Up\n", __func__);
return NULL;
}
- pr_info("%s: modem Up\n", __func__);
+ pr_debug("%s: modem Up\n", __func__);
}
if (apr_get_svc(svc_name, dest_id, &client_id, &svc_idx, &svc_id)) {
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index ad5f1b5..67ef0ad 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1,6 +1,6 @@
/* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2013, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -861,10 +861,9 @@
}
param.msw_ts = buf_node->meta_info.meta_in.ntimestamp.highpart;
param.lsw_ts = buf_node->meta_info.meta_in.ntimestamp.lowpart;
+ param.flags = buf_node->meta_info.meta_in.nflags;
/* If no meta_info enaled, indicate no time stamp valid */
- if (audio->buf_cfg.meta_info_enable)
- param.flags = 0;
- else
+ if (!audio->buf_cfg.meta_info_enable)
param.flags = 0xFF00;
if ((buf_node != NULL) &&
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
index 5ffffd2..de4e1f0 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, Code Aurora Forum. 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
@@ -16,7 +16,7 @@
#define __Q6_AUDIO_COMMON_H__
#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM9625) \
- || defined(CONFIG_ARCH_MSM8226)
+ || defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610)
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 26a1eb3..ee459d6 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -320,6 +320,8 @@
[169] = MSM_CPU_8625Q,
[170] = MSM_CPU_8625Q,
+ /* 8064AA IDs */
+ [172] = MSM_CPU_8064AA,
/* Uninitialized IDs are not known to run Linux.
MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
diff --git a/arch/arm/mach-msm/test-lpm.c b/arch/arm/mach-msm/test-lpm.c
index dbc8100..031b2dc 100644
--- a/arch/arm/mach-msm/test-lpm.c
+++ b/arch/arm/mach-msm/test-lpm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,9 @@
#if defined(CONFIG_MSM_RPM)
#include "rpm_resources.h"
#endif
+#if defined(CONFIG_MSM_RPM_SMD)
+#include "lpm_resources.h"
+#endif
#include "timer.h"
#include "test-lpm.h"
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 4eac9cb..ab9e83a 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -895,10 +895,7 @@
len = ALIGN(len, pce_dev->ce_sps.ce_burst_size);
while (len > 0) {
if (len > SPS_MAX_PKT_SIZE) {
- if ((len % SPS_MAX_PKT_SIZE) > 0)
- data_cnt = (len % SPS_MAX_PKT_SIZE);
- else
- data_cnt = SPS_MAX_PKT_SIZE;
+ data_cnt = SPS_MAX_PKT_SIZE;
iovec->size = data_cnt;
iovec->addr = addr;
iovec->flags = 0;
@@ -1251,8 +1248,27 @@
notify->data.transfer.iovec.addr,
notify->data.transfer.iovec.size,
notify->data.transfer.iovec.flags);
- /* done */
- _aead_complete(pce_dev);
+
+ if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+ /* done */
+ _aead_complete(pce_dev);
+ } else {
+ int rc = 0;
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+ pce_dev->ce_sps.out_transfer.iovec_count = 0;
+ _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+ CRYPTO_RESULT_DUMP_SIZE,
+ &pce_dev->ce_sps.out_transfer);
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+ rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
+ &pce_dev->ce_sps.out_transfer);
+ if (rc) {
+ pr_err("sps_xfr() fail (producer pipe=0x%x) rc = %d,",
+ (u32)pce_dev->ce_sps.producer.pipe, rc);
+ }
+ }
};
static void _aead_sps_consumer_callback(struct sps_event_notify *notify)
@@ -1307,8 +1323,27 @@
notify->data.transfer.iovec.addr,
notify->data.transfer.iovec.size,
notify->data.transfer.iovec.flags);
- /* done */
- _ablk_cipher_complete(pce_dev);
+
+ if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+ /* done */
+ _ablk_cipher_complete(pce_dev);
+ } else {
+ int rc = 0;
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+ pce_dev->ce_sps.out_transfer.iovec_count = 0;
+ _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+ CRYPTO_RESULT_DUMP_SIZE,
+ &pce_dev->ce_sps.out_transfer);
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+ rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
+ &pce_dev->ce_sps.out_transfer);
+ if (rc) {
+ pr_err("sps_xfr() fail (producer pipe=0x%x) rc = %d,",
+ (u32)pce_dev->ce_sps.producer.pipe, rc);
+ }
+ }
};
static void _ablk_cipher_sps_consumer_callback(struct sps_event_notify *notify)
@@ -2258,7 +2293,6 @@
pr_err("Producer callback registration failed rc = %d\n", rc);
goto bad;
}
-
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.consumer.event.callback = _aead_sps_consumer_callback;
rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
@@ -2283,11 +2317,21 @@
_qce_sps_add_sg_data(pce_dev, areq->dst, out_len +
areq->assoclen + hw_pad_out,
&pce_dev->ce_sps.out_transfer);
- _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+ if (totallen_in > SPS_MAX_PKT_SIZE) {
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ pce_dev->ce_sps.producer.event.options =
+ SPS_O_DESC_DONE;
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+ } else {
+ _qce_sps_add_data(GET_PHYS_ADDR(
+ pce_dev->ce_sps.result_dump),
CRYPTO_RESULT_DUMP_SIZE,
- &pce_dev->ce_sps.out_transfer);
- _qce_set_flag(&pce_dev->ce_sps.out_transfer,
- SPS_IOVEC_FLAG_INT);
+ &pce_dev->ce_sps.out_transfer);
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+ }
} else {
_qce_sps_add_sg_data(pce_dev, areq->assoc, areq->assoclen,
&pce_dev->ce_sps.in_transfer);
@@ -2307,11 +2351,21 @@
/* Pass through to ignore hw_pad (padding of the MAC data) */
_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.ignore_buffer),
hw_pad_out, &pce_dev->ce_sps.out_transfer);
-
- _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
- CRYPTO_RESULT_DUMP_SIZE, &pce_dev->ce_sps.out_transfer);
- _qce_set_flag(&pce_dev->ce_sps.out_transfer,
- SPS_IOVEC_FLAG_INT);
+ if (totallen_in > SPS_MAX_PKT_SIZE) {
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ pce_dev->ce_sps.producer.event.options =
+ SPS_O_DESC_DONE;
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+ } else {
+ _qce_sps_add_data(
+ GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+ CRYPTO_RESULT_DUMP_SIZE,
+ &pce_dev->ce_sps.out_transfer);
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+ }
}
rc = _qce_sps_transfer(pce_dev);
if (rc)
@@ -2395,7 +2449,6 @@
pr_err("Producer callback registration failed rc = %d\n", rc);
goto bad;
}
-
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.consumer.event.callback =
_ablk_cipher_sps_consumer_callback;
@@ -2417,10 +2470,19 @@
_qce_sps_add_sg_data(pce_dev, areq->dst, areq->nbytes,
&pce_dev->ce_sps.out_transfer);
- _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+ if (areq->nbytes > SPS_MAX_PKT_SIZE) {
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+ } else {
+ pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+ _qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
CRYPTO_RESULT_DUMP_SIZE,
&pce_dev->ce_sps.out_transfer);
- _qce_set_flag(&pce_dev->ce_sps.out_transfer, SPS_IOVEC_FLAG_INT);
+ _qce_set_flag(&pce_dev->ce_sps.out_transfer,
+ SPS_IOVEC_FLAG_INT);
+ }
rc = _qce_sps_transfer(pce_dev);
if (rc)
goto bad;
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index 7a7aacc..8533636 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, Code Aurora Forum. 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
@@ -36,7 +36,7 @@
/* QCE max number of descriptor in a descriptor list */
#define QCE_MAX_NUM_DESC 128
-#define SPS_MAX_PKT_SIZE (16 * 1024)
+#define SPS_MAX_PKT_SIZE (32 * 1024 - 64)
/* State of consumer/producer Pipe */
enum qce_pipe_st_enum {
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 042ba37..844c65f 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -7,7 +7,7 @@
* Copyright (c) 2000 Nokia Research Center
* Tampere, FINLAND
*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -100,6 +100,9 @@
int disc_indicator_set;
int pes_length_mismatch;
u64 stc;
+ u32 tei_counter;
+ u32 cont_err_counter;
+ u32 ts_packets_num;
} pes_end;
struct {
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index f5a505c..bddbb5f 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1861,6 +1861,9 @@
event.params.pes.flags = 0;
event.params.pes.stc = 0;
+ event.params.pes.transport_error_indicator_counter = 0;
+ event.params.pes.continuity_error_counter = 0;
+ event.params.pes.ts_packets_num = 0;
dvb_dmxdev_add_event(events, &event);
events->current_event_data_size = 0;
@@ -2109,6 +2112,13 @@
DMX_FILTER_PES_LENGTH_ERROR;
event.params.pes.stc = dmx_data_ready->pes_end.stc;
+ event.params.pes.transport_error_indicator_counter =
+ dmx_data_ready->pes_end.tei_counter;
+ event.params.pes.continuity_error_counter =
+ dmx_data_ready->pes_end.cont_err_counter;
+ event.params.pes.ts_packets_num =
+ dmx_data_ready->pes_end.ts_packets_num;
+
dvb_dmxdev_add_event(events, &event);
events->current_event_data_size = 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index eea83c2..488f42c 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -5,7 +5,7 @@
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -127,15 +127,15 @@
{
int count = payload(buf);
int p;
- //int ccok;
- //u8 cc;
+ int ccok;
+ u8 cc;
+ struct dmx_data_ready data;
if (count == 0)
return -1;
p = 188 - count;
- /*
cc = buf[3] & 0x0f;
if (feed->first_cc)
ccok = 1;
@@ -144,26 +144,41 @@
feed->first_cc = 0;
feed->cc = cc;
- if (!ccok)
- printk("missed packet!\n");
- */
/* PUSI ? */
if (buf[1] & 0x40) {
- if (feed->pusi_seen)
+ if (feed->pusi_seen) {
/* We had seen PUSI before, this means
* that previous PES can be closed now.
*/
- feed->cb.ts(NULL, 0, NULL, 0,
- &feed->feed.ts, DMX_OK_PES_END);
+ data.status = DMX_OK_PES_END;
+ data.data_length = 0;
+ data.pes_end.start_gap = 0;
+ data.pes_end.actual_length = feed->peslen;
+ data.pes_end.disc_indicator_set = 0;
+ data.pes_end.pes_length_mismatch = 0;
+ data.pes_end.stc = 0;
+ data.pes_end.tei_counter = feed->pes_tei_counter;
+ data.pes_end.cont_err_counter =
+ feed->pes_cont_err_counter;
+ data.pes_end.ts_packets_num = feed->pes_ts_packets_num;
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ }
feed->pusi_seen = 1;
feed->peslen = 0;
+ feed->pes_tei_counter = 0;
+ feed->pes_ts_packets_num = 0;
+ feed->pes_cont_err_counter = 0;
}
if (feed->pusi_seen == 0)
return 0;
+ feed->pes_ts_packets_num++;
+ feed->pes_cont_err_counter += !ccok;
+ feed->pes_tei_counter += (buf[1] & 0x80) ? 1 : 0;
+
feed->peslen += count;
return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
@@ -1243,6 +1258,9 @@
feed->demux = demux;
feed->pid = 0xffff;
feed->peslen = 0;
+ feed->pes_tei_counter = 0;
+ feed->pes_ts_packets_num = 0;
+ feed->pes_cont_err_counter = 0;
feed->buffer = NULL;
feed->tsp_out_format = DMX_TSP_FORMAT_188;
memset(&feed->indexing_params, 0,
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 2e4a468..5e98ea1 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -4,7 +4,7 @@
* Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
* for convergence integrated media GmbH
*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -105,6 +105,9 @@
int pusi_seen; /* prevents feeding of garbage from previous section */
u32 peslen;
+ u32 pes_tei_counter;
+ u32 pes_cont_err_counter;
+ u32 pes_ts_packets_num;
struct list_head list_head;
unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.c b/drivers/media/video/msm_vidc/hfi_packetization.c
index 4d3d07d..06e230d 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.c
+++ b/drivers/media/video/msm_vidc/hfi_packetization.c
@@ -1104,3 +1104,36 @@
}
return rc;
}
+
+static int get_hfi_ssr_type(enum hal_ssr_trigger_type type)
+{
+ int rc = HFI_TEST_SSR_HW_WDOG_IRQ;
+ switch (type) {
+ case SSR_ERR_FATAL:
+ rc = HFI_TEST_SSR_SW_ERR_FATAL;
+ break;
+ case SSR_SW_DIV_BY_ZERO:
+ rc = HFI_TEST_SSR_SW_DIV_BY_ZERO;
+ break;
+ case SSR_HW_WDOG_IRQ:
+ rc = HFI_TEST_SSR_HW_WDOG_IRQ;
+ break;
+ default:
+ dprintk(VIDC_WARN,
+ "SSR trigger type not recognized, using WDOG.\n");
+ }
+ return rc;
+}
+
+int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
+ struct hfi_cmd_sys_test_ssr_packet *pkt)
+{
+ if (!pkt) {
+ dprintk(VIDC_ERR, "Invalid params, device: %p\n", pkt);
+ return -EINVAL;
+ }
+ pkt->size = sizeof(struct hfi_cmd_sys_test_ssr_packet);
+ pkt->packet_type = HFI_CMD_SYS_TEST_SSR;
+ pkt->trigger_type = get_hfi_ssr_type(type);
+ return 0;
+}
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/video/msm_vidc/hfi_packetization.h
index a3edc7c..b2c6e08 100644
--- a/drivers/media/video/msm_vidc/hfi_packetization.h
+++ b/drivers/media/video/msm_vidc/hfi_packetization.h
@@ -79,5 +79,6 @@
struct hfi_cmd_session_set_property_packet *pkt,
u32 session_id, enum hal_property ptype, void *pdata);
+int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
+ struct hfi_cmd_sys_test_ssr_packet *pkt);
#endif
-
diff --git a/drivers/media/video/msm_vidc/hfi_response_handler.c b/drivers/media/video/msm_vidc/hfi_response_handler.c
index 23829e5..cedd789 100644
--- a/drivers/media/video/msm_vidc/hfi_response_handler.c
+++ b/drivers/media/video/msm_vidc/hfi_response_handler.c
@@ -650,8 +650,8 @@
data_done.output_done.offset1 = pkt->offset;
data_done.output_done.frame_width = pkt->frame_width;
data_done.output_done.frame_height = pkt->frame_height;
- data_done.output_done.start_xCoord = pkt->start_x_coord;
- data_done.output_done.start_yCoord = pkt->start_y_coord;
+ data_done.output_done.start_x_coord = pkt->start_x_coord;
+ data_done.output_done.start_y_coord = pkt->start_y_coord;
data_done.output_done.input_tag1 = pkt->input_tag;
data_done.output_done.picture_type = pkt->picture_type;
data_done.output_done.packet_buffer1 = pkt->packet_buffer;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index d4bb5a7..7e8732a 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -422,6 +422,9 @@
inst->buff_req.buffer[i].buffer_count_actual,
inst->buff_req.buffer[i].buffer_size);
}
+ dprintk(VIDC_PROF, "Input buffers: %d, Output buffers: %d\n",
+ inst->buff_req.buffer[0].buffer_count_actual,
+ inst->buff_req.buffer[1].buffer_count_actual);
signal_session_msg_receipt(cmd, inst);
}
@@ -716,6 +719,10 @@
(u32)fill_buf_done->packet_buffer1);
if (vb) {
vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
+ vb->v4l2_planes[0].reserved[2] = fill_buf_done->start_x_coord;
+ vb->v4l2_planes[0].reserved[3] = fill_buf_done->start_y_coord;
+ vb->v4l2_planes[0].reserved[4] = fill_buf_done->frame_width;
+ vb->v4l2_planes[0].reserved[5] = fill_buf_done->frame_height;
if (!(fill_buf_done->flags1 &
HAL_BUFFERFLAG_TIMESTAMPINVALID) &&
fill_buf_done->filled_len1) {
@@ -2208,3 +2215,18 @@
}
return ret;
};
+
+int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
+ enum hal_ssr_trigger_type type)
+{
+ int rc = 0;
+ struct hfi_device *hdev;
+ if (!core && !core->device) {
+ dprintk(VIDC_WARN, "Invalid parameters: %p\n", core);
+ return -EINVAL;
+ }
+ hdev = core->device;
+ if (core->state == VIDC_CORE_INIT_DONE)
+ rc = hdev->core_trigger_ssr(hdev->hfi_device_data, type);
+ return rc;
+}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
index ff829d7..65a518f 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.c
@@ -87,6 +87,33 @@
.read = core_info_read,
};
+static int trigger_ssr_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t trigger_ssr_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos) {
+ u32 ssr_trigger_val;
+ int rc;
+ struct msm_vidc_core *core = filp->private_data;
+ rc = sscanf(buf, "%d", &ssr_trigger_val);
+ if (rc < 0) {
+ dprintk(VIDC_WARN, "returning error err %d\n", rc);
+ rc = -EINVAL;
+ } else {
+ msm_vidc_trigger_ssr(core, ssr_trigger_val);
+ rc = count;
+ }
+ return rc;
+}
+
+static const struct file_operations ssr_fops = {
+ .open = trigger_ssr_open,
+ .write = trigger_ssr_write,
+};
+
struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core,
struct dentry *parent)
{
@@ -117,6 +144,11 @@
dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
goto failed_create_dir;
}
+ if (!debugfs_create_file("trigger_ssr", S_IWUSR,
+ dir, core, &ssr_fops)) {
+ dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+ goto failed_create_dir;
+ }
failed_create_dir:
return dir;
}
@@ -165,6 +197,10 @@
completion_done(&inst->completions[SESSION_MSG_INDEX(i)]) ?
"pending" : "done");
}
+ write_str(&dbg_buf, "ETB Count: %d\n", inst->count.etb);
+ write_str(&dbg_buf, "EBD Count: %d\n", inst->count.ebd);
+ write_str(&dbg_buf, "FTB Count: %d\n", inst->count.ftb);
+ write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd);
return simple_read_from_buffer(buf, count, ppos,
dbg_buf.ptr, dbg_buf.filled_size);
}
@@ -213,8 +249,12 @@
break;
case MSM_VIDC_DEBUGFS_EVENT_EBD:
inst->count.ebd++;
- if (inst->count.ebd && inst->count.ebd == inst->count.etb)
+ if (inst->count.ebd && inst->count.ebd == inst->count.etb) {
toc(inst, FRAME_PROCESSING);
+ dprintk(VIDC_PROF, "EBD: FW needs input buffers\n");
+ }
+ if (inst->count.ftb == inst->count.fbd)
+ dprintk(VIDC_PROF, "EBD: FW needs output buffers\n");
break;
case MSM_VIDC_DEBUGFS_EVENT_FTB: {
inst->count.ftb++;
@@ -226,8 +266,12 @@
break;
case MSM_VIDC_DEBUGFS_EVENT_FBD:
inst->debug.samples++;
- if (inst->count.ebd && inst->count.fbd == inst->count.ftb)
+ if (inst->count.ebd && inst->count.fbd == inst->count.ftb) {
toc(inst, FRAME_PROCESSING);
+ dprintk(VIDC_PROF, "FBD: FW needs output buffers\n");
+ }
+ if (inst->count.etb == inst->count.ebd)
+ dprintk(VIDC_PROF, "FBD: FW needs input buffers\n");
break;
default:
dprintk(VIDC_ERR, "Invalid state in debugfs: %d\n", e);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 52c1de8..16bf753 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -237,4 +237,6 @@
};
void handle_cmd_response(enum command_response cmd, void *data);
+int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
+ enum hal_ssr_trigger_type type);
#endif
diff --git a/drivers/media/video/msm_vidc/venus_hfi.c b/drivers/media/video/msm_vidc/venus_hfi.c
index 1ccd583..0cd6b9f 100644
--- a/drivers/media/video/msm_vidc/venus_hfi.c
+++ b/drivers/media/video/msm_vidc/venus_hfi.c
@@ -1371,6 +1371,33 @@
return rc;
}
+static int venus_hfi_core_trigger_ssr(void *device,
+ enum hal_ssr_trigger_type type)
+{
+ struct hfi_cmd_sys_test_ssr_packet pkt;
+ int rc = 0;
+ struct venus_hfi_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_ssr_cmd(type, &pkt);
+ if (rc) {
+ dprintk(VIDC_ERR, "core_ping: failed to create packet");
+ goto err_create_pkt;
+ }
+
+ if (venus_hfi_iface_cmdq_write(dev, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
static int venus_hfi_session_set_property(void *sess,
enum hal_property ptype, void *pdata)
{
@@ -2192,7 +2219,7 @@
break;
ret = table[i].freq;
}
- dprintk(VIDC_DBG, "Required clock rate = %lu\n", ret);
+ dprintk(VIDC_PROF, "Required clock rate = %lu\n", ret);
return ret;
}
@@ -2977,6 +3004,7 @@
hdev->core_release = venus_hfi_core_release;
hdev->core_pc_prep = venus_hfi_core_pc_prep;
hdev->core_ping = venus_hfi_core_ping;
+ hdev->core_trigger_ssr = venus_hfi_core_trigger_ssr;
hdev->session_init = venus_hfi_session_init;
hdev->session_end = venus_hfi_session_end;
hdev->session_abort = venus_hfi_session_abort;
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_api.h b/drivers/media/video/msm_vidc/vidc_hfi_api.h
index 370785c..e12153a 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_api.h
@@ -407,6 +407,12 @@
HAL_UNUSED_COLOR = 0x10000000,
};
+enum hal_ssr_trigger_type {
+ SSR_ERR_FATAL = 1,
+ SSR_SW_DIV_BY_ZERO,
+ SSR_HW_WDOG_IRQ,
+};
+
struct hal_uncompressed_format_select {
enum hal_buffer buffer_type;
enum hal_uncompressed_format format;
@@ -924,8 +930,8 @@
u32 offset1;
u32 frame_width;
u32 frame_height;
- u32 start_xCoord;
- u32 start_yCoord;
+ u32 start_x_coord;
+ u32 start_y_coord;
u32 input_tag;
u32 input_tag1;
enum hal_picture picture_type;
@@ -1009,6 +1015,7 @@
int (*core_release)(void *device);
int (*core_pc_prep)(void *device);
int (*core_ping)(void *device);
+ int (*core_trigger_ssr)(void *device, enum hal_ssr_trigger_type);
void *(*session_init)(void *device, u32 session_id,
enum hal_domain session_type, enum hal_video_codec codec_type);
int (*session_end)(void *session);
diff --git a/drivers/media/video/msm_vidc/vidc_hfi_helper.h b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
index 7531811..37c051e 100644
--- a/drivers/media/video/msm_vidc/vidc_hfi_helper.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -685,6 +685,11 @@
#define HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE \
(HFI_MSG_SESSION_COMMON_START + 0x2)
+#define HFI_CMD_SYS_TEST_SSR (HFI_CMD_SYS_TEST_START + 0x1)
+#define HFI_TEST_SSR_SW_ERR_FATAL 0x1
+#define HFI_TEST_SSR_SW_DIV_BY_ZERO 0x2
+#define HFI_TEST_SSR_HW_WDOG_IRQ 0x3
+
struct vidc_hal_msg_pkt_hdr {
u32 size;
u32 packet;
@@ -871,4 +876,10 @@
u8 rg_data[1];
};
+struct hfi_cmd_sys_test_ssr_packet {
+ u32 size;
+ u32 packet_type;
+ u32 trigger_type;
+};
+
#endif
diff --git a/drivers/media/video/msmb/sensor/msm_sensor.c b/drivers/media/video/msmb/sensor/msm_sensor.c
index 1f54951..78c3207 100644
--- a/drivers/media/video/msmb/sensor/msm_sensor.c
+++ b/drivers/media/video/msmb/sensor/msm_sensor.c
@@ -783,7 +783,7 @@
int32_t msm_sensor_power_up(struct msm_sensor_ctrl_t *s_ctrl)
{
- int32_t rc = 0, index = 0, clk_index = 0;
+ int32_t rc = 0, index = 0;
struct msm_sensor_power_setting_array *power_setting_array = NULL;
struct msm_sensor_power_setting *power_setting = NULL;
struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
@@ -900,17 +900,22 @@
return 0;
power_up_failed:
pr_err("%s:%d failed\n", __func__, __LINE__);
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
+ s_ctrl->sensor_i2c_client->i2c_func_tbl->i2c_util(
+ s_ctrl->sensor_i2c_client, MSM_CCI_RELEASE);
+ }
+
for (index--; index >= 0; index--) {
CDBG("%s index %d\n", __func__, index);
power_setting = &power_setting_array->power_setting[index];
CDBG("%s type %d\n", __func__, power_setting->seq_type);
switch (power_setting->seq_type) {
case SENSOR_CLK:
- for (clk_index--; clk_index >= 0; clk_index--)
- msm_cam_clk_enable(s_ctrl->dev,
- &s_ctrl->clk_info[clk_index],
- (struct clk **)&power_setting->data[0],
- 1, 0);
+ msm_cam_clk_enable(s_ctrl->dev,
+ &s_ctrl->clk_info[0],
+ (struct clk **)&power_setting->data[0],
+ s_ctrl->clk_info_size,
+ 0);
break;
case SENSOR_GPIO:
gpio_set_value_cansleep(
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 295c55c..83f486c 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 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
@@ -746,6 +746,112 @@
return 0;
}
+/* support for 9 new rmnet ports */
+#define RMNET_REV_DEVICE_COUNT (9)
+static struct net_device *netdevs_rev[RMNET_REV_DEVICE_COUNT];
+static struct platform_driver bam_rmnet_rev_drivers[RMNET_REV_DEVICE_COUNT];
+
+static int bam_rmnet_rev_probe(struct platform_device *pdev)
+{
+ int i;
+ char name[BAM_DMUX_CH_NAME_MAX_LEN];
+ struct rmnet_private *p;
+
+ for (i = 0; i < RMNET_REV_DEVICE_COUNT; ++i) {
+ scnprintf(name, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
+ (i+BAM_DMUX_DATA_REV_RMNET_0));
+ if (!strncmp(pdev->name, name, BAM_DMUX_CH_NAME_MAX_LEN))
+ break;
+ }
+
+ if (i >= RMNET_REV_DEVICE_COUNT) {
+ pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
+ return 0;
+ }
+
+ p = netdev_priv(netdevs_rev[i]);
+ if (p->in_reset) {
+ p->in_reset = 0;
+ msm_bam_dmux_open(p->ch_id, netdevs_rev[i], bam_notify);
+ netif_carrier_on(netdevs_rev[i]);
+ netif_start_queue(netdevs_rev[i]);
+ }
+
+ return 0;
+}
+
+static int bam_rmnet_rev_remove(struct platform_device *pdev)
+{
+ int i;
+ char name[BAM_DMUX_CH_NAME_MAX_LEN];
+ struct rmnet_private *p;
+
+ for (i = 0; i < RMNET_REV_DEVICE_COUNT; ++i) {
+ scnprintf(name, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
+ (i+BAM_DMUX_DATA_REV_RMNET_0));
+ if (!strncmp(pdev->name, name, BAM_DMUX_CH_NAME_MAX_LEN))
+ break;
+ }
+
+ if (i >= RMNET_REV_DEVICE_COUNT) {
+ pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
+ return 0;
+ }
+
+ p = netdev_priv(netdevs_rev[i]);
+ p->in_reset = 1;
+ if (p->waiting_for_ul_skb != NULL) {
+ dev_kfree_skb_any(p->waiting_for_ul_skb);
+ p->waiting_for_ul_skb = NULL;
+ }
+ msm_bam_dmux_close(p->ch_id);
+ netif_carrier_off(netdevs_rev[i]);
+ netif_stop_queue(netdevs_rev[i]);
+ return 0;
+}
+
+#ifdef CONFIG_MSM_RMNET_DEBUG
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static int rmnet_debug_init_timeout_suspend(struct net_device *dev)
+{
+ struct device *d;
+ d = &(dev->dev);
+ return device_create_file(d, &dev_attr_timeout_suspend);
+}
+#else
+static int rmnet_debug_init_timeout_suspend(struct net_device *dev)
+{
+ return 0;
+}
+#endif
+static int rmnet_debug_init(struct net_device *dev)
+{
+
+ struct device *d;
+ struct rmnet_private *p;
+ int err = 0;
+ d = &(dev->dev);
+ p = netdev_priv(dev);
+ p->timeout_us = 0;
+ p->wakeups_xmit = p->wakeups_rcv = 0;
+ err = device_create_file(d, &dev_attr_timeout);
+ if (err)
+ return err;
+ err = device_create_file(d, &dev_attr_wakeups_xmit);
+ if (err)
+ return err;
+ err = device_create_file(d, &dev_attr_wakeups_rcv);
+ if (err)
+ return err;
+ err = rmnet_debug_init_timeout_suspend(dev);
+ return err;
+}
+#else
+static int rmnet_debug_init(struct net_device *dev)
+{
+ return 0;
+}
+#endif
static int __init rmnet_init(void)
{
int ret;
@@ -828,6 +934,53 @@
return ret;
}
}
+ /*Support for new rmnet ports */
+ for (n = 0; n < RMNET_REV_DEVICE_COUNT; n++) {
+ dev = alloc_netdev(sizeof(struct rmnet_private),
+ "rev_rmnet%d", rmnet_setup);
+
+ if (!dev) {
+ pr_err("%s: no memory for rev netdev %d\n",
+ __func__, n);
+ return -ENOMEM;
+ }
+
+ netdevs_rev[n] = dev;
+ d = &(dev->dev);
+ p = netdev_priv(dev);
+ /* Initial config uses Ethernet */
+ p->operation_mode = RMNET_MODE_LLP_ETH;
+ p->ch_id = n+BAM_DMUX_DATA_REV_RMNET_0;
+ p->waiting_for_ul_skb = NULL;
+ p->in_reset = 0;
+ spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
+
+ ret = register_netdev(dev);
+ if (ret) {
+ pr_err("%s: unable to register rev netdev %d rc=%d\n",
+ __func__, n, ret);
+ free_netdev(dev);
+ return ret;
+ }
+ if (rmnet_debug_init(dev))
+ continue;
+ bam_rmnet_rev_drivers[n].probe = bam_rmnet_rev_probe;
+ bam_rmnet_rev_drivers[n].remove = bam_rmnet_rev_remove;
+ tempname = kmalloc(BAM_DMUX_CH_NAME_MAX_LEN, GFP_KERNEL);
+ if (tempname == NULL)
+ return -ENOMEM;
+ scnprintf(tempname, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
+ (n+BAM_DMUX_DATA_REV_RMNET_0));
+ bam_rmnet_rev_drivers[n].driver.name = tempname;
+ bam_rmnet_rev_drivers[n].driver.owner = THIS_MODULE;
+ ret = platform_driver_register(&bam_rmnet_rev_drivers[n]);
+ if (ret) {
+ pr_err("%s: new rev driver registration failed n=%d rc=%d\n",
+ __func__, n, ret);
+ return ret;
+ }
+ }
return 0;
}
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 2e75fcc..061be69 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3994,8 +3994,6 @@
#define ENUM_TIMER_STOP_BIT BIT(1)
#define BOOT_DONE_BIT BIT(6)
-#define BOOT_TIMER_EN_BIT BIT(1)
-#define BOOT_DONE_MASK (BOOT_DONE_BIT | BOOT_TIMER_EN_BIT)
#define CHG_BATFET_ON_BIT BIT(3)
#define CHG_VCP_EN BIT(0)
#define CHG_BAT_TEMP_DIS_BIT BIT(2)
@@ -4018,7 +4016,7 @@
detect_battery_removal(chip);
rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
- BOOT_DONE_MASK, BOOT_DONE_MASK);
+ BOOT_DONE_BIT, BOOT_DONE_BIT);
if (rc) {
pr_err("Failed to set BOOT_DONE_BIT rc=%d\n", rc);
return rc;
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index d4fb02b..9b0b8b4 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1061,7 +1061,7 @@
dev_err(dev->dev, "rx thread wait error:%d", ret);
/* 1 irq notification per message */
- if (!dev->use_rx_msgqs) {
+ if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
msm_slim_rxwq(dev);
continue;
}
@@ -1255,9 +1255,9 @@
spin_lock_init(&dev->rx_lock);
dev->ee = 1;
if (rxreg_access)
- dev->use_rx_msgqs = 0;
+ dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
else
- dev->use_rx_msgqs = 1;
+ dev->use_rx_msgqs = MSM_MSGQ_RESET;
dev->irq = irq->start;
dev->bam.irq = bam_irq->start;
@@ -1328,7 +1328,7 @@
* Manager register initialization
* If RX msg Q is used, disable RX_MSG_RCVD interrupt
*/
- if (dev->use_rx_msgqs)
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
writel_relaxed((MGR_INT_RECFG_DONE | MGR_INT_TX_NACKED_2 |
MGR_INT_MSG_BUF_CONTE | /* MGR_INT_RX_MSG_RCVD | */
MGR_INT_TX_MSG_SENT), dev->base + MGR_INT_EN);
@@ -1357,7 +1357,7 @@
mb();
/* Enable RX msg Q */
- if (dev->use_rx_msgqs)
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
writel_relaxed(MGR_CFG_ENABLE | MGR_CFG_RX_MSGQ_EN,
dev->base + MGR_CFG);
else
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index a37a7803..eb741ef 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -129,7 +129,7 @@
* queuing work
*/
mb();
- if (dev->use_rx_msgqs)
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
dev_err(dev->dev,
"direct message received even with RX MSGQs");
else
@@ -225,8 +225,17 @@
u8 wbuf[SLIM_RX_MSGQ_BUF_LEN];
if (txn->mc == (SLIM_MSG_CLK_PAUSE_SEQ_FLG |
- SLIM_MSG_MC_RECONFIGURE_NOW))
- return msm_slim_qmi_power_request(dev, false);
+ SLIM_MSG_MC_RECONFIGURE_NOW)) {
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
+ ret = sps_disconnect(dev->rx_msgq.sps);
+ dev->use_rx_msgqs = MSM_MSGQ_RESET;
+ }
+ if (!ret)
+ ret = msm_slim_qmi_power_request(dev, false);
+ else
+ pr_err("SPS pipe disconnect error:%d", ret);
+ return ret;
+ }
else if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
return 0;
@@ -543,7 +552,7 @@
return ret;
txn.len = 0;
}
- return ret;
+ return 0;
}
static int ngd_set_laddr(struct slim_controller *ctrl, const u8 *ea,
@@ -581,6 +590,24 @@
return ret;
}
+static void ngd_slim_setup_rx_path(struct msm_slim_ctrl *dev)
+{
+ int ret;
+ if (dev->state == MSM_CTRL_DOWN) {
+ msm_slim_sps_init(dev, dev->bam_mem,
+ NGD_BASE(dev->ctrl.nr,
+ dev->ver) + NGD_STATUS, true);
+ } else {
+ if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
+ return;
+ ret = msm_slim_connect_endp(dev, &dev->rx_msgq,
+ &dev->rx_msgq_notify);
+ if (!ret)
+ dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
+ else
+ pr_err("RX msgq not being used:%d", ret);
+ }
+}
static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
{
u8 mc, mt, len;
@@ -608,12 +635,9 @@
txn.wbuf = wbuf;
txn.len = 4;
pr_info("SLIM SAT: Received master capability");
- if (dev->state == MSM_CTRL_DOWN) {
- dev->use_rx_msgqs = 1;
- msm_slim_sps_init(dev, dev->bam_mem,
- NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_STATUS,
- true);
- if (dev->use_rx_msgqs)
+ if (dev->state >= MSM_CTRL_ASLEEP) {
+ ngd_slim_setup_rx_path(dev);
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
msgq_en |= NGD_CFG_RX_MSGQ_EN;
writel_relaxed(msgq_en, dev->base +
NGD_BASE(dev->ctrl.nr, dev->ver));
@@ -691,8 +715,7 @@
int timeout, ret;
enum msm_ctrl_state cur_state = dev->state;
u32 laddr;
- u32 msgq_en = 1;
- u32 ngd_int = (NGD_INT_RECFG_DONE | NGD_INT_TX_NACKED_2 |
+ u32 ngd_int = (NGD_INT_TX_NACKED_2 |
NGD_INT_MSG_BUF_CONTE | NGD_INT_MSG_TX_INVAL |
NGD_INT_IE_VE_CHG | NGD_INT_DEV_ERR |
NGD_INT_TX_MSG_SENT | NGD_INT_RX_MSG_RCVD);
@@ -721,12 +744,11 @@
* ADSP power collapse case, where HW wasn't reset.
* Reconnect BAM pipes if disconnected
*/
+ ngd_slim_setup_rx_path(dev);
return 0;
} else if (cur_state != MSM_CTRL_DOWN) {
pr_info("ADSP P.C. CTRL state:%d NGD not enumerated:0x%x",
dev->state, laddr);
- if (dev->use_rx_msgqs)
- msgq_en |= NGD_CFG_RX_MSGQ_EN;
}
/*
@@ -739,7 +761,7 @@
* Enable NGD. Configure NGD in register acc. mode until master
* announcement is received
*/
- writel_relaxed(msgq_en, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
+ writel_relaxed(1, dev->base + NGD_BASE(dev->ctrl.nr, dev->ver));
/* make sure NGD enabling goes through */
mb();
@@ -815,7 +837,7 @@
continue;
}
/* 1 irq notification per message */
- if (!dev->use_rx_msgqs) {
+ if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
msm_slim_rx_dequeue(dev, (u8 *)buffer);
ngd_slim_rx(dev, (u8 *)buffer);
continue;
@@ -879,7 +901,6 @@
ngd_slim_enable(dev, false);
/* disconnect BAM pipes */
msm_slim_sps_exit(dev, false);
- dev->use_rx_msgqs = 0;
mutex_lock(&ctrl->m_ctrl);
/* device up should be called again after SSR */
list_for_each_entry(sbdev, &ctrl->devs, dev_list)
@@ -908,6 +929,7 @@
struct resource *slim_mem;
struct resource *irq, *bam_irq;
enum apr_subsys_state q6_state;
+ bool rxreg_access = false;
q6_state = apr_get_q6_state();
if (q6_state == APR_SUBSYS_DOWN) {
@@ -970,6 +992,8 @@
dev_err(&pdev->dev, "Cell index not specified:%d", ret);
goto err_ctrl_failed;
}
+ rxreg_access = of_property_read_bool(pdev->dev.of_node,
+ "qcom,rxreg-access");
} else {
dev->ctrl.nr = pdev->id;
}
@@ -1000,6 +1024,10 @@
dev->irq = irq->start;
dev->bam.irq = bam_irq->start;
+ if (rxreg_access)
+ dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
+ else
+ dev->use_rx_msgqs = MSM_MSGQ_RESET;
init_completion(&dev->rx_msgq_notify);
/* Register with framework */
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 72a8669..3e19f9b 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -9,7 +9,6 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
#include <linux/slimbus/slimbus.h>
@@ -378,53 +377,19 @@
return ret;
}
-static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
+int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
+ struct msm_slim_endp *endpoint,
+ struct completion *notify)
{
int i, ret;
- u32 pipe_offset;
- struct msm_slim_endp *endpoint = &dev->rx_msgq;
- struct sps_connect *config = &endpoint->config;
- struct sps_mem_buffer *descr = &config->desc;
- struct sps_mem_buffer *mem = &endpoint->buf;
- struct completion *notify = &dev->rx_msgq_notify;
-
struct sps_register_event sps_error_event; /* SPS_ERROR */
struct sps_register_event sps_descr_event; /* DESCR_DONE */
-
- init_completion(notify);
- if (!dev->use_rx_msgqs)
- return 0;
-
- /* Allocate the endpoint */
- ret = msm_slim_init_endpoint(dev, endpoint);
- if (ret) {
- dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
- goto sps_init_endpoint_failed;
- }
-
- /* Get the pipe indices for the message queues */
- pipe_offset = (readl_relaxed(dev->base + pipe_reg) & 0xfc) >> 2;
- dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
-
- config->mode = SPS_MODE_SRC;
- config->source = dev->bam.hdl;
- config->destination = SPS_DEV_HANDLE_MEM;
- config->src_pipe_index = pipe_offset;
- config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
- SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
-
- /* Allocate memory for the FIFO descriptors */
- ret = msm_slim_sps_mem_alloc(dev, descr,
- MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
- if (ret) {
- dev_err(dev->dev, "unable to allocate SPS descriptors\n");
- goto alloc_descr_failed;
- }
+ struct sps_connect *config = &endpoint->config;
ret = sps_connect(endpoint->sps, config);
if (ret) {
dev_err(dev->dev, "sps_connect failed 0x%x\n", ret);
- goto sps_connect_failed;
+ return ret;
}
memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
@@ -453,13 +418,6 @@
goto sps_reg_event_failed;
}
- /* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
- ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
- if (ret) {
- dev_err(dev->dev, "dma_alloc_coherent failed\n");
- goto alloc_buffer_failed;
- }
-
/*
* Call transfer_one for each 4-byte buffer
* Use (buf->size/4) - 1 for the number of buffer to post
@@ -475,20 +433,74 @@
}
return 0;
-
sps_transfer_failed:
- msm_slim_sps_mem_free(dev, mem);
-alloc_buffer_failed:
memset(&sps_error_event, 0x00, sizeof(sps_error_event));
sps_register_event(endpoint->sps, &sps_error_event);
sps_reg_event_failed:
sps_disconnect(endpoint->sps);
-sps_connect_failed:
+ return ret;
+}
+static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
+{
+ int ret;
+ u32 pipe_offset;
+ struct msm_slim_endp *endpoint = &dev->rx_msgq;
+ struct sps_connect *config = &endpoint->config;
+ struct sps_mem_buffer *descr = &config->desc;
+ struct sps_mem_buffer *mem = &endpoint->buf;
+ struct completion *notify = &dev->rx_msgq_notify;
+
+ init_completion(notify);
+ if (dev->use_rx_msgqs == MSM_MSGQ_DISABLED)
+ return 0;
+
+ /* Allocate the endpoint */
+ ret = msm_slim_init_endpoint(dev, endpoint);
+ if (ret) {
+ dev_err(dev->dev, "init_endpoint failed 0x%x\n", ret);
+ goto sps_init_endpoint_failed;
+ }
+
+ /* Get the pipe indices for the message queues */
+ pipe_offset = (readl_relaxed(dev->base + pipe_reg) & 0xfc) >> 2;
+ dev_dbg(dev->dev, "Message queue pipe offset %d\n", pipe_offset);
+
+ config->mode = SPS_MODE_SRC;
+ config->source = dev->bam.hdl;
+ config->destination = SPS_DEV_HANDLE_MEM;
+ config->src_pipe_index = pipe_offset;
+ config->options = SPS_O_DESC_DONE | SPS_O_ERROR |
+ SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE;
+
+ /* Allocate memory for the FIFO descriptors */
+ ret = msm_slim_sps_mem_alloc(dev, descr,
+ MSM_SLIM_DESC_NUM * sizeof(struct sps_iovec));
+ if (ret) {
+ dev_err(dev->dev, "unable to allocate SPS descriptors\n");
+ goto alloc_descr_failed;
+ }
+
+ /* Allocate memory for the message buffer(s), N descrs, 4-byte mesg */
+ ret = msm_slim_sps_mem_alloc(dev, mem, MSM_SLIM_DESC_NUM * 4);
+ if (ret) {
+ dev_err(dev->dev, "dma_alloc_coherent failed\n");
+ goto alloc_buffer_failed;
+ }
+
+ ret = msm_slim_connect_endp(dev, endpoint, notify);
+
+ if (!ret) {
+ dev->use_rx_msgqs = MSM_MSGQ_ENABLED;
+ return 0;
+ }
+
+ msm_slim_sps_mem_free(dev, mem);
+alloc_buffer_failed:
msm_slim_sps_mem_free(dev, descr);
alloc_descr_failed:
msm_slim_free_endpoint(endpoint);
sps_init_endpoint_failed:
- dev->use_rx_msgqs = 0;
+ dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
return ret;
}
@@ -550,7 +562,7 @@
ret = sps_register_bam_device(&bam_props, &bam_handle);
if (ret) {
dev_err(dev->dev, "disabling BAM: reg-bam failed 0x%x\n", ret);
- dev->use_rx_msgqs = 0;
+ dev->use_rx_msgqs = MSM_MSGQ_DISABLED;
goto init_rx_msgq;
}
dev->bam.hdl = bam_handle;
@@ -569,7 +581,7 @@
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg)
{
- if (dev->use_rx_msgqs) {
+ if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED) {
struct msm_slim_endp *endpoint = &dev->rx_msgq;
struct sps_connect *config = &endpoint->config;
struct sps_mem_buffer *descr = &config->desc;
@@ -581,6 +593,7 @@
sps_disconnect(endpoint->sps);
msm_slim_sps_mem_free(dev, descr);
msm_slim_free_endpoint(endpoint);
+ dev->use_rx_msgqs = MSM_MSGQ_RESET;
}
if (dereg) {
sps_deregister_bam_device(dev->bam.hdl);
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 1c6db32..6e329b3 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -155,6 +155,12 @@
MSM_CTRL_DOWN,
};
+enum msm_slim_msgq {
+ MSM_MSGQ_DISABLED,
+ MSM_MSGQ_RESET,
+ MSM_MSGQ_ENABLED,
+};
+
struct msm_slim_sps_bam {
u32 hdl;
void __iomem *base;
@@ -209,7 +215,7 @@
struct clk *hclk;
struct mutex tx_lock;
u8 pgdla;
- bool use_rx_msgqs;
+ enum msm_slim_msgq use_rx_msgqs;
int pipe_b;
struct completion reconf;
bool reconf_busy;
@@ -273,6 +279,9 @@
u32 pipe_reg, bool remote);
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg);
+int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
+ struct msm_slim_endp *endpoint,
+ struct completion *notify);
void msm_slim_qmi_exit(struct msm_slim_ctrl *dev);
int msm_slim_qmi_init(struct msm_slim_ctrl *dev, bool apps_is_master);
int msm_slim_qmi_power_request(struct msm_slim_ctrl *dev, bool active);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 8c04863..98eb5c9 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3569,8 +3569,7 @@
void __iomem *regs)
{
struct ci13xxx *udc;
- struct ci13xxx_platform_data *pdata =
- (struct ci13xxx_platform_data *)(dev->platform_data);
+ struct ci13xxx_platform_data *pdata;
int retval = 0, i;
trace("%p, %p, %p", dev, regs, driver->name);
@@ -3599,6 +3598,7 @@
INIT_LIST_HEAD(&udc->gadget.ep_list);
udc->gadget.ep0 = NULL;
+ pdata = dev->platform_data;
if (pdata)
udc->gadget.usb_core_id = pdata->usb_core_id;
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
index 746c041..575d85b 100644
--- a/drivers/usb/gadget/u_data_hsic.c
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -634,10 +634,10 @@
ghsic_data_free_buffers(port);
- data_bridge_close(port->brdg.ch_id);
-
+ cancel_work_sync(&port->connect_w);
+ if (test_and_clear_bit(CH_OPENED, &port->bridge_sts))
+ data_bridge_close(port->brdg.ch_id);
clear_bit(CH_READY, &port->bridge_sts);
- clear_bit(CH_OPENED, &port->bridge_sts);
return 0;
}
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 34d90fb..5c87691 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -1,6 +1,6 @@
/* ehci-msm2.c - HSUSB Host Controller Driver Implementation
*
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
*
* Partly derived from ehci-fsl.c and ehci-hcd.c
* Copyright (c) 2000-2004 by David Brownell
@@ -32,6 +32,7 @@
#include <linux/usb/ulpi.h>
#include <linux/usb/msm_hsusb_hw.h>
#include <linux/usb/msm_hsusb.h>
+#include <linux/of.h>
#include <mach/clk.h>
#include <mach/msm_xo.h>
#include <mach/msm_iomap.h>
@@ -42,10 +43,12 @@
struct msm_hcd {
struct ehci_hcd ehci;
+ spinlock_t wakeup_lock;
struct device *dev;
struct clk *iface_clk;
struct clk *core_clk;
struct clk *alt_core_clk;
+ struct clk *phy_sleep_clk;
struct regulator *hsusb_vddcx;
struct regulator *hsusb_3p3;
struct regulator *hsusb_1p8;
@@ -60,6 +63,9 @@
atomic_t pm_usage_cnt;
struct wake_lock wlock;
struct work_struct phy_susp_fail_work;
+ int async_irq;
+ bool async_irq_enabled;
+ uint32_t async_int_cnt;
};
static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
@@ -272,6 +278,7 @@
int rc = 0;
struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
const struct msm_usb_host_platform_data *pdata;
+ int ret = 0;
pdata = mhcd->dev->platform_data;
@@ -282,7 +289,11 @@
}
mhcd->vbus = devm_regulator_get(mhcd->dev, "vbus");
- if (IS_ERR(mhcd->vbus)) {
+ ret = PTR_ERR(mhcd->vbus);
+ if (ret == -EPROBE_DEFER) {
+ pr_debug("failed to get vbus handle, defer probe\n");
+ return ret;
+ } else if (IS_ERR(mhcd->vbus)) {
pr_err("Unable to get vbus\n");
return -ENODEV;
}
@@ -435,18 +446,38 @@
return 0;
}
+/**
+ * Do hard reset to USB hardware block using one of reset methodology based
+ * on availablity of alt_core_clk. There are two kinds of hardware resets.
+ * 1. Conventional synchronous reset where clocks to blocks to be ON while
+ * issuing the reset. 2. Asynchronous reset which requires clocks to be OFF.
+ */
static int msm_ehci_link_clk_reset(struct msm_hcd *mhcd, bool assert)
{
int ret;
if (assert) {
- ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_ASSERT);
+ if (!IS_ERR(mhcd->alt_core_clk)) {
+ ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_ASSERT);
+ } else {
+ /* Using asynchronous block reset to the hardware */
+ clk_disable(mhcd->iface_clk);
+ clk_disable(mhcd->core_clk);
+ ret = clk_reset(mhcd->core_clk, CLK_RESET_ASSERT);
+ }
if (ret)
- dev_err(mhcd->dev, "usb alt_core_clk assert failed\n");
+ dev_err(mhcd->dev, "usb clk assert failed\n");
} else {
- ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_DEASSERT);
+ if (!IS_ERR(mhcd->alt_core_clk)) {
+ ret = clk_reset(mhcd->alt_core_clk, CLK_RESET_DEASSERT);
+ } else {
+ ret = clk_reset(mhcd->core_clk, CLK_RESET_DEASSERT);
+ ndelay(200);
+ clk_enable(mhcd->core_clk);
+ clk_enable(mhcd->iface_clk);
+ }
if (ret)
- dev_err(mhcd->dev, "usb alt_core_clk deassert failed\n");
+ dev_err(mhcd->dev, "usb clk deassert failed\n");
}
return ret;
@@ -455,6 +486,7 @@
static int msm_ehci_phy_reset(struct msm_hcd *mhcd)
{
struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ struct msm_usb_host_platform_data *pdata;
u32 val;
int ret;
int retries;
@@ -463,12 +495,17 @@
if (ret)
return ret;
- udelay(1);
+ usleep_range(10, 12);
ret = msm_ehci_link_clk_reset(mhcd, 0);
if (ret)
return ret;
+ pdata = mhcd->dev->platform_data;
+ if (pdata && pdata->use_sec_phy)
+ /* select secondary phy if offset is set for USB operation */
+ writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+ USB_PHY_CTRL2);
val = readl_relaxed(USB_PORTSC) & ~PORTSC_PTS_MASK;
writel_relaxed(val | PORTSC_PTS_ULPI, USB_PORTSC);
@@ -499,10 +536,13 @@
static int msm_hsusb_reset(struct msm_hcd *mhcd)
{
struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+ struct msm_usb_host_platform_data *pdata;
unsigned long timeout;
int ret;
- clk_prepare_enable(mhcd->alt_core_clk);
+ if (!IS_ERR(mhcd->alt_core_clk))
+ clk_prepare_enable(mhcd->alt_core_clk);
+
ret = msm_ehci_phy_reset(mhcd);
if (ret) {
dev_err(mhcd->dev, "phy_reset failed\n");
@@ -521,6 +561,11 @@
/* select ULPI phy */
writel_relaxed(0x80000000, USB_PORTSC);
+ pdata = mhcd->dev->platform_data;
+ if (pdata && pdata->use_sec_phy)
+ writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+ USB_PHY_CTRL2);
+
msleep(100);
writel_relaxed(0x0, USB_AHBBURST);
@@ -528,7 +573,9 @@
/* Ensure that RESET operation is completed before turning off clock */
mb();
- clk_disable_unprepare(mhcd->alt_core_clk);
+
+ if (!IS_ERR(mhcd->alt_core_clk))
+ clk_disable_unprepare(mhcd->alt_core_clk);
/*rising edge interrupts with Dp rise and fall enabled*/
msm_ulpi_write(mhcd, ULPI_INT_DP, ULPI_USB_INT_EN_RISE);
@@ -626,6 +673,11 @@
enable_irq_wake(mhcd->pmic_gpio_dp_irq);
enable_irq(mhcd->pmic_gpio_dp_irq);
}
+ if (mhcd->async_irq) {
+ mhcd->async_irq_enabled = 1;
+ enable_irq_wake(mhcd->async_irq);
+ enable_irq(mhcd->async_irq);
+ }
wake_unlock(&mhcd->wlock);
dev_info(mhcd->dev, "EHCI USB in low power mode\n");
@@ -639,6 +691,7 @@
unsigned long timeout;
unsigned temp;
int ret;
+ unsigned long flags;
if (!atomic_read(&mhcd->in_lpm)) {
dev_dbg(mhcd->dev, "%s called in !in_lpm\n", __func__);
@@ -650,6 +703,14 @@
disable_irq_nosync(mhcd->pmic_gpio_dp_irq);
mhcd->pmic_gpio_dp_irq_enabled = 0;
}
+ spin_lock_irqsave(&mhcd->wakeup_lock, flags);
+ if (mhcd->async_irq_enabled) {
+ disable_irq_wake(mhcd->async_irq);
+ disable_irq_nosync(mhcd->async_irq);
+ mhcd->async_irq_enabled = 0;
+ }
+ spin_unlock_irqrestore(&mhcd->wakeup_lock, flags);
+
wake_lock(&mhcd->wlock);
/* Vote for TCXO when waking up the phy */
@@ -722,6 +783,36 @@
return ehci_irq(hcd);
}
+static irqreturn_t msm_async_irq(int irq, void *data)
+{
+ struct msm_hcd *mhcd = data;
+ int ret;
+
+ mhcd->async_int_cnt++;
+ dev_dbg(mhcd->dev, "%s: hsusb host remote wakeup interrupt cnt: %u\n",
+ __func__, mhcd->async_int_cnt);
+
+ wake_lock(&mhcd->wlock);
+
+ spin_lock(&mhcd->wakeup_lock);
+ if (mhcd->async_irq_enabled) {
+ mhcd->async_irq_enabled = 0;
+ disable_irq_wake(irq);
+ disable_irq_nosync(irq);
+ }
+ spin_unlock(&mhcd->wakeup_lock);
+
+ if (!atomic_read(&mhcd->pm_usage_cnt)) {
+ ret = pm_runtime_get(mhcd->dev);
+ if ((ret == 1) || (ret == -EINPROGRESS))
+ pm_runtime_put_noidle(mhcd->dev);
+ else
+ atomic_set(&mhcd->pm_usage_cnt, 1);
+ }
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t msm_ehci_host_wakeup_irq(int irq, void *data)
{
@@ -751,6 +842,8 @@
static int msm_ehci_reset(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct msm_hcd *mhcd = hcd_to_mhcd(hcd);
+ struct msm_usb_host_platform_data *pdata;
int retval;
ehci->caps = USB_CAPLENGTH;
@@ -785,6 +878,11 @@
/* Disable streaming mode and select host mode */
writel_relaxed(0x13, USB_USBMODE);
+ pdata = mhcd->dev->platform_data;
+ if (pdata && pdata->use_sec_phy)
+ writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+ USB_PHY_CTRL2);
+
ehci_port_power(ehci, 1);
return 0;
}
@@ -844,12 +942,10 @@
/* 60MHz alt_core_clk is for LINK to be used during PHY RESET */
mhcd->alt_core_clk = clk_get(mhcd->dev, "alt_core_clk");
- if (IS_ERR(mhcd->alt_core_clk)) {
- dev_err(mhcd->dev, "failed to get alt_core_clk\n");
- ret = PTR_ERR(mhcd->alt_core_clk);
- return ret;
- }
- clk_set_rate(mhcd->alt_core_clk, 60000000);
+ if (IS_ERR(mhcd->alt_core_clk))
+ dev_dbg(mhcd->dev, "failed to get alt_core_clk\n");
+ else
+ clk_set_rate(mhcd->alt_core_clk, 60000000);
/* iface_clk is required for data transfers */
mhcd->iface_clk = clk_get(mhcd->dev, "iface_clk");
@@ -871,6 +967,12 @@
}
clk_set_rate(mhcd->core_clk, INT_MAX);
+ mhcd->phy_sleep_clk = clk_get(mhcd->dev, "sleep_clk");
+ if (IS_ERR(mhcd->phy_sleep_clk))
+ dev_dbg(mhcd->dev, "failed to get sleep_clk\n");
+ else
+ clk_prepare_enable(mhcd->phy_sleep_clk);
+
clk_prepare_enable(mhcd->core_clk);
clk_prepare_enable(mhcd->iface_clk);
@@ -880,14 +982,39 @@
clk_disable_unprepare(mhcd->iface_clk);
clk_disable_unprepare(mhcd->core_clk);
clk_put(mhcd->core_clk);
+ if (!IS_ERR(mhcd->phy_sleep_clk)) {
+ clk_disable_unprepare(mhcd->phy_sleep_clk);
+ clk_put(mhcd->phy_sleep_clk);
+ }
put_iface_clk:
clk_put(mhcd->iface_clk);
put_alt_core_clk:
- clk_put(mhcd->alt_core_clk);
+ if (!IS_ERR(mhcd->alt_core_clk))
+ clk_put(mhcd->alt_core_clk);
return ret;
}
+struct msm_usb_host_platform_data *ehci_msm2_dt_to_pdata(
+ struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct msm_usb_host_platform_data *pdata;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "unable to allocate platform data\n");
+ return NULL;
+ }
+
+ pdata->use_sec_phy = of_property_read_bool(node,
+ "qcom,usb2-enable-hsphy2");
+ of_property_read_u32(node, "qcom,usb2-power-budget",
+ &pdata->power_budget);
+ return pdata;
+}
+
+static u64 ehci_msm_dma_mask = DMA_BIT_MASK(64);
static int __devinit ehci_msm2_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -899,6 +1026,19 @@
dev_dbg(&pdev->dev, "ehci_msm2 probe\n");
+ if (pdev->dev.of_node) {
+ dev_dbg(&pdev->dev, "device tree enabled\n");
+ pdev->dev.platform_data = ehci_msm2_dt_to_pdata(pdev);
+ }
+
+ if (!pdev->dev.platform_data)
+ dev_dbg(&pdev->dev, "No platform data given\n");
+
+ if (!pdev->dev.dma_mask)
+ pdev->dev.dma_mask = &ehci_msm_dma_mask;
+ if (!pdev->dev.coherent_dma_mask)
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
hcd = usb_create_hcd(&msm_hc2_driver, &pdev->dev,
dev_name(&pdev->dev));
if (!hcd) {
@@ -932,13 +1072,29 @@
mhcd = hcd_to_mhcd(hcd);
mhcd->dev = &pdev->dev;
+ spin_lock_init(&mhcd->wakeup_lock);
+
+ mhcd->async_irq = platform_get_irq_byname(pdev, "async_irq");
+ if (mhcd->async_irq < 0) {
+ dev_dbg(&pdev->dev, "platform_get_irq for async_int failed\n");
+ mhcd->async_irq = 0;
+ } else {
+ ret = request_irq(mhcd->async_irq, msm_async_irq,
+ IRQF_TRIGGER_RISING, "msm_ehci_host", mhcd);
+ if (ret) {
+ dev_err(&pdev->dev, "request irq failed (ASYNC INT)\n");
+ goto unmap;
+ }
+ disable_irq(mhcd->async_irq);
+ }
+
snprintf(pdev_name, PDEV_NAME_LEN, "%s.%d", pdev->name, pdev->id);
mhcd->xo_handle = msm_xo_get(MSM_XO_TCXO_D0, pdev_name);
if (IS_ERR(mhcd->xo_handle)) {
dev_err(&pdev->dev, "%s not able to get the handle "
"to vote for TCXO D0 buffer\n", __func__);
ret = PTR_ERR(mhcd->xo_handle);
- goto unmap;
+ goto free_async_irq;
}
ret = msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_ON);
@@ -1047,6 +1203,9 @@
msm_xo_mode_vote(mhcd->xo_handle, MSM_XO_MODE_OFF);
free_xo_handle:
msm_xo_put(mhcd->xo_handle);
+free_async_irq:
+ if (mhcd->async_irq)
+ free_irq(mhcd->async_irq, mhcd);
unmap:
iounmap(hcd->regs);
put_hcd:
@@ -1065,6 +1224,11 @@
disable_irq_wake(mhcd->pmic_gpio_dp_irq);
free_irq(mhcd->pmic_gpio_dp_irq, mhcd);
}
+ if (mhcd->async_irq) {
+ if (mhcd->async_irq_enabled)
+ disable_irq_wake(mhcd->async_irq);
+ free_irq(mhcd->async_irq, mhcd);
+ }
device_init_wakeup(&pdev->dev, 0);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
@@ -1160,6 +1324,12 @@
};
#endif
+static const struct of_device_id ehci_msm2_dt_match[] = {
+ { .compatible = "qcom,ehci-host",
+ },
+ {}
+};
+
static struct platform_driver ehci_msm2_driver = {
.probe = ehci_msm2_probe,
.remove = __devexit_p(ehci_msm2_remove),
@@ -1168,5 +1338,6 @@
#ifdef CONFIG_PM
.pm = &ehci_msm2_dev_pm_ops,
#endif
+ .of_match_table = ehci_msm2_dt_match,
},
};
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 655e2f6..fcbf0e1 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, 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
@@ -343,6 +343,9 @@
dev_dbg(&dev->intf->dev, "%s:\n", __func__);
+ cancel_work_sync(&dev->kevent);
+ cancel_work_sync(&dev->process_rx_w);
+
usb_unlink_anchored_urbs(&dev->tx_active);
usb_unlink_anchored_urbs(&dev->rx_active);
usb_unlink_anchored_urbs(&dev->delayed);
@@ -995,9 +998,6 @@
usb_set_intfdata(intf, NULL);
__dev[dev->id] = NULL;
- cancel_work_sync(&dev->process_rx_w);
- cancel_work_sync(&dev->kevent);
-
/*free rx urbs*/
head = &dev->rx_idle;
spin_lock_irqsave(&dev->rx_done.lock, flags);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index ef6e5b4..40cca22 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -308,6 +308,7 @@
int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
struct mdp_csc_cfg *data);
+int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op);
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl);
int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 89f3405..4ece15d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -584,43 +584,6 @@
return 0;
}
-static int mdss_mdp_vig_setup(struct mdss_mdp_pipe *pipe)
-{
- u32 opmode = 0;
-
- pr_debug("pnum=%x\n", pipe->num);
-
- /* CSC Post Processing enabled? */
- if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
- if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_CSC_CFG) {
- if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_ENABLE)
- opmode |= 1 << 17; /* CSC_1_EN */
- if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_IN)
- opmode |= 1 << 18; /* SRC_DATA=YCBCR */
- if (pipe->pp_cfg.csc_cfg.flags & MDP_CSC_FLAG_YUV_OUT)
- opmode |= 1 << 19; /* DST_DATA=YCBCR */
- /* only need to program once */
- if (pipe->play_cnt == 0)
- mdss_mdp_csc_setup_data(MDSS_MDP_BLOCK_SSPP,
- pipe->num, 1, &pipe->pp_cfg.csc_cfg);
- }
- } else {
- if (pipe->src_fmt->is_yuv)
- opmode |= (0 << 19) | /* DST_DATA=RGB */
- (1 << 18) | /* SRC_DATA=YCBCR */
- (1 << 17); /* CSC_1_EN */
- /* only need to program once */
- if (pipe->play_cnt == 0) {
- mdss_mdp_csc_setup(MDSS_MDP_BLOCK_SSPP, pipe->num, 1,
- MDSS_MDP_CSC_YUV2RGB);
- }
- }
-
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE, opmode);
-
- return 0;
-}
-
static void mdss_mdp_addr_add_offset(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_data *data)
{
@@ -678,7 +641,7 @@
struct mdss_mdp_data *src_data)
{
int ret = 0;
- u32 params_changed;
+ u32 params_changed, opmode;
if (!pipe) {
pr_err("pipe not setup properly for queue\n");
@@ -712,8 +675,10 @@
goto done;
}
+ mdss_mdp_pipe_pp_setup(pipe, &opmode);
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
- mdss_mdp_vig_setup(pipe);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
+ opmode);
ret = mdss_mdp_smp_reserve(pipe);
if (ret) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 7fd6a58..42e7337 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -159,7 +159,7 @@
struct mdp_ar_gc_lut_data
gc_lut_b[MDSS_BLOCK_DISP_NUM][GC_LUT_SEGMENTS];
u32 enhist_lut[MDSS_BLOCK_DISP_NUM][ENHIST_LUT_ENTRIES];
- struct mdp_pa_cfg_data pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
+ struct mdp_pa_cfg pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM];
struct mdp_pgc_lut_data argc_disp_cfg[MDSS_BLOCK_DISP_NUM];
@@ -181,19 +181,29 @@
static DEFINE_MUTEX(mdss_mdp_hist_mutex);
static struct mdss_pp_res_type *mdss_pp_res;
-
static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info);
-
static void pp_update_pcc_regs(u32 offset,
struct mdp_pcc_cfg_data *cfg_ptr);
static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
u32 offset, u32 blk_idx);
static void pp_update_gc_one_lut(u32 offset,
- struct mdp_ar_gc_lut_data *lut_data);
+ struct mdp_ar_gc_lut_data *lut_data);
static void pp_update_argc_lut(u32 offset,
- struct mdp_pgc_lut_data *config);
+ struct mdp_pgc_lut_data *config);
static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg);
-
+static void pp_pa_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_pa_cfg *pa_config);
+static void pp_pcc_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_pcc_cfg_data *pcc_config);
+static void pp_igc_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_igc_lut_data *igc_config,
+ u32 pipe_num);
+static void pp_enhist_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_hist_lut_data *enhist_cfg);
int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
struct mdp_csc_cfg *data)
@@ -283,6 +293,178 @@
data = &mdp_csc_convert[csc_type];
return mdss_mdp_csc_setup_data(block, blk_idx, tbl_idx, data);
}
+
+static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
+ u32 base, u32 *gamut_sts)
+{
+ u32 offset;
+ int i, j;
+ if (gamut_cfg->flags & MDP_PP_OPS_WRITE) {
+ offset = base + MDSS_MDP_REG_DSPP_GAMUT_BASE;
+ for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+ for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+ MDSS_MDP_REG_WRITE(offset,
+ (u32)gamut_cfg->r_tbl[i][j]);
+ offset += 4;
+ }
+ for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+ for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+ MDSS_MDP_REG_WRITE(offset,
+ (u32)gamut_cfg->g_tbl[i][j]);
+ offset += 4;
+ }
+ for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
+ for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
+ MDSS_MDP_REG_WRITE(offset,
+ (u32)gamut_cfg->b_tbl[i][j]);
+ offset += 4;
+ }
+ if (gamut_cfg->gamut_first)
+ *gamut_sts |= PP_STS_GAMUT_FIRST;
+ }
+
+ if (gamut_cfg->flags & MDP_PP_OPS_DISABLE)
+ *gamut_sts &= ~PP_STS_ENABLE;
+ else if (gamut_cfg->flags & MDP_PP_OPS_ENABLE)
+ *gamut_sts |= PP_STS_ENABLE;
+}
+
+static void pp_pa_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_pa_cfg *pa_config)
+{
+ if (flags & PP_FLAGS_DIRTY_PA) {
+ if (pa_config->flags & MDP_PP_OPS_WRITE) {
+ MDSS_MDP_REG_WRITE(base, pa_config->hue_adj);
+ base += 4;
+ MDSS_MDP_REG_WRITE(base, pa_config->sat_adj);
+ base += 4;
+ MDSS_MDP_REG_WRITE(base, pa_config->val_adj);
+ base += 4;
+ MDSS_MDP_REG_WRITE(base, pa_config->cont_adj);
+ }
+ if (pa_config->flags & MDP_PP_OPS_DISABLE)
+ pp_sts->pa_sts &= ~PP_STS_ENABLE;
+ else if (pa_config->flags & MDP_PP_OPS_ENABLE)
+ pp_sts->pa_sts |= PP_STS_ENABLE;
+ }
+}
+
+static void pp_pcc_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_pcc_cfg_data *pcc_config)
+{
+ if (flags & PP_FLAGS_DIRTY_PCC) {
+ if (pcc_config->ops & MDP_PP_OPS_WRITE)
+ pp_update_pcc_regs(base, pcc_config);
+
+ if (pcc_config->ops & MDP_PP_OPS_DISABLE)
+ pp_sts->pcc_sts &= ~PP_STS_ENABLE;
+ else if (pcc_config->ops & MDP_PP_OPS_ENABLE)
+ pp_sts->pcc_sts |= PP_STS_ENABLE;
+ }
+}
+
+static void pp_igc_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_igc_lut_data *igc_config,
+ u32 pipe_num)
+{
+ u32 tbl_idx;
+ if (flags & PP_FLAGS_DIRTY_IGC) {
+ if (igc_config->ops & MDP_PP_OPS_WRITE)
+ pp_update_igc_lut(igc_config, base, pipe_num);
+
+ if (igc_config->ops & MDP_PP_IGC_FLAG_ROM0) {
+ pp_sts->pcc_sts |= PP_STS_ENABLE;
+ tbl_idx = 1;
+ } else if (igc_config->ops & MDP_PP_IGC_FLAG_ROM1) {
+ pp_sts->pcc_sts |= PP_STS_ENABLE;
+ tbl_idx = 2;
+ } else {
+ tbl_idx = 0;
+ }
+ pp_sts->igc_tbl_idx = tbl_idx;
+ if (igc_config->ops & MDP_PP_OPS_DISABLE)
+ pp_sts->igc_sts &= ~PP_STS_ENABLE;
+ else if (igc_config->ops & MDP_PP_OPS_ENABLE)
+ pp_sts->igc_sts |= PP_STS_ENABLE;
+ }
+}
+
+static void pp_enhist_config(unsigned long flags, u32 base,
+ struct pp_sts_type *pp_sts,
+ struct mdp_hist_lut_data *enhist_cfg)
+{
+ if (flags & PP_FLAGS_DIRTY_ENHIST) {
+ if (enhist_cfg->ops & MDP_PP_OPS_WRITE)
+ pp_update_hist_lut(base, enhist_cfg);
+
+ if (enhist_cfg->ops & MDP_PP_OPS_DISABLE)
+ pp_sts->enhist_sts &= ~PP_STS_ENABLE;
+ else if (enhist_cfg->ops & MDP_PP_OPS_ENABLE)
+ pp_sts->enhist_sts |= PP_STS_ENABLE;
+ }
+}
+
+static int pp_vig_pipe_setup(struct mdss_mdp_pipe *pipe, u32 *op)
+{
+ u32 opmode = 0;
+
+ pr_debug("pnum=%x\n", pipe->num);
+
+ if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
+ if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_CSC_CFG) {
+ opmode |= !!(pipe->pp_cfg.csc_cfg.flags &
+ MDP_CSC_FLAG_ENABLE) << 17;
+ opmode |= !!(pipe->pp_cfg.csc_cfg.flags &
+ MDP_CSC_FLAG_YUV_IN) << 18;
+ opmode |= !!(pipe->pp_cfg.csc_cfg.flags &
+ MDP_CSC_FLAG_YUV_OUT) << 19;
+ /*
+ * TODO: Allow pipe to be programmed whenever new CSC is
+ * applied (i.e. dirty bit)
+ */
+ if (pipe->play_cnt == 0)
+ mdss_mdp_csc_setup_data(MDSS_MDP_BLOCK_SSPP,
+ pipe->num, 1, &pipe->pp_cfg.csc_cfg);
+ }
+ } else {
+ if (pipe->src_fmt->is_yuv)
+ opmode |= (0 << 19) | /* DST_DATA=RGB */
+ (1 << 18) | /* SRC_DATA=YCBCR */
+ (1 << 17); /* CSC_1_EN */
+ /*
+ * TODO: Needs to be part of dirty bit logic: if there is a
+ * previously configured pipe need to re-configure CSC matrix
+ */
+ if (pipe->play_cnt == 0) {
+ mdss_mdp_csc_setup(MDSS_MDP_BLOCK_SSPP, pipe->num, 1,
+ MDSS_MDP_CSC_YUV2RGB);
+ }
+ }
+
+ *op = opmode;
+
+ return 0;
+}
+
+int mdss_mdp_pipe_pp_setup(struct mdss_mdp_pipe *pipe, u32 *op)
+{
+ int ret = 0;
+ if (!pipe)
+ return -ENODEV;
+
+ if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
+ ret = pp_vig_pipe_setup(pipe, op);
+ else if (pipe->type == MDSS_MDP_PIPE_TYPE_RGB)
+ ret = -EINVAL;
+ else if (pipe->type == MDSS_MDP_PIPE_TYPE_DMA)
+ ret = -EINVAL;
+
+ return ret;
+}
+
static int pp_mixer_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
struct mdss_mdp_mixer *mixer)
{
@@ -326,65 +508,16 @@
}
return 0;
}
-static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
- u32 base,
- u32 *gamut_sts)
-{
- u32 offset;
- int i, j;
- if (gamut_cfg->flags & MDP_PP_OPS_WRITE) {
- offset = base + MDSS_MDP_REG_DSPP_GAMUT_BASE;
- for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
- for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
- MDSS_MDP_REG_WRITE(offset,
- (u32)gamut_cfg->r_tbl[i][j]);
- offset += 4;
- }
- for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
- for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
- MDSS_MDP_REG_WRITE(offset,
- (u32)gamut_cfg->g_tbl[i][j]);
- offset += 4;
- }
- for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) {
- for (j = 0; j < gamut_cfg->tbl_size[i]; j++)
- MDSS_MDP_REG_WRITE(offset,
- (u32)gamut_cfg->b_tbl[i][j]);
- offset += 4;
- }
- if (gamut_cfg->gamut_first)
- *gamut_sts |= PP_STS_GAMUT_FIRST;
- }
-
- if (gamut_cfg->flags & MDP_PP_OPS_DISABLE)
- *gamut_sts &= ~PP_STS_ENABLE;
- else if (gamut_cfg->flags & MDP_PP_OPS_ENABLE)
- *gamut_sts |= PP_STS_ENABLE;
-}
-
-/* Note: Assumes that its inputs have been checked by calling function */
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg)
-{
- int i;
- for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
- MDSS_MDP_REG_WRITE(offset, cfg->data[i]);
- /* swap */
- MDSS_MDP_REG_WRITE(offset + 4, 1);
-}
static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
- struct mdss_mdp_mixer *mixer)
+ struct mdss_mdp_mixer *mixer)
{
u32 flags, base, offset, dspp_num, opmode = 0;
- struct mdp_pa_cfg_data *pa_config;
- struct mdp_pcc_cfg_data *pcc_config;
- struct mdp_igc_lut_data *igc_config;
- struct mdp_hist_lut_data *enhist_cfg;
struct mdp_dither_cfg_data *dither_cfg;
struct pp_hist_col_info *hist_info;
struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
- u32 data, tbl_idx, col_state;
+ u32 data, col_state;
unsigned long flag;
int i;
@@ -423,76 +556,32 @@
/* nothing to update */
if ((!flags) && (!(hist_info->col_en)))
return 0;
+
pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
- if (flags & PP_FLAGS_DIRTY_PA) {
- pa_config = &mdss_pp_res->pa_disp_cfg[disp_num];
- if (pa_config->pa_data.flags & MDP_PP_OPS_WRITE) {
- offset = base + MDSS_MDP_REG_DSPP_PA_BASE;
- MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.hue_adj);
- offset += 4;
- MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.sat_adj);
- offset += 4;
- MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.val_adj);
- offset += 4;
- MDSS_MDP_REG_WRITE(offset, pa_config->pa_data.cont_adj);
- }
- if (pa_config->pa_data.flags & MDP_PP_OPS_DISABLE)
- pp_sts->pa_sts &= ~PP_STS_ENABLE;
- else if (pa_config->pa_data.flags & MDP_PP_OPS_ENABLE)
- pp_sts->pa_sts |= PP_STS_ENABLE;
- }
+
+ pp_pa_config(flags, base + MDSS_MDP_REG_DSPP_PA_BASE, pp_sts,
+ &mdss_pp_res->pa_disp_cfg[disp_num]);
+
+ pp_pcc_config(flags, base + MDSS_MDP_REG_DSPP_PCC_BASE, pp_sts,
+ &mdss_pp_res->pcc_disp_cfg[disp_num]);
+
+ pp_igc_config(flags, MDSS_MDP_REG_IGC_DSPP_BASE, pp_sts,
+ &mdss_pp_res->igc_disp_cfg[disp_num], dspp_num);
+
+ pp_enhist_config(flags, base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
+ pp_sts, &mdss_pp_res->enhist_disp_cfg[disp_num]);
+
if (pp_sts->pa_sts & PP_STS_ENABLE)
opmode |= (1 << 20); /* PA_EN */
- if (flags & PP_FLAGS_DIRTY_PCC) {
- pcc_config = &mdss_pp_res->pcc_disp_cfg[disp_num];
- if (pcc_config->ops & MDP_PP_OPS_WRITE) {
- offset = base + MDSS_MDP_REG_DSPP_PCC_BASE;
- pp_update_pcc_regs(offset, pcc_config);
- }
- if (pcc_config->ops & MDP_PP_OPS_DISABLE)
- pp_sts->pcc_sts &= ~PP_STS_ENABLE;
- else if (pcc_config->ops & MDP_PP_OPS_ENABLE)
- pp_sts->pcc_sts |= PP_STS_ENABLE;
- }
+
if (pp_sts->pcc_sts & PP_STS_ENABLE)
opmode |= (1 << 4); /* PCC_EN */
- if (flags & PP_FLAGS_DIRTY_IGC) {
- igc_config = &mdss_pp_res->igc_disp_cfg[disp_num];
- if (igc_config->ops & MDP_PP_OPS_WRITE) {
- offset = MDSS_MDP_REG_IGC_DSPP_BASE;
- pp_update_igc_lut(igc_config, offset, dspp_num);
- }
- if (igc_config->ops & MDP_PP_IGC_FLAG_ROM0) {
- pp_sts->pcc_sts |= PP_STS_ENABLE;
- tbl_idx = 1;
- } else if (igc_config->ops & MDP_PP_IGC_FLAG_ROM1) {
- pp_sts->pcc_sts |= PP_STS_ENABLE;
- tbl_idx = 2;
- } else {
- tbl_idx = 0;
- }
- pp_sts->igc_tbl_idx = tbl_idx;
- if (igc_config->ops & MDP_PP_OPS_DISABLE)
- pp_sts->igc_sts &= ~PP_STS_ENABLE;
- else if (igc_config->ops & MDP_PP_OPS_ENABLE)
- pp_sts->igc_sts |= PP_STS_ENABLE;
- }
if (pp_sts->igc_sts & PP_STS_ENABLE) {
opmode |= (1 << 0) | /* IGC_LUT_EN */
(pp_sts->igc_tbl_idx << 1);
}
- if (flags & PP_FLAGS_DIRTY_ENHIST) {
- enhist_cfg = &mdss_pp_res->enhist_disp_cfg[disp_num];
- if (enhist_cfg->ops & MDP_PP_OPS_WRITE) {
- offset = base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE;
- pp_update_hist_lut(offset, enhist_cfg);
- }
- if (enhist_cfg->ops & MDP_PP_OPS_DISABLE)
- pp_sts->enhist_sts &= ~PP_STS_ENABLE;
- else if (enhist_cfg->ops & MDP_PP_OPS_ENABLE)
- pp_sts->enhist_sts |= PP_STS_ENABLE;
- }
+
if (pp_sts->enhist_sts & PP_STS_ENABLE) {
opmode |= (1 << 19) | /* HIST_LUT_EN */
(1 << 20); /* PA_EN */
@@ -557,6 +646,7 @@
ctl->flush_bits |= BIT(13 + dspp_num); /* DSPP */
return 0;
}
+
int mdss_mdp_pp_setup(struct mdss_mdp_ctl *ctl)
{
u32 disp_num;
@@ -676,7 +766,7 @@
*copyback = 1;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
} else {
- mdss_pp_res->pa_disp_cfg[disp_num] = *config;
+ mdss_pp_res->pa_disp_cfg[disp_num] = config->pa_data;
mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_PA;
}
@@ -1056,6 +1146,17 @@
pp_read_gc_one_lut(offset, config->b_data);
return ret;
}
+
+/* Note: Assumes that its inputs have been checked by calling function */
+static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg)
+{
+ int i;
+ for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
+ MDSS_MDP_REG_WRITE(offset, cfg->data[i]);
+ /* swap */
+ MDSS_MDP_REG_WRITE(offset + 4, 1);
+}
+
int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback)
{
int ret = 0;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 460cba3..53bbd5e 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -5,7 +5,7 @@
* & Ralph Metzler <ralph@convergence.de>
* for convergence integrated media GmbH
*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -250,6 +250,18 @@
/* Flags passed in filter events */
__u32 flags;
+
+ /*
+ * Number of TS packets with Transport Error Indicator (TEI)
+ * found while constructing the PES.
+ */
+ __u32 transport_error_indicator_counter;
+
+ /* Number of continuity errors found while constructing the PES */
+ __u32 continuity_error_counter;
+
+ /* Total number of TS packets holding the PES */
+ __u32 ts_packets_num;
};
/* Section info associated with DMX_EVENT_NEW_SECTION event */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 9240277..671889b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -412,6 +412,7 @@
unsigned int power_budget;
int pmic_gpio_dp_irq;
unsigned int dock_connect_irq;
+ bool use_sec_phy;
};
/**
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 6e36f56..900fc00 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -28,6 +28,7 @@
#define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8)
#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
+#define USB_PHY_CTRL2 (MSM_USB_BASE + 0x0278)
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 2787e8d..b2a8d10 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
#ifndef VCAP_FMT_H
#define VCAP_FMT_H
#include <linux/videodev2.h>
diff --git a/include/sound/msm-dai-q6-v2.h b/include/sound/msm-dai-q6-v2.h
index c04cbfc..347503d 100644
--- a/include/sound/msm-dai-q6-v2.h
+++ b/include/sound/msm-dai-q6-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index fdc3cb9..6e5e649 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -49,4 +49,8 @@
int adm_get_copp_id(int port_id);
+void adm_set_multi_ch_map(char *channel_map);
+
+void adm_get_multi_ch_map(char *channel_map);
+
#endif /* __Q6_ADM_V2_H__ */
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index a436a6e..876d815 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -262,7 +262,8 @@
uint32_t rate, uint32_t channels);
int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
- uint32_t rate, uint32_t channels);
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap, char *channel_map);
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d7521f8..85214ec 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -339,7 +339,7 @@
struct wcd9xxx_pdata *pdata;
u32 anc_slot;
-
+ bool anc_func;
bool no_mic_headset_override;
/* Delayed work to report long button press */
struct delayed_work mbhc_btn_dwork;
@@ -539,6 +539,48 @@
return 0;
}
+static int tabla_get_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ ucontrol->value.integer.value[0] = (tabla->anc_func == true ? 1 : 0);
+ return 0;
+}
+
+static int tabla_put_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ mutex_lock(&dapm->codec->mutex);
+
+ tabla->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+ dev_dbg(codec->dev, "%s: anc_func %x", __func__, tabla->anc_func);
+
+ if (tabla->anc_func == true) {
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "HPHR");
+ snd_soc_dapm_disable_pin(dapm, "HPHL");
+ snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_enable_pin(dapm, "HPHR");
+ snd_soc_dapm_enable_pin(dapm, "HPHL");
+ snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+ }
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
+ return 0;
+}
+
static int tabla_pa_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -987,6 +1029,10 @@
return 0;
}
+static const char *const tabla_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum tabla_anc_func_enum =
+ SOC_ENUM_SINGLE_EXT(2, tabla_anc_func_text);
+
static const char *tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
static const struct soc_enum tabla_ear_pa_gain_enum[] = {
SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
@@ -1130,6 +1176,8 @@
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tabla_get_anc_slot,
tabla_put_anc_slot),
+ SOC_ENUM_EXT("ANC Function", tabla_anc_func_enum, tabla_get_anc_func,
+ tabla_put_anc_func),
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -2476,111 +2524,6 @@
return 0;
}
-static int tabla_codec_enable_anc(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- const char *filename;
- const struct firmware *fw;
- int i;
- int ret;
- int num_anc_slots;
- struct anc_header *anc_head;
- struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- u32 anc_writes_size = 0;
- int anc_size_remaining;
- u32 *anc_ptr;
- u16 reg;
- u8 mask, val, old_val;
-
- pr_debug("%s %d\n", __func__, event);
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
-
- filename = "wcd9310/wcd9310_anc.bin";
-
- ret = request_firmware(&fw, filename, codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
- ret);
- return -ENODEV;
- }
-
- if (fw->size < sizeof(struct anc_header)) {
- dev_err(codec->dev, "Not enough data\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- /* First number is the number of register writes */
- anc_head = (struct anc_header *)(fw->data);
- anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
- anc_size_remaining = fw->size - sizeof(struct anc_header);
- num_anc_slots = anc_head->num_anc_slots;
-
- if (tabla->anc_slot >= num_anc_slots) {
- dev_err(codec->dev, "Invalid ANC slot selected\n");
- release_firmware(fw);
- return -EINVAL;
- }
-
- for (i = 0; i < num_anc_slots; i++) {
-
- if (anc_size_remaining < TABLA_PACKED_REG_SIZE) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -EINVAL;
- }
- anc_writes_size = (u32)(*anc_ptr);
- anc_size_remaining -= sizeof(u32);
- anc_ptr += 1;
-
- if (anc_writes_size * TABLA_PACKED_REG_SIZE
- > anc_size_remaining) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- if (tabla->anc_slot == i)
- break;
-
- anc_size_remaining -= (anc_writes_size *
- TABLA_PACKED_REG_SIZE);
- anc_ptr += anc_writes_size;
- }
- if (i == num_anc_slots) {
- dev_err(codec->dev, "Selected ANC slot not present\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- for (i = 0; i < anc_writes_size; i++) {
- TABLA_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
- mask, val);
- old_val = snd_soc_read(codec, reg);
- snd_soc_write(codec, reg, (old_val & ~mask) |
- (val & mask));
- }
- release_firmware(fw);
-
- TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
- /* if MBHC polling is active, set TX7_MBHC_EN bit 7 */
- if (tabla->mbhc_polling_active)
- snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80,
- 0x80);
- TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
- break;
- case SND_SOC_DAPM_POST_PMD:
- /* unset TX7_MBHC_EN bit 7 */
- snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
-
- snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
- snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
- break;
- }
- return 0;
-}
/* called under codec_resource_lock acquisition */
static void tabla_codec_start_hs_polling(struct snd_soc_codec *codec)
@@ -3283,6 +3226,160 @@
WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
}
+static int tabla_codec_enable_anc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ const char *filename;
+ const struct firmware *fw;
+ int i;
+ int ret;
+ int num_anc_slots;
+ struct anc_header *anc_head;
+ struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+ u32 anc_writes_size = 0;
+ int anc_size_remaining;
+ u32 *anc_ptr;
+ u16 reg;
+ u8 mask, val, old_val;
+ u8 mbhc_micb_ctl_val;
+
+ pr_debug("%s: DAPM Event %d ANC func is %d\n",
+ __func__, event, tabla->anc_func);
+
+ if (tabla->anc_func == 0)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mbhc_micb_ctl_val = snd_soc_read(codec,
+ tabla->mbhc_bias_regs.ctl_reg);
+
+ if (!(mbhc_micb_ctl_val & 0x80)) {
+ TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+ tabla_codec_switch_micbias(codec, 1);
+ TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+ }
+
+ filename = "wcd9310/wcd9310_anc.bin";
+
+ ret = request_firmware(&fw, filename, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ if (fw->size < sizeof(struct anc_header)) {
+ dev_err(codec->dev, "Not enough data\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ /* First number is the number of register writes */
+ anc_head = (struct anc_header *)(fw->data);
+ anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+ anc_size_remaining = fw->size - sizeof(struct anc_header);
+ num_anc_slots = anc_head->num_anc_slots;
+
+ if (tabla->anc_slot >= num_anc_slots) {
+ dev_err(codec->dev, "Invalid ANC slot selected\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_anc_slots; i++) {
+
+ if (anc_size_remaining < TABLA_PACKED_REG_SIZE) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ anc_writes_size = (u32)(*anc_ptr);
+ anc_size_remaining -= sizeof(u32);
+ anc_ptr += 1;
+
+ if (anc_writes_size * TABLA_PACKED_REG_SIZE
+ > anc_size_remaining) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ if (tabla->anc_slot == i)
+ break;
+
+ anc_size_remaining -= (anc_writes_size *
+ TABLA_PACKED_REG_SIZE);
+ anc_ptr += anc_writes_size;
+ }
+ if (i == num_anc_slots) {
+ dev_err(codec->dev, "Selected ANC slot not present\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < anc_writes_size; i++) {
+ TABLA_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+ mask, val);
+ old_val = snd_soc_read(codec, reg);
+ snd_soc_write(codec, reg, (old_val & ~mask) |
+ (val & mask));
+ }
+ usleep_range(10000, 10000);
+ snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x30);
+ msleep(30);
+ release_firmware(fw);
+ TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+ /* if MBHC polling is active, set TX7_MBHC_EN bit 7 */
+ if (tabla->mbhc_polling_active)
+ snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80,
+ 0x80);
+ TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* schedule work is required because at the time HPH PA DAPM
+ * event callback is called by DAPM framework, CODEC dapm mutex
+ * would have been locked while snd_soc_jack_report also
+ * attempts to acquire same lock.
+ */
+ if (w->shift == 5) {
+ clear_bit(TABLA_HPHL_PA_OFF_ACK,
+ &tabla->hph_pa_dac_state);
+ clear_bit(TABLA_HPHL_DAC_OFF_ACK,
+ &tabla->hph_pa_dac_state);
+ if (tabla->hph_status & SND_JACK_OC_HPHL)
+ schedule_work(&tabla->hphlocp_work);
+ } else if (w->shift == 4) {
+ clear_bit(TABLA_HPHR_PA_OFF_ACK,
+ &tabla->hph_pa_dac_state);
+ clear_bit(TABLA_HPHR_DAC_OFF_ACK,
+ &tabla->hph_pa_dac_state);
+ if (tabla->hph_status & SND_JACK_OC_HPHR)
+ schedule_work(&tabla->hphrocp_work);
+ }
+
+ TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+ tabla_codec_switch_micbias(codec, 0);
+ TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, TABLA_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ msleep(40);
+ /* unset TX7_MBHC_EN bit 7 */
+ snd_soc_update_bits(codec, TABLA_A_TX_7_MBHC_EN, 0x80, 0x00);
+ snd_soc_update_bits(codec, TABLA_A_CDC_ANC1_CTL, 0x01, 0x00);
+ snd_soc_update_bits(codec, TABLA_A_CDC_ANC2_CTL, 0x01, 0x00);
+ msleep(20);
+ snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
+ snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+ snd_soc_write(codec, TABLA_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+ break;
+ }
+ return 0;
+}
+
static int tabla_hph_pa_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -3592,7 +3689,6 @@
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
- {"ANC", NULL, "ANC1 FB MUX"},
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
@@ -3607,19 +3703,26 @@
{"HPHL DAC", NULL, "CP"},
{"HPHR DAC", NULL, "CP"},
- {"ANC", NULL, "ANC1 MUX"},
- {"ANC", NULL, "ANC2 MUX"},
+ {"ANC HEADPHONE", NULL, "ANC HPHL"},
+ {"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+ {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+ {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
{"ANC1 MUX", "ADC1", "ADC1"},
{"ANC1 MUX", "ADC2", "ADC2"},
{"ANC1 MUX", "ADC3", "ADC3"},
{"ANC1 MUX", "ADC4", "ADC4"},
+ {"ANC1 MUX", "DMIC1", "DMIC1"},
+ {"ANC1 MUX", "DMIC2", "DMIC2"},
+ {"ANC1 MUX", "DMIC3", "DMIC3"},
+ {"ANC1 MUX", "DMIC4", "DMIC4"},
{"ANC2 MUX", "ADC1", "ADC1"},
{"ANC2 MUX", "ADC2", "ADC2"},
{"ANC2 MUX", "ADC3", "ADC3"},
{"ANC2 MUX", "ADC4", "ADC4"},
- {"ANC", NULL, "CDC_CONN"},
-
+ {"ANC HPHR", NULL, "CDC_CONN"},
{"DAC1", "Switch", "RX1 CHAIN"},
{"HPHL DAC", "Switch", "RX1 CHAIN"},
{"HPHR DAC", NULL, "RX2 CHAIN"},
@@ -3646,8 +3749,8 @@
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
- {"RX1 CHAIN", NULL, "ANC"},
- {"RX2 CHAIN", NULL, "ANC"},
+ {"RX1 MIX2", NULL, "ANC1 MUX"},
+ {"RX2 MIX2", NULL, "ANC2 MUX"},
{"CP", NULL, "RX_BIAS"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
@@ -4052,6 +4155,14 @@
(reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
return 1;
+ /* ANC filter registers are not cacheable */
+ if ((reg >= TABLA_A_CDC_ANC1_FILT1_B1_CTL) &&
+ (reg <= TABLA_A_CDC_ANC1_FILT2_B3_CTL))
+ return 1;
+ if ((reg >= TABLA_A_CDC_ANC2_FILT1_B1_CTL) &&
+ (reg <= TABLA_A_CDC_ANC2_FILT2_B3_CTL))
+ return 1;
+
/* Digital gain register is not cacheable so we have to write
* the setting even it is the same
*/
@@ -5284,9 +5395,13 @@
SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
- SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
- tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 0, 0, NULL, 0,
+ tabla_codec_enable_anc,
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 0, 0, NULL, 0,
+ tabla_codec_enable_anc, SND_SOC_DAPM_PRE_PMU),
+
SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
@@ -6779,6 +6894,13 @@
* only report the mic line
*/
tabla_codec_report_plug(codec, 1, SND_JACK_HEADSET);
+ if (!tabla->mbhc_micbias_switched &&
+ tabla_is_hph_pa_on(codec)) {
+ /*If the headphone path is on, switch the micbias
+ to VDDIO to avoid noise due to button polling */
+ tabla_codec_switch_micbias(codec, 1);
+ pr_debug("%s: HPH path is still up\n", __func__);
+ }
msleep(100);
tabla_codec_start_hs_polling(codec);
} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
@@ -7201,7 +7323,6 @@
} else if (plug_type == PLUG_TYPE_HEADSET) {
pr_debug("%s: Headset detected\n", __func__);
tabla_codec_report_plug(codec, 1, SND_JACK_HEADSET);
-
/* avoid false button press detect */
msleep(50);
tabla_codec_start_hs_polling(codec);
@@ -7685,6 +7806,7 @@
0x08, 0x00);
/* Turn off override */
tabla_turn_onoff_override(codec, false);
+ tabla_codec_switch_micbias(codec, 0);
}
}
@@ -8650,6 +8772,12 @@
"tabla_gpio_irq_resend");
tabla->gpio_irq_resend = false;
+ mutex_lock(&dapm->codec->mutex);
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
#ifdef CONFIG_DEBUG_FS
if (ret == 0) {
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 6712941..c5b2a52 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -137,6 +137,7 @@
static int msm_btsco_rate = BTSCO_RATE_8KHZ;
static int msm_btsco_ch = 1;
+static int msm_hdmi_rx_ch = 2;
static struct mutex cdc_mclk_mutex;
static struct q_clkdiv *codec_clk;
@@ -413,6 +414,8 @@
static const char *const spk_function[] = {"Off", "On"};
static const char *const slim0_rx_ch_text[] = {"One", "Two"};
static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
+ "Six", "Seven", "Eight"};
static const struct soc_enum msm_enum[] = {
SOC_ENUM_SINGLE_EXT(2, spk_function),
@@ -488,6 +491,30 @@
return 0;
}
+static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__,
+ msm_hdmi_rx_ch);
+ ucontrol->value.integer.value[0] = msm_hdmi_rx_ch - 2;
+
+ return 0;
+}
+
+static int msm_hdmi_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_hdmi_rx_ch = ucontrol->value.integer.value[0] + 2;
+ if (msm_hdmi_rx_ch > 8) {
+ pr_err("%s: channels exceeded 8.Limiting to max channels-8\n",
+ __func__);
+ msm_hdmi_rx_ch = 8;
+ }
+ pr_debug("%s: msm_hdmi_rx_ch = %d\n", __func__, msm_hdmi_rx_ch);
+
+ return 1;
+}
+
static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
msm_btsco_rate_get, msm_btsco_rate_put),
@@ -571,7 +598,10 @@
pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
channels->min, channels->max);
+ if (channels->max < 2)
+ channels->min = channels->max = 2;
rate->min = rate->max = 48000;
+ channels->min = channels->max = msm_hdmi_rx_ch;
return 0;
}
@@ -742,6 +772,7 @@
SOC_ENUM_SINGLE_EXT(2, spk_function),
SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+ SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -753,6 +784,8 @@
msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
SOC_ENUM_EXT("AUX PCM SampleRate", msm8974_auxpcm_enum[0],
msm8974_auxpcm_rate_get, msm8974_auxpcm_rate_put),
+ SOC_ENUM_EXT("HDMI_RX Channels", msm_snd_enum[3],
+ msm_hdmi_rx_ch_get, msm_hdmi_rx_ch_put),
};
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 58a07d6..4c50b53 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -1267,6 +1267,8 @@
int ret = 0, i = 0;
/* Assumes port_ids have already been validated during adm_open */
int index = afe_get_port_index(copp_id);
+ int copp_cnt;
+
if (index < 0 || index >= AFE_MAX_PORTS) {
pr_err("%s: invalid port idx %d token %d\n",
__func__, index, copp_id);
@@ -1289,9 +1291,19 @@
route.hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS;
route.num_sessions = 1;
route.session[0].id = session_id;
- route.session[0].num_copps = num_copps;
- for (i = 0; i < num_copps; i++) {
+ if (num_copps < ADM_MAX_COPPS) {
+ copp_cnt = num_copps;
+ } else {
+ copp_cnt = ADM_MAX_COPPS;
+ /* print out warning for now as playback/capture to/from
+ * COPPs more than maximum allowed is extremely unlikely
+ */
+ pr_warn("%s: max out routable COPPs\n", __func__);
+ }
+
+ route.session[0].num_copps = copp_cnt;
+ for (i = 0; i < copp_cnt; i++) {
int tmp;
port_id[i] = afe_convert_virtual_to_portid(port_id[i]);
@@ -1304,7 +1316,8 @@
route.session[0].copp_id[i] =
atomic_read(&this_adm.copp_id[tmp]);
}
- if (num_copps % 2)
+
+ if (copp_cnt % 2)
route.session[0].copp_id[i] = 0;
switch (path) {
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 48d9e1e..329d293 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,11 +24,20 @@
#include <sound/q6afe-v2.h>
#include <sound/msm-dai-q6-v2.h>
+#define HDMI_RX_CA_MAX 0x32
+
enum {
STATUS_PORT_STARTED, /* track if AFE port has started */
STATUS_MAX
};
+struct msm_hdmi_ca {
+ bool set_ca;
+ u32 ca;
+};
+
+static struct msm_hdmi_ca hdmi_ca = { false, 0x0 };
+
struct msm_dai_q6_hdmi_dai_data {
DECLARE_BITMAP(status_mask, STATUS_MAX);
u32 rate;
@@ -57,6 +66,20 @@
return 0;
}
+static int msm_dai_q6_hdmi_ca_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ hdmi_ca.ca = ucontrol->value.integer.value[0];
+ hdmi_ca.set_ca = true;
+ return 0;
+}
+
+static int msm_dai_q6_hdmi_ca_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = hdmi_ca.ca;
+ return 0;
+}
/* HDMI format field for AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG command
* 0: linear PCM
@@ -75,6 +98,10 @@
SOC_ENUM_EXT("HDMI RX Format", hdmi_config_enum[0],
msm_dai_q6_hdmi_format_get,
msm_dai_q6_hdmi_format_put),
+ SOC_SINGLE_MULTI_EXT("HDMI RX CA", SND_SOC_NOPM, 0,
+ HDMI_RX_CA_MAX, 0, 1,
+ msm_dai_q6_hdmi_ca_get,
+ msm_dai_q6_hdmi_ca_put),
};
/* Current implementation assumes hw_param is called once
@@ -152,6 +179,10 @@
struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
int rc = 0;
+ if (hdmi_ca.set_ca)
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ hdmi_ca.ca;
+
if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
rc = afe_port_start(dai->id, &dai_data->port_config,
dai_data->rate);
@@ -186,6 +217,12 @@
rc = snd_ctl_add(dai->card->snd_card,
snd_ctl_new1(kcontrol, dai_data));
+
+ kcontrol = &hdmi_config_controls[1];
+
+ rc = snd_ctl_add(dai->card->snd_card,
+ snd_ctl_new1(kcontrol, dai_data));
+
return rc;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index ab92269..4f90400 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 1d6e106..fa8609e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -40,6 +40,12 @@
struct snd_pcm *pcm;
};
+struct snd_msm_volume {
+ struct msm_audio *prtd;
+ unsigned volume;
+};
+static struct snd_msm_volume pcm_audio = {NULL, 0x2000};
+
#define PLAYBACK_NUM_PERIODS 8
#define PLAYBACK_MAX_PERIOD_SIZE 12288
#define PLAYBACK_MIN_PERIOD_SIZE 2048
@@ -213,8 +219,11 @@
if (prtd->enabled)
return 0;
- ret = q6asm_media_format_block_pcm(prtd->audio_client, runtime->rate,
- runtime->channels);
+ ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
+ runtime->rate,
+ runtime->channels,
+ !prtd->set_channel_map,
+ prtd->channel_map);
if (ret < 0)
pr_info("%s: CMD Format block failed\n", __func__);
@@ -365,7 +374,9 @@
}
prtd->dsp_cnt = 0;
+ prtd->set_channel_map = false;
runtime->private_data = prtd;
+ pcm_audio.prtd = prtd;
return 0;
}
@@ -449,7 +460,8 @@
prtd->audio_client);
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
- SNDRV_PCM_STREAM_PLAYBACK);
+ SNDRV_PCM_STREAM_PLAYBACK);
+ pcm_audio.prtd = NULL;
q6asm_audio_client_free(prtd->audio_client);
kfree(prtd);
return 0;
@@ -691,13 +703,49 @@
.mmap = msm_pcm_mmap,
};
+static int pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+ pr_debug("%s", __func__);
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+ channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
+ if (pcm_audio.prtd) {
+ pcm_audio.prtd->set_channel_map = true;
+ memcpy(pcm_audio.prtd->channel_map, channel_mapping,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+ return 0;
+}
+
static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- int ret = 0;
+ struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+ struct snd_pcm_chmap *chmap_info;
+ struct snd_kcontrol *kctl;
+ char device_num[3];
+ int i, ret = 0;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ pr_debug("%s, Channel map cntrl add\n", __func__);
+ ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ NULL, PCM_FORMAT_MAX_NUM_CHANNEL, 0,
+ &chmap_info);
+ if (ret < 0)
+ return ret;
+ kctl = chmap_info->kctl;
+ for (i = 0; i < kctl->count; i++)
+ kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
+ snprintf(device_num, sizeof(device_num), "%d", pcm->device);
+ strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
+ pr_debug("%s, Overwriting channel map control name to: %s",
+ __func__, kctl->id.name);
+ kctl->put = pcm_chmap_ctl_put;
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index e25d356..9a770bf 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -82,6 +82,8 @@
int periods;
int mmap_flag;
atomic_t pending_buffer;
+ bool set_channel_map;
+ char channel_map[8];
};
struct output_meta_data_st {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 26f634b..6b957f6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -805,6 +805,31 @@
return 0;
}
+static int msm_routing_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
+ int i;
+
+ adm_get_multi_ch_map(channel_map);
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+ ucontrol->value.integer.value[i] = (unsigned) channel_map[i];
+ return 0;
+}
+
+static int msm_routing_put_channel_map_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ char channel_map[PCM_FORMAT_MAX_NUM_CHANNEL];
+ int i;
+
+ for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+ channel_map[i] = (char)(ucontrol->value.integer.value[i]);
+ adm_set_multi_ch_map(channel_map);
+
+ return 0;
+}
+
static int msm_routing_get_srs_trumedia_control(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1577,6 +1602,12 @@
msm_routing_set_compressed_vol_mixer, compressed_rx_vol_gain),
};
+static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
+ SOC_SINGLE_MULTI_EXT("Playback Channel Map", SND_SOC_NOPM, 0, 16,
+ 0, 8, msm_routing_get_channel_map_mixer,
+ msm_routing_put_channel_map_mixer),
+};
+
static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SRS TruMedia",
@@ -2491,6 +2522,10 @@
snd_soc_add_platform_controls(platform,
lpa_SRS_trumedia_controls_I2S,
ARRAY_SIZE(lpa_SRS_trumedia_controls_I2S));
+
+ snd_soc_add_platform_controls(platform,
+ multi_ch_channel_map_mixer_controls,
+ ARRAY_SIZE(multi_ch_channel_map_mixer_controls));
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 660e6a8..bc11304 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -52,6 +52,15 @@
static struct adm_ctl this_adm;
+struct adm_multi_ch_map {
+ bool set_channel_map;
+ char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+};
+
+static struct adm_multi_ch_map multi_ch_map = { false,
+ {0, 0, 0, 0, 0, 0, 0, 0}
+ };
+
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
{
struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
@@ -266,6 +275,21 @@
__func__, data->opcode, data->payload_size);
}
+void adm_set_multi_ch_map(char *channel_map)
+{
+ memcpy(multi_ch_map.channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ multi_ch_map.set_channel_map = true;
+}
+
+void adm_get_multi_ch_map(char *channel_map)
+{
+ if (multi_ch_map.set_channel_map) {
+ memcpy(channel_map, multi_ch_map.channel_mapping,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+}
+
static int32_t adm_callback(struct apr_client_data *data, void *priv)
{
uint32_t *payload;
@@ -743,6 +767,11 @@
channel_mode);
return -EINVAL;
}
+ if ((open.dev_num_channel > 2) &&
+ multi_ch_map.set_channel_map)
+ memcpy(open.dev_channel_mapping,
+ multi_ch_map.channel_mapping,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
pr_debug("%s: port_id=%#x rate=%d topology_id=0x%X\n",
__func__, open.endpoint_id_1, open.sample_rate,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 8d579c6..fc8bfeb 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1851,12 +1851,12 @@
lchannel_mapping[3] = PCM_CHANNEL_LB;
lchannel_mapping[4] = PCM_CHANNEL_RB;
} else if (channels == 6) {
- channel_mapping[0] = PCM_CHANNEL_FC;
- channel_mapping[1] = PCM_CHANNEL_FL;
- channel_mapping[2] = PCM_CHANNEL_FR;
- channel_mapping[3] = PCM_CHANNEL_LB;
- channel_mapping[4] = PCM_CHANNEL_RB;
- channel_mapping[5] = PCM_CHANNEL_LFE;
+ lchannel_mapping[0] = PCM_CHANNEL_FC;
+ lchannel_mapping[1] = PCM_CHANNEL_FL;
+ lchannel_mapping[2] = PCM_CHANNEL_FR;
+ lchannel_mapping[3] = PCM_CHANNEL_LB;
+ lchannel_mapping[4] = PCM_CHANNEL_RB;
+ lchannel_mapping[5] = PCM_CHANNEL_LFE;
} else if (channels == 8) {
lchannel_mapping[0] = PCM_CHANNEL_FL;
lchannel_mapping[1] = PCM_CHANNEL_FR;
@@ -2166,6 +2166,56 @@
return -EINVAL;
}
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels,
+ bool use_default_chmap, char *channel_map)
+{
+ struct asm_multi_channel_pcm_fmt_blk_v2 fmt;
+ u8 *channel_mapping;
+ int rc = 0;
+
+ pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
+ channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmt_blk);
+ fmt.num_channels = channels;
+ fmt.bits_per_sample = 16;
+ fmt.sample_rate = rate;
+ fmt.is_signed = 1;
+
+ channel_mapping = fmt.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (use_default_chmap) {
+ if (q6asm_map_channels(channel_mapping, channels)) {
+ pr_err("%s: map channels failed", __func__);
+ return -EINVAL;
+ }
+ } else {
+ memcpy(channel_mapping, channel_map,
+ PCM_FORMAT_MAX_NUM_CHANNEL);
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd open failed\n", __func__);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout. waited for format update\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 63741ec..bd65213 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -4005,7 +4005,7 @@
if (data->payload_size) {
ptr = data->payload;
- pr_info("%x %x\n", ptr[0], ptr[1]);
+ pr_debug("%x %x\n", ptr[0], ptr[1]);
/* ping mvm service ACK */
switch (ptr[0]) {
case VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
@@ -4137,7 +4137,7 @@
if (data->payload_size) {
ptr = data->payload;
- pr_info("%x %x\n", ptr[0], ptr[1]);
+ pr_debug("%x %x\n", ptr[0], ptr[1]);
if (ptr[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, ptr[0], ptr[1]);
@@ -4380,7 +4380,7 @@
if (data->payload_size) {
ptr = data->payload;
- pr_info("%x %x\n", ptr[0], ptr[1]);
+ pr_debug("%x %x\n", ptr[0], ptr[1]);
if (ptr[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
__func__, ptr[0], ptr[1]);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 5ac643416..99047178 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -78,7 +78,7 @@
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_aif_in] = 1,
[snd_soc_dapm_aif_out] = 1,
- [snd_soc_dapm_adc] = 1,
+ [snd_soc_dapm_adc] = 5,
[snd_soc_dapm_hp] = 2,
[snd_soc_dapm_spk] = 2,
[snd_soc_dapm_out_drv] = 2,