Merge "msm: camera2: Enhance cpp driver."
diff --git a/Documentation/devicetree/bindings/arm/msm/bcl.txt b/Documentation/devicetree/bindings/arm/msm/bcl.txt
new file mode 100644
index 0000000..e11a817
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/bcl.txt
@@ -0,0 +1,15 @@
+* Battery Current Limit
+
+This Battery Current Limit device, provides an interface to detect and notify
+interested applications when the SOC is drawing current in excess of the limits
+specified.
+
+The device tree parameters for bcl are:
+
+Required parameters:
+- compatible: Must be "qcom,bcl"
+
+Example:
+ qcom,bcl {
+ compatible = "qcom,bcl";
+ };
diff --git a/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt b/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
deleted file mode 100644
index 01301be..0000000
--- a/Documentation/devicetree/bindings/arm/msm/debug-pc-cntr.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-* MSM PC Debug Counters
-
-MSM PC debug counter reserves 16 registers in the IMEM memory space which
-maintains a count on the state of power collapse on each core. This count
-will be useful to debug the power collapse state on each core.
-
-The required nodes for MSM PC Debug Counters are:
-
-- compatible: "qcom,pc-cntr"
-- reg: physical IMEM address reserved for PC counters
-
-Example:
-
-qcom,pc-cntr@fe800000 {
- compatible = "qcom,pc-cntr";
- reg = <0xfe800664 0x40>;
- };
-
diff --git a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
new file mode 100644
index 0000000..e62b9ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
@@ -0,0 +1,17 @@
+* MSM Timetick counter (mpm-v2)
+
+The MPM provides a timetick that starts when the device is powered up and
+is not reset by any of the boot loaders or the HLOS. The MPM timetick counter
+driver provides an api to get this value.
+
+The required nodes for the MPM timetick counter driver are:
+
+- compatible: "qcom,mpm-counter"
+- reg: Specifies the physical address of the timetick count register.
+
+Example:
+ qcom,mpm-counter@fc4a3000 {
+ compatible = "qcom,mpm-counter";
+ reg = <0xfc4a3000 0x1000>;
+ };
+
diff --git a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
index b429072..a372912 100644
--- a/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
+++ b/Documentation/devicetree/bindings/arm/msm/pm-8x60.txt
@@ -5,6 +5,9 @@
the kernel to be notified of idle and suspend states and when called, follows
through the set of instructions in putting the application cores to the lowest
power mode possible.
+The PC debug counter reserves 16 registers in the IMEM memory space which maintains
+a count on the state of power collapse on each core. This count will be useful to
+debug the power collapse state on each core.
The required properties for PM-8x60 are:
@@ -12,17 +15,22 @@
The optional properties are:
+- reg: physical IMEM address reserved for PC counters and the size
- qcom,use-sync-timer: Indicates whether the target uses the synchronized QTimer.
- qcom,pc-mode: Indicates the type of power collapse used by the target. The
- valid values for this are:
+ valid values for this are:
0 (Power collapse terminates in TZ; integrated L2 cache controller)
1, (Power collapse doesn't terminate in TZ; external L2 cache controller)
2 (Power collapse terminates in TZ; external L2 cache controller)
+- qcom,saw-turns-off-pll: Version of SAW2.1 or can turn off the HFPLL, when
+ doing power collapse and so the core need to switch to Global PLL before
+ PC.
Example:
-qcom,pm-8x60 {
+qcom,pm-8x60@fe800664 {
compatible = "qcom,pm-8x60";
+ reg = <0xfe800664 0x40>;
qcom,pc-mode = <0>;
qcom,use-sync-timer;
};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index b1f6717..8f602b6 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -21,8 +21,6 @@
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.
Optional properties:
- vdd_pll-supply: Reference to the regulator that supplies the PLL's rail.
@@ -46,10 +44,4 @@
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/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 03b01ee..a868b75 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -34,6 +34,8 @@
system thermal mitigation level.
Parent node optional properties:
+- qcom,chg-maxinput-usb-ma: Maximum input current USB.
+- qcom,chg-maxinput-dc-ma: Maximum input current DC.
- qcom,chg-charging-disabled: Set this property to disable charging
by default. This can then be overriden
writing the the module parameter
diff --git a/Documentation/devicetree/bindings/spi/spi_qsd.txt b/Documentation/devicetree/bindings/spi/spi_qsd.txt
index 939f77b..4b912f3 100644
--- a/Documentation/devicetree/bindings/spi/spi_qsd.txt
+++ b/Documentation/devicetree/bindings/spi/spi_qsd.txt
@@ -1,25 +1,51 @@
Qualcomm Serial Peripheral Interface (SPI)
Required properties:
-- compatible : should be "qcom,spi-qup-v2".
-- reg : offset and length of the QUP register map.
-- interrupts : should contain the QUP core interrupt.
-- spi-max-frequency : specifies maximum SPI clock frequency, Units - Hz.
+- compatible : Should be "qcom,spi-qup-v2".
+- reg : Offset and length of the register regions for the device
+- reg-names : Register region names referenced in reg above.
+ Required register resource entries are:
+ "spi_physical" : Physical address of controller register blocks.
+- interrupts : Interrupt numbers used by this controller
+- interrupt-names : Interrupt resource names referenced in interrupts above.
+ Required interrupt resource entries are:
+ "spi_irq" : QUP-core interrupt.
+- spi-max-frequency : Specifies maximum SPI clock frequency, Units - Hz.
+
+Required alias:
+- The desired bus-number is specified via an alias with the following format
+ 'spi{n}' where n is the bus number.
Optional properties:
-- gpios : specifies the gpio pins to be used for SPI CLK, MISO, MOSI in
+- gpios : Specifies the gpio pins to be used for SPI CLK, MISO, MOSI in
that order.
-- cs-gpios : specifies the gpio pins to be used for chipselects.
+- cs-gpios : Specifies the gpio pins to be used for chipselects.
+- qcom,infinite-mode: When missing or set to zero, QUP uses infinite-mode. When
+ value is non-zero, the value is the number of words in maximum transfer
+ length.
-SPI slave nodes must be children of the SPI master node and contain
+Optional properties which are required for support of BAM-mode:
+- qcom,ver-reg-exists : Boolean. When present, allows driver to verify if HW
+ version support latest features (e.g. BAM) and then enable them. Should be
+ removed for legacy HW.
+- qcom,use-bam : Boolean. When present, enables BAM-mode.
+- qcom,bam-consumer-pipe-index : BAM consumer-pipe index.
+- qcom,bam-producer-pipe-index : BAM producer-pipe index.
+- reg-names : register region names referenced in reg.
+ Required register resource for BAM are:
+ "spi_bam_physical" : Physical address of BAM for this controller.
+- interrupt-names : interrupt resource names referenced in interrupts.
+ Required interrupt resource from BAM are:
+ "spi_bam_irq" : BAM interrupt used by the controller.
+
+Optional SPI slave nodes must be children of the SPI master node and contain
the following properties.
-- reg : (required) chip select address of device.
-- compatible : (required) name of SPI device following generic names
- recommended practice
+- reg: (required) chip-select address of the device.
+- compatible : (required) Name of SPI device following generic names.
- spi-max-frequency : (required) Maximum SPI clocking speed of device in Hz
-- interrupts : (recommended) should contain the SPI slave interrupt number
+- interrupts : (recommended) Should contain the SPI slave interrupt number
encoded depending on the type of the interrupt controller.
-- interrupt-parent : (recommended) the phandle for the interrupt controller
+- interrupt-parent : (recommended) The phandle for the interrupt controller
that services interrupts for this device.
- spi-cpol : (optional) Empty property indicating device requires inverse
clock polarity (CPOL) mode
@@ -29,18 +55,30 @@
chip select active high
Example:
- spi@f9924000 {
- compatible = "qcom,spi-qup-v2";
- reg = <0xf9924000 0x1000>;
- interrupts = <0 96 0>;
- spi-max-frequency = <24000000>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- device@0 {
- compatible = "spidev";
- reg = <0>;
- spi-max-frequency = <5000000>;
- };
+ aliases {
+ spi0 = &spi_0;
};
+ spi_0: spi@f9923000 {
+ compatible = "qcom,spi-qup-v2";
+
+ reg-names = "spi_physical", "spi_bam_physical";
+ reg = <0xf9923000 0x1000>,
+ <0xf9904000 0x10000>;
+ interrupt-names = "spi_irq", "spi_bam_irq";
+ interrupts = <0 95 0>, <0 238 0>;
+
+ spi-max-frequency = <19200000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpios = <&msmgpio 3 0>, /* CLK */
+ <&msmgpio 1 0>, /* MISO */
+ <&msmgpio 0 0>; /* MOSI */
+ cs-gpios = <&msmgpio 9 0>;
+
+ qcom,infinite-mode = <0>;
+ qcom,use-bam;
+ qcom,bam-consumer-pipe-index = <12>;
+ qcom,bam-producer-pipe-index = <13>;
+ qcom,ver-reg-exists;
+ };
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 0e06ac5..ce4513b 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -16,6 +16,113 @@
interrupt-controller;
#interrupt-cells = <3>;
+ qcom,pm8226@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8226_gpios: gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8226-gpio";
+
+ gpio@c000 {
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,pin-num = <4>;
+ };
+
+ gpio@c400 {
+ reg = <0xc400 0x100>;
+ qcom,pin-num = <5>;
+ };
+
+ gpio@c500 {
+ reg = <0xc500 0x100>;
+ qcom,pin-num = <6>;
+ };
+
+ gpio@c600 {
+ reg = <0xc600 0x100>;
+ qcom,pin-num = <7>;
+ };
+
+ gpio@c700 {
+ reg = <0xc700 0x100>;
+ qcom,pin-num = <8>;
+ };
+ };
+
+ pm8226_mpps: mpps {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-pin";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8226-mpp";
+
+ mpp@a000 {
+ reg = <0xa000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
+ };
+
+ mpp@a400 {
+ reg = <0xa400 0x100>;
+ qcom,pin-num = <5>;
+ };
+
+ mpp@a500 {
+ reg = <0xa500 0x100>;
+ qcom,pin-num = <6>;
+ };
+
+ mpp@a600 {
+ reg = <0xa600 0x100>;
+ qcom,pin-num = <7>;
+ };
+
+ mpp@a700 {
+ reg = <0xa700 0x100>;
+ qcom,pin-num = <8>;
+ };
+ };
+ };
+
qcom,pm8226@1 {
spmi-slave-container;
reg = <0x1>;
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index f2269d5..50d2dba 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,275 +10,300 @@
* GNU General Public License for more details.
*/
- /* Stub Regulators */
+/* Stub Regulators */
- / {
- pm8026_s1: regulator-s1 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_s1";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
-
+/ {
pm8026_s1_corner: regulator-s1-corner {
compatible = "qcom,stub-regulator";
- regulator-name = "8026_s1_corner";
+ regulator-name = "8226_s1_corner";
qcom,hpm-min-load = <100000>;
regulator-min-microvolt = <1>;
regulator-max-microvolt = <7>;
qcom,consumer-supplies = "vdd_dig", "";
};
+};
- pm8026_s2: regulator-s2 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_s2";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- };
+/* QPNP controlled regulators: */
- pm8026_s3: regulator-s3 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_s3";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- };
+&spmi_bus {
- pm8026_s4: regulator-s4 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_s4";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <2100000>;
- regulator-max-microvolt = <2100000>;
- };
+ qcom,pm8226@1 {
- pm8026_s5: regulator-s5 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_s5";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
+ pm8226_s1: regulator@1400 {
+ status = "okay";
+ regulator-name = "8226_s1";
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ regulator-min-microvolt = <1287500>;
+ regulator-max-microvolt = <1287500>;
+ };
- pm8026_l1: regulator-l1 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l1";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- };
+ pm8226_s2: regulator@1700 {
+ status = "okay";
+ regulator-name = "8226_s2";
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
- pm8026_l2: regulator-l2 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l2";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
+ pm8226_s3: regulator@1a00 {
+ status = "okay";
+ regulator-name = "8226_s3";
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
- pm8026_l3: regulator-l3 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l3";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
+ pm8226_s4: regulator@1d00 {
+ status = "okay";
+ regulator-name = "8226_s4";
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ regulator-min-microvolt = <2100000>;
+ regulator-max-microvolt = <2100000>;
+ };
- pm8026_l4: regulator-l4 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l4";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
+ pm8226_s5: regulator@2000 {
+ status = "okay";
+ regulator-name = "8226_s5";
+ qcom,enable-time = <500>;
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
- pm8026_l5: regulator-l5 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l5";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
+ pm8226_l1: regulator@4000 {
+ status = "okay";
+ regulator-name = "8226_l1";
+ parent-supply = <&pm8226_s3>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
- pm8026_l6: regulator-l6 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l6";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8226_l2: regulator@4100 {
+ status = "okay";
+ regulator-name = "8226_l2";
+ parent-supply = <&pm8226_s3>;
+ regulator-always-on;
+ qcom,enable-time = <200>;
+ qcom,system-load = <10000>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
- pm8026_l7: regulator-l7 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l7";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1850000>;
- regulator-max-microvolt = <1850000>;
- };
+ pm8226_l3: regulator@4200 {
+ status = "okay";
+ regulator-name = "8226_l3";
+ parent-supply = <&pm8226_s3>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1287500>;
+ regulator-max-microvolt = <1287500>;
+ };
- pm8026_l8: regulator-l8 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l8";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,consumer-supplies = "vdd_sr2_pll", "";
- };
+ pm8226_l4: regulator@4300 {
+ status = "okay";
+ regulator-name = "8226_l4";
+ parent-supply = <&pm8226_s3>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
- pm8026_l9: regulator-l9 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l9";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- };
+ pm8226_l5: regulator@4400 {
+ status = "okay";
+ regulator-name = "8226_l5";
+ parent-supply = <&pm8226_s3>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
- pm8026_l10: regulator-l10 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l10";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8226_l6: regulator@4500 {
+ status = "okay";
+ regulator-name = "8226_l6";
+ parent-supply = <&pm8226_s4>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
- pm8026_l12: regulator-l12 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l12";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8226_l7: regulator@4600 {
+ status = "okay";
+ regulator-name = "8226_l7";
+ parent-supply = <&pm8226_s4>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
- pm8026_l14: regulator-l14 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l14";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <2750000>;
- regulator-max-microvolt = <2750000>;
- };
+ pm8226_l8: regulator@4700 {
+ status = "okay";
+ regulator-name = "8226_l8";
+ parent-supply = <&pm8226_s4>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,consumer-supplies = "vdd_sr2_pll", "";
+ };
- pm8026_l15: regulator-l15 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l15";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- };
+ pm8226_l9: regulator@4800 {
+ status = "okay";
+ regulator-name = "8226_l9";
+ parent-supply = <&pm8226_s4>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
- pm8026_l16: regulator-l16 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l16";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- };
+ pm8226_l10: regulator@4900 {
+ status = "okay";
+ regulator-name = "8226_l10";
+ parent-supply = <&pm8226_s4>;
+ qcom,enable-time = <200>;
+ qcom,system-load = <5000>;
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
- pm8026_l17: regulator-l17 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l17";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l12: regulator@4b00 {
+ status = "okay";
+ regulator-name = "8226_l12";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
- pm8026_l18: regulator-l18 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l18";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l14: regulator@4d00 {
+ status = "okay";
+ regulator-name = "8226_l14";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
- pm8026_l19: regulator-l19 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l19";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- };
+ pm8226_l15: regulator@4e00 {
+ status = "okay";
+ regulator-name = "8226_l15";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
- pm8026_l20: regulator-l20 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l20";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- };
+ pm8226_l16: regulator@4f00 {
+ status = "okay";
+ regulator-name = "8226_l16";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ };
- pm8026_l21: regulator-l21 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l21";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l17: regulator@5000 {
+ status = "okay";
+ regulator-name = "8226_l17";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
- pm8026_l22: regulator-l22 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l22";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l18: regulator@5100 {
+ status = "okay";
+ regulator-name = "8226_l18";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
- pm8026_l23: regulator-l23 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l23";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l19: regulator@5200 {
+ status = "okay";
+ regulator-name = "8226_l19";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
- pm8026_l24: regulator-l24 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l24";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- };
+ pm8226_l20: regulator@5300 {
+ status = "okay";
+ regulator-name = "8226_l20";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
- pm8026_l26: regulator-l26 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l26";
- parent-supply = <&pm8026_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- };
+ pm8226_l21: regulator@5400 {
+ status = "okay";
+ regulator-name = "8226_l21";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
- pm8026_l27: regulator-l27 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l27";
- parent-supply = <&pm8026_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- };
+ pm8226_l22: regulator@5500 {
+ status = "okay";
+ regulator-name = "8226_l22";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
- pm8026_l28: regulator-l28 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_l28";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8226_l23: regulator@5600 {
+ status = "okay";
+ regulator-name = "8226_l23";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
- pm8026_lvs1: regulator-lvs1 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8026_lvs1";
- parent-supply = <&pm8026_l6>;
+ pm8226_l24: regulator@5700 {
+ status = "okay";
+ regulator-name = "8226_l24";
+ parent-supply = <&pm8226_s3>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_l26: regulator@5900 {
+ status = "okay";
+ regulator-name = "8226_l26";
+ parent-supply = <&pm8226_s3>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l27: regulator@5a00 {
+ status = "okay";
+ regulator-name = "8226_l27";
+ parent-supply = <&pm8226_s4>;
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l28: regulator@5b00 {
+ status = "okay";
+ regulator-name = "8226_l28";
+ qcom,enable-time = <200>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_lvs1: regulator@8000 {
+ status = "okay";
+ regulator-name = "8226_lvs1";
+ parent-supply = <&pm8226_l6>;
+ qcom,enable-time = <200>;
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index 9a0ec17..f9ab957 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -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
@@ -39,8 +39,8 @@
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
- vdd-supply = <&pm8026_l17>;
- vdd-io-supply = <&pm8026_l6>;
+ vdd-supply = <&pm8226_l17>;
+ vdd-io-supply = <&pm8226_l6>;
qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
qcom,sup-voltages = <2950 2950>;
@@ -50,8 +50,8 @@
};
&sdcc2 {
- vdd-supply = <&pm8026_l18>;
- vdd-io-supply = <&pm8026_l21>;
+ vdd-supply = <&pm8226_l18>;
+ vdd-io-supply = <&pm8226_l21>;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
@@ -74,3 +74,57 @@
status = "ok";
};
+
+&pm8226_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+
+ gpio@c600 { /* GPIO 7 */
+ };
+
+ gpio@c700 { /* GPIO 8 */
+ };
+};
+
+&pm8226_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ };
+
+ mpp@a600 { /* MPP 7 */
+ };
+
+ mpp@a700 { /* MPP 8 */
+ };
+};
+
+
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 5227004..3ae69fd 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -81,9 +81,9 @@
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>, <0 140 0>;
interrupt-names = "core_irq", "async_irq";
- HSUSB_VDDCX-supply = <&pm8026_s1>;
- HSUSB_1p8-supply = <&pm8026_l10>;
- HSUSB_3p3-supply = <&pm8026_l20>;
+ HSUSB_VDDCX-supply = <&pm8226_s1>;
+ HSUSB_1p8-supply = <&pm8226_l10>;
+ HSUSB_3p3-supply = <&pm8226_l20>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-mode = <1>;
@@ -123,23 +123,23 @@
17 18 19 20 21 22 23 24 25 26 27 28>;
qcom,cdc-reset-gpio = <&msmgpio 72 0>;
- cdc-vdd-buck-supply = <&pm8026_s4>;
+ cdc-vdd-buck-supply = <&pm8226_s4>;
qcom,cdc-vdd-buck-voltage = <2100000 2100000>;
qcom,cdc-vdd-buck-current = <650000>;
- cdc-vdd-h-supply = <&pm8026_l6>;
+ cdc-vdd-h-supply = <&pm8226_l6>;
qcom,cdc-vdd-h-voltage = <1800000 1800000>;
qcom,cdc-vdd-h-current = <25000>;
- cdc-vdd-px-supply = <&pm8026_l6>;
+ cdc-vdd-px-supply = <&pm8226_l6>;
qcom,cdc-vdd-px-voltage = <1800000 1800000>;
qcom,cdc-vdd-px-current = <25000>;
- cdc-vdd-a-1p2v-supply = <&pm8026_l4>;
+ cdc-vdd-a-1p2v-supply = <&pm8226_l4>;
qcom,cdc-vdd-a-1p2v-voltage = <1200000 1200000>;
qcom,cdc-vdd-a-1p2v-current = <10000>;
- cdc-vdd-cx-supply = <&pm8026_l4>;
+ cdc-vdd-cx-supply = <&pm8226_l4>;
qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
qcom,cdc-vdd-cx-current = <10000>;
@@ -466,8 +466,8 @@
compatible = "qcom,acpuclk-a7";
reg = <0xf9011050 0x8>;
reg-names = "rcg_base";
- a7_cpu-supply = <&pm8026_s2>;
- a7_mem-supply = <&pm8026_l3>;
+ a7_cpu-supply = <&pm8226_s2>;
+ a7_mem-supply = <&pm8226_l3>;
};
qcom,ocmem@fdd00000 {
@@ -510,7 +510,7 @@
<0xfd485300 0xc>;
reg-names = "pmu_base", "clk_base", "halt_base";
interrupts = <0 149 1>;
- vdd_pronto_pll-supply = <&pm8026_l8>;
+ vdd_pronto_pll-supply = <&pm8226_l8>;
qcom,firmware-name = "wcnss";
};
@@ -566,5 +566,5 @@
status = "ok";
};
-/include/ "msm8226-regulator.dtsi"
/include/ "msm-pm8226.dtsi"
+/include/ "msm8226-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 12804fb..16883ef 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -534,3 +534,11 @@
mpp@a300 { /* MPP 4 */
};
};
+
+&slim_msm {
+ taiko_codec {
+ qcom,cdc-micbias1-ext-cap;
+ qcom,cdc-micbias3-ext-cap;
+ qcom,cdc-micbias4-ext-cap;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 7cc10e2..11c835f 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -207,7 +207,10 @@
&slim_msm {
taiko_codec {
+ qcom,cdc-micbias1-ext-cap;
qcom,cdc-micbias2-ext-cap;
+ qcom,cdc-micbias3-ext-cap;
+ qcom,cdc-micbias4-ext-cap;
};
};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 76b23a1..e97678a 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -585,6 +585,7 @@
&slim_msm {
taiko_codec {
qcom,cdc-micbias2-ext-cap;
+ qcom,cdc-micbias3-ext-cap;
};
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index ea57389..e21610b 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -512,7 +512,9 @@
&slim_msm {
taiko_codec {
+ qcom,cdc-micbias1-ext-cap;
qcom,cdc-micbias2-ext-cap;
+ qcom,cdc-micbias4-ext-cap;
};
};
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
index 60f63a8..511f91f 100644
--- a/arch/arm/boot/dts/msm8974-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -103,29 +103,6 @@
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";
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index f9b9e33..2de5fad 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -419,13 +419,9 @@
<40 95>;
};
- qcom,pc-cntr@fe805664 {
- compatible = "qcom,pc-cntr";
- reg = <0xfe805664 0x40>;
- };
-
- qcom,pm-8x60 {
+ qcom,pm-8x60@fe805664 {
compatible = "qcom,pm-8x60";
+ reg = <0xfe805664 0x40>;
qcom,pc-mode = <0>; /*MSM_PC_TZ_L2_INT */
qcom,use-sync-timer;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
index 584869d..c974884 100644
--- a/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-iommu.dtsi
@@ -71,6 +71,7 @@
};
venus_sec_bitstream: qcom,iommu-ctx@fdc8d000 {
+ qcom,iommu-ctx-sids = <0x80 0x81 0x82 0x83 0x84>;
label = "venus_sec_bitstream";
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 1ef376f..e6376d4 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -25,6 +25,11 @@
compatible = "qcom,msm8974";
interrupt-parent = <&intc>;
+ aliases {
+ spi0 = &spi_0;
+ spi7 = &spi_7;
+ };
+
intc: interrupt-controller@F9000000 {
compatible = "qcom,msm-qgic2";
interrupt-controller;
@@ -60,6 +65,11 @@
clock-frequency = <19200000>;
};
+ qcom,mpm-counter@fc4a3000 {
+ compatible = "qcom,mpm-counter";
+ reg = <0xfc4a3000 0x1000>;
+ };
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
@@ -376,9 +386,8 @@
qcom,bam-dma-res-pipes = <6>;
};
- spi_epm: spi@f9966000 {
+ spi_7: spi_epm: spi@f9966000 {
compatible = "qcom,spi-qup-v2";
- cell-index = <7>;
reg = <0xf9966000 0x1000>;
interrupts = <0 104 0>;
spi-max-frequency = <19200000>;
@@ -567,8 +576,7 @@
qcom,i2c-src-freq = <19200000>;
};
- spi@f9923000 {
- cell-index = <0>;
+ spi_0: spi@f9923000 {
compatible = "qcom,spi-qup-v2";
reg = <0xf9923000 0x1000>;
interrupts = <0 95 0>;
@@ -883,12 +891,6 @@
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 {
@@ -1261,6 +1263,10 @@
qcom,irq-no-suspend;
};
};
+
+ qcom,bcl {
+ compatible = "qcom,bcl";
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 793d27b..a735609 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -189,8 +189,38 @@
qcom,gic-parent = <&intc>;
qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
- <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
- <0xff 208>; /* summary_irq_kpss */
+ <41 180>, /* usb_async_wakeup_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_lo */
+ <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>, /* q6ss_irq_out(4) */
+ <0xff 189>, /* q6ss_irq_out(5) */
+ <0xff 190>, /* q6ss_irq_out(6) */
+ <0xff 191>, /* q6ss_irq_out(7) */
+ <0xff 192>, /* audio_out0_irq */
+ <0xff 193>, /* midi_arm_irq */
+ <0xff 194>, /* q6ss_wdog_exp_irq */
+ <0xff 195>, /* slimbus_core_ee1_irq */
+ <0xff 196>, /* bam_irq(1) */
+ <0xff 197>, /* qdss_irq_out(7) */
+ <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 = <4 1>,
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
new file mode 100644
index 0000000..8702184
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
@@ -0,0 +1,99 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625-v2-1.dtsi"
+
+/ {
+ model = "Qualcomm MSM 9625V2.1 CDP";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
+ <150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
+ <173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
+
+ i2c@f9925000 {
+ charger@57 {
+ compatible = "summit,smb137c";
+ reg = <0x57>;
+ summit,chg-current-ma = <1500>;
+ summit,term-current-ma = <50>;
+ summit,pre-chg-current-ma = <100>;
+ summit,float-voltage-mv = <4200>;
+ summit,thresh-voltage-mv = <3000>;
+ summit,recharge-thresh-mv = <75>;
+ summit,system-voltage-mv = <4250>;
+ summit,charging-timeout = <382>;
+ summit,pre-charge-timeout = <48>;
+ summit,therm-current-ua = <10>;
+ summit,temperature-min = <4>; /* 0 C */
+ summit,temperature-max = <3>; /* 45 C */
+ };
+ };
+
+ wlan0: qca,wlan {
+ cell-index = <0>;
+ compatible = "qca,ar6004-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ };
+};
+
+/* PM8019 GPIO and MPP configuration */
+&pm8019_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ /* ext_2p95v regulator enable config */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,invert = <0>; /* Output low */
+ qcom,out-strength = <1>; /* Low */
+ qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>; /* Enable GPIO */
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+};
+
+&pm8019_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
new file mode 100644
index 0000000..2dc040c
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
@@ -0,0 +1,99 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm9625-v2-1.dtsi"
+
+/ {
+ model = "Qualcomm MSM 9625V2.1 MTP";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
+ <150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
+ <173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
+
+ i2c@f9925000 {
+ charger@57 {
+ compatible = "summit,smb137c";
+ reg = <0x57>;
+ summit,chg-current-ma = <1500>;
+ summit,term-current-ma = <50>;
+ summit,pre-chg-current-ma = <100>;
+ summit,float-voltage-mv = <4200>;
+ summit,thresh-voltage-mv = <3000>;
+ summit,recharge-thresh-mv = <75>;
+ summit,system-voltage-mv = <4250>;
+ summit,charging-timeout = <382>;
+ summit,pre-charge-timeout = <48>;
+ summit,therm-current-ua = <10>;
+ summit,temperature-min = <4>; /* 0 C */
+ summit,temperature-max = <3>; /* 45 C */
+ };
+ };
+
+ wlan0: qca,wlan {
+ cell-index = <0>;
+ compatible = "qca,ar6004-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ };
+};
+
+/* PM8019 GPIO and MPP configuration */
+&pm8019_gpios {
+ gpio@c000 { /* GPIO 1 */
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ /* ext_2p95v regulator enable config */
+ qcom,mode = <1>; /* Digital output */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,invert = <0>; /* Output low */
+ qcom,out-strength = <1>; /* Low */
+ qcom,vin-sel = <2>; /* PM8019 L11 - 1.8V */
+ qcom,src-sel = <0>; /* Constant */
+ qcom,master-en = <1>; /* Enable GPIO */
+ };
+
+ gpio@c400 { /* GPIO 5 */
+ };
+
+ gpio@c500 { /* GPIO 6 */
+ };
+};
+
+&pm8019_mpps {
+ mpp@a000 { /* MPP 1 */
+ };
+
+ mpp@a100 { /* MPP 2 */
+ };
+
+ mpp@a200 { /* MPP 3 */
+ };
+
+ mpp@a300 { /* MPP 4 */
+ };
+
+ mpp@a400 { /* MPP 5 */
+ };
+
+ mpp@a500 { /* MPP 6 */
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1.dtsi b/arch/arm/boot/dts/msm9625-v2-1.dtsi
new file mode 100644
index 0000000..c3c2c49
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-v2-1.dtsi
@@ -0,0 +1,36 @@
+/* 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm9625.dtsi file.
+ */
+
+/include/ "msm9625.dtsi"
+
+/ {
+ qcom,msm-imem@fe807800 {
+ compatible = "qcom,msm-imem";
+ reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
+ };
+
+ android_usb@fe8078c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfe8078c8 0xc8>;
+ qcom,android-usb-swfi-latency = <100>;
+ };
+};
+
+&ipa_hw {
+ qcom,ipa-hw-ver = <2>; /* IPA h-w revision */
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index d5a33ee..922616c 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -21,6 +21,10 @@
compatible = "qcom,msm9625";
interrupt-parent = <&intc>;
+ aliases {
+ spi0 = &spi_0;
+ };
+
intc: interrupt-controller@F9000000 {
compatible = "qcom,msm-qgic2";
interrupt-controller;
@@ -186,8 +190,7 @@
interrupt-names = "bam_irq";
};
- spi@f9924000 {
- cell-index = <0>;
+ spi_0: spi@f9924000 {
compatible = "qcom,spi-qup-v2";
reg = <0xf9924000 0x1000>;
interrupts = <0 96 0>;
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 1623d45..2bf4630 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -139,6 +139,7 @@
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_WCD9306_CODEC=y
+CONFIG_GPIO_QPNP_PIN=y
# CONFIG_HWMON is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_STUB=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 2f2e0b3..6780761 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -308,6 +308,7 @@
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_WCD9320_CODEC=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index ecea32b..cb5e712 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -411,3 +411,5 @@
obj-$(CONFIG_MSM_SMCMOD) += smcmod.o
obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o
+
+obj-$(CONFIG_ARCH_MSM8974) += msm_mpmctr.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index b451d08..202b8dd 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -68,6 +68,8 @@
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v1-rumi.dtb
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-cdp.dtb
dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-1-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM9625) += msm9625-v2-1-cdp.dtb
# MSM8226
zreladdr-$(CONFIG_ARCH_MSM8226) := 0x00008000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 6ba11b2..d8f5425 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -252,7 +252,15 @@
{ 0, { 0 } }
};
-static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+ [0][0] = { acpu_freq_tbl_pvs0, sizeof(acpu_freq_tbl_pvs0) },
+ [0][1] = { acpu_freq_tbl_pvs1, sizeof(acpu_freq_tbl_pvs1) },
+ [0][2] = { acpu_freq_tbl_pvs2, sizeof(acpu_freq_tbl_pvs2) },
+ [0][3] = { acpu_freq_tbl_pvs3, sizeof(acpu_freq_tbl_pvs3) },
+ [0][4] = { acpu_freq_tbl_pvs4, sizeof(acpu_freq_tbl_pvs4) },
+};
+
+static struct pvs_table pvs_v2[NUM_SPEED_BINS][NUM_PVS] __initdata = {
[0][0] = { acpu_freq_tbl_pvs0, sizeof(acpu_freq_tbl_pvs0) },
[0][1] = { acpu_freq_tbl_pvs1, sizeof(acpu_freq_tbl_pvs1) },
[0][2] = { acpu_freq_tbl_pvs2, sizeof(acpu_freq_tbl_pvs2) },
@@ -269,7 +277,7 @@
.scalable = scalable,
.scalable_size = sizeof(scalable),
.hfpll_data = &hfpll_data,
- .pvs_tables = pvs_tables,
+ .pvs_tables = pvs_v2,
.l2_freq_tbl = l2_freq_tbl,
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
@@ -278,7 +286,7 @@
.stby_khz = 300000,
};
-static void __init apply_l2_workaround(void)
+static void __init apply_v1_l2_workaround(void)
{
static struct l2_level resticted_l2_tbl[] __initdata = {
[0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 1050000, 0 },
@@ -290,7 +298,7 @@
for (s = 0; s < NUM_SPEED_BINS; s++)
for (p = 0; p < NUM_PVS; p++)
- for (l = pvs_tables[s][p].table; l && l->speed.khz; l++)
+ for (l = pvs_v1[s][p].table; l && l->speed.khz; l++)
l->l2_level = l->l2_level > 5 ? 1 : 0;
acpuclk_8974_params.l2_freq_tbl = resticted_l2_tbl;
@@ -305,9 +313,11 @@
* and 1497.6MHz (non-inclusive), or when vdd_mx is less than 1.05V.
* Restrict L2 operation to safe performance points on these devices.
*/
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2 &&
- SOCINFO_VERSION_MINOR(socinfo_get_version()) < 2)
- apply_l2_workaround();
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) {
+ acpuclk_8974_params.pvs_tables = pvs_v1;
+ if (SOCINFO_VERSION_MINOR(socinfo_get_version()) < 2)
+ apply_v1_l2_workaround();
+ }
return acpuclk_krait_init(&pdev->dev, &acpuclk_8974_params);
}
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index 5b72a3f..dd3f346 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -83,4 +83,5 @@
.pc_temp_ocv_lut = &desay_5200_pc_temp_ocv,
.pc_sf_lut = &desay_5200_pc_sf,
.default_rbatt_mohm = 156,
+ .rbatt_capacitive_mohm = 50,
};
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 824cf6b..0c39df6 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -105,4 +105,5 @@
.pc_temp_ocv_lut = &pc_temp_ocv,
.rbatt_sf_lut = &rbatt_sf,
.default_rbatt_mohm = 236,
+ .rbatt_capacitive_mohm = 50,
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index a89ea61..beb064b 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2723,7 +2723,6 @@
&apq8064_device_uart_gsbi1,
&apq8064_device_uart_gsbi4,
&msm_device_sps_apq8064,
- &msm8064_pc_cntr,
};
static struct platform_device *common_i2s_devices[] __initdata = {
@@ -2888,7 +2887,6 @@
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
- &msm8064_pc_cntr,
};
static struct platform_device
@@ -3861,11 +3859,13 @@
if (cpu_is_apq8064ab())
apq8064ab_update_krait_spm();
if (cpu_is_krait_v3()) {
- msm_pm_set_tz_retention_flag(0);
+ struct msm_pm_init_data_type *pdata =
+ msm8064_pm_8x60.dev.platform_data;
+ pdata->retention_calls_tz = false;
apq8064ab_update_retention_spm();
- } else {
- msm_pm_set_tz_retention_flag(1);
}
+ platform_device_register(&msm8064_pm_8x60);
+
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
msm_spm_l2_init(msm_spm_l2_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index a8e117f..25ba1aa 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2473,7 +2473,6 @@
&msm8930_iommu_domain_device,
&msm_tsens_device,
&msm8930_cache_dump_device,
- &msm8930_pc_cntr,
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -2955,11 +2954,14 @@
msm8930_i2c_init();
msm8930_init_gpu();
if (cpu_is_krait_v3()) {
- msm_pm_set_tz_retention_flag(0);
+ struct msm_pm_init_data_type *pdata =
+ msm8930_pm_8x60.dev.platform_data;
+ pdata->retention_calls_tz = false;
msm8930ab_update_retention_spm();
- } else {
- msm_pm_set_tz_retention_flag(1);
}
+
+ platform_device_register(&msm8930_pm_8x60);
+
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
msm_spm_l2_init(msm_spm_l2_data);
msm8930_init_buses();
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 6524832..95f618a 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2955,7 +2955,6 @@
&msm8960_cache_dump_device,
&msm8960_iommu_domain_device,
&msm_tsens_device,
- &msm8960_pc_cntr,
};
static struct platform_device *cdp_devices[] __initdata = {
@@ -3488,11 +3487,13 @@
if (cpu_is_msm8960ab())
msm8960ab_update_krait_spm();
if (cpu_is_krait_v3()) {
- msm_pm_set_tz_retention_flag(0);
+ struct msm_pm_init_data_type *pdata =
+ msm8960_pm_8x60.dev.platform_data;
+ pdata->retention_calls_tz = false;
msm8960ab_update_retention_spm();
- } else {
- msm_pm_set_tz_retention_flag(1);
}
+ platform_device_register(&msm8960_pm_8x60);
+
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
msm_spm_l2_init(msm_spm_l2_data);
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index eb99073..b3cc9b7 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -258,12 +258,6 @@
.dir = GPIOMUX_OUT_HIGH,
};
-static struct gpiomux_setting mhl_active_2_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_UP,
-};
-
static struct gpiomux_setting hdmi_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -299,14 +293,6 @@
[GPIOMUX_ACTIVE] = &mhl_active_1_cfg,
},
},
- {
- /* mhl-sii8334 reset */
- .gpio = 8,
- .settings = {
- [GPIOMUX_SUSPENDED] = &mhl_suspend_config,
- [GPIOMUX_ACTIVE] = &mhl_active_2_cfg,
- },
- },
};
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index c45cf11..02a753a 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -5299,6 +5299,7 @@
&msm_device_tz_log,
&msm_rtb_device,
&msm8660_iommu_domain_device,
+ &msm8660_pm_8x60,
};
#ifdef CONFIG_ION_MSM
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index c3e1e3e..d26b4b2 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -526,7 +526,6 @@
#define mm_gnd_source_val 6
#define gpll1_hsic_source_val 4
#define cxo_lpass_source_val 0
-#define lpapll0_lpass_source_val 1
#define gpll0_lpass_source_val 5
#define edppll_270_mm_source_val 4
#define edppll_350_mm_source_val 4
@@ -742,21 +741,6 @@
},
};
-static struct pll_vote_clk lpapll0_clk_src = {
- .en_reg = (void __iomem *)LPASS_LPA_PLL_VOTE_APPS_REG,
- .en_mask = BIT(0),
- .status_reg = (void __iomem *)LPAPLL_STATUS_REG,
- .status_mask = BIT(17),
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &cxo_clk_src.c,
- .rate = 491520000,
- .dbg_name = "lpapll0_clk_src",
- .ops = &clk_ops_pll_vote,
- CLK_INIT(lpapll0_clk_src.c),
- },
-};
-
static struct pll_vote_clk mmpll0_clk_src = {
.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS_REG,
.en_mask = BIT(0),
@@ -4350,411 +4334,6 @@
},
};
-static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
- F_LPASS(24576000, lpapll0, 4, 1, 5),
- F_END
-};
-
-static struct rcg_clk audio_core_slimbus_core_clk_src = {
- .cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_slimbus_core_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_core_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 70000000, NOMINAL, 140000000),
- CLK_INIT(audio_core_slimbus_core_clk_src.c),
- },
-};
-
-static struct branch_clk audio_core_slimbus_core_clk = {
- .cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_slimbus_core_clk_src.c,
- .dbg_name = "audio_core_slimbus_core_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_slimbus_core_clk.c),
- },
-};
-
-static struct branch_clk audio_core_slimbus_lfabif_clk = {
- .cbcr_reg = AUDIO_CORE_SLIMBUS_LFABIF_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_lfabif_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_slimbus_lfabif_clk.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_audio_core_lpaif_clock[] = {
- F_LPASS( 512000, lpapll0, 16, 1, 60),
- F_LPASS( 768000, lpapll0, 16, 1, 40),
- F_LPASS( 1024000, lpapll0, 16, 1, 30),
- F_LPASS( 1536000, lpapll0, 16, 1, 20),
- F_LPASS( 2048000, lpapll0, 16, 1, 15),
- F_LPASS( 3072000, lpapll0, 16, 1, 10),
- F_LPASS( 4096000, lpapll0, 15, 1, 8),
- F_LPASS( 6144000, lpapll0, 10, 1, 8),
- F_LPASS( 8192000, lpapll0, 15, 1, 4),
- F_LPASS(12288000, lpapll0, 10, 1, 4),
- F_END
-};
-
-static struct rcg_clk audio_core_lpaif_codec_spkr_clk_src = {
- .cmd_rcgr_reg = LPAIF_SPKR_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pri_clk_src = {
- .cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_pri_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_sec_clk_src = {
- .cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_sec_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_ter_clk_src = {
- .cmd_rcgr_reg = LPAIF_TER_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_ter_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_ter_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_quad_clk_src = {
- .cmd_rcgr_reg = LPAIF_QUAD_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_quad_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_quad_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pcm0_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_pcm0_clk_src.c),
- },
-};
-
-static struct rcg_clk audio_core_lpaif_pcm1_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm1_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12000000, NOMINAL, 25000000),
- CLK_INIT(audio_core_lpaif_pcm1_clk_src.c),
- },
-};
-
-struct rcg_clk audio_core_lpaif_pcmoe_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcmoe_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP1(LOW, 12290000),
- CLK_INIT(audio_core_lpaif_pcmoe_clk_src.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_codec_spkr_clk_src.c,
- .dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_codec_spkr_clk_src.c,
- .dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pri_clk_src.c,
- .dbg_name = "audio_core_lpaif_pri_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pri_clk_src.c,
- .dbg_name = "audio_core_lpaif_pri_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_sec_clk_src.c,
- .dbg_name = "audio_core_lpaif_sec_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_sec_clk_src.c,
- .dbg_name = "audio_core_lpaif_sec_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_ter_clk_src.c,
- .dbg_name = "audio_core_lpaif_ter_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_ter_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_ter_clk_src.c,
- .dbg_name = "audio_core_lpaif_ter_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_quad_clk_src.c,
- .dbg_name = "audio_core_lpaif_quad_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_quad_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 15,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_quad_clk_src.c,
- .dbg_name = "audio_core_lpaif_quad_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pcm0_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pcm1_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pcm1_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
- },
-};
-
-struct branch_clk audio_core_lpaif_pcmoe_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_lpaif_pcmoe_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcmoe_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcmoe_clk.c),
- },
-};
-
static struct branch_clk q6ss_ahb_lfabif_clk = {
.cbcr_reg = LPASS_Q6SS_AHB_LFABIF_CBCR,
.has_sibling = 1,
@@ -4766,16 +4345,6 @@
},
};
-static struct branch_clk audio_core_ixfabric_clk = {
- .cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_ixfabric_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_ixfabric_clk.c),
- },
-};
static struct branch_clk gcc_lpass_q6_axi_clk = {
.cbcr_reg = LPASS_Q6_AXI_CBCR,
@@ -4811,17 +4380,6 @@
},
};
-static struct branch_clk audio_wrapper_br_clk = {
- .cbcr_reg = AUDIO_WRAPPER_BR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_wrapper_br_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_wrapper_br_clk.c),
- },
-};
-
static DEFINE_CLK_MEASURE(l2_m_clk);
static DEFINE_CLK_MEASURE(krait0_m_clk);
static DEFINE_CLK_MEASURE(krait1_m_clk);
@@ -5004,20 +4562,9 @@
{&mdss_hdmi_ahb_clk.c, MMSS_BASE, 0x0023},
{&mdss_pclk0_clk.c, MMSS_BASE, 0x0016},
{&mdss_pclk1_clk.c, MMSS_BASE, 0x0017},
- {&audio_core_lpaif_pri_clk_src.c, LPASS_BASE, 0x0017},
- {&audio_core_lpaif_sec_clk_src.c, LPASS_BASE, 0x0016},
- {&audio_core_lpaif_ter_clk_src.c, LPASS_BASE, 0x0015},
- {&audio_core_lpaif_quad_clk_src.c, LPASS_BASE, 0x0014},
- {&audio_core_lpaif_pcm0_clk_src.c, LPASS_BASE, 0x0013},
- {&audio_core_lpaif_pcm1_clk_src.c, LPASS_BASE, 0x0012},
- {&audio_core_lpaif_pcmoe_clk_src.c, LPASS_BASE, 0x000f},
- {&audio_core_slimbus_core_clk.c, LPASS_BASE, 0x003d},
- {&audio_core_slimbus_lfabif_clk.c, LPASS_BASE, 0x003e},
{&q6ss_xo_clk.c, LPASS_BASE, 0x002b},
{&q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
{&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
- {&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
- {&audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
{&krait0_m_clk, APCS_BASE, M_ACPU0},
{&krait1_m_clk, APCS_BASE, M_ACPU1},
@@ -5639,57 +5186,6 @@
/* LPASS clocks */
- CLK_LOOKUP("bus_clk", audio_core_ixfabric_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
- CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
- "fe12f000.slim"),
- CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_codec_spkr_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_codec_spkr_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_codec_spkr_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pri_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_pri_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_ter_clk_src.c, ""),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_ter_osr_clk.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_ter_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_ter_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_quad_clk_src.c,
- "msm-dai-q6-mi2s.3"),
- CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c,
- "msm-dai-q6-mi2s.3"),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c,
- "msm-dai-q6-mi2s.3"),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c,
- "msm-dai-q6-mi2s.3"),
- CLK_LOOKUP("pcm_clk", audio_core_lpaif_pcm0_clk_src.c,
- "msm-dai-q6.4106"),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
- "msm-dai-q6.4106"),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
- CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
- CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c,
- "msm-dai-q6.4106"),
- CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
- "msm-dai-q6.4106"),
- CLK_LOOKUP("pcm_clk", audio_core_lpaif_pcm0_clk_src.c,
- "msm-dai-q6.4107"),
- CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
- "msm-dai-q6.4107"),
- CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c,
- "msm-dai-q6.4107"),
- CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
- "msm-dai-q6.4107"),
- CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
-
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "fc880000.qcom,mss"),
@@ -5880,32 +5376,6 @@
.main_output_mask = BIT(0),
};
-static struct pll_config_regs lpapll0_regs __initdata = {
- .l_reg = (void __iomem *)LPAPLL_L_REG,
- .m_reg = (void __iomem *)LPAPLL_M_REG,
- .n_reg = (void __iomem *)LPAPLL_N_REG,
- .config_reg = (void __iomem *)LPAPLL_USER_CTL_REG,
- .mode_reg = (void __iomem *)LPAPLL_MODE_REG,
- .base = &virt_bases[LPASS_BASE],
-};
-
-/* LPAPLL0 at 491.52 MHz, main output enabled. */
-static struct pll_config lpapll0_config __initdata = {
- .l = 0x33,
- .m = 0x1,
- .n = 0x5,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = BVAL(14, 12, 0x1),
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
#define PWR_ON_MASK BIT(31)
#define EN_REST_WAIT_MASK (0xF << 20)
#define EN_FEW_WAIT_MASK (0xF << 16)
@@ -5922,8 +5392,7 @@
static void __init reg_init(void)
{
- u32 regval, status;
- int ret;
+ u32 regval;
configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
@@ -5934,7 +5403,6 @@
configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
configure_sr_hpm_lp_pll(&mmpll3_config, &mmpll3_regs, 0);
}
- configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
/* Vote for GPLL0 to turn on. Needed by acpuclock. */
regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
@@ -5957,31 +5425,6 @@
* register.
*/
writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
-
- /*
- * TODO: The following sequence enables the LPASS audio core GDSC.
- * Remove when this becomes unnecessary.
- */
-
- /*
- * Disable HW trigger: collapse/restore occur based on registers writes.
- * Disable SW override: Use hardware state-machine for sequencing.
- */
- regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
- regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
-
- /* Configure wait time between states. */
- regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
- regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
- writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
-
- regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
- regval &= ~BIT(0);
- writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
-
- ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
- status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
- WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
}
static void __init mdss_clock_setup(void)
@@ -6021,11 +5464,6 @@
*/
clk_prepare_enable(&cxo_a_clk_src.c);
- /* TODO: Temporarily enable a clock to allow access to LPASS core
- * registers.
- */
- clk_prepare_enable(&audio_core_ixfabric_clk.c);
-
/*
* TODO: Temporarily enable NOC configuration AHB clocks. Remove when
* the bus driver is ready.
@@ -6060,8 +5498,6 @@
clk_set_rate(&esc1_clk_src.c, esc1_clk_src.freq_tbl[0].freq_hz);
clk_set_rate(&hdmi_clk_src.c, hdmi_clk_src.freq_tbl[0].freq_hz);
clk_set_rate(&vsync_clk_src.c, vsync_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&audio_core_slimbus_core_clk_src.c,
- audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
}
#define GCC_CC_PHYS 0xFC400000
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index c1cc27b..ee91a34 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -245,6 +245,14 @@
return rc;
}
+static int rpm_branch_clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (rate == clk->rate)
+ return 0;
+
+ return -EPERM;
+}
+
static unsigned long rpm_clk_get_rate(struct clk *clk)
{
struct rpm_clk *r = to_rpm_clk(clk);
@@ -335,6 +343,7 @@
struct clk_ops clk_ops_rpm_branch = {
.prepare = rpm_clk_prepare,
.unprepare = rpm_clk_unprepare,
+ .set_rate = rpm_branch_clk_set_rate,
.is_local = rpm_clk_is_local,
.handoff = rpm_clk_handoff,
};
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index 1e3f8a0..e87c7b5 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -72,16 +72,19 @@
struct cpuidle_device *dev, struct cpuidle_driver *drv, int index)
{
int ret = 0;
- int i = 0;
+ int i;
enum msm_pm_sleep_mode pm_mode;
- struct cpuidle_state_usage *st_usage = NULL;
cpu_pm_enter();
+
pm_mode = msm_pm_idle_enter(dev, drv, index);
+
for (i = 0; i < dev->state_count; i++) {
- st_usage = &dev->states_usage[i];
- if ((enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage)
- == pm_mode) {
+ struct cpuidle_state_usage *st_usage = &dev->states_usage[i];
+ enum msm_pm_sleep_mode last_mode =
+ (enum msm_pm_sleep_mode)cpuidle_get_statedata(st_usage);
+
+ if (last_mode == pm_mode) {
ret = i;
break;
}
@@ -93,7 +96,7 @@
return ret;
}
-static void __init msm_cpuidle_set_states(void)
+static void __devinit msm_cpuidle_set_states(void)
{
int i = 0;
int state_count = 0;
@@ -149,7 +152,7 @@
dev->state_count = state_count; /* Per cpu state count */
}
-int __init msm_cpuidle_init(void)
+int __devinit msm_cpuidle_init(void)
{
unsigned int cpu = 0;
int ret = 0;
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index f87c540..10ee1e3 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -49,6 +49,7 @@
#include <mach/mpm.h>
#include <mach/iommu_domains.h>
#include <mach/msm_cache_dump.h>
+#include "pm.h"
/* Address of GSBI blocks */
#define MSM_GSBI1_PHYS 0x12440000
@@ -120,11 +121,24 @@
},
};
-struct platform_device msm8064_pc_cntr = {
- .name = "pc-cntr",
+static uint32_t msm_pm_cp15_regs[] = {0x4501, 0x5501, 0x6501, 0x7501, 0x0500};
+
+static struct msm_pm_init_data_type msm_pm_data = {
+ .retention_calls_tz = true,
+ .cp15_data.save_cp15 = true,
+ .cp15_data.qsb_pc_vdd = 0x98,
+ .cp15_data.reg_data = &msm_pm_cp15_regs[0],
+ .cp15_data.reg_saved_state_size = ARRAY_SIZE(msm_pm_cp15_regs),
+};
+
+struct platform_device msm8064_pm_8x60 = {
+ .name = "pm-8x60",
.id = -1,
.num_resources = ARRAY_SIZE(msm8064_resources_pccntr),
.resource = msm8064_resources_pccntr,
+ .dev = {
+ .platform_data = &msm_pm_data,
+ },
};
static struct msm_watchdog_pdata msm_watchdog_pdata = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index aad512e..6fe8ccb 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.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
@@ -32,6 +32,7 @@
#include "rpm_rbcpr_stats.h"
#include "footswitch.h"
#include "acpuclock-krait.h"
+#include "pm.h"
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -48,11 +49,18 @@
},
};
-struct platform_device msm8930_pc_cntr = {
- .name = "pc-cntr",
+static struct msm_pm_init_data_type msm_pm_data = {
+ .retention_calls_tz = true,
+};
+
+struct platform_device msm8930_pm_8x60 = {
+ .name = "pm-8x60",
.id = -1,
.num_resources = ARRAY_SIZE(msm8930_resources_pccntr),
.resource = msm8930_resources_pccntr,
+ .dev = {
+ .platform_data = &msm_pm_data,
+ },
};
struct msm_rpm_platform_data msm8930_rpm_data __initdata = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index c3748fa..6a344be 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -53,6 +53,7 @@
#include <mach/msm_dcvs.h>
#include <mach/iommu_domains.h>
#include <mach/socinfo.h>
+#include "pm.h"
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -116,11 +117,18 @@
},
};
-struct platform_device msm8960_pc_cntr = {
- .name = "pc-cntr",
+static struct msm_pm_init_data_type msm_pm_data = {
+ .retention_calls_tz = true,
+};
+
+struct platform_device msm8960_pm_8x60 = {
+ .name = "pm-8x60",
.id = -1,
.num_resources = ARRAY_SIZE(msm8960_resources_pccntr),
.resource = msm8960_resources_pccntr,
+ .dev = {
+ .platform_data = &msm_pm_data,
+ },
};
static struct resource resources_otg[] = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 58416c7..cfa9281 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -3181,3 +3181,9 @@
.platform_data = &msm8660_iommu_domain_pdata,
}
};
+
+struct platform_device msm8660_pm_8x60 = {
+ .name = "pm-8x60",
+ .id = -1,
+};
+
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index d3810a2..53eca3e 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -1,7 +1,7 @@
/* linux/arch/arm/mach-msm/devices.h
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-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
@@ -113,11 +113,11 @@
extern struct platform_device msm_device_sdc3;
extern struct platform_device msm_device_sdc4;
+extern struct platform_device msm8960_pm_8x60;
+extern struct platform_device msm8064_pm_8x60;
+extern struct platform_device msm8930_pm_8x60;
extern struct platform_device msm9615_pm_8x60;
-
-extern struct platform_device msm8960_pc_cntr;
-extern struct platform_device msm8064_pc_cntr;
-extern struct platform_device msm8930_pc_cntr;
+extern struct platform_device msm8660_pm_8x60;
extern struct platform_device msm_device_gadget_peripheral;
extern struct platform_device msm_device_hsusb_host;
diff --git a/arch/arm/mach-msm/include/mach/msm_mpmctr.h b/arch/arm/mach-msm/include/mach/msm_mpmctr.h
new file mode 100644
index 0000000..d3d853f
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_mpmctr.h
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+#ifndef __MSM_MPMCTR_H__
+#define __MSM_MPMCTR_H__
+
+/*
+ * returns the count value of the mpm timetick.
+ */
+uint32_t msm_mpm_get_count(void);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index cd70457..92ae6b6 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -136,6 +136,9 @@
int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
struct ocmem_map_list *list);
+int ocmem_drop(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list);
+
int ocmem_dump(int client_id, struct ocmem_buf *buffer,
unsigned long dst_phys_addr);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index a4adfb8..abb5653 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.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
@@ -29,6 +29,16 @@
#define TO_OCMEM 0x0
#define TO_DDR 0x1
+#define OCMEM_SVC_ID 15
+#define OCMEM_LOCK_CMD_ID 0x1
+#define OCMEM_UNLOCK_CMD_ID 0x2
+#define OCMEM_ENABLE_DUMP_CMD_ID 0x3
+#define OCMEM_DISABLE_DUMP_CMD_ID 0x4
+
+#define OCMEM_SECURE_SVC_ID 12
+#define OCMEM_SECURE_CFG_ID 0x2
+#define OCMEM_SECURE_DEV_ID 0x5
+
struct ocmem_zone;
struct ocmem_zone_ops {
@@ -158,6 +168,8 @@
/* Request Power State */
unsigned power_state;
struct ocmem_eviction_data *edata;
+ /* Request that triggered eviction */
+ struct ocmem_req *e_handle;
};
struct ocmem_handle {
@@ -187,6 +199,10 @@
int ocmem_notifier_init(void);
int check_notifier(int);
const char *get_name(int);
+int get_tz_id(int);
+int ocmem_enable_sec_program(int);
+int ocmem_enable_dump(enum ocmem_client, unsigned long, unsigned long);
+int ocmem_disable_dump(enum ocmem_client, unsigned long, unsigned long);
int check_id(int);
int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
@@ -197,6 +213,7 @@
unsigned long, bool, bool);
int process_free(int, struct ocmem_handle *);
int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *, int);
+int process_drop(int, struct ocmem_handle *, struct ocmem_map_list *);
int process_evict(int);
int process_restore(int);
int process_shrink(int, struct ocmem_handle *, unsigned long);
diff --git a/arch/arm/mach-msm/include/mach/usb_gadget_xport.h b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
index 9cd4f3f..a183f0e 100644
--- a/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
+++ b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -19,6 +19,7 @@
USB_GADGET_XPORT_TTY,
USB_GADGET_XPORT_SDIO,
USB_GADGET_XPORT_SMD,
+ USB_GADGET_XPORT_QTI,
USB_GADGET_XPORT_BAM,
USB_GADGET_XPORT_BAM2BAM,
USB_GADGET_XPORT_BAM2BAM_IPA,
@@ -38,6 +39,8 @@
return "SDIO";
case USB_GADGET_XPORT_SMD:
return "SMD";
+ case USB_GADGET_XPORT_QTI:
+ return "QTI";
case USB_GADGET_XPORT_BAM:
return "BAM";
case USB_GADGET_XPORT_BAM2BAM:
@@ -63,6 +66,8 @@
return USB_GADGET_XPORT_SDIO;
if (!strncasecmp("SMD", name, XPORT_STR_LEN))
return USB_GADGET_XPORT_SMD;
+ if (!strncasecmp("QTI", name, XPORT_STR_LEN))
+ return USB_GADGET_XPORT_QTI;
if (!strncasecmp("BAM", name, XPORT_STR_LEN))
return USB_GADGET_XPORT_BAM;
if (!strncasecmp("BAM2BAM", name, XPORT_STR_LEN))
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 01be641..0c1e279 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -291,6 +291,11 @@
int krait_power_mdd_enable(int cpu_num, bool on)
{
+ /*
+ * Expected to be called when the cpu goes to retention mode as a part
+ * of idle power collapse. IT is guaranteed that cpu won't be put in
+ * retention while being hotplugged out
+ */
struct krait_power_vreg *kvreg = per_cpu(krait_vregs, cpu_num);
if (!on && kvreg->mode == LDO_MODE) {
@@ -298,7 +303,7 @@
return -EINVAL;
}
- if ((on && kvreg->mode == LDO_MODE) || (!on && kvreg->mode == HS_MODE))
+ if (on && kvreg->mode == LDO_MODE)
return 0;
__krait_power_mdd_enable(kvreg, on);
@@ -801,6 +806,8 @@
int rc;
mutex_lock(&pvreg->krait_power_vregs_lock);
+ if (kvreg->mode == LDO_MODE)
+ __krait_power_mdd_enable(kvreg, true);
kvreg->online = true;
rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
if (rc < 0)
@@ -830,6 +837,8 @@
goto dis_err;
rc = _set_voltage(rdev, kvreg->uV, kvreg->uV);
+ if (kvreg->mode == LDO_MODE)
+ __krait_power_mdd_enable(kvreg, false);
dis_err:
mutex_unlock(&pvreg->krait_power_vregs_lock);
return rc;
@@ -894,8 +903,6 @@
/* setup the bandgap that configures the reference to the LDO */
writel_relaxed(0x00000190, kvreg->mdd_base + MDD_CONFIG_CTL);
- /* Enable MDD */
- writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
mb();
}
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 8571bda..539a4fe 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -57,6 +57,8 @@
bool from_idle, bool notify_rpm)
{
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;
@@ -64,33 +66,34 @@
atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
MSM_LPM_STATE_ENTER, &sleep_data);
- if (notify_rpm) {
- int debug_mask;
- struct msm_rpmrs_limits *l = (struct msm_rpmrs_limits *)limits;
+ if (from_idle)
+ debug_mask = msm_lpm_lvl_dbg_msk &
+ MSM_LPM_LVL_DBG_IDLE_LIMITS;
+ else
+ debug_mask = msm_lpm_lvl_dbg_msk &
+ MSM_LPM_LVL_DBG_SUSPEND_LIMITS;
- ret = msm_rpm_enter_sleep();
+ if (debug_mask)
+ pr_info("%s(): pxo:%d l2:%d mem:0x%x(0x%x) dig:0x%x(0x%x)\n",
+ __func__, l->pxo, l->l2_cache,
+ l->vdd_mem_lower_bound,
+ l->vdd_mem_upper_bound,
+ l->vdd_dig_lower_bound,
+ l->vdd_dig_upper_bound);
+
+ ret = msm_lpmrs_enter_sleep(sclk_count, l, from_idle, notify_rpm);
+ if (ret) {
+ pr_warn("%s() LPM resources failed to enter sleep\n",
+ __func__);
+ goto bail;
+ }
+ if (notify_rpm) {
+ ret = msm_rpm_enter_sleep(debug_mask);
if (ret) {
pr_warn("%s(): RPM failed to enter sleep err:%d\n",
__func__, ret);
goto bail;
}
- if (from_idle)
- debug_mask = msm_lpm_lvl_dbg_msk &
- MSM_LPM_LVL_DBG_IDLE_LIMITS;
- else
- debug_mask = msm_lpm_lvl_dbg_msk &
- MSM_LPM_LVL_DBG_SUSPEND_LIMITS;
-
- if (debug_mask)
- pr_info("%s(): pxo:%d l2:%d mem:0x%x(0x%x) dig:0x%x(0x%x)\n",
- __func__, l->pxo, l->l2_cache,
- l->vdd_mem_lower_bound,
- l->vdd_mem_upper_bound,
- l->vdd_dig_lower_bound,
- l->vdd_dig_upper_bound);
-
- ret = msm_lpmrs_enter_sleep(sclk_count, l, from_idle,
- notify_rpm);
}
bail:
return ret;
@@ -99,9 +102,11 @@
static void msm_lpm_exit_sleep(void *limits, bool from_idle,
bool notify_rpm, bool collapsed)
{
- msm_rpm_exit_sleep();
+
msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
from_idle, notify_rpm, collapsed);
+ if (notify_rpm)
+ msm_rpm_exit_sleep();
atomic_notifier_call_chain(&__get_cpu_var(lpm_notify_head),
MSM_LPM_STATE_EXIT, NULL);
}
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 5d7fc94..a62ee92 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.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
@@ -668,7 +668,8 @@
}
msm_lpm_get_rpm_notif = true;
- msm_mpm_enter_sleep(sclk_count, from_idle);
+ if (notify_rpm)
+ msm_mpm_enter_sleep(sclk_count, from_idle);
return ret;
}
diff --git a/arch/arm/mach-msm/msm_mpmctr.c b/arch/arm/mach-msm/msm_mpmctr.c
new file mode 100644
index 0000000..4ab82ab
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mpmctr.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_mpmctr.h>
+
+static void __iomem *mpm_timer_base;
+
+uint32_t msm_mpm_get_count(void)
+{
+ uint32_t count;
+ if (!mpm_timer_base)
+ return 0;
+
+ count = __raw_readl_no_log(mpm_timer_base);
+ pr_debug("mpm sclk sync:(%u)", count);
+ return count;
+}
+EXPORT_SYMBOL(msm_mpm_get_count);
+
+static inline void msm_mpmctr_show_count(void)
+{
+ unsigned long long t;
+ unsigned long nsec_rem;
+
+ t = sched_clock();
+
+ nsec_rem = do_div(t, 1000000000)/1000;
+
+ printk(KERN_INFO "mpm_counter: [%5lu.%06lu]:(%u)\n",
+ (unsigned long)t, nsec_rem,
+ msm_mpm_get_count());
+
+}
+
+static struct of_device_id msm_mpmctr_of_match[] = {
+ {.compatible = "qcom,mpm-counter"},
+ {}
+};
+
+static struct platform_driver msm_mpmctr_driver = {
+ .driver = {
+ .name = "msm_mpctr",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_mpmctr_of_match,
+ },
+};
+
+static int __init mpmctr_set_register(struct device_node *np)
+{
+ if (of_get_address(np, 0, NULL, NULL)) {
+ mpm_timer_base = of_iomap(np, 0);
+ if (!mpm_timer_base) {
+ pr_err("%s: cannot map timer base\n", __func__);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static int __init msm_mpmctr_probe(struct platform_device *pdev)
+{
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ if (mpmctr_set_register(pdev->dev.of_node))
+ return -ENODEV;
+
+ msm_mpmctr_show_count();
+
+ return 0;
+}
+
+static int __init mpmctr_init(void)
+{
+ return platform_driver_probe(&msm_mpmctr_driver, msm_mpmctr_probe);
+}
+
+module_init(mpmctr_init)
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 1729742..4685f02 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -693,7 +693,7 @@
}
/* Enable the ocmem graphics mpU as a workaround */
-/* This will be programmed by TZ after TZ support is integrated */
+#ifdef CONFIG_MSM_OCMEM_NONSECURE
static int ocmem_init_gfx_mpu(struct platform_device *pdev)
{
int rc;
@@ -714,6 +714,12 @@
ocmem_disable_core_clock();
return 0;
}
+#else
+static int ocmem_init_gfx_mpu(struct platform_device *pdev)
+{
+ return 0;
+}
+#endif /* CONFIG_MSM_OCMEM_NONSECURE */
static int __devinit ocmem_debugfs_init(struct platform_device *pdev)
{
@@ -783,6 +789,11 @@
platform_set_drvdata(pdev, ocmem_pdata);
+ /* Parameter to be updated based on TZ */
+ /* Allow the OCMEM CSR to be programmed */
+ if (ocmem_enable_sec_program(OCMEM_SECURE_DEV_ID))
+ return -EBUSY;
+
if (ocmem_debugfs_init(pdev))
return -EBUSY;
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index ef3cbae..16dd8b8 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.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
@@ -52,9 +52,10 @@
ret = process_free(id, handle);
mutex_unlock(&handle->handle_mutex);
- if (ret)
- return -EINVAL;
-
+ if (ret) {
+ pr_err("ocmem: Free failed for client %s\n", get_name(id));
+ return ret;
+ }
free_handle(handle);
return 0;
}
@@ -400,6 +401,40 @@
}
EXPORT_SYMBOL(ocmem_unmap);
+int ocmem_drop(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list)
+{
+ int ret = 0;
+ struct ocmem_handle *handle = NULL;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client id: %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return -EINVAL;
+ }
+
+ if (!buffer) {
+ pr_err("ocmem: Invalid buffer\n");
+ return -EINVAL;
+ }
+
+ if (pre_validate_chunk_list(list) != 0)
+ return -EINVAL;
+
+ handle = buffer_to_handle(buffer);
+ mutex_lock(&handle->handle_mutex);
+ ret = process_drop(client_id, handle, list);
+ mutex_unlock(&handle->handle_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(ocmem_drop);
+
+
int ocmem_dump(int client_id, struct ocmem_buf *buffer,
unsigned long dst_phys_addr)
{
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index a011576..4ea1de9 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -17,6 +17,7 @@
#include <mach/ocmem_priv.h>
#include <mach/rpm-smd.h>
+#include <mach/scm.h>
static unsigned num_regions;
static unsigned num_macros;
@@ -514,6 +515,23 @@
ocmem_clear(offset, len);
return 0;
}
+
+int ocmem_enable_sec_program(int sec_id)
+{
+ return 0;
+}
+
+int ocmem_enable_dump(enum ocmem_client id, unsigned long offset,
+ unsigned long len)
+{
+ return 0;
+}
+
+int ocmem_disable_dump(enum ocmem_client id, unsigned long offset,
+ unsigned long len)
+{
+ return 0;
+}
#else
static int ocmem_gfx_mpu_set(unsigned long offset, unsigned long len)
{
@@ -532,19 +550,117 @@
static int do_lock(enum ocmem_client id, unsigned long offset,
unsigned long len, enum region_mode mode)
{
- return 0;
+ int rc;
+ struct ocmem_tz_lock {
+ u32 id;
+ u32 offset;
+ u32 size;
+ } request;
+
+ request.id = get_tz_id(id);
+ request.offset = offset;
+ request.size = len;
+
+ rc = scm_call(OCMEM_SVC_ID, OCMEM_LOCK_CMD_ID, &request,
+ sizeof(request), NULL, 0);
+ if (rc)
+ pr_err("ocmem: Failed to lock region %s[%lx -- %lx] ret = %d\n",
+ get_name(id), offset, offset + len - 1, rc);
+ return rc;
}
static int do_unlock(enum ocmem_client id, unsigned long offset,
unsigned long len)
{
- return 0;
+ int rc;
+ struct ocmem_tz_unlock {
+ u32 id;
+ u32 offset;
+ u32 size;
+ } request;
+
+ request.id = get_tz_id(id);
+ request.offset = offset;
+ request.size = len;
+
+ rc = scm_call(OCMEM_SVC_ID, OCMEM_UNLOCK_CMD_ID, &request,
+ sizeof(request), NULL, 0);
+ if (rc)
+ pr_err("ocmem: Failed to unlock region %s[%lx -- %lx] ret = %d\n",
+ get_name(id), offset, offset + len - 1, rc);
+ return rc;
+}
+
+int ocmem_enable_dump(enum ocmem_client id, unsigned long offset,
+ unsigned long len)
+{
+ int rc;
+ struct ocmem_tz_en_dump {
+ u32 id;
+ u32 offset;
+ u32 size;
+ } request;
+
+ request.id = get_tz_id(id);
+ request.offset = offset;
+ request.size = len;
+
+ rc = scm_call(OCMEM_SVC_ID, OCMEM_ENABLE_DUMP_CMD_ID, &request,
+ sizeof(request), NULL, 0);
+ if (rc)
+ pr_err("ocmem: Failed to enable dump %s[%lx -- %lx] ret = %d\n",
+ get_name(id), offset, offset + len - 1, rc);
+ return rc;
+}
+
+int ocmem_disable_dump(enum ocmem_client id, unsigned long offset,
+ unsigned long len)
+{
+ int rc;
+ struct ocmem_tz_dis_dump {
+ u32 id;
+ u32 offset;
+ u32 size;
+ } request;
+
+ request.id = get_tz_id(id);
+ request.offset = offset;
+ request.size = len;
+
+ rc = scm_call(OCMEM_SVC_ID, OCMEM_DISABLE_DUMP_CMD_ID, &request,
+ sizeof(request), NULL, 0);
+ if (rc)
+ pr_err("ocmem: Failed to disable dump %s[%lx -- %lx] ret = %d\n",
+ get_name(id), offset, offset + len - 1, rc);
+ return rc;
+}
+
+int ocmem_enable_sec_program(int sec_id)
+{
+ int rc, scm_ret = 0;
+ struct msm_scm_sec_cfg {
+ unsigned int id;
+ unsigned int spare;
+ } cfg;
+
+ cfg.id = sec_id;
+
+ rc = scm_call(OCMEM_SECURE_SVC_ID, OCMEM_SECURE_CFG_ID, &cfg,
+ sizeof(cfg), &scm_ret, sizeof(scm_ret));
+
+ if (rc || scm_ret) {
+ pr_err("ocmem: Failed to enable secure programming\n");
+ return rc ? rc : -EINVAL;
+ }
+
+ return rc;
}
#endif /* CONFIG_MSM_OCMEM_NONSECURE */
int ocmem_lock(enum ocmem_client id, unsigned long offset, unsigned long len,
enum region_mode mode)
{
+ int rc = 0;
if (len < OCMEM_MIN_ALLOC) {
pr_err("ocmem: Invalid len %lx for lock\n", len);
@@ -561,27 +677,38 @@
commit_region_modes();
- do_lock(id, offset, len, mode);
+ rc = do_lock(id, offset, len, mode);
+ if (rc)
+ goto lock_fail;
mutex_unlock(®ion_ctrl_lock);
return 0;
-
+lock_fail:
+ switch_region_mode(offset, len, MODE_DEFAULT);
switch_region_fail:
+ ocmem_gfx_mpu_remove();
mutex_unlock(®ion_ctrl_lock);
return -EINVAL;
}
int ocmem_unlock(enum ocmem_client id, unsigned long offset, unsigned long len)
{
+ int rc = 0;
+
if (id == OCMEM_GRAPHICS)
ocmem_gfx_mpu_remove();
mutex_lock(®ion_ctrl_lock);
- do_unlock(id, offset, len);
+ rc = do_unlock(id, offset, len);
+ if (rc)
+ goto unlock_fail;
switch_region_mode(offset, len , MODE_DEFAULT);
commit_region_modes();
mutex_unlock(®ion_ctrl_lock);
return 0;
+unlock_fail:
+ mutex_unlock(®ion_ctrl_lock);
+ return -EINVAL;
}
#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
index c0603d6..4190aea 100644
--- a/arch/arm/mach-msm/ocmem_rdm.c
+++ b/arch/arm/mach-msm/ocmem_rdm.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
@@ -296,10 +296,6 @@
init_completion(&dm_clear_event);
init_completion(&dm_transfer_event);
- /* Clear DM Mask */
- ocmem_write(DM_MASK_RESET, dm_base + DM_INTR_MASK);
- /* enable dm interrupts */
- ocmem_write(DM_INTR_RESET, dm_base + DM_INTR_CLR);
ocmem_disable_core_clock();
return 0;
}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 08f93e2..868fd1a 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.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
@@ -25,16 +25,19 @@
#include <mach/ocmem_priv.h>
enum request_states {
- R_FREE = 0x0, /* request is not allocated */
- R_PENDING, /* request has a pending operation */
- R_ALLOCATED, /* request has been allocated */
- R_MUST_GROW, /* request must grow as a part of pending operation */
- R_MUST_SHRINK, /* request must shrink as a part of pending operation */
- R_MUST_MAP, /* request must be mapped before being used */
- R_MUST_UNMAP, /* request must be unmapped when not being used */
- R_MAPPED, /* request is mapped and actively used by client */
- R_UNMAPPED, /* request is not mapped, so it's not in active use */
- R_EVICTED, /* request is evicted and must be restored */
+ R_FREE = 0x0, /* request is not allocated */
+ R_PENDING, /* request has a pending operation */
+ R_ALLOCATED, /* request has been allocated */
+ R_ENQUEUED, /* request has been enqueued for future retry */
+ R_MUST_GROW, /* request must grow as a part of pending operation */
+ R_MUST_SHRINK, /* request must shrink */
+ R_WF_SHRINK, /* shrink must be ack'ed by a client */
+ R_SHRUNK, /* request was shrunk */
+ R_MUST_MAP, /* request must be mapped before being used */
+ R_MUST_UNMAP, /* request must be unmapped when not being used */
+ R_MAPPED, /* request is mapped and actively used by client */
+ R_UNMAPPED, /* request is not mapped, so it's not in active use */
+ R_EVICTED, /* request is evicted and must be restored */
};
#define SET_STATE(x, val) (set_bit((val), &(x)->state))
@@ -109,6 +112,16 @@
OCMEM_SYSNOC = 3,
};
+enum ocmem_tz_client {
+ TZ_UNUSED = 0x0,
+ TZ_GRAPHICS,
+ TZ_VIDEO,
+ TZ_LP_AUDIO,
+ TZ_SENSORS,
+ TZ_OTHER_OS,
+ TZ_DEBUG,
+};
+
/**
* Primary OCMEM Arbitration Table
**/
@@ -117,20 +130,30 @@
int priority;
int mode;
int hw_interconnect;
+ int tz_id;
} ocmem_client_table[OCMEM_CLIENT_MAX] = {
- {OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT},
- {OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
- {OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
- {OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED},
- {OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
- {OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
- {OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
- {OCMEM_OTHER_OS, PRIO_OTHER_OS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+ {OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT,
+ TZ_GRAPHICS},
+ {OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC,
+ TZ_VIDEO},
+ {OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC,
+ TZ_UNUSED},
+ {OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED,
+ TZ_UNUSED},
+ {OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED,
+ TZ_UNUSED},
+ {OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC,
+ TZ_LP_AUDIO},
+ {OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC,
+ TZ_SENSORS},
+ {OCMEM_OTHER_OS, PRIO_OTHER_OS, OCMEM_LOW_POWER, OCMEM_SYSNOC,
+ TZ_OTHER_OS},
};
static struct rb_root sched_tree;
static struct mutex sched_mutex;
static struct mutex allocation_mutex;
+static struct mutex free_mutex;
/* A region represents a continuous interval in OCMEM address space */
struct ocmem_region {
@@ -225,6 +248,14 @@
WIDE_MODE : THIN_MODE;
}
+inline int get_tz_id(int id)
+{
+ if (!check_id(id))
+ return TZ_UNUSED;
+ else
+ return ocmem_client_table[id].tz_id;
+}
+
/* Returns the address that can be used by a device core to access OCMEM */
static unsigned long device_address(int id, unsigned long addr)
{
@@ -489,12 +520,21 @@
return TEST_STATE(req, R_MAPPED);
}
+static inline int is_pending_shrink(struct ocmem_req *req)
+{
+ return TEST_STATE(req, R_MUST_SHRINK) ||
+ TEST_STATE(req, R_WF_SHRINK);
+}
+
/* Must be called with sched_mutex held */
static int __sched_unmap(struct ocmem_req *req)
{
struct ocmem_req *matched_req = NULL;
struct ocmem_region *matched_region = NULL;
+ if (!TEST_STATE(req, R_MAPPED))
+ goto invalid_op_error;
+
matched_region = find_region_match(req->req_start, req->req_end);
matched_req = find_req_match(req->req_id, matched_region);
@@ -1024,8 +1064,8 @@
retry = false;
- pr_debug("ocmem: do_allocate: %s request size %lx\n",
- get_name(owner), sz);
+ pr_debug("ocmem: do_allocate: %s request %p size %lx\n",
+ get_name(owner), req, sz);
retry_next_step:
@@ -1146,14 +1186,34 @@
return OP_FAIL;
}
+/* Remove the request from eviction lists */
+static void cancel_restore(struct ocmem_req *e_handle,
+ struct ocmem_req *req)
+{
+ struct ocmem_eviction_data *edata = e_handle->edata;
+
+ if (!edata || !req)
+ return;
+
+ if (list_empty(&edata->req_list))
+ return;
+
+ list_del_init(&req->eviction_list);
+ req->e_handle = NULL;
+
+ return;
+}
+
static int sched_enqueue(struct ocmem_req *priv)
{
struct ocmem_req *next = NULL;
mutex_lock(&sched_queue_mutex);
+ SET_STATE(priv, R_ENQUEUED);
list_add_tail(&priv->sched_list, &sched_queue[priv->owner]);
pr_debug("enqueued req %p\n", priv);
list_for_each_entry(next, &sched_queue[priv->owner], sched_list) {
- pr_debug("pending requests for client %p\n", next);
+ pr_debug("pending request %p for client %s\n", next,
+ get_name(next->owner));
}
mutex_unlock(&sched_queue_mutex);
return 0;
@@ -1178,13 +1238,13 @@
list_for_each_entry_safe(req, next, &sched_queue[id], sched_list)
{
if (req == victim_req) {
- pr_debug("ocmem: Cancelling pending request %p\n",
- req);
- list_del(&req->sched_list);
- goto dequeue_done;
+ pr_debug("ocmem: Cancelling pending request %p for %s\n",
+ req, get_name(req->owner));
+ list_del_init(&victim_req->sched_list);
+ CLEAR_STATE(victim_req, R_ENQUEUED);
+ break;
}
}
-
dequeue_done:
mutex_unlock(&sched_queue_mutex);
return;
@@ -1206,7 +1266,8 @@
pr_debug("ocmem: Fetched pending request %p\n",
req);
list_del(&req->sched_list);
- break;
+ CLEAR_STATE(req, R_ENQUEUED);
+ break;
}
}
}
@@ -1400,31 +1461,67 @@
unsigned long offset = 0;
int rc = 0;
+ mutex_lock(&free_mutex);
+
if (is_blocked(id)) {
pr_err("Client %d cannot request free\n", id);
- return -EINVAL;
+ goto free_invalid;
}
req = handle_to_req(handle);
buffer = handle_to_buffer(handle);
- if (!req)
- return -EINVAL;
+ if (!req) {
+ pr_err("ocmem: No valid request to free\n");
+ goto free_invalid;
+ }
if (req->req_start != core_address(id, buffer->addr)) {
pr_err("Invalid buffer handle passed for free\n");
- return -EINVAL;
+ goto free_invalid;
}
- mutex_lock(&sched_mutex);
- sched_dequeue(req);
- mutex_unlock(&sched_mutex);
+ if (req->edata != NULL) {
+ pr_err("ocmem: Request %p(%2lx) yet to process eviction %p\n",
+ req, req->state, req->edata);
+ goto free_invalid;
+ }
- if (TEST_STATE(req, R_MAPPED)) {
- /* unmap the interval and clear the memory */
- rc = process_unmap(req, req->req_start, req->req_end);
- if (rc < 0)
- return -EINVAL;
+ if (is_pending_shrink(req)) {
+ pr_err("ocmem: Request %p(%2lx) yet to process eviction\n",
+ req, req->state);
+ goto pending_shrink;
+ }
+
+ /* Remove the request from any restore lists */
+ if (req->e_handle)
+ cancel_restore(req->e_handle, req);
+
+ /* Remove the request from any pending opreations */
+ if (TEST_STATE(req, R_ENQUEUED)) {
+ mutex_lock(&sched_mutex);
+ sched_dequeue(req);
+ mutex_unlock(&sched_mutex);
+ }
+
+ if (!TEST_STATE(req, R_FREE)) {
+
+ if (TEST_STATE(req, R_MAPPED)) {
+ /* unmap the interval and clear the memory */
+ rc = process_unmap(req, req->req_start, req->req_end);
+
+ if (rc < 0) {
+ pr_err("ocmem: Failed to unmap %p\n", req);
+ goto free_fail;
+ }
+
+ rc = do_free(req);
+ if (rc < 0) {
+ pr_err("ocmem: Failed to free %p\n", req);
+ goto free_fail;
+ }
+ } else
+ pr_debug("request %p was already shrunk to 0\n", req);
}
/* Turn off the memory */
@@ -1436,7 +1533,7 @@
if (rc < 0) {
pr_err("Failed to switch OFF memory macros\n");
- return -EINVAL;
+ goto free_fail;
}
}
@@ -1454,7 +1551,15 @@
handle->req = NULL;
ocmem_schedule_pending();
+ mutex_unlock(&free_mutex);
return 0;
+free_fail:
+free_invalid:
+ mutex_unlock(&free_mutex);
+ return -EINVAL;
+pending_shrink:
+ mutex_unlock(&free_mutex);
+ return -EAGAIN;
}
static void ocmem_rdm_worker(struct work_struct *work)
@@ -1504,6 +1609,42 @@
return 0;
}
+int process_drop(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf *buffer = NULL;
+ int rc = 0;
+
+ if (is_blocked(id)) {
+ pr_err("Client %d cannot request drop\n", id);
+ return -EINVAL;
+ }
+
+ if (is_tcm(id))
+ pr_err("Client %d cannot request drop\n", id);
+
+ req = handle_to_req(handle);
+ buffer = handle_to_buffer(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (req->req_start != core_address(id, buffer->addr)) {
+ pr_err("Invalid buffer handle passed for drop\n");
+ return -EINVAL;
+ }
+
+ if (TEST_STATE(req, R_MAPPED)) {
+ rc = process_unmap(req, req->req_start, req->req_end);
+ if (rc < 0)
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
int process_xfer_out(int id, struct ocmem_handle *handle,
struct ocmem_map_list *list)
{
@@ -1552,7 +1693,6 @@
goto transfer_in_error;
}
-
inc_ocmem_stat(zone_of(req), NR_TRANSFERS_TO_OCMEM);
rc = queue_transfer(req, handle, list, TO_OCMEM);
@@ -1585,16 +1725,23 @@
if (!req)
return -EINVAL;
+ mutex_lock(&free_mutex);
+
if (req->req_start != core_address(id, buffer->addr)) {
pr_err("Invalid buffer handle passed for shrink\n");
- return -EINVAL;
+ goto shrink_fail;
}
- edata = req->edata;
+ if (!req->e_handle) {
+ pr_err("Unable to find evicting request\n");
+ goto shrink_fail;
+ }
+
+ edata = req->e_handle->edata;
if (!edata) {
pr_err("Unable to find eviction data\n");
- return -EINVAL;
+ goto shrink_fail;
}
pr_debug("Found edata %p in request %p\n", edata, req);
@@ -1603,29 +1750,37 @@
if (size == 0) {
pr_debug("req %p being shrunk to zero\n", req);
- if (is_mapped(req))
+ if (is_mapped(req)) {
rc = process_unmap(req, req->req_start, req->req_end);
if (rc < 0)
- return -EINVAL;
+ goto shrink_fail;
+ }
rc = do_free(req);
if (rc < 0)
- return -EINVAL;
+ goto shrink_fail;
+ SET_STATE(req, R_FREE);
} else {
rc = do_shrink(req, size);
if (rc < 0)
- return -EINVAL;
+ goto shrink_fail;
}
- req->edata = NULL;
CLEAR_STATE(req, R_ALLOCATED);
- SET_STATE(req, R_FREE);
+ CLEAR_STATE(req, R_WF_SHRINK);
+ SET_STATE(req, R_SHRUNK);
if (atomic_dec_and_test(&edata->pending)) {
pr_debug("ocmem: All conflicting allocations were shrunk\n");
complete(&edata->completion);
}
+ mutex_unlock(&free_mutex);
return 0;
+shrink_fail:
+ pr_err("ocmem: Failed to shrink request %p of %s\n",
+ req, get_name(req->owner));
+ mutex_unlock(&free_mutex);
+ return -EINVAL;
}
int process_xfer(int id, struct ocmem_handle *handle,
@@ -1730,11 +1885,12 @@
if (needs_eviction) {
pr_debug("adding %p in region %p to eviction list\n",
e_req, tmp_region);
+ SET_STATE(e_req, R_MUST_SHRINK);
list_add_tail(
&e_req->eviction_list,
&edata->req_list);
atomic_inc(&edata->pending);
- e_req->edata = edata;
+ e_req->e_handle = req;
}
}
} else {
@@ -1744,9 +1900,7 @@
pr_debug("%d requests will be evicted\n", atomic_read(&edata->pending));
- if (!atomic_read(&edata->pending))
- return -EINVAL;
- return 0;
+ return atomic_read(&edata->pending);
}
static void trigger_eviction(struct ocmem_eviction_data *edata)
@@ -1768,8 +1922,10 @@
pr_debug("ocmem: Evicting request %p\n", req);
buffer.addr = req->req_start;
buffer.len = 0x0;
+ CLEAR_STATE(req, R_MUST_SHRINK);
dispatch_notification(req->owner, OCMEM_ALLOC_SHRINK,
&buffer);
+ SET_STATE(req, R_WF_SHRINK);
}
}
return;
@@ -1791,7 +1947,7 @@
rc = __evict_common(edata, NULL);
- if (rc < 0)
+ if (rc == 0)
goto skip_eviction;
trigger_eviction(edata);
@@ -1825,9 +1981,10 @@
edata->passive = false;
+ mutex_lock(&free_mutex);
rc = __evict_common(edata, req);
- if (rc < 0)
+ if (rc == 0)
goto skip_eviction;
trigger_eviction(edata);
@@ -1835,6 +1992,8 @@
pr_debug("ocmem: attaching eviction %p to request %p", edata, req);
req->edata = edata;
+ mutex_unlock(&free_mutex);
+
wait_for_completion(&edata->completion);
pr_debug("ocmem: eviction completed successfully\n");
@@ -1843,28 +2002,30 @@
skip_eviction:
pr_err("ocmem: Unable to run eviction\n");
free_eviction(edata);
- return -EINVAL;
+ req->edata = NULL;
+ mutex_unlock(&free_mutex);
+ return 0;
}
static int __restore_common(struct ocmem_eviction_data *edata)
{
struct ocmem_req *req = NULL;
- struct ocmem_req *next = NULL;
if (!edata)
return -EINVAL;
- list_for_each_entry_safe(req, next, &edata->req_list, eviction_list)
- {
- if (req) {
- pr_debug("ocmem: restoring evicted request %p\n",
- req);
- list_del(&req->eviction_list);
- req->op = SCHED_ALLOCATE;
- sched_enqueue(req);
- inc_ocmem_stat(zone_of(req), NR_RESTORES);
- }
+ while (!list_empty(&edata->req_list)) {
+ req = list_first_entry(&edata->req_list, struct ocmem_req,
+ eviction_list);
+ list_del_init(&req->eviction_list);
+ pr_debug("ocmem: restoring evicted request %p\n",
+ req);
+ req->edata = NULL;
+ req->e_handle = NULL;
+ req->op = SCHED_ALLOCATE;
+ inc_ocmem_stat(zone_of(req), NR_RESTORES);
+ sched_enqueue(req);
}
pr_debug("Scheduled all evicted regions\n");
@@ -1883,12 +2044,15 @@
if (!req->edata)
return 0;
+ mutex_lock(&free_mutex);
rc = __restore_common(req->edata);
+ mutex_unlock(&free_mutex);
if (rc < 0)
return -EINVAL;
free_eviction(req->edata);
+ req->edata = NULL;
return 0;
}
@@ -1900,7 +2064,9 @@
if (!edata)
return -EINVAL;
+ mutex_lock(&free_mutex);
rc = __restore_common(edata);
+ mutex_unlock(&free_mutex);
if (rc < 0) {
pr_err("Failed to restore evicted requests\n");
@@ -1986,6 +2152,7 @@
void __iomem *req_vaddr;
unsigned long offset = 0x0;
+ int rc = 0;
down_write(&req->rw_sem);
@@ -1996,12 +2163,23 @@
if (!req_vaddr)
goto err_do_dump;
+ rc = ocmem_enable_dump(req->owner, offset, req->req_sz);
+
+ if (rc < 0)
+ goto err_do_dump;
+
pr_debug("Dumping client %s buffer ocmem p: %lx (v: %p) to ddr %lx\n",
get_name(req->owner), req->req_start,
req_vaddr, addr);
memcpy((void *)addr, req_vaddr, req->req_sz);
+ rc = ocmem_disable_dump(req->owner, offset, req->req_sz);
+
+ if (rc < 0)
+ pr_err("Failed to secure request %p of %s after dump\n",
+ req, get_name(req->owner));
+
up_write(&req->rw_sem);
return 0;
err_do_dump:
@@ -2252,6 +2430,7 @@
sched_tree = RB_ROOT;
pdata = platform_get_drvdata(pdev);
mutex_init(&allocation_mutex);
+ mutex_init(&free_mutex);
mutex_init(&sched_mutex);
mutex_init(&sched_queue_mutex);
ocmem_vaddr = pdata->vbase;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index e85831a..c1d4ab4 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-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012, 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,7 +24,6 @@
#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>
@@ -88,8 +87,6 @@
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;
@@ -445,17 +442,18 @@
subsystem_restart_dev(drv->subsys);
}
-static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
+static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
{
- struct mba_data *drv = dev_id;
+ struct mba_data *drv = data;
- /* Ignore if we're the one that set the force stop GPIO */
+ /* Ignore if we're the one that set SMSM_RESET */
if (drv->crash_shutdown)
- return IRQ_HANDLED;
+ return;
- pr_err("Fatal error on the modem.\n");
- restart_modem(drv);
- return IRQ_HANDLED;
+ if (new_state & SMSM_RESET) {
+ pr_err("Probable fatal error on the modem.\n");
+ restart_modem(drv);
+ }
}
static int modem_shutdown(const struct subsys_desc *subsys)
@@ -495,7 +493,7 @@
{
struct mba_data *drv = subsys_to_drv(subsys);
drv->crash_shutdown = true;
- gpio_set_value(drv->force_stop_gpio, 1);
+ smsm_reset_modem(SMSM_RESET);
}
static struct ramdump_segment smem_segments[] = {
@@ -632,11 +630,10 @@
goto err_irq;
}
- ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
- modem_err_fatal_intr_handler,
- IRQF_TRIGGER_RISING, "pil-mss", drv);
+ ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
+ smsm_state_cb, drv);
if (ret < 0) {
- dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
+ dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
goto err_irq;
}
@@ -646,11 +643,14 @@
ret = PTR_ERR(drv->adsp_state_notifier);
dev_err(&pdev->dev, "%s: Registration with the SSR notification driver failed (%d)",
__func__, ret);
- goto err_irq;
+ goto err_smsm;
}
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, err_fatal_gpio;
+ int ret;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -774,22 +774,6 @@
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);
}
@@ -799,6 +783,8 @@
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/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 7f8d3b9..0263faf 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -167,7 +167,7 @@
/* Assert Q6 resets */
val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
- val = (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA);
+ val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA);
writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
/* Kill power at block headswitch */
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index f7f2fef..b52d284 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -40,7 +41,6 @@
#ifdef CONFIG_VFP
#include <asm/vfp.h>
#endif
-
#include "acpuclock.h"
#include "clock.h"
#include "avs.h"
@@ -54,9 +54,27 @@
#include <mach/event_timer.h>
#define CREATE_TRACE_POINTS
#include "trace_msm_low_power.h"
-/******************************************************************************
- * Debug Definitions
- *****************************************************************************/
+
+#define SCM_L2_RETENTION (0x2)
+#define SCM_CMD_TERMINATE_PC (0x2)
+
+#define GET_CPU_OF_ATTR(attr) \
+ (container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
+
+#define SCLK_HZ (32768)
+#define MSM_PM_SLEEP_TICK_LIMIT (0x6DDD000)
+
+#define NUM_OF_COUNTERS 3
+#define MAX_BUF_SIZE 512
+
+static int msm_pm_debug_mask = 1;
+module_param_named(
+ debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
+);
+
+static int msm_pm_sleep_time_override;
+module_param_named(sleep_time_override,
+ msm_pm_sleep_time_override, int, S_IRUGO | S_IWUSR | S_IWGRP);
enum {
MSM_PM_DEBUG_SUSPEND = BIT(0),
@@ -70,24 +88,12 @@
MSM_PM_DEBUG_HOTPLUG = BIT(8),
};
-static int msm_pm_debug_mask = 1;
-module_param_named(
- debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
-);
-static int msm_pm_retention_tz_call;
-
-/******************************************************************************
- * Sleep Modes and Parameters
- *****************************************************************************/
enum {
MSM_PM_MODE_ATTR_SUSPEND,
MSM_PM_MODE_ATTR_IDLE,
MSM_PM_MODE_ATTR_NR,
};
-#define SCM_L2_RETENTION (0x2)
-#define SCM_CMD_TERMINATE_PC (0x2)
-
static char *msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_NR] = {
[MSM_PM_MODE_ATTR_SUSPEND] = "suspend_enabled",
[MSM_PM_MODE_ATTR_IDLE] = "idle_enabled",
@@ -98,9 +104,6 @@
struct kobj_attribute ka;
};
-#define GET_CPU_OF_ATTR(attr) \
- (container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
-
struct msm_pm_sysfs_sleep_mode {
struct kobject *kobj;
struct attribute_group attr_group;
@@ -116,10 +119,15 @@
"standalone_power_collapse",
};
-static struct msm_pm_init_data_type msm_pm_init_data;
static struct hrtimer pm_hrtimer;
static struct msm_pm_sleep_ops pm_sleep_ops;
static bool msm_pm_ldo_retention_enabled = true;
+static bool msm_pm_use_sync_timer;
+static struct msm_pm_cp15_save_data cp15_data;
+static bool msm_pm_retention_calls_tz;
+static uint32_t msm_pm_max_sleep_time;
+static bool msm_no_ramp_down_pc;
+
/*
* Write out the attribute.
*/
@@ -166,9 +174,6 @@
return ret;
}
-/*
- * Read in the new attribute value.
- */
static ssize_t msm_pm_mode_attr_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf, size_t count)
{
@@ -205,10 +210,7 @@
return ret ? ret : count;
}
-/*
- * Add sysfs entries for one cpu.
- */
-static int __init msm_pm_mode_sysfs_add_cpu(
+static int __devinit msm_pm_mode_sysfs_add_cpu(
unsigned int cpu, struct kobject *modes_kobj)
{
char cpu_name[8];
@@ -291,10 +293,7 @@
return ret;
}
-/*
- * Add sysfs entries for the sleep modes.
- */
-static int __init msm_pm_mode_sysfs_add(void)
+int __devinit msm_pm_mode_sysfs_add(void)
{
struct kobject *module_kobj;
struct kobject *modes_kobj;
@@ -328,10 +327,6 @@
return ret;
}
-/******************************************************************************
- * Configure Hardware before/after Low Power Mode
- *****************************************************************************/
-
/*
* Configure hardware registers in preparation for Apps power down.
*/
@@ -374,22 +369,6 @@
return;
}
-
-/******************************************************************************
- * Suspend Max Sleep Time
- *****************************************************************************/
-
-#ifdef CONFIG_MSM_SLEEP_TIME_OVERRIDE
-static int msm_pm_sleep_time_override;
-module_param_named(sleep_time_override,
- msm_pm_sleep_time_override, int, S_IRUGO | S_IWUSR | S_IWGRP);
-#endif
-
-#define SCLK_HZ (32768)
-#define MSM_PM_SLEEP_TICK_LIMIT (0x6DDD000)
-
-static uint32_t msm_pm_max_sleep_time;
-
/*
* Convert time from nanoseconds to slow clock ticks, then cap it to the
* specified limit
@@ -408,36 +387,21 @@
if (max_sleep_time_ns == 0) {
msm_pm_max_sleep_time = 0;
} else {
- msm_pm_max_sleep_time = (uint32_t)msm_pm_convert_and_cap_time(
+ msm_pm_max_sleep_time =
+ (uint32_t)msm_pm_convert_and_cap_time(
max_sleep_time_ns, MSM_PM_SLEEP_TICK_LIMIT);
if (msm_pm_max_sleep_time == 0)
msm_pm_max_sleep_time = 1;
}
- if (msm_pm_debug_mask & MSM_PM_DEBUG_SUSPEND)
+ if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s: Requested %lld ns Giving %u sclk ticks\n",
- __func__, max_sleep_time_ns, msm_pm_max_sleep_time);
+ __func__, max_sleep_time_ns,
+ msm_pm_max_sleep_time);
}
EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
-struct reg_data {
- uint32_t reg;
- uint32_t val;
-};
-
-static struct reg_data reg_saved_state[] = {
- { .reg = 0x4501, },
- { .reg = 0x5501, },
- { .reg = 0x6501, },
- { .reg = 0x7501, },
- { .reg = 0x0500, },
-};
-
-static unsigned int active_vdd;
-static bool msm_pm_save_cp15;
-static const unsigned int pc_vdd = 0x98;
-
static void msm_pm_save_cpu_reg(void)
{
int i;
@@ -455,11 +419,12 @@
* rate. Then restore the active vdd before switching the acpuclk rate.
*/
if (msm_pm_get_l2_flush_flag() == 1) {
- active_vdd = msm_spm_get_vdd(0);
- for (i = 0; i < ARRAY_SIZE(reg_saved_state); i++)
- reg_saved_state[i].val =
- get_l2_indirect_reg(reg_saved_state[i].reg);
- msm_spm_set_vdd(0, pc_vdd);
+ cp15_data.active_vdd = msm_spm_get_vdd(0);
+ for (i = 0; i < cp15_data.reg_saved_state_size; i++)
+ cp15_data.reg_val[i] =
+ get_l2_indirect_reg(
+ cp15_data.reg_data[i]);
+ msm_spm_set_vdd(0, cp15_data.qsb_pc_vdd);
}
}
@@ -472,10 +437,11 @@
return;
if (msm_pm_get_l2_flush_flag() == 1) {
- for (i = 0; i < ARRAY_SIZE(reg_saved_state); i++)
- set_l2_indirect_reg(reg_saved_state[i].reg,
- reg_saved_state[i].val);
- msm_spm_set_vdd(0, active_vdd);
+ for (i = 0; i < cp15_data.reg_saved_state_size; i++)
+ set_l2_indirect_reg(
+ cp15_data.reg_data[i],
+ cp15_data.reg_val[i]);
+ msm_spm_set_vdd(0, cp15_data.active_vdd);
}
}
@@ -485,7 +451,6 @@
msm_arch_idle();
}
-
static void msm_pm_retention(void)
{
int ret = 0;
@@ -494,7 +459,7 @@
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_RETENTION, false);
WARN_ON(ret);
- if (msm_pm_retention_tz_call)
+ if (msm_pm_retention_calls_tz)
scm_call_atomic1(SCM_SVC_BOOT, SCM_CMD_TERMINATE_PC,
SCM_L2_RETENTION);
else
@@ -565,7 +530,7 @@
static bool msm_pm_power_collapse(bool from_idle)
{
unsigned int cpu = smp_processor_id();
- unsigned long saved_acpuclk_rate;
+ unsigned long saved_acpuclk_rate = 0;
unsigned int avsdscr;
unsigned int avscsr;
bool collapsed;
@@ -582,28 +547,28 @@
avscsr = avs_get_avscsr();
avs_set_avscsr(0); /* Disable AVS */
- if (cpu_online(cpu))
+ if (cpu_online(cpu) && !msm_no_ramp_down_pc)
saved_acpuclk_rate = acpuclk_power_collapse();
- else
- saved_acpuclk_rate = 0;
if (MSM_PM_DEBUG_CLOCK & msm_pm_debug_mask)
pr_info("CPU%u: %s: change clock rate (old rate = %lu)\n",
cpu, __func__, saved_acpuclk_rate);
- if (msm_pm_save_cp15)
+ if (cp15_data.save_cp15)
msm_pm_save_cpu_reg();
collapsed = msm_pm_spm_power_collapse(cpu, from_idle, true);
- if (msm_pm_save_cp15)
+ if (cp15_data.save_cp15)
msm_pm_restore_cpu_reg();
if (cpu_online(cpu)) {
if (MSM_PM_DEBUG_CLOCK & msm_pm_debug_mask)
pr_info("CPU%u: %s: restore clock rate to %lu\n",
cpu, __func__, saved_acpuclk_rate);
- if (acpuclk_set_rate(cpu, saved_acpuclk_rate, SETRATE_PC) < 0)
+ if (!msm_no_ramp_down_pc &&
+ acpuclk_set_rate(cpu, saved_acpuclk_rate, SETRATE_PC)
+ < 0)
pr_err("CPU%u: %s: failed to restore clock rate(%lu)\n",
cpu, __func__, saved_acpuclk_rate);
} else {
@@ -633,15 +598,9 @@
return collapsed;
}
-static void msm_pm_target_init(void)
-{
- if (cpu_is_apq8064())
- msm_pm_save_cp15 = true;
-}
-
static int64_t msm_pm_timer_enter_idle(void)
{
- if (msm_pm_init_data.use_sync_timer)
+ if (msm_pm_use_sync_timer)
return ktime_to_ns(tick_nohz_get_sleep_length());
return msm_timer_enter_idle();
@@ -649,7 +608,7 @@
static void msm_pm_timer_exit_idle(bool timer_halted)
{
- if (msm_pm_init_data.use_sync_timer)
+ if (msm_pm_use_sync_timer)
return;
msm_timer_exit_idle((int) timer_halted);
@@ -659,7 +618,7 @@
{
int64_t time = 0;
- if (msm_pm_init_data.use_sync_timer)
+ if (msm_pm_use_sync_timer)
return ktime_to_ns(ktime_get());
time = msm_timer_get_sclk_time(period);
@@ -671,7 +630,7 @@
static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
{
- if (msm_pm_init_data.use_sync_timer)
+ if (msm_pm_use_sync_timer)
return ktime_to_ns(ktime_get()) - time;
if (time != 0) {
@@ -794,6 +753,7 @@
bool allow;
uint32_t power;
int idx;
+ void *rs_limits = NULL;
mode = (enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage);
idx = MSM_PM_MODE(dev->cpu, mode);
@@ -803,11 +763,9 @@
switch (mode) {
case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- if (num_online_cpus() > 1) {
+ if (num_online_cpus() > 1)
allow = false;
- break;
- }
- /* fall through */
+ break;
case MSM_PM_SLEEP_MODE_RETENTION:
/*
* The Krait BHS regulator doesn't have enough head
@@ -815,63 +773,41 @@
* has disabled retention
*/
if (!msm_pm_ldo_retention_enabled)
- break;
-
- if (!allow)
- break;
-
- if (msm_pm_retention_tz_call &&
- num_online_cpus() > 1) {
allow = false;
- break;
- }
- /* fall through */
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
- if (!allow)
- break;
- /* fall through */
-
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- if (!allow)
- break;
- /* fall through */
-
- if (pm_sleep_ops.lowest_limits)
- *msm_pm_idle_rs_limits =
- pm_sleep_ops.lowest_limits(
- true, mode,
- &time_param, &power);
-
- if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
- pr_info("CPU%u: %s: %s, latency %uus, "
- "sleep %uus, limit %p\n",
- dev->cpu, __func__, state->desc,
- time_param.latency_us,
- time_param.sleep_us,
- *msm_pm_idle_rs_limits);
-
- if (!*msm_pm_idle_rs_limits)
+ if (msm_pm_retention_calls_tz && num_online_cpus() > 1)
allow = false;
break;
-
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+ case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+ break;
default:
allow = false;
break;
}
+ if (!allow)
+ continue;
+
+ if (pm_sleep_ops.lowest_limits)
+ rs_limits = pm_sleep_ops.lowest_limits(true,
+ mode, &time_param, &power);
+
if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
- pr_info("CPU%u: %s: allow %s: %d\n",
- dev->cpu, __func__, state->desc, (int)allow);
+ pr_info("CPU%u:%s:%s, latency %uus, slp %uus, lim %p\n",
+ dev->cpu, __func__, state->desc,
+ time_param.latency_us,
+ time_param.sleep_us, rs_limits);
+ if (!rs_limits)
+ continue;
- if (allow) {
- if (power < power_usage) {
- power_usage = power;
- modified_time_us = time_param.modified_time_us;
- ret = mode;
- }
-
+ if (power < power_usage) {
+ power_usage = power;
+ modified_time_us = time_param.modified_time_us;
+ ret = mode;
+ *msm_pm_idle_rs_limits = rs_limits;
}
+
}
if (modified_time_us && !dev->cpu)
@@ -924,67 +860,64 @@
if (pm_sleep_ops.enter_sleep)
ret = pm_sleep_ops.enter_sleep(sleep_delay,
- msm_pm_idle_rs_limits,
- true, notify_rpm);
- if (!ret) {
+ msm_pm_idle_rs_limits, true, notify_rpm);
+ if (ret)
+ goto cpuidle_enter_bail;
- switch (sleep_mode) {
- case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
- msm_pm_swfi();
- exit_stat = MSM_PM_STAT_IDLE_WFI;
- break;
+ switch (sleep_mode) {
+ case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+ msm_pm_swfi();
+ exit_stat = MSM_PM_STAT_IDLE_WFI;
+ break;
- case MSM_PM_SLEEP_MODE_RETENTION:
- msm_pm_retention();
- exit_stat = MSM_PM_STAT_RETENTION;
- break;
+ case MSM_PM_SLEEP_MODE_RETENTION:
+ msm_pm_retention();
+ exit_stat = MSM_PM_STAT_RETENTION;
+ break;
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
- collapsed = msm_pm_power_collapse_standalone(true);
- exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
- break;
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+ collapsed = msm_pm_power_collapse_standalone(true);
+ exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
+ break;
- case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
- if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
- clock_debug_print_enabled();
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+ if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
+ clock_debug_print_enabled();
- collapsed = msm_pm_power_collapse(true);
- timer_halted = true;
+ collapsed = msm_pm_power_collapse(true);
+ timer_halted = true;
- exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
- msm_pm_timer_exit_idle(timer_halted);
- break;
-
- case MSM_PM_SLEEP_MODE_NOT_SELECTED:
- goto cpuidle_enter_bail;
- break;
-
- default:
- __WARN();
- goto cpuidle_enter_bail;
- break;
- }
- if (pm_sleep_ops.exit_sleep)
- pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits,
- true, notify_rpm, collapsed);
-
- time = ktime_to_ns(ktime_get()) - time;
- msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode,
- collapsed);
- if (exit_stat >= 0)
- msm_pm_add_stat(exit_stat, time);
- do_div(time, 1000);
- dev->last_residency = (int) time;
- return sleep_mode;
-
- } else if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
+ exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
msm_pm_timer_exit_idle(timer_halted);
- sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
- } else
- sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
+ break;
+
+ case MSM_PM_SLEEP_MODE_NOT_SELECTED:
+ goto cpuidle_enter_bail;
+ break;
+
+ default:
+ __WARN();
+ goto cpuidle_enter_bail;
+ break;
+ }
+
+ if (pm_sleep_ops.exit_sleep)
+ pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits, true,
+ notify_rpm, collapsed);
+
+ time = ktime_to_ns(ktime_get()) - time;
+ msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode, collapsed);
+ if (exit_stat >= 0)
+ msm_pm_add_stat(exit_stat, time);
+ do_div(time, 1000);
+ dev->last_residency = (int) time;
+ return sleep_mode;
cpuidle_enter_bail:
dev->last_residency = 0;
+ if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
+ msm_pm_timer_exit_idle(timer_halted);
+ sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
return sleep_mode;
}
@@ -1079,17 +1012,16 @@
clock_debug_print_enabled();
-#ifdef CONFIG_MSM_SLEEP_TIME_OVERRIDE
if (msm_pm_sleep_time_override > 0) {
int64_t ns = NSEC_PER_SEC *
(int64_t) msm_pm_sleep_time_override;
msm_pm_set_max_sleep_time(ns);
msm_pm_sleep_time_override = 0;
}
-#endif /* CONFIG_MSM_SLEEP_TIME_OVERRIDE */
+
if (pm_sleep_ops.lowest_limits)
rs_limits = pm_sleep_ops.lowest_limits(false,
- MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power);
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE, &time_param, &power);
if (rs_limits) {
if (pm_sleep_ops.enter_sleep)
@@ -1123,7 +1055,6 @@
msm_pm_swfi();
}
-
enter_exit:
if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
pr_info("%s: return\n", __func__);
@@ -1131,66 +1062,18 @@
return 0;
}
-static struct platform_suspend_ops msm_pm_ops = {
- .enter = msm_pm_enter,
- .valid = suspend_valid_only_mem,
-};
-
-/******************************************************************************
- * Initialization routine
- *****************************************************************************/
void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
{
if (ops)
pm_sleep_ops = *ops;
}
-void __init msm_pm_set_tz_retention_flag(unsigned int flag)
-{
- msm_pm_retention_tz_call = flag;
-}
-
-static int __devinit msm_pc_debug_probe(struct platform_device *pdev)
-{
- struct resource *res = NULL;
- int i ;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- goto fail;
-
- msm_pc_debug_counters_phys = res->start;
- WARN_ON(resource_size(res) < SZ_64);
- msm_pc_debug_counters = devm_ioremap_nocache(&pdev->dev, res->start,
- resource_size(res));
-
- if (!msm_pc_debug_counters)
- goto fail;
-
- for (i = 0; i < resource_size(res)/4; i++)
- __raw_writel(0, msm_pc_debug_counters + i * 4);
- return 0;
-fail:
- msm_pc_debug_counters = 0;
- msm_pc_debug_counters_phys = 0;
- return -EFAULT;
-}
-
-static struct of_device_id msm_pc_debug_table[] = {
- {.compatible = "qcom,pc-cntr"},
- {},
+static const struct platform_suspend_ops msm_pm_ops = {
+ .enter = msm_pm_enter,
+ .valid = suspend_valid_only_mem,
};
-static struct platform_driver msm_pc_counter_driver = {
- .probe = msm_pc_debug_probe,
- .driver = {
- .name = "pc-cntr",
- .owner = THIS_MODULE,
- .of_match_table = msm_pc_debug_table,
- },
-};
-
-static int __init msm_pm_init(void)
+static int __devinit msm_pm_init(void)
{
pgd_t *pc_pgd;
pmd_t *pmd;
@@ -1205,7 +1088,6 @@
unsigned long exit_phys;
/* Page table for cores to come back up safely. */
-
pc_pgd = pgd_alloc(&init_mm);
if (!pc_pgd)
return -ENOMEM;
@@ -1244,18 +1126,13 @@
msm_pm_mode_sysfs_add();
msm_pm_add_stats(enable_stats, ARRAY_SIZE(enable_stats));
-
suspend_set_ops(&msm_pm_ops);
- msm_pm_target_init();
hrtimer_init(&pm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
msm_cpuidle_init();
- platform_driver_register(&msm_pc_counter_driver);
return 0;
}
-late_initcall(msm_pm_init);
-
static void __devinit msm_pm_set_flush_fn(uint32_t pc_mode)
{
msm_pm_disable_l2_fn = NULL;
@@ -1268,41 +1145,203 @@
}
}
+struct msm_pc_debug_counters_buffer {
+ void __iomem *reg;
+ u32 len;
+ char buf[MAX_BUF_SIZE];
+};
+
+static inline u32 msm_pc_debug_counters_read_register(
+ void __iomem *reg, int index , int offset)
+{
+ return readl_relaxed(reg + (index * 4 + offset) * 4);
+}
+
+static char *counter_name[] = {
+ "PC Entry Counter",
+ "Warmboot Entry Counter",
+ "PC Bailout Counter"
+};
+
+static int msm_pc_debug_counters_copy(
+ struct msm_pc_debug_counters_buffer *data)
+{
+ int j;
+ u32 stat;
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu) {
+ data->len += scnprintf(data->buf + data->len,
+ sizeof(data->buf)-data->len,
+ "CPU%d\n", cpu);
+
+ for (j = 0; j < NUM_OF_COUNTERS; j++) {
+ stat = msm_pc_debug_counters_read_register(
+ data->reg, cpu, j);
+ data->len += scnprintf(data->buf + data->len,
+ sizeof(data->buf)-data->len,
+ "\t%s : %d\n", counter_name[j],
+ stat);
+ }
+
+ }
+
+ return data->len;
+}
+
+static int msm_pc_debug_counters_file_read(struct file *file,
+ char __user *bufu, size_t count, loff_t *ppos)
+{
+ struct msm_pc_debug_counters_buffer *data;
+
+ data = file->private_data;
+
+ if (!data)
+ return -EINVAL;
+
+ if (!bufu || count < 0)
+ return -EINVAL;
+
+ if (!access_ok(VERIFY_WRITE, bufu, count))
+ return -EFAULT;
+
+ if (*ppos >= data->len && data->len == 0)
+ data->len = msm_pc_debug_counters_copy(data);
+
+ return simple_read_from_buffer(bufu, count, ppos,
+ data->buf, data->len);
+}
+
+static int msm_pc_debug_counters_file_open(struct inode *inode,
+ struct file *file)
+{
+ struct msm_pc_debug_counters_buffer *buf;
+ void __iomem *msm_pc_debug_counters_reg;
+
+ msm_pc_debug_counters_reg = inode->i_private;
+
+ if (!msm_pc_debug_counters_reg)
+ return -EINVAL;
+
+ file->private_data = kzalloc(
+ sizeof(struct msm_pc_debug_counters_buffer), GFP_KERNEL);
+
+ if (!file->private_data) {
+ pr_err("%s: ERROR kmalloc failed to allocate %d bytes\n",
+ __func__, sizeof(struct msm_pc_debug_counters_buffer));
+
+ return -ENOMEM;
+ }
+
+ buf = file->private_data;
+ buf->reg = msm_pc_debug_counters_reg;
+
+ return 0;
+}
+
+static int msm_pc_debug_counters_file_close(struct inode *inode,
+ struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+static const struct file_operations msm_pc_debug_counters_fops = {
+ .open = msm_pc_debug_counters_file_open,
+ .read = msm_pc_debug_counters_file_read,
+ .release = msm_pc_debug_counters_file_close,
+ .llseek = no_llseek,
+};
+
static int __devinit msm_pm_8x60_probe(struct platform_device *pdev)
{
char *key = NULL;
+ struct dentry *dent = NULL;
uint32_t val = 0;
+ struct resource *res = NULL;
+ int i ;
+ struct msm_pm_init_data_type pdata_local;
int ret = 0;
+ memset(&pdata_local, 0, sizeof(struct msm_pm_init_data_type));
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res) {
+ msm_pc_debug_counters_phys = res->start;
+ WARN_ON(resource_size(res) < SZ_64);
+ msm_pc_debug_counters = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (msm_pc_debug_counters)
+ for (i = 0; i < resource_size(res)/4; i++)
+ __raw_writel(0, msm_pc_debug_counters + i * 4);
+
+ }
+
+ if (!msm_pc_debug_counters) {
+ msm_pc_debug_counters = 0;
+ msm_pc_debug_counters_phys = 0;
+ } else {
+ dent = debugfs_create_file("pc_debug_counter", S_IRUGO, NULL,
+ msm_pc_debug_counters,
+ &msm_pc_debug_counters_fops);
+ if (!dent)
+ pr_err("%s: ERROR debugfs_create_file failed\n",
+ __func__);
+ }
+
if (!pdev->dev.of_node) {
struct msm_pm_init_data_type *d = pdev->dev.platform_data;
if (!d)
goto pm_8x60_probe_done;
- msm_pm_init_data.pc_mode = d->pc_mode;
- msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
- msm_pm_init_data.use_sync_timer = d->use_sync_timer;
+ memcpy(&pdata_local, d, sizeof(struct msm_pm_init_data_type));
+
} else {
key = "qcom,pc-mode";
ret = of_property_read_u32(pdev->dev.of_node, key, &val);
-
if (ret) {
pr_debug("%s: Cannot read %s,defaulting to 0",
__func__, key);
val = MSM_PM_PC_TZ_L2_INT;
ret = 0;
}
-
- msm_pm_init_data.pc_mode = val;
- msm_pm_set_flush_fn(msm_pm_init_data.pc_mode);
+ pdata_local.pc_mode = val;
key = "qcom,use-sync-timer";
- msm_pm_init_data.use_sync_timer =
+ pdata_local.use_sync_timer =
of_property_read_bool(pdev->dev.of_node, key);
+
+ key = "qcom,saw-turns-off-pll";
+ msm_no_ramp_down_pc = of_property_read_bool(pdev->dev.of_node,
+ key);
}
+ if (pdata_local.cp15_data.reg_data &&
+ pdata_local.cp15_data.reg_saved_state_size > 0) {
+ cp15_data.reg_data = kzalloc(sizeof(uint32_t) *
+ pdata_local.cp15_data.reg_saved_state_size,
+ GFP_KERNEL);
+ if (!cp15_data.reg_data)
+ return -ENOMEM;
+
+ cp15_data.reg_val = kzalloc(sizeof(uint32_t) *
+ pdata_local.cp15_data.reg_saved_state_size,
+ GFP_KERNEL);
+ if (cp15_data.reg_val)
+ return -ENOMEM;
+
+ memcpy(cp15_data.reg_data, pdata_local.cp15_data.reg_data,
+ pdata_local.cp15_data.reg_saved_state_size *
+ sizeof(uint32_t));
+ }
+
+ msm_pm_set_flush_fn(pdata_local.pc_mode);
+ msm_pm_use_sync_timer = pdata_local.use_sync_timer;
+ msm_pm_retention_calls_tz = pdata_local.retention_calls_tz;
+
pm_8x60_probe_done:
+ msm_pm_init();
return ret;
}
@@ -1324,4 +1363,4 @@
{
return platform_driver_register(&msm_pm_8x60_driver);
}
-module_init(msm_pm_8x60_init);
+device_initcall(msm_pm_8x60_init);
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 43bb7de..af0744c 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -97,8 +97,19 @@
external L2 cache controller */
};
+struct msm_pm_cp15_save_data {
+ bool save_cp15;
+ uint32_t active_vdd;
+ uint32_t qsb_pc_vdd;
+ uint32_t reg_saved_state_size;
+ uint32_t *reg_data;
+ uint32_t *reg_val;
+};
+
struct msm_pm_init_data_type {
enum msm_pm_pc_mode_type pc_mode;
+ bool retention_calls_tz;
+ struct msm_pm_cp15_save_data cp15_data;
bool use_sync_timer;
};
diff --git a/arch/arm/mach-msm/qdsp5/audio_mvs.c b/arch/arm/mach-msm/qdsp5/audio_mvs.c
index 7d2766d..d1aba82 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mvs.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mvs.c
@@ -1734,6 +1734,7 @@
{
MM_DBG("\n");
+ wake_lock_destroy(&audio_mvs_info.suspend_lock);
misc_deregister(&audio_mvs_misc);
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 654f547..e6b9549 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -897,6 +897,11 @@
struct audio_client *ac;
struct audio_aio_write_param param;
+ if (!audio || !buf_node) {
+ pr_err("%s NULL pointer audio=[0x%p], buf_node=[0x%p]\n",
+ __func__, audio, buf_node);
+ return;
+ }
pr_debug("%s[%p]: Send write buff %p phy %lx len %d meta_enable = %d\n",
__func__, audio, buf_node, buf_node->paddr,
buf_node->buf.data_len,
@@ -922,8 +927,7 @@
if (!audio->buf_cfg.meta_info_enable)
param.flags = 0xFF00;
- if ((buf_node != NULL) &&
- (buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOF_SET))
+ if (buf_node->meta_info.meta_in.nflags & AUDIO_DEC_EOF_SET)
param.flags |= AUDIO_DEC_EOF_SET;
param.uid = param.paddr;
diff --git a/arch/arm/mach-msm/rpm-notifier.h b/arch/arm/mach-msm/rpm-notifier.h
index b9815a5..16de77e 100644
--- a/arch/arm/mach-msm/rpm-notifier.h
+++ b/arch/arm/mach-msm/rpm-notifier.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
@@ -40,8 +40,12 @@
/**
* msm_rpm_enter_sleep - Notify RPM driver to prepare for entering sleep
+ *
+ * @bool - flag to enable print contents of sleep buffer.
+ *
+ * return 0 on success errno on failure.
*/
-int msm_rpm_enter_sleep(void);
+int msm_rpm_enter_sleep(bool print);
/**
* msm_rpm_exit_sleep - Notify RPM driver about resuming from power collapse
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 4295fd4..b84ade9 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -32,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/rbtree.h>
#include <mach/socinfo.h>
#include <mach/msm_smd.h>
#include <mach/rpm-smd.h>
@@ -62,6 +63,9 @@
};
#define DEFAULT_BUFFER_SIZE 256
+#define DEBUG_PRINT_BUFFER_SIZE 512
+#define MAX_SLEEP_BUFFER 128
+
#define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
#define INV_RSC "resource does not exist"
#define ERR "err\0"
@@ -106,6 +110,11 @@
uint32_t data_len;
};
+struct kvp {
+ unsigned int k;
+ unsigned int s;
+};
+
struct msm_rpm_kvp_data {
uint32_t key;
uint32_t nbytes; /* number of bytes */
@@ -113,6 +122,301 @@
bool valid;
};
+struct slp_buf {
+ struct rb_node node;
+ char ubuf[MAX_SLEEP_BUFFER];
+ char *buf;
+ bool valid;
+};
+static struct rb_root tr_root = RB_ROOT;
+
+static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq);
+static uint32_t msm_rpm_get_next_msg_id(void);
+
+static inline unsigned int get_rsc_type(char *buf)
+{
+ struct rpm_message_header *h;
+ h = (struct rpm_message_header *)
+ (buf + sizeof(struct rpm_request_header));
+ return h->resource_type;
+}
+
+static inline unsigned int get_rsc_id(char *buf)
+{
+ struct rpm_message_header *h;
+ h = (struct rpm_message_header *)
+ (buf + sizeof(struct rpm_request_header));
+ return h->resource_id;
+}
+
+#define get_data_len(buf) \
+ (((struct rpm_message_header *) \
+ (buf + sizeof(struct rpm_request_header)))->data_len)
+
+#define get_req_len(buf) \
+ (((struct rpm_request_header *)(buf))->request_len)
+
+#define get_msg_id(buf) \
+ (((struct rpm_message_header *) \
+ (buf + sizeof(struct rpm_request_header)))->msg_id)
+
+
+static inline int get_buf_len(char *buf)
+{
+ return get_req_len(buf) + sizeof(struct rpm_request_header);
+}
+
+static inline struct kvp *get_first_kvp(char *buf)
+{
+ return (struct kvp *)(buf + sizeof(struct rpm_request_header)
+ + sizeof(struct rpm_message_header));
+}
+
+static inline struct kvp *get_next_kvp(struct kvp *k)
+{
+ return (struct kvp *)((void *)k + sizeof(*k) + k->s);
+}
+
+static inline void *get_data(struct kvp *k)
+{
+ return (void *)k + sizeof(*k);
+}
+
+
+static void delete_kvp(char *msg, struct kvp *d)
+{
+ struct kvp *n;
+ int dec, size;
+
+ n = get_next_kvp(d);
+ dec = (void *)n - (void *)d;
+ size = get_data_len(msg) - ((void *)n - (void *)get_first_kvp(msg));
+
+ memcpy((void *)d, (void *)n, size);
+
+ get_data_len(msg) -= dec;
+ get_req_len(msg) -= dec;
+}
+
+static inline void update_kvp_data(struct kvp *dest, struct kvp *src)
+{
+ memcpy(get_data(dest), get_data(src), src->s);
+}
+
+static void add_kvp(char *buf, struct kvp *n)
+{
+ int inc = sizeof(*n) + n->s;
+ BUG_ON((get_req_len(buf) + inc) > MAX_SLEEP_BUFFER);
+
+ memcpy(buf + get_buf_len(buf), n, inc);
+
+ get_data_len(buf) += inc;
+ get_req_len(buf) += inc;
+}
+
+static struct slp_buf *tr_search(struct rb_root *root, char *slp)
+{
+ unsigned int type = get_rsc_type(slp);
+ unsigned int id = get_rsc_id(slp);
+
+ struct rb_node *node = root->rb_node;
+
+ while (node) {
+ struct slp_buf *cur = rb_entry(node, struct slp_buf, node);
+ unsigned int ctype = get_rsc_type(cur->buf);
+ unsigned int cid = get_rsc_id(cur->buf);
+
+ if (type < ctype)
+ node = node->rb_left;
+ else if (type > ctype)
+ node = node->rb_right;
+ else if (id < cid)
+ node = node->rb_left;
+ else if (id > cid)
+ node = node->rb_right;
+ else
+ return cur;
+ }
+ return NULL;
+}
+
+static int tr_insert(struct rb_root *root, struct slp_buf *slp)
+{
+ unsigned int type = get_rsc_type(slp->buf);
+ unsigned int id = get_rsc_id(slp->buf);
+
+ struct rb_node **node = &(root->rb_node), *parent = NULL;
+
+ while (*node) {
+ struct slp_buf *curr = rb_entry(*node, struct slp_buf, node);
+ unsigned int ctype = get_rsc_type(curr->buf);
+ unsigned int cid = get_rsc_id(curr->buf);
+
+ parent = *node;
+
+ if (type < ctype)
+ node = &((*node)->rb_left);
+ else if (type > ctype)
+ node = &((*node)->rb_right);
+ else if (id < cid)
+ node = &((*node)->rb_left);
+ else if (id > cid)
+ node = &((*node)->rb_right);
+ else
+ return -EINVAL;
+ }
+
+ rb_link_node(&slp->node, parent, node);
+ rb_insert_color(&slp->node, root);
+ slp->valid = true;
+ return 0;
+}
+
+#define for_each_kvp(buf, k) \
+ for (k = (struct kvp *)get_first_kvp(buf); \
+ ((void *)k - (void *)get_first_kvp(buf)) < get_data_len(buf);\
+ k = get_next_kvp(k))
+
+
+static void tr_update(struct slp_buf *s, char *buf)
+{
+ struct kvp *e, *n;
+
+ for_each_kvp(buf, n) {
+ for_each_kvp(s->buf, e) {
+ if (n->k == e->k) {
+ if (n->s == e->s) {
+ void *e_data = get_data(e);
+ void *n_data = get_data(n);
+ if (memcmp(e_data, n_data, n->s)) {
+ update_kvp_data(e, n);
+ s->valid = true;
+ }
+ } else {
+ delete_kvp(s->buf, e);
+ add_kvp(s->buf, n);
+ s->valid = true;
+ }
+ break;
+ }
+ }
+ }
+}
+
+int msm_rpm_smd_buffer_request(char *buf, int size, gfp_t flag)
+{
+ struct slp_buf *slp;
+ static DEFINE_SPINLOCK(slp_buffer_lock);
+ unsigned long flags;
+
+ if (size > MAX_SLEEP_BUFFER)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&slp_buffer_lock, flags);
+ slp = tr_search(&tr_root, buf);
+
+ if (!slp) {
+ slp = kzalloc(sizeof(struct slp_buf), GFP_ATOMIC);
+ if (!slp) {
+ spin_unlock_irqrestore(&slp_buffer_lock, flags);
+ return -ENOMEM;
+ }
+ slp->buf = PTR_ALIGN(&slp->ubuf[0], sizeof(u32));
+ memcpy(slp->buf, buf, size);
+ if (tr_insert(&tr_root, slp))
+ pr_err("%s(): Error updating sleep request\n",
+ __func__);
+ } else {
+ /* handle unsent requests */
+ tr_update(slp, buf);
+ }
+
+ spin_unlock_irqrestore(&slp_buffer_lock, flags);
+
+ return 0;
+}
+static void msm_rpm_print_sleep_buffer(struct slp_buf *s)
+{
+ char buf[DEBUG_PRINT_BUFFER_SIZE] = {0};
+ int pos;
+ int buflen = DEBUG_PRINT_BUFFER_SIZE;
+ char ch[5] = {0};
+ u32 type;
+ struct kvp *e;
+
+ if (!s)
+ return;
+
+ if (!s->valid)
+ return;
+
+ type = get_rsc_type(s->buf);
+ memcpy(ch, &type, sizeof(u32));
+
+ pos = scnprintf(buf, buflen,
+ "Sleep request type = 0x%08x(%s)",
+ get_rsc_type(s->buf), ch);
+ pos += scnprintf(buf + pos, buflen - pos, " id = 0%x",
+ get_rsc_id(s->buf));
+ for_each_kvp(s->buf, e) {
+ int i;
+ char *data = get_data(e);
+
+ memcpy(ch, &e->k, sizeof(u32));
+
+ pos += scnprintf(buf + pos, buflen - pos,
+ "\n\t\tkey = 0x%08x(%s)",
+ e->k, ch);
+ pos += scnprintf(buf + pos, buflen - pos,
+ " sz= %d data =", e->s);
+
+ for (i = 0; i < e->s; i++)
+ pos += scnprintf(buf + pos, buflen - pos,
+ " 0x%02X", data[i]);
+ }
+ pos += scnprintf(buf + pos, buflen - pos, "\n");
+ printk(buf);
+}
+
+static int msm_rpm_flush_requests(bool print)
+{
+ struct rb_node *t;
+ int ret;
+
+ for (t = rb_first(&tr_root); t; t = rb_next(t)) {
+
+ struct slp_buf *s = rb_entry(t, struct slp_buf, node);
+
+ if (!s->valid)
+ continue;
+
+ if (print)
+ msm_rpm_print_sleep_buffer(s);
+
+ get_msg_id(s->buf) = msm_rpm_get_next_msg_id();
+ ret = msm_rpm_send_smd_buffer(s->buf,
+ get_buf_len(s->buf), true);
+ /* By not adding the message to a wait list we can reduce
+ * latency involved in waiting for a ACK from RPM. The ACK
+ * messages will be processed when we wakeup from sleep but
+ * processing should be minimal
+ * msm_rpm_wait_for_ack_noirq(get_msg_id(s->buf));
+ */
+
+ WARN_ON(ret != get_buf_len(s->buf));
+
+ trace_rpm_send_message(true, MSM_RPM_CTX_SLEEP_SET,
+ get_rsc_type(s->buf),
+ get_rsc_id(s->buf),
+ get_msg_id(s->buf));
+
+ s->valid = false;
+ }
+ return 0;
+
+}
+
+
static atomic_t msm_rpm_msg_id = ATOMIC_INIT(0);
static struct msm_rpm_driver_data msm_rpm_data;
@@ -450,7 +754,12 @@
}
elem = NULL;
}
- WARN_ON(!elem);
+ /* Special case where the sleep driver doesn't
+ * wait for ACKs. This would decrease the latency involved with
+ * entering RPM assisted power collapse.
+ */
+ if (!elem)
+ trace_rpm_ack_recd(0, msg_id);
spin_unlock_irqrestore(&msm_rpm_list_lock, flags);
}
@@ -544,8 +853,6 @@
}
}
-#define DEBUG_PRINT_BUFFER_SIZE 512
-
static void msm_rpm_log_request(struct msm_rpm_request *cdata)
{
char buf[DEBUG_PRINT_BUFFER_SIZE];
@@ -677,13 +984,42 @@
pos += scnprintf(buf + pos, buflen - pos, "\n");
printk(buf);
}
+static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq)
+{
+ unsigned long flags;
+ int ret;
+ spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags);
+ ret = smd_write_avail(msm_rpm_data.ch_info);
+
+ while ((ret = smd_write_avail(msm_rpm_data.ch_info)) < size) {
+ if (ret < 0)
+ break;
+ if (!noirq) {
+ spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write,
+ flags);
+ cpu_relax();
+ spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags);
+ } else
+ udelay(5);
+ }
+
+ if (ret < 0) {
+ pr_err("%s(): SMD not initialized\n", __func__);
+ spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
+ return ret;
+ }
+
+ ret = smd_write(msm_rpm_data.ch_info, buf, size);
+ spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
+ return ret;
+
+}
static int msm_rpm_send_data(struct msm_rpm_request *cdata,
int msg_type, bool noirq)
{
uint8_t *tmpbuff;
int i, ret, msg_size;
- unsigned long flags;
int req_hdr_sz, msg_hdr_sz;
@@ -695,8 +1031,6 @@
cdata->req_hdr.service_type = msm_rpm_request_service[msg_type];
- cdata->msg_hdr.msg_id = msm_rpm_get_next_msg_id();
-
cdata->req_hdr.request_len = cdata->msg_hdr.data_len + msg_hdr_sz;
msg_size = cdata->req_hdr.request_len + req_hdr_sz;
@@ -714,8 +1048,6 @@
tmpbuff = cdata->buf;
- memcpy(tmpbuff, &cdata->req_hdr, req_hdr_sz + msg_hdr_sz);
-
tmpbuff += req_hdr_sz + msg_hdr_sz;
for (i = 0; (i < cdata->write_idx); i++) {
@@ -740,6 +1072,17 @@
}
+ memcpy(cdata->buf, &cdata->req_hdr, req_hdr_sz + msg_hdr_sz);
+
+ if ((cdata->msg_hdr.set == MSM_RPM_CTX_SLEEP_SET) &&
+ !msm_rpm_smd_buffer_request(cdata->buf, msg_size,
+ GFP_FLAG(noirq)))
+ return 1;
+
+ cdata->msg_hdr.msg_id = msm_rpm_get_next_msg_id();
+
+ memcpy(cdata->buf + req_hdr_sz, &cdata->msg_hdr, msg_hdr_sz);
+
if (msm_rpm_debug_mask
& (MSM_RPM_LOG_REQUEST_PRETTY | MSM_RPM_LOG_REQUEST_RAW))
msm_rpm_log_request(cdata);
@@ -755,29 +1098,7 @@
msm_rpm_add_wait_list(cdata->msg_hdr.msg_id);
- spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags);
-
- ret = smd_write_avail(msm_rpm_data.ch_info);
-
- if (ret < 0) {
- pr_err("%s(): SMD not initialized\n", __func__);
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
- return 0;
- }
-
- while ((ret < msg_size)) {
- if (!noirq) {
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write,
- flags);
- cpu_relax();
- spin_lock_irqsave(&msm_rpm_data.smd_lock_write, flags);
- } else
- udelay(5);
- ret = smd_write_avail(msm_rpm_data.ch_info);
- }
-
- ret = smd_write(msm_rpm_data.ch_info, &cdata->buf[0], msg_size);
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
+ ret = msm_rpm_send_smd_buffer(&cdata->buf[0], msg_size, noirq);
if (ret == msg_size) {
trace_rpm_send_message(noirq, cdata->msg_hdr.set,
@@ -958,11 +1279,13 @@
* During power collapse, the rpm driver disables the SMD interrupts to make
* sure that the interrupt doesn't wakes us from sleep.
*/
-int msm_rpm_enter_sleep(void)
+int msm_rpm_enter_sleep(bool print)
{
if (standalone)
return 0;
+ msm_rpm_flush_requests(print);
+
return smd_mask_receive_interrupt(msm_rpm_data.ch_info, true);
}
EXPORT_SYMBOL(msm_rpm_enter_sleep);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 19e48759..56623c9 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -134,6 +134,16 @@
uint32_t pmic_die_revision;
};
+struct socinfo_v8 {
+ struct socinfo_v7 v7;
+
+ /* only valid when format==8*/
+ uint32_t pmic_model_1;
+ uint32_t pmic_die_revision_1;
+ uint32_t pmic_model_2;
+ uint32_t pmic_die_revision_2;
+};
+
static union {
struct socinfo_v1 v1;
struct socinfo_v2 v2;
@@ -142,6 +152,7 @@
struct socinfo_v5 v5;
struct socinfo_v6 v6;
struct socinfo_v7 v7;
+ struct socinfo_v8 v8;
} *socinfo;
static enum msm_cpu cpu_of_id[] = {
@@ -865,6 +876,7 @@
device_create_file(msm_soc_device, &msm_soc_attr_vendor);
switch (legacy_format) {
+ case 8:
case 7:
device_create_file(msm_soc_device,
&msm_soc_attr_pmic_model);
@@ -1054,6 +1066,7 @@
socinfo->v5.accessory_chip,
socinfo->v6.hw_platform_subtype);
break;
+ case 8:
case 7:
pr_info("%s: v%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u\n",
__func__,
@@ -1076,7 +1089,11 @@
int __init socinfo_init(void)
{
- socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+ socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v8));
+
+ if (!socinfo)
+ socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v7));
if (!socinfo)
socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 0a14979..2c0e5ae 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -262,8 +262,9 @@
extra_iova_addr = data->iova_addr + buffer->size;
if (extra) {
- ret = msm_iommu_map_extra(domain, extra_iova_addr, extra, SZ_4K,
- prot);
+ unsigned long phys_addr = sg_phys(table->sgl);
+ ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+ extra, SZ_4K, prot);
if (ret)
goto out2;
}
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 764b044..ba88a42 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -465,8 +465,11 @@
}
ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle);
- if (ret)
+ if (ret) {
+ drm_gem_object_release(obj);
+ DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret);
return ret;
+ }
create->handle = handle;
return 0;
@@ -539,6 +542,106 @@
}
int
+kgsl_gem_create_from_ion_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_kgsl_gem_create_from_ion *args = data;
+ struct drm_gem_object *obj;
+ struct ion_handle *ion_handle;
+ struct drm_kgsl_gem_object *priv;
+ struct sg_table *sg_table;
+ struct scatterlist *s;
+ int ret, handle;
+ unsigned long size;
+
+ ion_handle = ion_import_dma_buf(kgsl_drm_ion_client, args->ion_fd);
+ if (IS_ERR_OR_NULL(ion_handle)) {
+ DRM_ERROR("Unable to import dmabuf. Error number = %d\n",
+ (int)PTR_ERR(ion_handle));
+ return -EINVAL;
+ }
+
+ ion_handle_get_size(kgsl_drm_ion_client, ion_handle, &size);
+
+ if (size == 0) {
+ ion_free(kgsl_drm_ion_client, ion_handle);
+ DRM_ERROR(
+ "cannot create GEM object from zero size ION buffer\n");
+ return -EINVAL;
+ }
+
+ obj = drm_gem_object_alloc(dev, size);
+
+ if (obj == NULL) {
+ ion_free(kgsl_drm_ion_client, ion_handle);
+ DRM_ERROR("Unable to allocate the GEM object\n");
+ return -ENOMEM;
+ }
+
+ ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle);
+ if (ret) {
+ ion_free(kgsl_drm_ion_client, ion_handle);
+ drm_gem_object_release(obj);
+ DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret);
+ return ret;
+ }
+
+ priv = obj->driver_private;
+ priv->ion_handle = ion_handle;
+
+ priv->type = DRM_KGSL_GEM_TYPE_KMEM;
+ list_add(&priv->list, &kgsl_mem_list);
+
+ priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+
+ priv->memdesc.pagetable = priv->pagetable;
+
+ sg_table = ion_sg_table(kgsl_drm_ion_client,
+ priv->ion_handle);
+ if (IS_ERR_OR_NULL(priv->ion_handle)) {
+ DRM_ERROR("Unable to get ION sg table\n");
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ kgsl_mmu_putpagetable(priv->pagetable);
+ drm_gem_object_release(obj);
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ priv->memdesc.sg = sg_table->sgl;
+
+ /* Calculate the size of the memdesc from the sglist */
+
+ priv->memdesc.sglen = 0;
+
+ for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) {
+ priv->memdesc.size += s->length;
+ priv->memdesc.sglen++;
+ }
+
+ ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
+ GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ if (ret) {
+ DRM_ERROR("kgsl_mmu_map failed. ret = %d\n", ret);
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ kgsl_mmu_putpagetable(priv->pagetable);
+ drm_gem_object_release(obj);
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ priv->bufs[0].offset = 0;
+ priv->bufs[0].gpuaddr = priv->memdesc.gpuaddr;
+ priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED;
+
+ args->handle = handle;
+ return 0;
+}
+
+int
kgsl_gem_get_ion_fd_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
@@ -563,6 +666,12 @@
if (priv->ion_handle) {
args->ion_fd = ion_share_dma_buf(
kgsl_drm_ion_client, priv->ion_handle);
+ if (args->ion_fd < 0) {
+ DRM_ERROR(
+ "Could not share ion buffer. Error = %d\n",
+ args->ion_fd);
+ ret = -EINVAL;
+ }
} else {
DRM_ERROR("GEM object has no ion memory allocated.\n");
ret = -EINVAL;
@@ -1266,6 +1375,8 @@
DRM_IOCTL_DEF_DRV(KGSL_GEM_MMAP, kgsl_gem_mmap_ioctl, 0),
DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFINFO, kgsl_gem_get_bufinfo_ioctl, 0),
DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_ION_FD, kgsl_gem_get_ion_fd_ioctl, 0),
+ DRM_IOCTL_DEF_DRV(KGSL_GEM_CREATE_FROM_ION,
+ kgsl_gem_create_from_ion_ioctl, 0),
DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_BUFCOUNT,
kgsl_gem_set_bufcount_ioctl, 0),
DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_ACTIVE, kgsl_gem_set_active_ioctl, 0),
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2945b7b..89335f3 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1001,7 +1001,7 @@
}
/* Set the CPU latency to 501usec to allow low latency PC modes */
- pwr->pm_qos_latency = 3;
+ pwr->pm_qos_latency = 501;
pm_runtime_enable(device->parentdev);
register_early_suspend(&device->display_off);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 11f351c..3fdc68f 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -125,6 +125,7 @@
#define QPNP_BIT_SHIFT_8 8
#define QPNP_RSENSE_MSB_SIGN_CHECK 0x80
#define QPNP_ADC_COMPLETION_TIMEOUT HZ
+#define QPNP_IADC_ERR_CHK_RATELIMIT 3
struct qpnp_iadc_drv {
struct qpnp_adc_drv *adc;
@@ -134,6 +135,9 @@
bool iadc_initialized;
int64_t die_temp_calib_offset;
struct delayed_work iadc_work;
+ struct mutex iadc_vadc_lock;
+ bool iadc_mode_sel;
+ uint32_t iadc_err_cnt;
struct sensor_device_attribute sens_attr[0];
};
@@ -292,7 +296,7 @@
}
static int32_t qpnp_iadc_configure(enum qpnp_iadc_channels channel,
- uint16_t *raw_code)
+ uint16_t *raw_code, uint32_t mode_sel)
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
u8 qpnp_iadc_mode_reg = 0, qpnp_iadc_ch_sel_reg = 0;
@@ -303,7 +307,11 @@
qpnp_iadc_dig_param_reg |= iadc->adc->amux_prop->decimation <<
QPNP_IADC_DEC_RATIO_SEL;
- qpnp_iadc_mode_reg |= QPNP_ADC_TRIM_EN;
+ if (iadc->iadc_mode_sel)
+ qpnp_iadc_mode_reg |= (QPNP_ADC_TRIM_EN | QPNP_VADC_SYNCH_EN);
+ else
+ qpnp_iadc_mode_reg |= QPNP_ADC_TRIM_EN;
+
qpnp_iadc_conv_req = QPNP_IADC_CONV_REQ;
rc = qpnp_iadc_write_reg(QPNP_IADC_MODE_CTL, qpnp_iadc_mode_reg);
@@ -403,8 +411,10 @@
uint8_t rslt_lsb, rslt_msb;
int32_t rc = 0;
uint16_t raw_data;
+ uint32_t mode_sel = 0;
- rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV, &raw_data);
+ rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
+ &raw_data, mode_sel);
if (rc < 0) {
pr_err("qpnp adc result read failed with %d\n", rc);
goto fail;
@@ -412,8 +422,8 @@
iadc->adc->calib.gain_raw = raw_data;
- rc = qpnp_iadc_configure(OFFSET_CALIBRATION_SHORT_CADC_LEADS,
- &raw_data);
+ rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+ &raw_data, mode_sel);
if (rc < 0) {
pr_err("qpnp adc result read failed with %d\n", rc);
goto fail;
@@ -470,12 +480,15 @@
mutex_lock(&iadc->adc->adc_lock);
rc = qpnp_iadc_calibrate_for_trim();
- if (rc)
+ if (rc) {
pr_err("periodic IADC calibration failed\n");
+ iadc->iadc_err_cnt++;
+ }
mutex_unlock(&iadc->adc->adc_lock);
- schedule_delayed_work(&iadc->iadc_work,
+ if (iadc->iadc_err_cnt < QPNP_IADC_ERR_CHK_RATELIMIT)
+ schedule_delayed_work(&iadc->iadc_work,
round_jiffies_relative(msecs_to_jiffies
(QPNP_IADC_CALIB_SECONDS)));
@@ -568,22 +581,24 @@
struct qpnp_iadc_result *result)
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
- int32_t rc, rsense_n_ohms, sign = 0, num;
+ int32_t rc, rsense_n_ohms, sign = 0, num, mode_sel = 0;
int64_t result_current;
uint16_t raw_data;
if (!iadc || !iadc->iadc_initialized)
return -EPROBE_DEFER;
- rc = qpnp_check_pmic_temp();
- if (rc) {
- pr_err("Error checking pmic therm temp\n");
- return rc;
+ if (!iadc->iadc_mode_sel) {
+ rc = qpnp_check_pmic_temp();
+ if (rc) {
+ pr_err("Error checking pmic therm temp\n");
+ return rc;
+ }
}
mutex_lock(&iadc->adc->adc_lock);
- rc = qpnp_iadc_configure(channel, &raw_data);
+ rc = qpnp_iadc_configure(channel, &raw_data, mode_sel);
if (rc < 0) {
pr_err("qpnp adc result read failed with %d\n", rc);
goto fail;
@@ -644,6 +659,50 @@
}
EXPORT_SYMBOL(qpnp_iadc_get_gain_and_offset);
+int32_t qpnp_iadc_vadc_sync_read(
+ enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
+ enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
+{
+ struct qpnp_iadc_drv *iadc = qpnp_iadc;
+ int rc = 0;
+
+ if (!iadc || !iadc->iadc_initialized)
+ return -EPROBE_DEFER;
+
+ mutex_lock(&iadc->iadc_vadc_lock);
+
+ rc = qpnp_check_pmic_temp();
+ if (rc) {
+ pr_err("PMIC die temp check failed\n");
+ goto fail;
+ }
+
+ iadc->iadc_mode_sel = true;
+
+ rc = qpnp_vadc_iadc_sync_request(v_channel);
+ if (rc) {
+ pr_err("Configuring VADC failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_iadc_read(i_channel, i_result);
+ if (rc)
+ pr_err("Configuring IADC failed\n");
+ /* Intentional fall through to release VADC */
+
+ rc = qpnp_vadc_iadc_sync_complete_request(v_channel,
+ v_result);
+ if (rc)
+ pr_err("Releasing VADC failed\n");
+fail:
+ iadc->iadc_mode_sel = false;
+
+ mutex_unlock(&iadc->iadc_vadc_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_iadc_vadc_sync_read);
+
static ssize_t qpnp_iadc_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
@@ -786,6 +845,8 @@
schedule_delayed_work(&iadc->iadc_work,
round_jiffies_relative(msecs_to_jiffies
(QPNP_IADC_CALIB_SECONDS)));
+ mutex_init(&iadc->iadc_vadc_lock);
+ iadc->iadc_err_cnt = 0;
iadc->iadc_initialized = true;
return 0;
@@ -801,6 +862,7 @@
struct device_node *child;
int i = 0;
+ mutex_destroy(&iadc->iadc_vadc_lock);
for_each_child_of_node(node, child) {
device_remove_file(&spmi->dev,
&iadc->sens_attr[i].dev_attr);
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 3df19d7..edbde44 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.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
@@ -98,6 +98,7 @@
bool vadc_init_calib;
bool vadc_initialized;
int max_channels_available;
+ bool vadc_iadc_sync_lock;
struct sensor_device_attribute sens_attr[0];
};
@@ -304,11 +305,14 @@
if (rc)
return rc;
- /* Request conversion */
- rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ, QPNP_VADC_CONV_REQ_SET);
- if (rc < 0) {
- pr_err("Request conversion failed\n");
- return rc;
+ if (!vadc->vadc_iadc_sync_lock) {
+ /* Request conversion */
+ rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ,
+ QPNP_VADC_CONV_REQ_SET);
+ if (rc < 0) {
+ pr_err("Request conversion failed\n");
+ return rc;
+ }
}
return 0;
@@ -734,6 +738,121 @@
}
EXPORT_SYMBOL_GPL(qpnp_vadc_read);
+static void qpnp_vadc_lock(void)
+{
+ struct qpnp_vadc_drv *vadc = qpnp_vadc;
+
+ mutex_lock(&vadc->adc->adc_lock);
+}
+
+static void qpnp_vadc_unlock(void)
+{
+ struct qpnp_vadc_drv *vadc = qpnp_vadc;
+
+ mutex_unlock(&vadc->adc->adc_lock);
+}
+
+int32_t qpnp_vadc_iadc_sync_request(enum qpnp_vadc_channels channel)
+{
+ struct qpnp_vadc_drv *vadc = qpnp_vadc;
+ int rc = 0, dt_index = 0;
+
+ if (!vadc || !vadc->vadc_initialized)
+ return -EPROBE_DEFER;
+
+ qpnp_vadc_lock();
+
+ if (!vadc->vadc_init_calib) {
+ rc = qpnp_vadc_version_check();
+ if (rc)
+ goto fail;
+
+ rc = qpnp_vadc_calib_device();
+ if (rc) {
+ pr_err("Calibration failed\n");
+ goto fail;
+ } else
+ vadc->vadc_init_calib = true;
+ }
+
+ vadc->adc->amux_prop->amux_channel = channel;
+
+ while ((vadc->adc->adc_channels[dt_index].channel_num
+ != channel) && (dt_index < vadc->max_channels_available))
+ dt_index++;
+
+ if (dt_index >= vadc->max_channels_available) {
+ pr_err("not a valid VADC channel\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ vadc->adc->amux_prop->decimation =
+ vadc->adc->adc_channels[dt_index].adc_decimation;
+ vadc->adc->amux_prop->hw_settle_time =
+ vadc->adc->adc_channels[dt_index].hw_settle_time;
+ vadc->adc->amux_prop->fast_avg_setup =
+ vadc->adc->adc_channels[dt_index].fast_avg_setup;
+ vadc->adc->amux_prop->mode_sel = (ADC_OP_NORMAL_MODE
+ << QPNP_VADC_OP_MODE_SHIFT);
+ vadc->vadc_iadc_sync_lock = true;
+
+ rc = qpnp_vadc_configure(vadc->adc->amux_prop);
+ if (rc) {
+ pr_err("qpnp vadc configure failed with %d\n", rc);
+ goto fail;
+ }
+
+ return rc;
+fail:
+ vadc->vadc_iadc_sync_lock = false;
+ qpnp_vadc_unlock();
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_vadc_iadc_sync_request);
+
+int32_t qpnp_vadc_iadc_sync_complete_request(enum qpnp_vadc_channels channel,
+ struct qpnp_vadc_result *result)
+{
+ struct qpnp_vadc_drv *vadc = qpnp_vadc;
+ int rc = 0, scale_type, amux_prescaling, dt_index = 0;
+
+ vadc->adc->amux_prop->amux_channel = channel;
+
+ while ((vadc->adc->adc_channels[dt_index].channel_num
+ != channel) && (dt_index < vadc->max_channels_available))
+ dt_index++;
+
+ rc = qpnp_vadc_read_conversion_result(&result->adc_code);
+ if (rc) {
+ pr_err("qpnp vadc read adc code failed with %d\n", rc);
+ goto fail;
+ }
+
+ amux_prescaling =
+ vadc->adc->adc_channels[dt_index].chan_path_prescaling;
+
+ vadc->adc->amux_prop->chan_prop->offset_gain_numerator =
+ qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
+ vadc->adc->amux_prop->chan_prop->offset_gain_denominator =
+ qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
+
+ scale_type = vadc->adc->adc_channels[dt_index].adc_scale_fn;
+ if (scale_type >= SCALE_NONE) {
+ rc = -EBADF;
+ goto fail;
+ }
+
+ vadc_scale_fn[scale_type].chan(result->adc_code,
+ vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
+
+fail:
+ vadc->vadc_iadc_sync_lock = false;
+ qpnp_vadc_unlock();
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_vadc_iadc_sync_complete_request);
+
static ssize_t qpnp_adc_show(struct device *dev,
struct device_attribute *devattr, char *buf)
{
@@ -857,6 +976,7 @@
vadc->vadc_init_calib = false;
vadc->max_channels_available = count_adc_channel_list;
vadc->vadc_initialized = true;
+ vadc->vadc_iadc_sync_lock = false;
return 0;
fail:
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 717f763..eaf3519 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -128,6 +128,7 @@
};
#define QUP_MAX_CLK_STATE_RETRIES 300
+#define DEFAULT_CLK_RATE (19200000)
static char const * const i2c_rsrcs[] = {"i2c_clk", "i2c_sda"};
@@ -1235,18 +1236,26 @@
dev->clk_ctl = 0;
dev->pos = 0;
+ if (dev->pdata->src_clk_rate <= 0) {
+ dev_info(&pdev->dev,
+ "No src_clk_rate specified in platfrom data or "
+ "qcom,i2c-src-freq in DT\n");
+ dev_info(&pdev->dev, "Using default clock rate %dHz\n",
+ DEFAULT_CLK_RATE);
+ dev->pdata->src_clk_rate = DEFAULT_CLK_RATE;
+ }
+
+ ret = clk_set_rate(dev->clk, dev->pdata->src_clk_rate);
+ if (ret)
+ dev_info(&pdev->dev, "clk_set_rate(core_clk, %dHz):%d\n",
+ dev->pdata->src_clk_rate, ret);
+
+ clk_prepare_enable(dev->clk);
+ clk_prepare_enable(dev->pclk);
/*
* If bootloaders leave a pending interrupt on certain GSBI's,
* then we reset the core before registering for interrupts.
*/
-
- if (dev->pdata->src_clk_rate > 0)
- clk_set_rate(dev->clk, dev->pdata->src_clk_rate);
- else
- dev->pdata->src_clk_rate = 19200000;
-
- clk_prepare_enable(dev->clk);
- clk_prepare_enable(dev->pclk);
writel_relaxed(1, dev->base + QUP_SW_RESET);
if (qup_i2c_poll_state(dev, 0, true) != 0)
goto err_reset_failed;
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index c447231..abb5bbc 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -1529,7 +1529,7 @@
static ssize_t fwu_sysfs_config_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- unsigned char config_id[8];
+ unsigned char config_id[4];
/* device config id */
fwu->fn_ptr->read(fwu->rmi4_data,
fwu->f34_fd.ctrl_base_addr,
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index bea6842..fb1882c 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -27,6 +27,7 @@
#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
#define WLED_IDAC_DLY_REG(base, n) (WLED_MOD_EN_REG(base, n) + 0x01)
#define WLED_FULL_SCALE_REG(base, n) (WLED_IDAC_DLY_REG(base, n) + 0x01)
+#define WLED_MOD_SRC_SEL_REG(base, n) (WLED_FULL_SCALE_REG(base, n) + 0x01)
/* wled control registers */
#define WLED_BRIGHTNESS_CNTL_LSB(base, n) (base + 0x40 + 2*n)
@@ -83,7 +84,7 @@
#define FLASH_LED_1_CURR(base) (base + 0x43)
#define FLASH_CLAMP_CURR(base) (base + 0x44)
#define FLASH_LED_TMR_CTRL(base) (base + 0x48)
-#define FLASH_HEADROOM(base) (base + 0x49)
+#define FLASH_HEADROOM(base) (base + 0x4A)
#define FLASH_STARTUP_DELAY(base) (base + 0x4B)
#define FLASH_MASK_ENABLE(base) (base + 0x4C)
#define FLASH_VREG_OK_FORCE(base) (base + 0x4F)
@@ -111,7 +112,7 @@
#define FLASH_ENABLE_MODULE 0x80
#define FLASH_ENABLE_MODULE_MASK 0x80
#define FLASH_DISABLE_ALL 0x00
-#define FLASH_ENABLE_MASK 0x60
+#define FLASH_ENABLE_MASK 0xE0
#define FLASH_ENABLE_LED_0 0x40
#define FLASH_ENABLE_LED_1 0x20
#define FLASH_INIT_MASK 0xE0
@@ -454,6 +455,14 @@
/* Set led current */
if (val > 0) {
+ rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
+
rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
if (rc) {
@@ -487,6 +496,13 @@
"LED %d flash write failed(%d)\n", led->id, rc);
return rc;
}
+ rc = qpnp_led_masked_write(led, FLASH_VREG_OK_FORCE(led->base),
+ FLASH_VREG_MASK, FLASH_HW_VREG_OK);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Vreg OK reg write failed(%d)\n", rc);
+ return rc;
+ }
} else {
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
FLASH_ENABLE_MASK,
@@ -755,7 +771,7 @@
if (led->wled_cfg->dig_mod_gen_en) {
rc = qpnp_led_masked_write(led,
- WLED_MOD_EN_REG(led->base, i),
+ WLED_MOD_SRC_SEL_REG(led->base, i),
WLED_NO_MASK, WLED_USE_EXT_GEN_MOD_SRC);
if (rc) {
dev_err(&led->spmi_dev->dev,
@@ -883,7 +899,7 @@
}
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK, FLASH_ENABLE_MODULE);
+ FLASH_ENABLE_MODULE_MASK, FLASH_DISABLE_ALL);
if (rc) {
dev_err(&led->spmi_dev->dev,
"Enable reg write failed(%d)\n", rc);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 44e23ed..1cabc3e 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -39,6 +39,24 @@
return rc;
}
+int create_pkt_cmd_sys_idle_indicator(
+ struct hfi_cmd_sys_set_property_packet *pkt,
+ u32 enable)
+{
+ struct hfi_enable *hfi;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_sys_set_property_packet) +
+ sizeof(struct hfi_enable) + sizeof(u32);
+ pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+ pkt->num_properties = 1;
+ pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IDLE_INDICATOR;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = enable;
+ return 0;
+}
+
int create_pkt_set_cmd_sys_resource(
struct hfi_cmd_sys_set_resource_packet *pkt,
struct vidc_resource_hdr *resource_hdr,
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index b2c6e08..8c61a40 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -22,6 +22,10 @@
u32 arch_type);
int create_pkt_cmd_sys_pc_prep(struct hfi_cmd_sys_pc_prep_packet *pkt);
+int create_pkt_cmd_sys_idle_indicator(
+ struct hfi_cmd_sys_set_property_packet *pkt,
+ u32 enable);
+
int create_pkt_set_cmd_sys_resource(
struct hfi_cmd_sys_set_resource_packet *pkt,
struct vidc_resource_hdr *resource_hdr,
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index f6a9949..709eafc 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -823,19 +823,21 @@
callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
}
-void hfi_process_msg_packet(
+u32 hfi_process_msg_packet(
msm_vidc_callback callback, u32 device_id,
struct vidc_hal_msg_pkt_hdr *msg_hdr)
{
+ u32 rc = 0;
if (!callback || !msg_hdr || msg_hdr->size <
VIDC_IFACEQ_MIN_PKT_SIZE) {
dprintk(VIDC_ERR, "hal_process_msg_packet:bad"
"packet/packet size: %d", msg_hdr->size);
- return;
+ rc = -EINVAL;
+ return rc;
}
dprintk(VIDC_INFO, "Received: 0x%x in ", msg_hdr->packet);
-
+ rc = (u32) msg_hdr->packet;
switch (msg_hdr->packet) {
case HFI_MSG_EVENT_NOTIFY:
hfi_process_event_notify(callback, device_id,
@@ -846,6 +848,8 @@
(struct hfi_msg_sys_init_done_packet *)
msg_hdr);
break;
+ case HFI_MSG_SYS_IDLE:
+ break;
case HFI_MSG_SYS_SESSION_INIT_DONE:
hfi_process_session_init_done(callback, device_id,
(struct hfi_msg_sys_session_init_done_packet *)
@@ -915,4 +919,5 @@
dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
break;
}
+ return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 8e2aa30..125c699 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.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,7 +26,7 @@
unsigned long align, unsigned long *iova,
unsigned long *buffer_size, int flags)
{
- int rc;
+ int rc = 0;
if (!iova || !buffer_size || !hndl || !clnt) {
dprintk(VIDC_ERR, "Invalid params: %p, %p, %p, %p\n",
clnt, hndl, iova, buffer_size);
@@ -71,6 +71,7 @@
struct ion_handle *hndl;
unsigned long iova = 0;
unsigned long buffer_size = 0;
+ unsigned long ionflags = 0;
int rc = 0;
int align = SZ_4K;
hndl = ion_import_dma_buf(client->clnt, fd);
@@ -84,7 +85,20 @@
mem->domain = domain;
mem->partition_num = partition;
mem->flags = flags;
-
+ rc = ion_handle_get_flags(client->clnt, hndl, &ionflags);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to get ion flags: %d\n", rc);
+ goto fail_map;
+ }
+ if (ION_IS_CACHED(ionflags)) {
+ mem->kvaddr = ion_map_kernel(client->clnt, hndl);
+ if (!mem->kvaddr) {
+ dprintk(VIDC_ERR,
+ "Failed to map shared mem in kernel\n");
+ rc = -EIO;
+ goto fail_map;
+ }
+ }
if (flags & SMEM_SECURE)
align = ALIGN(align, SZ_1M);
@@ -103,7 +117,9 @@
mem->device_addr, mem->size);
return rc;
fail_device_address:
- ion_unmap_kernel(client->clnt, hndl);
+ if (mem->kvaddr)
+ ion_unmap_kernel(client->clnt, hndl);
+fail_map:
ion_free(client->clnt, hndl);
fail_import_fd:
return rc;
@@ -243,31 +259,79 @@
return mem;
}
-static int ion_mem_clean_invalidate(struct smem_client *clt,
- struct msm_smem *mem)
+static int ion_cache_operations(struct smem_client *client,
+ struct msm_smem *mem, enum smem_cache_ops cache_op)
{
- /*
- * Note: We're always mapping into iommu as uncached
- * as a result we don't need to flush/clean anything
- */
- return 0;
+ unsigned long ionflag = 0;
+ int rc = 0;
+ int msm_cache_ops = 0;
+ if (!mem || !client) {
+ dprintk(VIDC_ERR, "Invalid params: %p, %p\n",
+ mem, client);
+ return -EINVAL;
+ }
+ rc = ion_handle_get_flags(client->clnt, mem->smem_priv,
+ &ionflag);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "ion_handle_get_flags failed: %d\n", rc);
+ goto cache_op_failed;
+ }
+ if (ION_IS_CACHED(ionflag)) {
+ switch (cache_op) {
+ case SMEM_CACHE_CLEAN:
+ msm_cache_ops = ION_IOC_CLEAN_CACHES;
+ break;
+ case SMEM_CACHE_INVALIDATE:
+ msm_cache_ops = ION_IOC_INV_CACHES;
+ break;
+ case SMEM_CACHE_CLEAN_INVALIDATE:
+ msm_cache_ops = ION_IOC_CLEAN_INV_CACHES;
+ break;
+ default:
+ dprintk(VIDC_ERR, "cache operation not supported\n");
+ rc = -EINVAL;
+ goto cache_op_failed;
+ }
+ if (mem->kvaddr) {
+ rc = msm_ion_do_cache_op(client->clnt,
+ (struct ion_handle *)mem->smem_priv,
+ (unsigned long *) mem->kvaddr,
+ (unsigned long)mem->size,
+ msm_cache_ops);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "cache operation failed %d\n", rc);
+ goto cache_op_failed;
+ }
+ } else {
+ dprintk(VIDC_WARN,
+ "cache operation failed as no kernel mapping\n");
+ }
+ }
+cache_op_failed:
+ return rc;
}
-int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem)
+int msm_smem_cache_operations(void *clt, struct msm_smem *mem,
+ enum smem_cache_ops cache_op)
{
struct smem_client *client = clt;
- int rc;
- if (!client || !mem) {
- dprintk(VIDC_ERR, "Invalid client/handle passed\n");
+ int rc = 0;
+ if (!client) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n",
+ client);
return -EINVAL;
}
switch (client->mem_type) {
case SMEM_ION:
- rc = ion_mem_clean_invalidate(client, mem);
+ rc = ion_cache_operations(client, mem, cache_op);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed cache operations: %d\n", rc);
break;
default:
dprintk(VIDC_ERR, "Mem type not supported\n");
- rc = -EINVAL;
break;
}
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index 6e40bef..d1c8293 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.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
@@ -37,6 +37,13 @@
void *smem_priv;
};
+enum smem_cache_ops {
+ SMEM_CACHE_CLEAN,
+ SMEM_CACHE_INVALIDATE,
+ SMEM_CACHE_CLEAN_INVALIDATE,
+};
+
+
void *msm_smem_new_client(enum smem_type mtype);
struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
int domain, int partition, int map_kernel);
@@ -44,5 +51,6 @@
void msm_smem_delete_client(void *clt);
struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, int
domain, int partition, int flags);
-int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem);
+int msm_smem_cache_operations(void *clt, struct msm_smem *mem,
+ enum smem_cache_ops);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 47eccfa..54047eb 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -54,6 +54,50 @@
struct list_head registered_bufs;
};
+struct master_slave {
+ int masters_ocmem[2];
+ int masters_ddr[2];
+ int slaves_ocmem[2];
+ int slaves_ddr[2];
+};
+
+struct bus_pdata_config {
+ int *masters;
+ int *slaves;
+ char *name;
+};
+
+static struct master_slave bus_vectors_masters_slaves = {
+ .masters_ocmem = {MSM_BUS_MASTER_VIDEO_P0_OCMEM,
+ MSM_BUS_MASTER_VIDEO_P1_OCMEM},
+ .masters_ddr = {MSM_BUS_MASTER_VIDEO_P0, MSM_BUS_MASTER_VIDEO_P1},
+ .slaves_ocmem = {MSM_BUS_SLAVE_OCMEM, MSM_BUS_SLAVE_OCMEM},
+ .slaves_ddr = {MSM_BUS_SLAVE_EBI_CH0, MSM_BUS_SLAVE_EBI_CH0},
+};
+
+static struct bus_pdata_config bus_pdata_config_vector[] = {
+{
+ .masters = bus_vectors_masters_slaves.masters_ocmem,
+ .slaves = bus_vectors_masters_slaves.slaves_ocmem,
+ .name = "qcom,enc-ocmem-ab-ib",
+},
+{
+ .masters = bus_vectors_masters_slaves.masters_ocmem,
+ .slaves = bus_vectors_masters_slaves.slaves_ocmem,
+ .name = "qcom,dec-ocmem-ab-ib",
+},
+{
+ .masters = bus_vectors_masters_slaves.masters_ddr,
+ .slaves = bus_vectors_masters_slaves.slaves_ddr,
+ .name = "qcom,enc-ddr-ab-ib",
+},
+{
+ .masters = bus_vectors_masters_slaves.masters_ddr,
+ .slaves = bus_vectors_masters_slaves.slaves_ddr,
+ .name = "qcom,dec-ddr-ab-ib",
+},
+};
+
static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
{
return container_of(filp->private_data,
@@ -137,10 +181,12 @@
err_invalid_input:
return ret;
}
-static u32 device_to_uvaddr(struct list_head *list, u32 device_addr)
+
+static struct buffer_info *device_to_uvaddr(
+ struct list_head *list, u32 device_addr)
{
- struct buffer_info *temp;
- u32 uvaddr = 0;
+ struct buffer_info *temp = NULL;
+ int found = 0;
int i;
if (!list || !device_addr) {
dprintk(VIDC_ERR, "Invalid input\n");
@@ -154,16 +200,16 @@
== device_addr) {
dprintk(VIDC_INFO,
"Found same fd buffer\n");
- uvaddr = temp->uvaddr[i];
+ found = 1;
break;
}
}
- if (uvaddr)
+ if (found)
break;
}
}
err_invalid_input:
- return uvaddr;
+ return temp;
}
static int msm_v4l2_open(struct file *filp)
@@ -500,9 +546,10 @@
b->m.planes[i].m.userptr = binfo->device_addr[i];
dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
binfo->device_addr[i]);
- if (binfo->handle[i]) {
- rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
- binfo->handle[i]);
+ if (binfo->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
+ rc = msm_smem_cache_operations(v4l2_inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_CLEAN);
if (rc) {
dprintk(VIDC_ERR,
"Failed to clean caches: %d\n", rc);
@@ -522,6 +569,7 @@
int i;
struct msm_v4l2_vid_inst *v4l2_inst;
struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+ struct buffer_info *buffer_info;
if (b->length > VIDEO_MAX_PLANES) {
dprintk(VIDC_ERR, "num planes exceed maximum: %d\n",
b->length);
@@ -541,9 +589,10 @@
!b->m.planes[i].m.userptr) {
continue;
}
- b->m.planes[i].m.userptr = device_to_uvaddr(
+ buffer_info = device_to_uvaddr(
&v4l2_inst->registered_bufs,
b->m.planes[i].m.userptr);
+ b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
if (!b->m.planes[i].m.userptr) {
dprintk(VIDC_ERR,
"Failed to find user virtual address, 0x%lx, %d, %d\n",
@@ -551,6 +600,16 @@
rc = -EINVAL;
goto fail_dq_buf;
}
+ if (buffer_info->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+ rc = msm_smem_cache_operations(v4l2_inst->mem_client,
+ buffer_info->handle[i], SMEM_CACHE_INVALIDATE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to clean caches: %d\n", rc);
+ goto fail_dq_buf;
+ }
+ }
}
fail_dq_buf:
return rc;
@@ -743,6 +802,24 @@
res->reg_set.reg_tbl = NULL;
}
+static inline void msm_vidc_free_bus_vectors(
+ struct msm_vidc_platform_resources *res)
+{
+ int i, j;
+ if (res->bus_pdata) {
+ for (i = 0; i < ARRAY_SIZE(bus_pdata_config_vector); i++) {
+ for (j = 0; j < res->bus_pdata[i].num_usecases; j++) {
+ kfree(res->bus_pdata[i].usecase[j].vectors);
+ res->bus_pdata[i].usecase[j].vectors = NULL;
+ }
+ kfree(res->bus_pdata[i].usecase);
+ res->bus_pdata[i].usecase = NULL;
+ }
+ kfree(res->bus_pdata);
+ res->bus_pdata = NULL;
+ }
+}
+
static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
{
int rc = 0;
@@ -864,6 +941,144 @@
return rc;
}
+static void msm_vidc_free_bus_vector(struct msm_bus_scale_pdata *bus_pdata)
+{
+ int i;
+ for (i = 0; i < bus_pdata->num_usecases; i++) {
+ kfree(bus_pdata->usecase[i].vectors);
+ bus_pdata->usecase[i].vectors = NULL;
+ }
+
+ kfree(bus_pdata->usecase);
+ bus_pdata->usecase = NULL;
+}
+
+static int msm_vidc_load_bus_vector(struct platform_device *pdev,
+ struct msm_bus_scale_pdata *bus_pdata, u32 num_ports,
+ struct bus_pdata_config *bus_pdata_config)
+{
+ struct bus_values {
+ u32 ab;
+ u32 ib;
+ };
+ struct bus_values *values;
+ int i, j;
+ int rc = 0;
+
+ values = kzalloc(sizeof(*values) * bus_pdata->num_usecases, GFP_KERNEL);
+ if (!values) {
+ dprintk(VIDC_ERR, "%s Failed to alloc bus_values\n", __func__);
+ rc = -ENOMEM;
+ goto err_mem_alloc;
+ }
+
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ bus_pdata_config->name, (u32 *)values,
+ bus_pdata->num_usecases * (sizeof(*values)/sizeof(u32)))) {
+ dprintk(VIDC_ERR, "%s Failed to read bus values\n", __func__);
+ rc = -EINVAL;
+ goto err_parse_dt;
+ }
+
+ bus_pdata->usecase = kzalloc(sizeof(*bus_pdata->usecase) *
+ bus_pdata->num_usecases, GFP_KERNEL);
+ if (!bus_pdata->usecase) {
+ dprintk(VIDC_ERR,
+ "%s Failed to alloc bus_pdata usecase\n", __func__);
+ rc = -ENOMEM;
+ goto err_parse_dt;
+ }
+ bus_pdata->name = bus_pdata_config->name;
+ for (i = 0; i < bus_pdata->num_usecases; i++) {
+ bus_pdata->usecase[i].vectors = kzalloc(
+ sizeof(*bus_pdata->usecase[i].vectors) * num_ports,
+ GFP_KERNEL);
+ if (!bus_pdata->usecase) {
+ dprintk(VIDC_ERR,
+ "%s Failed to alloc bus_pdata usecase\n",
+ __func__);
+ break;
+ }
+ for (j = 0; j < num_ports; j++) {
+ bus_pdata->usecase[i].vectors[j].ab = (u64)values[i].ab
+ * 1000;
+ bus_pdata->usecase[i].vectors[j].ib = (u64)values[i].ib
+ * 1000;
+ bus_pdata->usecase[i].vectors[j].src =
+ bus_pdata_config->masters[j];
+ bus_pdata->usecase[i].vectors[j].dst =
+ bus_pdata_config->slaves[j];
+ dprintk(VIDC_DBG,
+ "ab = %llu, ib = %llu, src = %d, dst = %d\n",
+ bus_pdata->usecase[i].vectors[j].ab,
+ bus_pdata->usecase[i].vectors[j].ib,
+ bus_pdata->usecase[i].vectors[j].src,
+ bus_pdata->usecase[i].vectors[j].dst);
+ }
+ bus_pdata->usecase[i].num_paths = num_ports;
+ }
+ if (i < bus_pdata->num_usecases) {
+ for (--i; i >= 0; i--) {
+ kfree(bus_pdata->usecase[i].vectors);
+ bus_pdata->usecase[i].vectors = NULL;
+ }
+ kfree(bus_pdata->usecase);
+ bus_pdata->usecase = NULL;
+ rc = -EINVAL;
+ }
+err_parse_dt:
+ kfree(values);
+err_mem_alloc:
+ return rc;
+}
+
+static int msm_vidc_load_bus_vectors(struct msm_vidc_platform_resources *res)
+{
+ u32 num_ports = 0;
+ int rc = 0;
+ int i;
+ struct platform_device *pdev = res->pdev;
+ u32 num_bus_pdata = ARRAY_SIZE(bus_pdata_config_vector);
+
+ if (of_property_read_u32_array(pdev->dev.of_node, "qcom,bus-ports",
+ (u32 *)&num_ports, 1) || (num_ports == 0))
+ goto err_mem_alloc;
+
+ res->bus_pdata = kzalloc(sizeof(*res->bus_pdata) * num_bus_pdata,
+ GFP_KERNEL);
+ if (!res->bus_pdata) {
+ dprintk(VIDC_ERR, "Failed to alloc memory\n");
+ rc = -ENOMEM;
+ goto err_mem_alloc;
+ }
+ for (i = 0; i < num_bus_pdata; i++) {
+ res->bus_pdata[i].num_usecases = get_u32_array_num_elements(
+ pdev, bus_pdata_config_vector[i].name);
+ if (res->bus_pdata[i].num_usecases == 0) {
+ dprintk(VIDC_ERR, "no elements in %s\n",
+ bus_pdata_config_vector[i].name);
+ rc = -EINVAL;
+ break;
+ }
+
+ rc = msm_vidc_load_bus_vector(pdev, &res->bus_pdata[i],
+ num_ports, &bus_pdata_config_vector[i]);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to load bus vector: %d\n", i);
+ break;
+ }
+ }
+ if (i < num_bus_pdata) {
+ for (--i; i >= 0; i--)
+ msm_vidc_free_bus_vector(&res->bus_pdata[i]);
+ kfree(res->bus_pdata);
+ res->bus_pdata = NULL;
+ }
+err_mem_alloc:
+ return rc;
+}
+
static int read_platform_resources_from_dt(
struct msm_vidc_platform_resources *res)
{
@@ -900,8 +1115,16 @@
dprintk(VIDC_ERR, "Failed to load reg table: %d\n", rc);
goto err_load_reg_table;
}
+
+ rc = msm_vidc_load_bus_vectors(res);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to load bus vectors: %d\n", rc);
+ goto err_load_bus_vectors;
+ }
return rc;
+err_load_bus_vectors:
+ msm_vidc_free_reg_table(res);
err_load_reg_table:
msm_vidc_free_iommu_maps(res);
err_load_iommu_maps:
@@ -1132,6 +1355,7 @@
msm_vidc_free_freq_table(&core->resources);
msm_vidc_free_iommu_maps(&core->resources);
msm_vidc_free_reg_table(&core->resources);
+ msm_vidc_free_bus_vectors(&core->resources);
kfree(core);
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 12469a5..7a51728 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -913,7 +913,7 @@
case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
return HAL_H264_LEVEL_42;
case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
- return HAL_H264_LEVEL_3;
+ return HAL_H264_LEVEL_5;
case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
return HAL_H264_LEVEL_51;
default:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 3c012e7..6a83334 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -362,9 +362,7 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
struct v4l2_event dqevent;
- struct v4l2_control control = {0};
struct msm_vidc_cb_event *event_notify;
- int rc = 0;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
dqevent.id = 0;
@@ -372,16 +370,7 @@
switch (event_notify->hal_event_type) {
case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
- control.id =
- V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
- rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
- if (rc)
- dprintk(VIDC_WARN,
- "Failed to get Smooth streamng flag\n");
- if (!rc && control.value == true)
- dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+ V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
break;
case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
dqevent.type =
@@ -987,7 +976,7 @@
rc = call_hfi_op(hdev, unset_ocmem, hdev->hfi_device_data);
if (rc) {
- dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
+ dprintk(VIDC_INFO, "Failed to unset OCMEM on driver\n");
goto release_ocmem_failed;
}
rc = wait_for_completion_timeout(
@@ -1929,6 +1918,12 @@
rc = -ENOMEM;
goto err_no_mem;
}
+ rc = msm_smem_cache_operations(inst->mem_client,
+ handle, SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to clean cache may cause undefined behavior\n");
+ }
binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
if (!binfo) {
dprintk(VIDC_ERR, "Out of memory\n");
@@ -2014,6 +2009,12 @@
rc = -ENOMEM;
goto err_no_mem;
}
+ rc = msm_smem_cache_operations(inst->mem_client,
+ handle, SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to clean cache may cause undefined behavior\n");
+ }
binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
if (!binfo) {
dprintk(VIDC_ERR, "Out of memory\n");
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index b713d8b..65542bc 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -18,6 +18,7 @@
int msm_vidc_debug = 0x3;
int msm_fw_debug = 0x18;
int msm_fw_debug_mode = 0x1;
+int msm_fw_low_power_mode = 0x1;
struct debug_buffer {
char ptr[MAX_DBG_BUF_SIZE];
@@ -159,6 +160,11 @@
dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
goto failed_create_dir;
}
+ if (!debugfs_create_u32("fw_low_power_mode", S_IRUGO | S_IWUSR,
+ parent, &msm_fw_low_power_mode)) {
+ dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+ goto failed_create_dir;
+ }
failed_create_dir:
return dir;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index 07568ef..fb06af6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.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
@@ -44,6 +44,7 @@
extern int msm_vidc_debug;
extern int msm_fw_debug;
extern int msm_fw_debug_mode;
+extern int msm_fw_low_power_mode;
#define dprintk(__level, __fmt, arg...) \
do { \
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index ca8af9c..8fc6452 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -42,6 +42,7 @@
struct msm_vidc_iommu_info *iommu_maps;
uint32_t iommu_maps_size;
struct reg_set reg_set;
+ struct msm_bus_scale_pdata *bus_pdata;
struct platform_device *pdev;
};
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 7deef37..52150e9 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -48,408 +48,6 @@
{0xFA181000, 0x1000},
};
-static struct msm_bus_vectors enc_ocmem_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf1_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 138200000,
- .ib = 1222000000,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf2_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 414700000,
- .ib = 1222000000,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf3_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 940000000,
- .ib = 2444000000U,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf4_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 1880000000,
- .ib = 2444000000U,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf5_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 3008000000U,
- .ib = 3910400000U,
- },
-};
-
-static struct msm_bus_vectors enc_ocmem_perf6_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 3760000000U,
- .ib = 4888000000ULL,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf1_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 176900000,
- .ib = 1556640000,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf2_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 456200000,
- .ib = 1556640000,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf3_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 864800000,
- .ib = 1556640000,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf4_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 1729600000,
- .ib = 3113280000U,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf5_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 2767360000U,
- .ib = 4981248000ULL,
- },
-};
-
-static struct msm_bus_vectors dec_ocmem_perf6_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0_OCMEM,
- .dst = MSM_BUS_SLAVE_OCMEM,
- .ab = 3459200000U,
- .ib = 6226560000ULL,
- },
-};
-
-static struct msm_bus_paths enc_ocmem_perf_vectors[] = {
- {
- ARRAY_SIZE(enc_ocmem_init_vectors),
- enc_ocmem_init_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf1_vectors),
- enc_ocmem_perf1_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf2_vectors),
- enc_ocmem_perf2_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf3_vectors),
- enc_ocmem_perf3_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf4_vectors),
- enc_ocmem_perf4_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf5_vectors),
- enc_ocmem_perf5_vectors,
- },
- {
- ARRAY_SIZE(enc_ocmem_perf6_vectors),
- enc_ocmem_perf6_vectors,
- },
-};
-
-static struct msm_bus_paths dec_ocmem_perf_vectors[] = {
- {
- ARRAY_SIZE(dec_ocmem_init_vectors),
- dec_ocmem_init_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf1_vectors),
- dec_ocmem_perf1_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf2_vectors),
- dec_ocmem_perf2_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf3_vectors),
- dec_ocmem_perf3_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf4_vectors),
- dec_ocmem_perf4_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf5_vectors),
- dec_ocmem_perf5_vectors,
- },
- {
- ARRAY_SIZE(dec_ocmem_perf6_vectors),
- dec_ocmem_perf6_vectors,
- },
-};
-
-
-static struct msm_bus_scale_pdata enc_ocmem_bus_data = {
- .usecase = enc_ocmem_perf_vectors,
- .num_usecases = ARRAY_SIZE(enc_ocmem_perf_vectors),
- .name = "msm_vidc_enc_ocmem",
-};
-
-static struct msm_bus_scale_pdata dec_ocmem_bus_data = {
- .usecase = dec_ocmem_perf_vectors,
- .num_usecases = ARRAY_SIZE(dec_ocmem_perf_vectors),
- .name = "msm_vidc_dec_ocmem",
-};
-
-static struct msm_bus_vectors enc_ddr_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-
-static struct msm_bus_vectors enc_ddr_perf1_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 60000000,
- .ib = 664950000,
- },
-};
-
-static struct msm_bus_vectors enc_ddr_perf2_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 181000000,
- .ib = 664950000,
- },
-};
-
-static struct msm_bus_vectors enc_ddr_perf3_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 403000000,
- .ib = 664950000,
- },
-};
-
-static struct msm_bus_vectors enc_ddr_perf4_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 806000000,
- .ib = 1329900000,
- },
-};
-
-static struct msm_bus_vectors enc_ddr_perf5_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1289600000,
- .ib = 2127840000U,
- },
-};
-
-static struct msm_bus_vectors enc_ddr_perf6_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 161200000,
- .ib = 6400000000ULL,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf1_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 110000000,
- .ib = 909000000,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf2_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 268000000,
- .ib = 909000000,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf3_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 505000000,
- .ib = 909000000,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf4_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1010000000,
- .ib = 1818000000,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf5_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1616000000,
- .ib = 2908800000U,
- },
-};
-
-static struct msm_bus_vectors dec_ddr_perf6_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VIDEO_P0,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 2020000000U,
- .ib = 6400000000ULL,
- },
-};
-
-static struct msm_bus_paths enc_ddr_perf_vectors[] = {
- {
- ARRAY_SIZE(enc_ddr_init_vectors),
- enc_ddr_init_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf1_vectors),
- enc_ddr_perf1_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf2_vectors),
- enc_ddr_perf2_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf3_vectors),
- enc_ddr_perf3_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf4_vectors),
- enc_ddr_perf4_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf5_vectors),
- enc_ddr_perf5_vectors,
- },
- {
- ARRAY_SIZE(enc_ddr_perf6_vectors),
- enc_ddr_perf6_vectors,
- },
-};
-
-static struct msm_bus_paths dec_ddr_perf_vectors[] = {
- {
- ARRAY_SIZE(dec_ddr_init_vectors),
- dec_ddr_init_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf1_vectors),
- dec_ddr_perf1_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf2_vectors),
- dec_ddr_perf2_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf3_vectors),
- dec_ddr_perf3_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf4_vectors),
- dec_ddr_perf4_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf5_vectors),
- dec_ddr_perf5_vectors,
- },
- {
- ARRAY_SIZE(dec_ddr_perf6_vectors),
- dec_ddr_perf6_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata enc_ddr_bus_data = {
- .usecase = enc_ddr_perf_vectors,
- .num_usecases = ARRAY_SIZE(enc_ddr_perf_vectors),
- .name = "msm_vidc_enc_ddr",
-};
-
-static struct msm_bus_scale_pdata dec_ddr_bus_data = {
- .usecase = dec_ddr_perf_vectors,
- .num_usecases = ARRAY_SIZE(dec_ddr_perf_vectors),
- .name = "msm_vidc_dec_ddr",
-};
-
#define TZBSP_MEM_PROTECT_VIDEO_VAR 0x8
struct tzbsp_memprot {
u32 cp_start;
@@ -755,20 +353,19 @@
rc = -ENOMEM;
goto fail_smem_alloc;
}
- rc = msm_smem_clean_invalidate(clnt, alloc);
- if (rc) {
- dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
- goto fail_clean_cache;
- }
dprintk(VIDC_DBG, "venus_hfi_alloc:ptr=%p,size=%d",
alloc->kvaddr, size);
+ rc = msm_smem_cache_operations(clnt, alloc,
+ SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_WARN, "Failed to clean cache\n");
+ dprintk(VIDC_WARN, "This may result in undefined behavior\n");
+ }
vmem->mem_size = alloc->size;
vmem->mem_data = alloc;
vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
vmem->align_device_addr = (u8 *)alloc->device_addr;
return rc;
-fail_clean_cache:
- msm_smem_free(clnt, alloc);
fail_smem_alloc:
return rc;
}
@@ -814,6 +411,93 @@
rmb();
return rc;
}
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device,
+ enum vidc_clocks clk_level)
+{
+ int i;
+ struct venus_core_clock *cl;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ if (device->clocks_enabled == 0) {
+ dprintk(VIDC_DBG, "VCODEC clocks are already disabled");
+ goto already_disabled;
+ }
+ for (i = 0; i < clk_level; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable_unprepare(cl->clk);
+ }
+already_disabled:
+ device->clocks_enabled = 0;
+}
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device,
+ enum vidc_clocks clk_level)
+{
+ int i;
+ struct venus_core_clock *cl;
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+ if (device->clocks_enabled == 1) {
+ dprintk(VIDC_DBG, "VCODEC clocks are already enabled");
+ goto already_enabled;
+ }
+ for (i = 0; i < clk_level; i++) {
+ cl = &device->resources.clock[i];
+ rc = clk_prepare_enable(cl->clk);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable clocks\n");
+ goto fail_clk_enable;
+ } else {
+ dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
+ }
+ }
+already_enabled:
+ device->clocks_enabled = 1;
+ return rc;
+fail_clk_enable:
+ for (; i >= 0; i--) {
+ cl = &device->resources.clock[i];
+ clk_disable_unprepare(cl->clk);
+ }
+ return rc;
+}
+
+static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
+ int num_mbs_per_sec)
+{
+ int num_rows = clock->count;
+ struct load_freq_table *table = clock->load_freq_tbl;
+ unsigned long ret = table[num_rows-1].freq;
+ int i;
+ for (i = 0; i < num_rows; i++) {
+ if (num_mbs_per_sec > table[i].load)
+ break;
+ ret = table[i].freq;
+ }
+ dprintk(VIDC_PROF, "Required clock rate = %lu\n", ret);
+ return ret;
+}
+
+static int venus_hfi_scale_clocks(void *dev, int load)
+{
+ int rc = 0;
+ struct venus_hfi_device *device = dev;
+ device->load = load;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid args: %p\n", device);
+ return -EINVAL;
+ }
+ rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
+ venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
+ load));
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
+ return rc;
+}
static int venus_hfi_iface_cmdq_write(struct venus_hfi_device *device,
void *pkt)
@@ -821,7 +505,6 @@
u32 rx_req_is_set = 0;
struct vidc_iface_q_info *q_info;
int result = -EPERM;
-
if (!device || !pkt) {
dprintk(VIDC_ERR, "Invalid Params");
return -EINVAL;
@@ -833,7 +516,16 @@
dprintk(VIDC_ERR, "cannot write to shared Q's");
goto err_q_write;
}
-
+ result = venus_hfi_clk_gating_off(device, VCODEC_CLK);
+ if (result) {
+ dprintk(VIDC_ERR, "VCODEC clock enable failed\n");
+ goto err_q_write;
+ }
+ result = venus_hfi_scale_clocks(device, device->load);
+ if (result) {
+ dprintk(VIDC_ERR, "VCODEC clock scaling failed\n");
+ goto err_q_write;
+ }
if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
if (rx_req_is_set)
venus_hfi_write_register(
@@ -1218,6 +910,18 @@
return -ENOTEMPTY;
return 0;
}
+static int venus_hfi_sys_set_idle_message(struct venus_hfi_device *device,
+ int enable)
+{
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+ struct hfi_cmd_sys_set_property_packet *pkt =
+ (struct hfi_cmd_sys_set_property_packet *) &packet;
+ create_pkt_cmd_sys_idle_indicator(pkt, enable);
+ if (venus_hfi_iface_cmdq_write(device, pkt))
+ return -ENOTEMPTY;
+ return 0;
+}
+
static int venus_hfi_core_init(void *device)
{
@@ -1660,6 +1364,8 @@
goto err_session_init_fail;
if (venus_hfi_sys_set_debug(dev, msm_fw_debug))
dprintk(VIDC_ERR, "Setting fw_debug msg ON failed");
+ if (venus_hfi_sys_set_idle_message(dev, msm_fw_low_power_mode))
+ dprintk(VIDC_ERR, "Setting idle response ON failed");
return (void *) new_session;
err_session_init_fail:
@@ -2049,10 +1755,50 @@
device->callback(SYS_WATCHDOG_TIMEOUT, &cmd_done);
}
+static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
+{
+ struct hfi_queue_header *queue;
+ struct vidc_iface_q_info *q_info;
+ u32 write_ptr, read_ptr;
+ u32 rc = 0;
+ q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+ if (!q_info)
+ dprintk(VIDC_ERR, "cannot read shared Q's");
+ queue = (struct hfi_queue_header *) q_info->q_hdr;
+ if (!queue) {
+ dprintk(VIDC_ERR, "queue not present");
+ return -ENOENT;
+ }
+ write_ptr = (u32)queue->qhdr_write_idx;
+ read_ptr = (u32)queue->qhdr_read_idx;
+ rc = read_ptr - write_ptr;
+ return rc;
+}
+
+static int venus_hfi_try_clk_gating(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ u32 ctrl_status = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+ mutex_lock(&device->write_lock);
+ rc = venus_hfi_is_cmd_pending(device);
+ ctrl_status = venus_hfi_read_register(
+ device->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG0);
+ if (((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
+ != 0) && !rc)
+ venus_hfi_clk_gating_on(device, VCODEC_CLK);
+ mutex_unlock(&device->write_lock);
+ return rc;
+}
+
static void venus_hfi_response_handler(struct venus_hfi_device *device)
{
u8 packet[VIDC_IFACEQ_MED_PKT_SIZE];
-
+ u32 rc = 0;
dprintk(VIDC_INFO, "#####venus_hfi_response_handler#####\n");
if (device) {
if ((device->intr_status &
@@ -2063,9 +1809,12 @@
}
while (!venus_hfi_iface_msgq_read(device, packet)) {
- hfi_process_msg_packet(device->callback,
+ rc = hfi_process_msg_packet(device->callback,
device->device_id,
(struct vidc_hal_msg_pkt_hdr *) packet);
+ if (rc == HFI_MSG_SYS_IDLE)
+ rc = venus_hfi_try_clk_gating(device);
+
}
while (!venus_hfi_iface_dbgq_read(device, packet)) {
struct hfi_msg_sys_debug_packet *pkt =
@@ -2233,50 +1982,45 @@
for (i = 0; i < VCODEC_MAX_CLKS; i++)
clk_put(device->resources.clock[i].clk);
}
-
-static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
- int num_mbs_per_sec)
+static inline void venus_hfi_disable_clks(struct venus_hfi_device *device)
{
- int num_rows = clock->count;
- struct load_freq_table *table = clock->load_freq_tbl;
- unsigned long ret = table[num_rows-1].freq;
int i;
- for (i = 0; i < num_rows; i++) {
- if (num_mbs_per_sec > table[i].load)
- break;
- ret = table[i].freq;
- }
- dprintk(VIDC_PROF, "Required clock rate = %lu\n", ret);
- return ret;
-}
-
-static int venus_hfi_scale_clocks(void *dev, int load)
-{
- int rc = 0;
- struct venus_hfi_device *device = dev;
+ struct venus_core_clock *cl;
if (!device) {
- dprintk(VIDC_ERR, "Invalid args: %p\n", device);
- return -EINVAL;
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ if (device->clocks_enabled) {
+ cl = &device->resources.clock[VCODEC_CLK];
+ clk_disable_unprepare(cl->clk);
}
- rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
- venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
- load));
- if (rc)
- dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);
- return rc;
+ for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable_unprepare(cl->clk);
+ }
+ device->clocks_enabled = 0;
}
-
static inline int venus_hfi_enable_clks(struct venus_hfi_device *device)
{
- int i;
+ int i = 0;
struct venus_core_clock *cl;
int rc = 0;
if (!device) {
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return -EINVAL;
}
- for (i = 0; i < VCODEC_MAX_CLKS; i++) {
+ if (!device->clocks_enabled) {
+ cl = &device->resources.clock[VCODEC_CLK];
+ rc = clk_prepare_enable(cl->clk);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to enable clocks\n");
+ goto fail_clk_enable;
+ } else {
+ dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
+ }
+ }
+ for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
cl = &device->resources.clock[i];
rc = clk_prepare_enable(cl->clk);
if (rc) {
@@ -2286,6 +2030,7 @@
dprintk(VIDC_DBG, "Clock: %s enabled\n", cl->name);
}
}
+ device->clocks_enabled = 1;
return rc;
fail_clk_enable:
for (; i >= 0; i--) {
@@ -2294,21 +2039,6 @@
}
return rc;
}
-
-static inline void venus_hfi_disable_clks(struct venus_hfi_device *device)
-{
- int i;
- struct venus_core_clock *cl;
- if (!device) {
- dprintk(VIDC_ERR, "Invalid params: %p\n", device);
- return;
- }
- for (i = 0; i < VCODEC_MAX_CLKS; i++) {
- cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
- }
-}
-
static int venus_hfi_register_iommu_domains(struct venus_hfi_device *device,
struct msm_vidc_platform_resources *res)
{
@@ -2403,31 +2133,31 @@
{
struct venus_bus_info *bus_info;
int rc = 0;
- if (!device)
+ if ((!device) || (!device->res->bus_pdata))
return -EINVAL;
bus_info = &device->resources.bus_info;
bus_info->ddr_handle[MSM_VIDC_ENCODER] =
- msm_bus_scale_register_client(&enc_ddr_bus_data);
+ msm_bus_scale_register_client(&device->res->bus_pdata[2]);
if (!bus_info->ddr_handle[MSM_VIDC_ENCODER]) {
dprintk(VIDC_ERR, "Failed to register bus scale client\n");
goto err_init_bus;
}
bus_info->ddr_handle[MSM_VIDC_DECODER] =
- msm_bus_scale_register_client(&dec_ddr_bus_data);
+ msm_bus_scale_register_client(&device->res->bus_pdata[3]);
if (!bus_info->ddr_handle[MSM_VIDC_DECODER]) {
dprintk(VIDC_ERR, "Failed to register bus scale client\n");
goto err_init_bus;
}
bus_info->ocmem_handle[MSM_VIDC_ENCODER] =
- msm_bus_scale_register_client(&enc_ocmem_bus_data);
+ msm_bus_scale_register_client(&device->res->bus_pdata[0]);
if (!bus_info->ocmem_handle[MSM_VIDC_ENCODER]) {
dprintk(VIDC_ERR, "Failed to register bus scale client\n");
goto err_init_bus;
}
bus_info->ocmem_handle[MSM_VIDC_DECODER] =
- msm_bus_scale_register_client(&dec_ocmem_bus_data);
+ msm_bus_scale_register_client(&device->res->bus_pdata[1]);
if (!bus_info->ocmem_handle[MSM_VIDC_DECODER]) {
dprintk(VIDC_ERR, "Failed to register bus scale client\n");
goto err_init_bus;
@@ -2553,17 +2283,25 @@
struct vidc_resource_hdr rhdr;
struct venus_hfi_device *device = dev;
int rc = 0;
- if (!device || !device->resources.ocmem.buf) {
+ if (!device) {
dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
__func__, device);
- return -EINVAL;
+ rc = -EINVAL;
+ goto ocmem_unset_failed;
}
+ if (!device->resources.ocmem.buf) {
+ dprintk(VIDC_INFO, "%s Trying to free OCMEM which is not set",
+ __func__);
+ rc = -EINVAL;
+ goto ocmem_unset_failed;
+ }
+
rhdr.resource_id = VIDC_RESOURCE_OCMEM;
rhdr.resource_handle = (u32) &device->resources.ocmem;
rc = venus_hfi_core_release_resource(device, &rhdr);
if (rc)
- dprintk(VIDC_ERR, "Failed to set OCMEM on driver\n");
-
+ dprintk(VIDC_ERR, "Failed to unset OCMEM on driver\n");
+ocmem_unset_failed:
return rc;
}
@@ -2862,6 +2600,12 @@
return -EINVAL;
}
+ rc = venus_hfi_iommu_attach(device);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to attach iommu");
+ goto fail_iommu_attach;
+ }
+
if (!device->resources.fw.cookie)
device->resources.fw.cookie = subsystem_get("venus");
@@ -2881,21 +2625,18 @@
rc = protect_cp_mem(device);
if (rc) {
dprintk(VIDC_ERR, "Failed to protect memory\n");
- goto fail_iommu_attach;
+ goto fail_protect_mem;
}
- rc = venus_hfi_iommu_attach(device);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to attach iommu");
- goto fail_iommu_attach;
- }
return rc;
-fail_iommu_attach:
+fail_protect_mem:
venus_hfi_disable_clks(device);
fail_enable_clks:
subsystem_put(device->resources.fw.cookie);
device->resources.fw.cookie = NULL;
fail_load_fw:
+ venus_hfi_iommu_detach(device);
+fail_iommu_attach:
return rc;
}
@@ -2908,9 +2649,9 @@
return;
}
if (device->resources.fw.cookie) {
- venus_hfi_iommu_detach(device);
venus_hfi_disable_clks(device);
subsystem_put(device->resources.fw.cookie);
+ venus_hfi_iommu_detach(device);
device->resources.fw.cookie = NULL;
}
}
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 58314dd..2ffb9d4 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -175,6 +175,8 @@
struct list_head sess_head;
u32 intr_status;
u32 device_id;
+ u32 load;
+ u32 clocks_enabled;
struct mutex read_lock;
struct mutex write_lock;
msm_vidc_callback callback;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index f565d3b..75594b3 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -830,7 +830,7 @@
extern struct hal_device_data hal_ctxt;
-void hfi_process_msg_packet(msm_vidc_callback callback,
+u32 hfi_process_msg_packet(msm_vidc_callback callback,
u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr);
#endif
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index 2bc8e6a..eeffe35 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.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
@@ -49,6 +49,7 @@
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT 0x1
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK 0x1
#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT 0x0
+#define VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK 0x40000000
/* HFI_QTBL_INFO */
#define VIDC_CPU_CS_SCIACMDARG1 (VIDC_CPU_CS_BASE_OFFS + 0x50)
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 4ea7013..6c60e04 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -59,12 +59,12 @@
};
static char *taiko_supplies[] = {
- "cdc-vdd-buck", "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
+ WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
"cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
};
static char *tapan_supplies[] = {
- "cdc-vdd-buck", "cdc-vdd-h", "cdc-vdd-px",
+ WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-h", "cdc-vdd-px",
"cdc-vdd-a-1p2v", "cdc-vdd-cx"
};
diff --git a/drivers/misc/smsc_hub.c b/drivers/misc/smsc_hub.c
index 2ffe4ca..bc338a4 100644
--- a/drivers/misc/smsc_hub.c
+++ b/drivers/misc/smsc_hub.c
@@ -491,9 +491,7 @@
{
int ret = 0;
- if (!IS_ERR(smsc_hub->ref_clk)) {
- clk_disable_unprepare(smsc_hub->ref_clk);
- } else {
+ if (smsc_hub->xo_handle) {
ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_OFF);
if (ret) {
pr_err("%s: failed to devote for TCXO\n"
@@ -507,9 +505,7 @@
{
int ret = 0;
- if (!IS_ERR(smsc_hub->ref_clk)) {
- clk_prepare_enable(smsc_hub->ref_clk);
- } else {
+ if (smsc_hub->xo_handle) {
ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_ON);
if (ret) {
pr_err("%s: failed to vote for TCXO\n"
diff --git a/drivers/power/battery_current_limit.c b/drivers/power/battery_current_limit.c
index d1750ec..ecda153 100644
--- a/drivers/power/battery_current_limit.c
+++ b/drivers/power/battery_current_limit.c
@@ -507,12 +507,18 @@
return 0;
}
+static struct of_device_id bcl_match_table[] = {
+ {.compatible = "qcom,bcl"},
+ {},
+};
+
static struct platform_driver bcl_driver = {
.probe = bcl_probe,
.remove = __devexit_p(bcl_remove),
.driver = {
.name = BCL_DEV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = bcl_match_table,
},
};
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 82d58ef..13e23e8 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -136,6 +136,7 @@
int amux_2_trim_delta;
uint16_t prev_last_good_ocv_raw;
int rconn_mohm;
+ int rbatt_capacitive_mohm;
struct mutex last_ocv_uv_mutex;
int last_ocv_uv;
int last_ocv_temp_decidegc;
@@ -847,8 +848,8 @@
{
int ibat_ua, vbat_uv, ocv_est_uv;
int rc;
-
- int rbatt_mohm = chip->default_rbatt_mohm + chip->rconn_mohm;
+ int rbatt_mohm = chip->default_rbatt_mohm + chip->rconn_mohm
+ + chip->rbatt_capacitive_mohm;
rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
&ibat_ua,
@@ -917,7 +918,10 @@
rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
&ibat_ua,
&vbat_uv);
-
+ /*
+ * don't include rbatt and rbatt_capacitve since we expect this to
+ * be used with a fake battery which does not have internal resistnaces
+ */
ocv_est_uv = vbat_uv + (ibat_ua * the_chip->rconn_mohm) / 1000;
pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
the_chip->last_ocv_uv = ocv_est_uv;
@@ -1072,6 +1076,10 @@
pr_debug("adding rconn_mohm = %d rbatt = %d\n",
the_chip->rconn_mohm, rbatt);
+ rbatt += the_chip->rbatt_capacitive_mohm;
+ pr_debug("adding rbatt_capacitive_mohm = %d rbatt = %d\n",
+ the_chip->rbatt_capacitive_mohm, rbatt);
+
if (is_between(20, 10, soc_rbatt))
rbatt = rbatt
+ ((20 - soc_rbatt) * chip->delta_rbatt_mohm) / 10;
@@ -1583,6 +1591,8 @@
}
EXPORT_SYMBOL(pm8921_bms_get_simultaneous_battery_voltage_and_current);
+#define SIGN(x) ((x) < 0 ? -1 : 1)
+
static void find_ocv_for_soc(struct pm8921_bms_chip *chip,
int batt_temp,
int chargecycles,
@@ -1597,7 +1607,6 @@
int pc, new_pc;
int batt_temp_degc = batt_temp / 10;
int ocv;
- int count = 0;
rc = (s64)shutdown_soc * (fcc_uah - uuc_uah);
rc = div_s64(rc, 100) + cc_uah + uuc_uah;
@@ -1611,17 +1620,55 @@
new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv);
pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
- /* try 10 times to get a close enough pc */
- while (abs(new_pc - pc) > 1 && count++ < 10) {
+ if (abs(new_pc - pc) > 0) {
+ /* Maximum spins to make in while-loop when searching in
+ * full resolution.
+ */
+ const unsigned int max_spin_count =
+ chip->max_voltage_uv / 1000 - chip->v_cutoff + 1;
+ unsigned int count = 0;
int delta_mv = 5;
+ int diff = abs(new_pc - pc);
+ char sign = SIGN(new_pc - pc);
+ char old_sign;
+ int old_diff;
+ int old_ocv;
- if (new_pc > pc)
- delta_mv = -1 * delta_mv;
+ do {
+ count++;
+ old_ocv = ocv;
+ old_diff = diff;
+ old_sign = sign;
- ocv = ocv + delta_mv;
- new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
- batt_temp_degc, ocv);
- pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
+ if (new_pc > pc)
+ ocv -= delta_mv;
+ else
+ ocv += delta_mv;
+
+ new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
+ batt_temp_degc, ocv);
+ pr_debug("test revlookup pc = %d for ocv = %d\n",
+ new_pc, ocv);
+ diff = abs(new_pc - pc);
+ sign = SIGN(new_pc - pc);
+
+ if (sign != old_sign) {
+ if (delta_mv == 5) {
+ /*
+ * we crossed our desired PC probably
+ * becuase we were overcorrecting
+ */
+ delta_mv = 1;
+ } else {
+ /* we crossed our desired PC even with
+ * 1mV steps, choose the best of two */
+ if (diff > old_diff)
+ ocv = old_ocv;
+
+ break;
+ }
+ }
+ } while (count <= max_spin_count && diff > 0);
}
*ocv_uv = ocv * 1000;
@@ -2869,6 +2916,8 @@
chip->default_rbatt_mohm
= palladium_1500_data.default_rbatt_mohm;
chip->delta_rbatt_mohm = palladium_1500_data.delta_rbatt_mohm;
+ chip->rbatt_capacitive_mohm
+ = palladium_1500_data.rbatt_capacitive_mohm;
return 0;
desay:
chip->fcc = desay_5200_data.fcc;
@@ -2878,6 +2927,8 @@
chip->rbatt_sf_lut = desay_5200_data.rbatt_sf_lut;
chip->default_rbatt_mohm = desay_5200_data.default_rbatt_mohm;
chip->delta_rbatt_mohm = desay_5200_data.delta_rbatt_mohm;
+ chip->rbatt_capacitive_mohm
+ = desay_5200_data.rbatt_capacitive_mohm;
return 0;
}
@@ -3008,9 +3059,9 @@
int ret = 0;
struct pm8921_soc_params raw;
- mutex_lock(&the_chip->bms_output_lock);
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
read_soc_params_raw(the_chip, &raw, 300);
- mutex_unlock(&the_chip->bms_output_lock);
+ mutex_lock(&the_chip->last_ocv_uv_mutex);
*val = 0;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3eaf262..e2ba042 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -70,7 +70,7 @@
#define CHGR_CHG_WDOG_PET 0x64
#define CHGR_CHG_WDOG_EN 0x65
#define CHGR_IR_DROP_COMPEN 0x67
-#define CHGR_USB_IUSB_MAX 0x44
+#define CHGR_I_MAX_REG 0x44
#define CHGR_USB_USB_SUSP 0x47
#define CHGR_USB_USB_OTG_CTL 0x48
#define CHGR_USB_ENUM_T_STOP 0x4E
@@ -172,6 +172,8 @@
* @resume_voltage_mv: voltage at which the battery resumes charging
* @term_current: the charging based term current
* @safe_current: battery safety current setting
+ * @maxinput_usb_ma: Maximum Input current USB
+ * @maxinput_dc_ma: Maximum Input current DC
* @revision: PMIC revision
* @thermal_levels amount of thermal mitigation levels
* @thermal_mitigation thermal mitigation level values
@@ -210,6 +212,8 @@
unsigned int min_voltage_mv;
unsigned int resume_voltage_mv;
unsigned int term_current;
+ unsigned int maxinput_usb_ma;
+ unsigned int maxinput_dc_ma;
unsigned int safe_current;
unsigned int revision;
unsigned int thermal_levels;
@@ -348,36 +352,73 @@
return (dcin_valid_rt_sts & DCIN_VALID_IRQ) ? 1 : 0;
}
-#define QPNP_CHG_IUSB_MAX_MIN_100 100
-#define QPNP_CHG_IUSB_MAX_MIN_150 150
-#define QPNP_CHG_IUSB_MAX_MIN_MA 200
-#define QPNP_CHG_IUSB_MAX_MAX_MA 2500
-#define QPNP_CHG_IUSB_MAX_STEP_MA 100
+#define QPNP_CHG_I_MAX_MIN_100 100
+#define QPNP_CHG_I_MAX_MIN_150 150
+#define QPNP_CHG_I_MAX_MIN_MA 200
+#define QPNP_CHG_I_MAX_MAX_MA 2500
+#define QPNP_CHG_I_MAXSTEP_MA 100
+static int
+qpnp_chg_idcmax_set(struct qpnp_chg_chip *chip, int mA)
+{
+ int rc = 0;
+ u8 dc = 0;
+
+ if (mA < QPNP_CHG_I_MAX_MIN_100
+ || mA > QPNP_CHG_I_MAX_MAX_MA) {
+ pr_err("bad mA=%d asked to set\n", mA);
+ return -EINVAL;
+ }
+
+ if (mA == QPNP_CHG_I_MAX_MIN_100) {
+ dc = 0x00;
+ pr_debug("current=%d setting %02x\n", mA, dc);
+ return qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+ } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
+ dc = 0x01;
+ pr_debug("current=%d setting %02x\n", mA, dc);
+ return qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+ }
+
+ dc = mA / QPNP_CHG_I_MAXSTEP_MA;
+
+ pr_debug("current=%d setting 0x%x\n", mA, dc);
+ rc = qpnp_chg_write(chip, &dc,
+ chip->dc_chgpth_base + CHGR_I_MAX_REG, 1);
+
+ return rc;
+}
+
static int
qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
{
int rc = 0;
u8 usb_reg = 0, temp = 8;
- if (mA == QPNP_CHG_IUSB_MAX_MIN_100) {
- usb_reg = 0x00;
- pr_debug("current=%d setting %02x\n", mA, usb_reg);
- return qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
- } else if (mA == QPNP_CHG_IUSB_MAX_MIN_150) {
- usb_reg = 0x01;
- pr_debug("current=%d setting %02x\n", mA, usb_reg);
- return qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
- }
-
- if (mA < QPNP_CHG_IUSB_MAX_MIN_MA
- || mA > QPNP_CHG_IUSB_MAX_MAX_MA) {
+ if (mA < QPNP_CHG_I_MAX_MIN_100
+ || mA > QPNP_CHG_I_MAX_MAX_MA) {
pr_err("bad mA=%d asked to set\n", mA);
return -EINVAL;
}
- usb_reg = mA / QPNP_CHG_IUSB_MAX_STEP_MA;
+ if (mA == QPNP_CHG_I_MAX_MIN_100) {
+ usb_reg = 0x00;
+ pr_debug("current=%d setting %02x\n", mA, usb_reg);
+ return qpnp_chg_write(chip, &usb_reg,
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+ } else if (mA == QPNP_CHG_I_MAX_MIN_150) {
+ usb_reg = 0x01;
+ pr_debug("current=%d setting %02x\n", mA, usb_reg);
+ return qpnp_chg_write(chip, &usb_reg,
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
+ }
+
+ /* Impose input current limit */
+ if (chip->maxinput_usb_ma)
+ mA = (chip->maxinput_usb_ma) <= mA ? chip->maxinput_usb_ma : mA;
+
+ usb_reg = mA / QPNP_CHG_I_MAXSTEP_MA;
if (chip->flags & CHG_FLAGS_VCP_WA) {
temp = 0xA5;
@@ -390,7 +431,7 @@
pr_debug("current=%d setting 0x%x\n", mA, usb_reg);
rc = qpnp_chg_write(chip, &usb_reg,
- chip->usb_chgpth_base + CHGR_USB_IUSB_MAX, 1);
+ chip->usb_chgpth_base + CHGR_I_MAX_REG, 1);
if (chip->flags & CHG_FLAGS_VCP_WA) {
temp = 0xA5;
@@ -875,12 +916,12 @@
chip->usb_psy->get_property(chip->usb_psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
- if ((ret.intval / 1000) <= QPNP_CHG_IUSB_MAX_MIN_MA)
+ if ((ret.intval / 1000) <= QPNP_CHG_I_MAX_MIN_MA)
qpnp_chg_usb_suspend_enable(chip, 1);
else
qpnp_chg_usb_suspend_enable(chip, 0);
} else {
- qpnp_chg_iusbmax_set(chip, QPNP_CHG_IUSB_MAX_MIN_100);
+ qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
qpnp_chg_usb_suspend_enable(chip, 0);
}
@@ -1429,6 +1470,33 @@
goto fail_chg_enable;
}
+ /* Get the ibatsafe property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-vbatdet-mv",
+ &chip->resume_voltage_mv);
+ if (rc) {
+ pr_err("Error reading vbatdet property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the maxinput-dc-ma property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-maxinput-dc-ma",
+ &chip->maxinput_dc_ma);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading maxinput-dc-ma property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
+ /* Get the maxinput-usb-ma property */
+ rc = of_property_read_u32(spmi->dev.of_node,
+ "qcom,chg-maxinput-usb-ma",
+ &chip->maxinput_usb_ma);
+ if (rc && rc != -EINVAL) {
+ pr_err("Error reading maxinput-usb-ma property %d\n", rc);
+ goto fail_chg_enable;
+ }
+
/* Get the charging-disabled property */
chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
"qcom,chg-charging-disabled");
@@ -1596,6 +1664,14 @@
power_supply_set_present(chip->usb_psy,
qpnp_chg_is_usb_chg_plugged_in(chip));
+ if (chip->maxinput_dc_ma) {
+ rc = qpnp_chg_idcmax_set(chip, chip->maxinput_dc_ma);
+ if (rc) {
+ pr_err("Error setting idcmax property %d\n", rc);
+ goto fail_chg_enable;
+ }
+ }
+
qpnp_chg_charge_en(chip, !chip->charging_disabled);
qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 6135e71..7f60128 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2375,7 +2375,7 @@
of_property_read_u32(node, "spi-max-frequency",
&pdata->max_clock_speed);
- of_property_read_u32(node, "infinite_mode",
+ of_property_read_u32(node, "qcom,infinite-mode",
&pdata->infinite_mode);
pdata->ver_reg_exists = of_property_read_bool(node
@@ -2485,13 +2485,12 @@
goto err_probe_exit;
}
- rc = of_property_read_u32(pdev->dev.of_node,
- "cell-index", &pdev->id);
- if (rc)
+ rc = of_alias_get_id(pdev->dev.of_node, "spi");
+ if (rc < 0)
dev_warn(&pdev->dev,
"using default bus_num %d\n", pdev->id);
else
- master->bus_num = pdev->id;
+ master->bus_num = pdev->id = rc;
for (i = 0; i < ARRAY_SIZE(spi_rsrcs); ++i) {
dd->spi_gpios[i] = of_get_gpio_flags(pdev->dev.of_node,
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 0e3daeb..5aca48d 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.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
@@ -81,7 +81,7 @@
{
static int limit_init;
struct tsens_device tsens_dev;
- unsigned long temp = 0;
+ long temp = 0;
uint32_t max_freq = limited_max_freq;
int cpu = 0;
int ret = 0;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 0011a1a..beba33f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -165,6 +165,7 @@
struct clk *iface_clk;
struct clk *sleep_clk;
struct clk *hsphy_sleep_clk;
+ struct clk *utmi_clk;
struct regulator *hsusb_3p3;
struct regulator *hsusb_1p8;
struct regulator *hsusb_vddcx;
@@ -1636,9 +1637,12 @@
clk_disable_unprepare(mdwc->core_clk);
clk_disable_unprepare(mdwc->iface_clk);
- /* USB PHY no more requires TCXO */
- if (!host_bus_suspend)
+ if (!host_bus_suspend) {
+ clk_disable_unprepare(mdwc->utmi_clk);
+
+ /* USB PHY no more requires TCXO */
clk_disable_unprepare(mdwc->xo_clk);
+ }
if (mdwc->bus_perf_client) {
ret = msm_bus_scale_client_update_request(
@@ -1705,8 +1709,12 @@
dwc3_ssusb_ldo_enable(1);
dwc3_ssusb_config_vddcx(1);
- if (!host_bus_suspend)
+
+ if (!host_bus_suspend) {
dwc3_hsusb_config_vddcx(1);
+ clk_prepare_enable(mdwc->utmi_clk);
+ }
+
clk_prepare_enable(mdwc->ref_clk);
usleep_range(1000, 1200);
@@ -2235,15 +2243,22 @@
}
clk_prepare_enable(msm->hsphy_sleep_clk);
+ msm->utmi_clk = devm_clk_get(&pdev->dev, "utmi_clk");
+ if (IS_ERR(msm->utmi_clk)) {
+ dev_err(&pdev->dev, "failed to get utmi_clk\n");
+ ret = PTR_ERR(msm->utmi_clk);
+ goto disable_sleep_a_clk;
+ }
+ clk_prepare_enable(msm->utmi_clk);
+
msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
if (IS_ERR(msm->ref_clk)) {
dev_err(&pdev->dev, "failed to get ref_clk\n");
ret = PTR_ERR(msm->ref_clk);
- goto disable_sleep_a_clk;
+ goto disable_utmi_clk;
}
clk_prepare_enable(msm->ref_clk);
-
of_get_property(node, "qcom,vdd-voltage-level", &len);
if (len == sizeof(tmp)) {
of_property_read_u32_array(node, "qcom,vdd-voltage-level",
@@ -2526,6 +2541,8 @@
dwc3_ssusb_config_vddcx(0);
disable_ref_clk:
clk_disable_unprepare(msm->ref_clk);
+disable_utmi_clk:
+ clk_disable_unprepare(msm->utmi_clk);
disable_sleep_a_clk:
clk_disable_unprepare(msm->hsphy_sleep_clk);
disable_sleep_clk:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2db9eea..0664376 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1205,7 +1205,10 @@
int ret;
+ spin_lock_irqsave(&dwc->lock, flags);
+
if (!dep->endpoint.desc) {
+ spin_unlock_irqrestore(&dwc->lock, flags);
dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
request, ep->name);
return -ESHUTDOWN;
@@ -1217,7 +1220,6 @@
WARN(!dep->direction && (request->length % ep->desc->wMaxPacketSize),
"trying to queue unaligned request (%d)\n", request->length);
- spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_queue(dep, req);
spin_unlock_irqrestore(&dwc->lock, flags);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 6df0c96..76d75ea 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -60,6 +60,7 @@
#include "u_smd.c"
#include "u_bam.c"
#include "u_rmnet_ctrl_smd.c"
+#include "u_rmnet_ctrl_qti.c"
#include "u_ctrl_hsic.c"
#include "u_data_hsic.c"
#include "u_ctrl_hsuart.c"
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index daa981f..d69e850 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.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
@@ -66,6 +66,7 @@
NCM_NOTIFY_NONE,
NCM_NOTIFY_CONNECT,
NCM_NOTIFY_SPEED,
+ NCM_NOTIFY_RESPONSE_AVAILABLE,
};
struct f_mbim {
@@ -223,6 +224,16 @@
.bmNetworkCapabilities = 0x20,
};
+static struct usb_cdc_ext_mbb_desc ext_mbb_desc = {
+ .bLength = sizeof ext_mbb_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_EXT_MBB_TYPE,
+
+ .bcdMbbExtendedVersion = cpu_to_le16(0x0100),
+ .bMaxOutstandingCmdMsges = 64,
+ .wMTU = 1500,
+};
+
/* the default data interface has no endpoints ... */
static struct usb_interface_descriptor mbim_data_nop_intf = {
.bLength = sizeof mbim_data_nop_intf,
@@ -285,6 +296,7 @@
(struct usb_descriptor_header *) &mbim_control_intf,
(struct usb_descriptor_header *) &mbim_header_desc,
(struct usb_descriptor_header *) &mbb_desc,
+ (struct usb_descriptor_header *) &ext_mbb_desc,
(struct usb_descriptor_header *) &fs_mbim_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &mbim_data_nop_intf,
@@ -329,6 +341,7 @@
(struct usb_descriptor_header *) &mbim_control_intf,
(struct usb_descriptor_header *) &mbim_header_desc,
(struct usb_descriptor_header *) &mbb_desc,
+ (struct usb_descriptor_header *) &ext_mbb_desc,
(struct usb_descriptor_header *) &hs_mbim_notify_desc,
/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &mbim_data_nop_intf,
@@ -571,6 +584,7 @@
return;
}
+ req->length = sizeof *event;
event = req->buf;
event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
| USB_RECIP_INTERFACE;
@@ -581,7 +595,7 @@
spin_unlock_irqrestore(&dev->lock, flags);
ret = usb_ep_queue(dev->not_port.notify,
- dev->not_port.notify_req, GFP_ATOMIC);
+ req, GFP_ATOMIC);
if (ret) {
atomic_dec(&dev->not_port.notify_count);
pr_err("ep enqueue error %d\n", ret);
@@ -610,6 +624,13 @@
return 0;
}
+ if (dev->not_port.notify_state != NCM_NOTIFY_RESPONSE_AVAILABLE) {
+ pr_err("dev:%p state=%d, recover!!\n", dev,
+ dev->not_port.notify_state);
+ mbim_free_ctrl_pkt(cpkt);
+ return 0;
+ }
+
spin_lock_irqsave(&dev->lock, flags);
list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
spin_unlock_irqrestore(&dev->lock, flags);
@@ -750,10 +771,18 @@
switch (mbim->not_port.notify_state) {
case NCM_NOTIFY_NONE:
+ if (atomic_read(&mbim->not_port.notify_count) > 0)
+ pr_err("Pending notifications in NCM_NOTIFY_NONE\n");
+ else
+ pr_debug("No pending notifications\n");
+
+ return;
+
+ case NCM_NOTIFY_RESPONSE_AVAILABLE:
pr_debug("Notification %02x sent\n", event->bNotificationType);
if (atomic_read(&mbim->not_port.notify_count) <= 0) {
- pr_debug("notify_none: done");
+ pr_debug("notify_response_avaliable: done");
return;
}
@@ -778,7 +807,7 @@
pr_info("notify connect %s\n",
mbim->is_open ? "true" : "false");
- mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+ mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
break;
case NCM_NOTIFY_SPEED:
@@ -830,7 +859,7 @@
*/
pr_debug("dev:%p\n", mbim);
- mbim->not_port.notify_state = NCM_NOTIFY_SPEED;
+ mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
mbim_do_notify(mbim);
}
@@ -1365,6 +1394,8 @@
pr_info("SET DEVICE OFFLINE");
atomic_set(&mbim->online, 0);
+ mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+
mbim_clear_queues(mbim);
mbim_reset_function_queue(mbim);
@@ -1674,7 +1705,7 @@
}
while (list_empty(&dev->cpkt_req_q)) {
- pr_err("Requests list is empty. Wait.\n");
+ pr_debug("Requests list is empty. Wait.\n");
ret = wait_event_interruptible(dev->read_wq,
!list_empty(&dev->cpkt_req_q));
if (ret < 0) {
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index e6613e8..0d8fa0f 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -55,6 +55,7 @@
#define NR_RMNET_PORTS 3
static unsigned int nr_rmnet_ports;
static unsigned int no_ctrl_smd_ports;
+static unsigned int no_ctrl_qti_ports;
static unsigned int no_ctrl_hsic_ports;
static unsigned int no_ctrl_hsuart_ports;
static unsigned int no_data_bam_ports;
@@ -402,6 +403,14 @@
return ret;
}
break;
+ case USB_GADGET_XPORT_QTI:
+ ret = gqti_ctrl_connect(&dev->port);
+ if (ret) {
+ pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
+ __func__, ret);
+ return ret;
+ }
+ break;
case USB_GADGET_XPORT_HSIC:
ret = ghsic_ctrl_connect(&dev->port, port_num);
if (ret) {
@@ -436,7 +445,10 @@
if (ret) {
pr_err("%s: gbam_connect failed: err:%d\n",
__func__, ret);
- gsmd_ctrl_disconnect(&dev->port, port_num);
+ if (cxport == USB_GADGET_XPORT_QTI)
+ gqti_ctrl_disconnect(&dev->port);
+ else
+ gsmd_ctrl_disconnect(&dev->port, port_num);
return ret;
}
break;
@@ -484,6 +496,9 @@
case USB_GADGET_XPORT_SMD:
gsmd_ctrl_disconnect(&dev->port, port_num);
break;
+ case USB_GADGET_XPORT_QTI:
+ gqti_ctrl_disconnect(&dev->port);
+ break;
case USB_GADGET_XPORT_HSIC:
ghsic_ctrl_disconnect(&dev->port, port_num);
break;
@@ -1170,6 +1185,7 @@
nr_rmnet_ports = 0;
no_ctrl_smd_ports = 0;
+ no_ctrl_qti_ports = 0;
no_data_bam_ports = 0;
no_data_bam2bam_ports = 0;
no_ctrl_hsic_ports = 0;
@@ -1215,6 +1231,10 @@
rmnet_port->ctrl_xport_num = no_ctrl_smd_ports;
no_ctrl_smd_ports++;
break;
+ case USB_GADGET_XPORT_QTI:
+ rmnet_port->ctrl_xport_num = no_ctrl_qti_ports;
+ no_ctrl_qti_ports++;
+ break;
case USB_GADGET_XPORT_HSIC:
rmnet_port->ctrl_xport_num = no_ctrl_hsic_ports;
no_ctrl_hsic_ports++;
@@ -1268,6 +1288,7 @@
nr_rmnet_ports = 0;
no_ctrl_smd_ports = 0;
+ no_ctrl_qti_ports = 0;
no_data_bam_ports = 0;
no_ctrl_hsic_ports = 0;
no_data_hsic_ports = 0;
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index 81ba223..cea9369 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -55,5 +55,7 @@
int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num);
int gsmd_ctrl_setup(unsigned int count);
+int gqti_ctrl_connect(struct grmnet *gr);
+void gqti_ctrl_disconnect(struct grmnet *gr);
#endif /* __U_RMNET_H*/
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_qti.c b/drivers/usb/gadget/u_rmnet_ctrl_qti.c
new file mode 100644
index 0000000..e92978f
--- /dev/null
+++ b/drivers/usb/gadget/u_rmnet_ctrl_qti.c
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/usb/rmnet_ctrl_qti.h>
+
+#include "u_rmnet.h"
+
+struct rmnet_ctrl_qti_port {
+ struct grmnet *port_usb;
+
+ bool is_open;
+
+ atomic_t connected;
+ atomic_t line_state;
+
+ atomic_t open_excl;
+ atomic_t read_excl;
+ atomic_t write_excl;
+ atomic_t ioctl_excl;
+
+ wait_queue_head_t read_wq;
+
+ struct list_head cpkt_req_q;
+
+ spinlock_t lock;
+};
+static struct rmnet_ctrl_qti_port *ctrl_port;
+
+static inline int rmnet_ctrl_lock(atomic_t *excl)
+{
+ if (atomic_inc_return(excl) == 1) {
+ return 0;
+ } else {
+ atomic_dec(excl);
+ return -EBUSY;
+ }
+}
+
+static inline void rmnet_ctrl_unlock(atomic_t *excl)
+{
+ atomic_dec(excl);
+}
+
+static void rmnet_ctrl_queue_notify(struct rmnet_ctrl_qti_port *port)
+{
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt = NULL;
+
+ pr_debug("%s: Queue empty packet for QTI", __func__);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (!port->is_open) {
+ pr_err("%s: rmnet ctrl file handler %p is not open",
+ __func__, port);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return;
+ }
+
+ cpkt = alloc_rmnet_ctrl_pkt(0, GFP_ATOMIC);
+ if (!cpkt) {
+ pr_err("%s: Unable to allocate reset function pkt\n", __func__);
+ spin_unlock_irqrestore(&port->lock, flags);
+ return;
+ }
+
+ list_add_tail(&cpkt->list, &port->cpkt_req_q);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ pr_debug("%s: Wake up read queue", __func__);
+ wake_up(&port->read_wq);
+}
+
+static int grmnet_ctrl_qti_send_cpkt_tomodem(u8 portno,
+ void *buf, size_t len)
+{
+ unsigned long flags;
+ struct rmnet_ctrl_qti_port *port = ctrl_port;
+ struct rmnet_ctrl_pkt *cpkt;
+
+ if (len > MAX_QTI_PKT_SIZE) {
+ pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
+ len, MAX_QTI_PKT_SIZE);
+ return -EINVAL;
+ }
+
+ cpkt = alloc_rmnet_ctrl_pkt(len, GFP_ATOMIC);
+ if (IS_ERR(cpkt)) {
+ pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(cpkt->buf, buf, len);
+ cpkt->len = len;
+
+ pr_debug("%s: Add to cpkt_req_q packet with len = %d\n", __func__, len);
+ spin_lock_irqsave(&port->lock, flags);
+
+ /* drop cpkt if port is not open */
+ if (!port->is_open) {
+ pr_err("rmnet file handler %p is not open", port);
+ spin_unlock_irqrestore(&port->lock, flags);
+ free_rmnet_ctrl_pkt(cpkt);
+ return 0;
+ }
+
+ list_add_tail(&cpkt->list, &port->cpkt_req_q);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* wakeup read thread */
+ pr_debug("%s: Wake up read queue", __func__);
+ wake_up(&port->read_wq);
+
+ return 0;
+}
+
+static void
+gqti_ctrl_notify_modem(void *gptr, u8 portno, int val)
+{
+ struct rmnet_ctrl_qti_port *port = ctrl_port;
+
+ atomic_set(&port->line_state, val);
+
+ /* send 0 len pkt to qti to notify state change */
+ rmnet_ctrl_queue_notify(port);
+}
+
+int gqti_ctrl_connect(struct grmnet *gr)
+{
+ struct rmnet_ctrl_qti_port *port;
+ unsigned long flags;
+
+ pr_debug("%s: grmnet:%p\n", __func__, gr);
+
+ if (!gr) {
+ pr_err("%s: grmnet port is null\n", __func__);
+ return -ENODEV;
+ }
+
+ port = ctrl_port;
+
+ spin_lock_irqsave(&port->lock, flags);
+ port->port_usb = gr;
+ gr->send_encap_cmd = grmnet_ctrl_qti_send_cpkt_tomodem;
+ gr->notify_modem = gqti_ctrl_notify_modem;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ atomic_set(&port->connected, 1);
+ wake_up(&port->read_wq);
+
+ if (port && port->port_usb && port->port_usb->connect)
+ port->port_usb->connect(port->port_usb);
+
+ return 0;
+}
+
+void gqti_ctrl_disconnect(struct grmnet *gr)
+{
+ struct rmnet_ctrl_qti_port *port = ctrl_port;
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt;
+
+ pr_debug("%s: grmnet:%p\n", __func__, gr);
+
+ if (!gr) {
+ pr_err("%s: grmnet port is null\n", __func__);
+ return;
+ }
+
+ if (port && port->port_usb && port->port_usb->disconnect)
+ port->port_usb->disconnect(port->port_usb);
+
+ atomic_set(&port->connected, 0);
+ atomic_set(&port->line_state, 0);
+ spin_lock_irqsave(&port->lock, flags);
+ port->port_usb = 0;
+ gr->send_encap_cmd = 0;
+ gr->notify_modem = 0;
+
+ while (!list_empty(&port->cpkt_req_q)) {
+ cpkt = list_first_entry(&port->cpkt_req_q,
+ struct rmnet_ctrl_pkt, list);
+
+ list_del(&cpkt->list);
+ free_rmnet_ctrl_pkt(cpkt);
+ }
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /* send 0 len pkt to qti to notify state change */
+ rmnet_ctrl_queue_notify(port);
+}
+
+static int rmnet_ctrl_open(struct inode *ip, struct file *fp)
+{
+ unsigned long flags;
+
+ pr_debug("Open rmnet_ctrl_qti device file\n");
+
+ if (rmnet_ctrl_lock(&ctrl_port->open_excl)) {
+ pr_debug("Already opened\n");
+ return -EBUSY;
+ }
+
+ fp->private_data = ctrl_port;
+
+ spin_lock_irqsave(&ctrl_port->lock, flags);
+ ctrl_port->is_open = true;
+ spin_unlock_irqrestore(&ctrl_port->lock, flags);
+
+ return 0;
+}
+
+static int rmnet_ctrl_release(struct inode *ip, struct file *fp)
+{
+ unsigned long flags;
+ struct rmnet_ctrl_qti_port *port = fp->private_data;
+
+ pr_debug("Close rmnet control file");
+
+ spin_lock_irqsave(&port->lock, flags);
+ port->is_open = false;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ rmnet_ctrl_unlock(&port->open_excl);
+
+ return 0;
+}
+
+static ssize_t
+rmnet_ctrl_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
+{
+ struct rmnet_ctrl_qti_port *port = fp->private_data;
+ struct rmnet_ctrl_pkt *cpkt = NULL;
+ unsigned long flags;
+ int ret = 0;
+
+ pr_debug("%s: Enter(%d)\n", __func__, count);
+
+ if (count > MAX_QTI_PKT_SIZE) {
+ pr_err("Buffer size is too big %d, should be at most %d\n",
+ count, MAX_QTI_PKT_SIZE);
+ return -EINVAL;
+ }
+
+ if (rmnet_ctrl_lock(&port->read_excl)) {
+ pr_err("Previous reading is not finished yet\n");
+ return -EBUSY;
+ }
+
+ /* block until online */
+ while (!(atomic_read(&port->connected))) {
+ pr_debug("Not connected. Wait.\n");
+ ret = wait_event_interruptible(port->read_wq,
+ atomic_read(&port->connected));
+ if (ret < 0) {
+ rmnet_ctrl_unlock(&port->read_excl);
+ if (ret == -ERESTARTSYS)
+ return -ERESTARTSYS;
+ else
+ return -EINTR;
+ }
+ }
+
+ /* block until a new packet is available */
+ do {
+ spin_lock_irqsave(&port->lock, flags);
+ if (!list_empty(&port->cpkt_req_q))
+ break;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ pr_debug("%s: Requests list is empty. Wait.\n", __func__);
+ ret = wait_event_interruptible(port->read_wq,
+ !list_empty(&port->cpkt_req_q));
+ if (ret < 0) {
+ pr_debug("Waiting failed\n");
+ rmnet_ctrl_unlock(&port->read_excl);
+ return -ERESTARTSYS;
+ }
+ } while (1);
+
+ cpkt = list_first_entry(&port->cpkt_req_q, struct rmnet_ctrl_pkt,
+ list);
+ list_del(&cpkt->list);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (cpkt->len > count) {
+ pr_err("cpkt size too big:%d > buf size:%d\n",
+ cpkt->len, count);
+ rmnet_ctrl_unlock(&port->read_excl);
+ free_rmnet_ctrl_pkt(cpkt);
+ return -ENOMEM;
+ }
+
+ pr_debug("%s: cpkt size:%d\n", __func__, cpkt->len);
+
+
+ rmnet_ctrl_unlock(&port->read_excl);
+
+ ret = copy_to_user(buf, cpkt->buf, cpkt->len);
+ if (ret) {
+ pr_err("copy_to_user failed: err %d\n", ret);
+ ret = -EFAULT;
+ } else {
+ pr_debug("%s: copied %d bytes to user\n", __func__, cpkt->len);
+ ret = cpkt->len;
+ }
+
+ free_rmnet_ctrl_pkt(cpkt);
+
+ return ret;
+}
+
+static ssize_t
+rmnet_ctrl_write(struct file *fp, const char __user *buf, size_t count,
+ loff_t *pos)
+{
+ struct rmnet_ctrl_qti_port *port = fp->private_data;
+ void *kbuf;
+ unsigned long flags;
+ int ret = 0;
+
+ pr_debug("%s: Enter(%d)", __func__, count);
+
+ if (!count) {
+ pr_debug("zero length ctrl pkt\n");
+ return -EINVAL;
+ }
+
+ if (count > MAX_QTI_PKT_SIZE) {
+ pr_debug("given pkt size too big:%d > max_pkt_size:%d\n",
+ count, MAX_QTI_PKT_SIZE);
+ return -EINVAL;
+ }
+
+ if (rmnet_ctrl_lock(&port->write_excl)) {
+ pr_err("Previous writing not finished yet\n");
+ return -EBUSY;
+ }
+
+ if (!atomic_read(&port->connected)) {
+ pr_debug("USB cable not connected\n");
+ rmnet_ctrl_unlock(&port->write_excl);
+ return -EPIPE;
+ }
+
+ kbuf = kmalloc(count, GFP_KERNEL);
+ if (!kbuf) {
+ pr_err("failed to allocate ctrl pkt\n");
+ rmnet_ctrl_unlock(&port->write_excl);
+ return -ENOMEM;
+ }
+ ret = copy_from_user(kbuf, buf, count);
+ if (ret) {
+ pr_err("copy_from_user failed err:%d\n", ret);
+ kfree(kbuf);
+ rmnet_ctrl_unlock(&port->write_excl);
+ return -EFAULT;
+ }
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (port->port_usb && port->port_usb->send_cpkt_response) {
+ ret = port->port_usb->send_cpkt_response(port->port_usb,
+ kbuf, count);
+ if (ret) {
+ pr_err("failed to send ctrl packet. error=%d\n", ret);
+ spin_unlock_irqrestore(&port->lock, flags);
+ kfree(kbuf);
+ rmnet_ctrl_unlock(&port->write_excl);
+ return ret;
+ }
+ } else {
+ pr_err("send_cpkt_response callback is NULL\n");
+ spin_unlock_irqrestore(&port->lock, flags);
+ kfree(kbuf);
+ rmnet_ctrl_unlock(&port->write_excl);
+ return -EINVAL;
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ kfree(kbuf);
+ rmnet_ctrl_unlock(&port->write_excl);
+
+ pr_debug("%s: Exit(%d)", __func__, count);
+
+ return count;
+
+}
+
+static long rmnet_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
+{
+ struct rmnet_ctrl_qti_port *port = fp->private_data;
+ int val, ret = 0;
+
+ pr_debug("%s: Received command %d", __func__, cmd);
+
+ if (rmnet_ctrl_lock(&port->ioctl_excl))
+ return -EBUSY;
+
+ switch (cmd) {
+ case FRMNET_CTRL_GET_LINE_STATE:
+ val = atomic_read(&port->line_state);
+ ret = copy_to_user((void __user *)arg, &val, sizeof(val));
+ if (ret) {
+ pr_err("copying to user space failed");
+ ret = -EFAULT;
+ }
+ pr_debug("%s: Sent line_state: %d", __func__,
+ atomic_read(&port->line_state));
+ break;
+ default:
+ pr_err("wrong parameter");
+ ret = -EINVAL;
+ }
+
+ rmnet_ctrl_unlock(&port->ioctl_excl);
+
+ return ret;
+}
+
+static unsigned int rmnet_ctrl_poll(struct file *file, poll_table *wait)
+{
+ struct rmnet_ctrl_qti_port *port = file->private_data;
+ unsigned long flags;
+ unsigned int mask = 0;
+
+ if (!port) {
+ pr_err("%s on a NULL device\n", __func__);
+ return POLLERR;
+ }
+
+ poll_wait(file, &port->read_wq, wait);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (!list_empty(&port->cpkt_req_q)) {
+ mask |= POLLIN | POLLRDNORM;
+ pr_debug("%s sets POLLIN for rmnet_ctrl_qti_port\n", __func__);
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ return mask;
+}
+
+/* file operations for rmnet device /dev/rmnet_ctrl */
+static const struct file_operations rmnet_ctrl_fops = {
+ .owner = THIS_MODULE,
+ .open = rmnet_ctrl_open,
+ .release = rmnet_ctrl_release,
+ .read = rmnet_ctrl_read,
+ .write = rmnet_ctrl_write,
+ .unlocked_ioctl = rmnet_ctrl_ioctl,
+ .poll = rmnet_ctrl_poll,
+};
+
+static struct miscdevice rmnet_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "rmnet_ctrl",
+ .fops = &rmnet_ctrl_fops,
+};
+
+static int __init gqti_ctrl_init(void)
+{
+ int ret;
+ struct rmnet_ctrl_qti_port *port = NULL;
+
+ port = kzalloc(sizeof(struct rmnet_ctrl_qti_port), GFP_KERNEL);
+ if (!port) {
+ pr_err("Failed to allocate rmnet control device\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&port->cpkt_req_q);
+ spin_lock_init(&port->lock);
+
+ atomic_set(&port->open_excl, 0);
+ atomic_set(&port->read_excl, 0);
+ atomic_set(&port->write_excl, 0);
+ atomic_set(&port->ioctl_excl, 0);
+ atomic_set(&port->connected, 0);
+ atomic_set(&port->line_state, 0);
+
+ init_waitqueue_head(&port->read_wq);
+
+ ctrl_port = port;
+
+ ret = misc_register(&rmnet_device);
+ if (ret) {
+ pr_err("rmnet control driver failed to register");
+ goto fail_init;
+ }
+
+ return ret;
+
+fail_init:
+ kfree(port);
+ ctrl_port = NULL;
+ return ret;
+}
+module_init(gqti_ctrl_init);
+
+static void __exit gqti_ctrl_cleanup(void)
+{
+ misc_deregister(&rmnet_device);
+
+ kfree(ctrl_port);
+ ctrl_port = NULL;
+}
+module_exit(gqti_ctrl_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 24f3cb1..a09b1ab 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -842,7 +842,7 @@
u32 __iomem *status_reg = &ehci->regs->port_status[
(wIndex & 0xff) - 1];
u32 __iomem *hostpc_reg = NULL;
- u32 temp, temp1, status, cmd = 0;
+ u32 temp, temp1, status;
unsigned long flags;
int retval = 0;
unsigned selector;
@@ -1221,31 +1221,13 @@
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (50);
}
-
- if (ehci->reset_sof_bug && (temp & PORT_RESET)) {
- cmd = ehci_readl(ehci, &ehci->regs->command);
- cmd &= ~CMD_RUN;
- ehci_writel(ehci, cmd, &ehci->regs->command);
- if (handshake(ehci, &ehci->regs->status,
- STS_HALT, STS_HALT, 16 * 125))
- ehci_info(ehci,
- "controller halt failed\n");
- }
- ehci_writel(ehci, temp, status_reg);
- if (ehci->reset_sof_bug && (temp & PORT_RESET)
- && hcd->driver->enable_ulpi_control) {
- hcd->driver->enable_ulpi_control(hcd,
- PORT_RESET);
+ if (ehci->reset_sof_bug && (temp & PORT_RESET) &&
+ hcd->driver->reset_sof_bug_handler) {
spin_unlock_irqrestore(&ehci->lock, flags);
- usleep_range(50000, 55000);
- if (handshake(ehci, status_reg,
- PORT_RESET, 0, 10 * 1000))
- ehci_info(ehci,
- "failed to clear reset\n");
+ hcd->driver->reset_sof_bug_handler(hcd, temp);
spin_lock_irqsave(&ehci->lock, flags);
- hcd->driver->disable_ulpi_control(hcd);
- cmd |= CMD_RUN;
- ehci_writel(ehci, cmd, &ehci->regs->command);
+ } else {
+ ehci_writel(ehci, temp, status_reg);
}
break;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index fc4d1b6..a559ccf 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -101,6 +101,8 @@
struct completion rt_completion;
int resume_status;
int resume_again;
+ int bus_reset;
+ int reset_again;
struct pm_qos_request pm_qos_req_dma;
};
@@ -430,7 +432,7 @@
}
-static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
+static int __maybe_unused ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
{
struct usb_hcd *hcd = hsic_to_hcd(mehci);
int cnt = 0;
@@ -501,37 +503,6 @@
return 0;
}
-#define HSIC_DBG1 0X38
-#define ULPI_MANUAL_ENABLE BIT(4)
-#define ULPI_LINESTATE_DATA BIT(5)
-#define ULPI_LINESTATE_STROBE BIT(6)
-static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate)
-{
- struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
- int val;
-
- switch (linestate) {
- case PORT_RESET:
- val = ulpi_read(mehci, HSIC_DBG1);
- val |= ULPI_MANUAL_ENABLE;
- val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE);
- ulpi_write(mehci, val, HSIC_DBG1);
- break;
- default:
- pr_info("%s: Unknown linestate:%0x\n", __func__, linestate);
- }
-}
-
-static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd)
-{
- struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
- int val;
-
- val = ulpi_read(mehci, HSIC_DBG1);
- val &= ~ULPI_MANUAL_ENABLE;
- ulpi_write(mehci, val, HSIC_DBG1);
-}
-
static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
{
int rc = 0;
@@ -955,6 +926,26 @@
__func__, ret);
}
+static int msm_hsic_reset_done(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ u32 __iomem *status_reg = &ehci->regs->port_status[0];
+ int ret;
+
+ ehci_writel(ehci, ehci_readl(ehci, status_reg) & ~(PORT_RWC_BITS |
+ PORT_RESET), status_reg);
+
+ ret = handshake(ehci, status_reg, PORT_RESET, 0, 1 * 1000);
+
+ if (ret)
+ pr_err("reset handshake failed in %s\n", __func__);
+ else
+ ehci_writel(ehci, ehci_readl(ehci, &ehci->regs->command) |
+ CMD_RUN, &ehci->regs->command);
+
+ return ret;
+}
+
#define STS_GPTIMER0_INTERRUPT BIT(24)
static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
{
@@ -982,16 +973,28 @@
if (status & STS_GPTIMER0_INTERRUPT) {
int timeleft;
- dbg_log_event(NULL, "FPR: gpt0_isr", 0);
+ dbg_log_event(NULL, "FPR: gpt0_isr", mehci->bus_reset);
timeleft = GPT_CNT(ehci_readl(ehci,
&mehci->timer->gptimer1_ctrl));
if (timeleft) {
- ehci_writel(ehci, ehci_readl(ehci,
- &ehci->regs->command) | CMD_RUN,
- &ehci->regs->command);
- } else
- mehci->resume_again = 1;
+ if (mehci->bus_reset) {
+ ret = msm_hsic_reset_done(hcd);
+ if (ret) {
+ mehci->reset_again = 1;
+ dbg_log_event(NULL, "RESET: fail", 0);
+ }
+ } else {
+ ehci_writel(ehci, ehci_readl(ehci,
+ &ehci->regs->command) | CMD_RUN,
+ &ehci->regs->command);
+ }
+ } else {
+ if (mehci->bus_reset)
+ mehci->reset_again = 1;
+ else
+ mehci->resume_again = 1;
+ }
dbg_log_event(NULL, "FPR: timeleft", timeleft);
@@ -1047,6 +1050,83 @@
#ifdef CONFIG_PM
+#define RESET_RETRY_LIMIT 3
+#define RESET_SIGNAL_TIME_SOF_USEC (50 * 1000)
+#define RESET_SIGNAL_TIME_USEC (20 * 1000)
+static void ehci_hsic_reset_sof_bug_handler(struct usb_hcd *hcd, u32 val)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+ struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+ u32 __iomem *status_reg = &ehci->regs->port_status[0];
+ unsigned long flags;
+ int retries = 0, ret, cnt = RESET_SIGNAL_TIME_USEC;
+
+ if (pdata && pdata->swfi_latency)
+ pm_qos_update_request(&mehci->pm_qos_req_dma,
+ pdata->swfi_latency + 1);
+
+ mehci->bus_reset = 1;
+retry:
+ retries++;
+ dbg_log_event(NULL, "RESET: start", retries);
+ pr_debug("reset begin %d\n", retries);
+ mehci->reset_again = 0;
+ spin_lock_irqsave(&ehci->lock, flags);
+ ehci_writel(ehci, val, status_reg);
+ ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_USEC - 1),
+ &mehci->timer->gptimer0_ld);
+ ehci_writel(ehci, GPT_RESET | GPT_RUN,
+ &mehci->timer->gptimer0_ctrl);
+ ehci_writel(ehci, INTR_MASK | STS_GPTIMER0_INTERRUPT,
+ &ehci->regs->intr_enable);
+
+ ehci_writel(ehci, GPT_LD(RESET_SIGNAL_TIME_SOF_USEC - 1),
+ &mehci->timer->gptimer1_ld);
+ ehci_writel(ehci, GPT_RESET | GPT_RUN,
+ &mehci->timer->gptimer1_ctrl);
+
+ spin_unlock_irqrestore(&ehci->lock, flags);
+ wait_for_completion(&mehci->gpt0_completion);
+
+ if (!mehci->reset_again)
+ goto done;
+
+ if (handshake(ehci, status_reg, PORT_RESET, 0, 10 * 1000)) {
+ pr_err("reset handshake fatal error\n");
+ dbg_log_event(NULL, "RESET: fatal", retries);
+ goto fail;
+ }
+
+ if (retries < RESET_RETRY_LIMIT)
+ goto retry;
+
+ /* complete reset in tight loop */
+ pr_info("RESET in tight loop\n");
+ dbg_log_event(NULL, "RESET: tight", 0);
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ ehci_writel(ehci, val, status_reg);
+ while (cnt--)
+ udelay(1);
+ ret = msm_hsic_reset_done(hcd);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+ if (ret) {
+ pr_err("RESET in tight loop failed\n");
+ dbg_log_event(NULL, "RESET: tight failed", 0);
+ goto fail;
+ }
+
+done:
+ dbg_log_event(NULL, "RESET: done", retries);
+ pr_debug("reset completed\n");
+fail:
+ mehci->bus_reset = 0;
+ if (pdata && pdata->swfi_latency)
+ pm_qos_update_request(&mehci->pm_qos_req_dma,
+ PM_QOS_DEFAULT_VALUE);
+}
+
static int ehci_hsic_bus_suspend(struct usb_hcd *hcd)
{
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
@@ -1321,10 +1401,8 @@
.log_urb = dbg_log_event,
.dump_regs = dump_hsic_regs,
- .enable_ulpi_control = ehci_msm_enable_ulpi_control,
- .disable_ulpi_control = ehci_msm_disable_ulpi_control,
-
.set_autosuspend_delay = ehci_msm_set_autosuspend_delay,
+ .reset_sof_bug_handler = ehci_hsic_reset_sof_bug_handler,
};
static int msm_hsic_init_clocks(struct msm_hsic_hcd *mehci, u32 init)
@@ -1933,6 +2011,12 @@
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;
+ /* If the device was removed no need to call pm_runtime_disable */
+ if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
+ pm_runtime_disable(&pdev->dev);
+
+ pm_runtime_set_suspended(&pdev->dev);
+
/* Remove the HCD prior to releasing our resources. */
usb_remove_hcd(hcd);
@@ -1966,12 +2050,6 @@
ehci_hsic_msm_debugfs_cleanup();
device_init_wakeup(&pdev->dev, 0);
- /* If the device was removed no need to call pm_runtime_disable */
- if (pdev->dev.power.power_state.event != PM_EVENT_INVALID)
- pm_runtime_disable(&pdev->dev);
-
- pm_runtime_set_suspended(&pdev->dev);
-
destroy_workqueue(ehci_wq);
msm_hsic_config_gpios(mehci, 0);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index c69676f..b6882b8 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -57,7 +57,6 @@
};
struct mdss_data_type {
- u32 rev;
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
struct regulator *fs;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 79115d8..5c89938 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -417,9 +417,6 @@
mfd->op_enable);
if (ret)
pr_warn("can't turn on display!\n");
-
- if (mfd->vsync_pending)
- mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
}
mfd->is_power_setting = false;
complete_all(&mfd->power_set_comp);
@@ -618,6 +615,12 @@
static int mdss_fb_blank(int blank_mode, struct fb_info *info)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ if (blank_mode == FB_BLANK_POWERDOWN) {
+ struct fb_event event;
+ event.info = info;
+ event.data = &blank_mode;
+ fb_notifier_call_chain(FB_EVENT_BLANK, &event);
+ }
mdss_fb_pan_idle(mfd);
if (mfd->op_enable == 0) {
if (blank_mode == FB_BLANK_UNBLANK)
@@ -1037,16 +1040,23 @@
void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd)
{
- int i, ret;
+ int i, ret = 0;
/* buf sync */
for (i = 0; i < mfd->acq_fen_cnt; i++) {
ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
- sync_fence_put(mfd->acq_fen[i]);
if (ret < 0) {
pr_err("%s: sync_fence_wait failed! ret = %x\n",
__func__, ret);
break;
}
+ sync_fence_put(mfd->acq_fen[i]);
+ }
+
+ if (ret < 0) {
+ while (i < mfd->acq_fen_cnt) {
+ sync_fence_put(mfd->acq_fen[i]);
+ i++;
+ }
}
mfd->acq_fen_cnt = 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index ce5f707..308ae87 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -27,6 +27,7 @@
#include <linux/iommu.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/memory_alloc.h>
@@ -55,7 +56,6 @@
static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_MUTEX(mdp_clk_lock);
-static DEFINE_MUTEX(mdp_suspend_mutex);
#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
{ \
@@ -111,7 +111,7 @@
static DEFINE_SPINLOCK(mdss_lock);
struct mdss_hw *mdss_irq_handlers[MDSS_MAX_HW_BLK];
-static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata);
+static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on);
static int mdss_mdp_parse_dt(struct platform_device *pdev);
static int mdss_mdp_parse_dt_pipe(struct platform_device *pdev);
static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev);
@@ -612,8 +612,7 @@
pr_err("unable to get gdsc regulator\n");
return -EINVAL;
}
- regulator_enable(mdata->fs);
- mdata->fs_ena = true;
+ mdata->fs_ena = false;
if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
@@ -673,7 +672,7 @@
int i;
if (!mdata->iommu_attached) {
- pr_warn("mdp iommu already dettached\n");
+ pr_debug("mdp iommu already dettached\n");
return 0;
}
@@ -754,9 +753,12 @@
static int mdss_hw_init(struct mdss_data_type *mdata)
{
+ int i, j;
+ char *offset;
+
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- mdata->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
+ pr_info_once("MDP Rev=%x\n", mdata->mdp_rev);
if (mdata->hw_settings) {
struct mdss_hw_settings *hws = mdata->hw_settings;
@@ -766,6 +768,16 @@
hws++;
}
}
+
+ for (i = 0; i < mdata->nmixers_intf; i++) {
+ offset = mdata->mixer_intf[i].dspp_base +
+ MDSS_MDP_REG_DSPP_HIST_LUT_BASE;
+ for (j = 0; j < ENHIST_LUT_ENTRIES; j++)
+ writel_relaxed(j, offset);
+
+ /* swap */
+ writel_relaxed(i, offset + 4);
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
pr_debug("MDP hw init done\n");
@@ -798,8 +810,6 @@
mdata->smp_mb_cnt = MDSS_MDP_SMP_MMB_BLOCKS;
mdata->smp_mb_size = MDSS_MDP_SMP_MMB_SIZE;
- pr_info("mdss_revision=%x\n", mdata->rev);
- pr_info("mdp_hw_revision=%x\n", mdata->mdp_rev);
mdata->iclient = msm_ion_client_create(-1, mdata->pdev->name);
if (IS_ERR_OR_NULL(mdata->iclient)) {
@@ -809,10 +819,6 @@
}
rc = mdss_iommu_init(mdata);
- if (!IS_ERR_VALUE(rc))
- mdss_iommu_attach(mdata);
-
- rc = mdss_hw_init(mdata);
return rc;
}
@@ -910,15 +916,16 @@
goto probe_done;
}
- rc = mdss_mdp_register_early_suspend(mdata);
+ rc = mdss_mdp_debug_init(mdata);
if (rc) {
- pr_err("unable to register early suspend\n");
+ pr_err("unable to initialize mdp debugging\n");
goto probe_done;
}
- rc = mdss_mdp_debug_init(mdata);
- if (rc)
- pr_err("unable to initialize mdp debugging\n");
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ if (!pm_runtime_enabled(&pdev->dev))
+ mdss_mdp_footswitch_ctrl(mdata, true);
probe_done:
if (IS_ERR_VALUE(rc)) {
@@ -1320,16 +1327,14 @@
static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
{
- mutex_lock(&mdp_suspend_mutex);
- if (!mdata->suspend || !mdata->fs) {
- mutex_unlock(&mdp_suspend_mutex);
+ if (!mdata->fs)
return;
- }
if (on && !mdata->fs_ena) {
pr_debug("Enable MDP FS\n");
regulator_enable(mdata->fs);
mdss_iommu_attach(mdata);
+ mdss_hw_init(mdata);
mdata->fs_ena = true;
} else if (!on && mdata->fs_ena) {
pr_debug("Disable MDP FS\n");
@@ -1337,7 +1342,6 @@
regulator_disable(mdata->fs);
mdata->fs_ena = false;
}
- mutex_unlock(&mdp_suspend_mutex);
}
static inline int mdss_mdp_suspend_sub(struct mdss_data_type *mdata)
@@ -1350,18 +1354,6 @@
return ret;
}
- flush_workqueue(mdata->clk_ctrl_wq);
-
- mutex_lock(&mdp_suspend_mutex);
- mdata->suspend = true;
- mutex_unlock(&mdp_suspend_mutex);
-
- if (mdata->clk_ena) {
- pr_err("MDP suspend failed\n");
- return -EBUSY;
- }
- mdss_mdp_footswitch_ctrl(mdata, false);
-
pr_debug("suspend done\n");
return 0;
@@ -1371,11 +1363,6 @@
{
int ret = 0;
- mdss_mdp_footswitch_ctrl(mdata, true);
- mutex_lock(&mdp_suspend_mutex);
- mdata->suspend = false;
- mutex_unlock(&mdp_suspend_mutex);
- mdss_hw_init(mdata);
ret = mdss_fb_resume_all();
if (IS_ERR_VALUE(ret))
pr_err("Unable to resume all fb panels (%d)\n", ret);
@@ -1385,7 +1372,37 @@
return ret;
}
-#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
+#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
+static int mdss_mdp_pm_suspend(struct device *dev)
+{
+ struct mdss_data_type *mdata;
+
+ mdata = dev_get_drvdata(dev);
+ if (!mdata)
+ return -ENODEV;
+
+ dev_dbg(dev, "display pm suspend\n");
+
+ return mdss_mdp_suspend_sub(mdata);
+}
+
+static int mdss_mdp_pm_resume(struct device *dev)
+{
+ struct mdss_data_type *mdata;
+
+ mdata = dev_get_drvdata(dev);
+ if (!mdata)
+ return -ENODEV;
+
+ dev_dbg(dev, "display pm resume\n");
+
+ return mdss_mdp_resume_sub(mdata);
+}
+
+#define mdss_mdp_suspend NULL
+#define mdss_mdp_resume NULL
+#else
static int mdss_mdp_suspend(struct platform_device *pdev, pm_message_t state)
{
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -1393,7 +1410,7 @@
if (!mdata)
return -ENODEV;
- pr_debug("display suspend\n");
+ dev_dbg(&pdev->dev, "display suspend\n");
return mdss_mdp_suspend_sub(mdata);
}
@@ -1405,62 +1422,63 @@
if (!mdata)
return -ENODEV;
- pr_debug("display resume\n");
+ dev_dbg(&pdev->dev, "display resume\n");
return mdss_mdp_resume_sub(mdata);
}
-#else
-#define mdss_mdp_suspend NULL
-#define mdss_mdp_resume NULL
#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static void mdss_mdp_early_suspend(struct early_suspend *h)
+#ifdef CONFIG_PM_RUNTIME
+static int mdss_mdp_runtime_resume(struct device *dev)
{
- struct mdss_data_type *mdata;
- mdata = container_of(h, struct mdss_data_type, early_suspend);
+ struct mdss_data_type *mdata = dev_get_drvdata(dev);
+ if (!mdata)
+ return -ENODEV;
- pr_debug("display early suspend\n");
+ dev_dbg(dev, "pm_runtime: resuming...\n");
- mdss_mdp_suspend_sub(mdata);
-}
-
-static void mdss_mdp_late_resume(struct early_suspend *h)
-{
- struct mdss_data_type *mdata;
- mdata = container_of(h, struct mdss_data_type, early_suspend);
-
- pr_debug("display early resume\n");
-
- mdss_mdp_resume_sub(mdata);
-}
-
-static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata)
-{
- mdata->early_suspend.suspend = mdss_mdp_early_suspend;
- mdata->early_suspend.resume = mdss_mdp_late_resume;
- mdata->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
- register_early_suspend(&mdata->early_suspend);
+ mdss_mdp_footswitch_ctrl(mdata, true);
return 0;
}
-static int mdss_mdp_remove_early_suspend(struct mdss_data_type *mdata)
+static int mdss_mdp_runtime_idle(struct device *dev)
{
- unregister_early_suspend(&mdata->early_suspend);
+ struct mdss_data_type *mdata = dev_get_drvdata(dev);
+ if (!mdata)
+ return -ENODEV;
+
+ dev_dbg(dev, "pm_runtime: idling...\n");
+
+ flush_workqueue(mdata->clk_ctrl_wq);
return 0;
}
-#else
-static int mdss_mdp_register_early_suspend(struct mdss_data_type *mdata)
+
+static int mdss_mdp_runtime_suspend(struct device *dev)
{
- return 0;
-}
-static int mdss_mdp_remove_early_suspend(struct mdss_data_type *mdata)
-{
+ struct mdss_data_type *mdata = dev_get_drvdata(dev);
+ if (!mdata)
+ return -ENODEV;
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+
+ if (mdata->clk_ena) {
+ pr_err("MDP suspend failed\n");
+ return -EBUSY;
+ }
+ mdss_mdp_footswitch_ctrl(mdata, false);
+
return 0;
}
#endif
+#endif
+
+static const struct dev_pm_ops mdss_mdp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(mdss_mdp_pm_suspend, mdss_mdp_pm_resume)
+ SET_RUNTIME_PM_OPS(mdss_mdp_runtime_suspend,
+ mdss_mdp_runtime_resume,
+ mdss_mdp_runtime_idle)
+};
static int mdss_mdp_remove(struct platform_device *pdev)
{
@@ -1470,7 +1488,6 @@
pm_runtime_disable(&pdev->dev);
mdss_mdp_pp_term(&pdev->dev);
mdss_mdp_bus_scale_unregister(mdata);
- mdss_mdp_remove_early_suspend(mdata);
mdss_debugfs_remove(mdata);
return 0;
}
@@ -1494,6 +1511,7 @@
*/
.name = "mdp",
.of_match_table = mdss_mdp_dt_match,
+ .pm = &mdss_mdp_pm_ops,
},
};
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 455f725..5158974 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -32,8 +32,6 @@
#define MAX_MIXER_HEIGHT 2400
#define MAX_IMG_WIDTH 0x3FFF
#define MAX_IMG_HEIGHT 0x3FFF
-#define MIN_DST_W 10
-#define MIN_DST_H 10
#define MAX_DST_W MAX_MIXER_WIDTH
#define MAX_DST_H MAX_MIXER_HEIGHT
#define MAX_PLANES 4
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 63a1aa4..0f52125 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -267,6 +267,13 @@
mutex_lock(&mdss_mdp_ctl_lock);
ctl->ref_cnt--;
+ ctl->mixer_left = NULL;
+ ctl->mixer_right = NULL;
+ ctl->power_on = false;
+ ctl->start_fnc = NULL;
+ ctl->stop_fnc = NULL;
+ ctl->prepare_fnc = NULL;
+ ctl->display_fnc = NULL;
mutex_unlock(&mdss_mdp_ctl_lock);
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 1aea4e0..0d4037c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -251,6 +251,7 @@
NULL, NULL);
ctx->ref_cnt--;
+ ctl->priv_data = NULL;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 283d3f0..0c891f9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
#include <mach/iommu_domains.h>
@@ -56,10 +57,19 @@
struct mdss_mdp_format_params *fmt)
{
u32 xres, yres;
+ u32 min_src_size, min_dst_size;
xres = mfd->fbi->var.xres;
yres = mfd->fbi->var.yres;
+ if (mfd->mdata->mdp_rev >= MDSS_MDP_HW_REV_102) {
+ min_src_size = fmt->is_yuv ? 2 : 1;
+ min_dst_size = 1;
+ } else {
+ min_src_size = fmt->is_yuv ? 10 : 5;
+ min_dst_size = 2;
+ }
+
if (req->z_order >= MDSS_MDP_MAX_STAGE) {
pr_err("zorder %d out of range\n", req->z_order);
return -ERANGE;
@@ -67,7 +77,7 @@
if (req->src.width > MAX_IMG_WIDTH ||
req->src.height > MAX_IMG_HEIGHT ||
- req->src_rect.w == 0 || req->src_rect.h == 0 ||
+ req->src_rect.w < min_src_size || req->src_rect.h < min_src_size ||
CHECK_BOUNDS(req->src_rect.x, req->src_rect.w, req->src.width) ||
CHECK_BOUNDS(req->src_rect.y, req->src_rect.h, req->src.height)) {
pr_err("invalid source image img wh=%dx%d rect=%d,%d,%d,%d\n",
@@ -77,18 +87,14 @@
return -EOVERFLOW;
}
- if (req->dst_rect.w < MIN_DST_W || req->dst_rect.h < MIN_DST_H ||
+ if (req->dst_rect.w < min_dst_size || req->dst_rect.h < min_dst_size ||
req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H) {
pr_err("invalid destination resolution (%dx%d)",
req->dst_rect.w, req->dst_rect.h);
return -EOVERFLOW;
}
- if (req->flags & MDSS_MDP_ROT_ONLY) {
- /* dst res should match src res in rotation only mode*/
- req->dst_rect.w = req->src_rect.w;
- req->dst_rect.h = req->src_rect.h;
- } else {
+ if (!(req->flags & MDSS_MDP_ROT_ONLY)) {
u32 dst_w, dst_h;
if ((CHECK_BOUNDS(req->dst_rect.x, req->dst_rect.w, xres) ||
@@ -154,10 +160,6 @@
pr_err("invalid odd src resolution or coordinates\n");
return -EINVAL;
}
- if ((req->dst_rect.w & 0x1) || (req->dst_rect.h & 0x1)) {
- pr_err("invalid odd dst resolution\n");
- return -EINVAL;
- }
}
return 0;
@@ -268,14 +270,16 @@
pipe->params_changed = true;
}
- if (req->id == MSMFB_NEW_REQUEST) {
- mixer = mdss_mdp_mixer_get(mfd->ctl, mixer_mux);
- if (!mixer) {
- pr_err("unable to get mixer\n");
- return -ENODEV;
- }
+ mixer = mdss_mdp_mixer_get(mfd->ctl, mixer_mux);
+ if (!mixer) {
+ pr_err("unable to get mixer\n");
+ return -ENODEV;
+ }
- if (fmt->is_yuv || (req->flags & MDP_OV_PIPE_SHARE))
+ if (req->id == MSMFB_NEW_REQUEST) {
+ if (req->flags & MDP_OV_PIPE_FORCE_DMA)
+ pipe_type = MDSS_MDP_PIPE_TYPE_DMA;
+ else if (fmt->is_yuv || (req->flags & MDP_OV_PIPE_SHARE))
pipe_type = MDSS_MDP_PIPE_TYPE_VIG;
else
pipe_type = MDSS_MDP_PIPE_TYPE_RGB;
@@ -311,6 +315,21 @@
pr_err("invalid pipe ndx=%x\n", req->id);
return pipe ? PTR_ERR(pipe) : -ENODEV;
}
+
+ if (pipe->mixer != mixer) {
+ if (!mixer->ctl || (mixer->ctl->mfd != mfd)) {
+ pr_err("Can't switch mixer %d->%d pnum %d!\n",
+ pipe->mixer->num, mixer->num,
+ pipe->num);
+ mdss_mdp_pipe_unmap(pipe);
+ return -EINVAL;
+ }
+ pr_debug("switching pipe mixer %d->%d pnum %d\n",
+ pipe->mixer->num, mixer->num,
+ pipe->num);
+ mdss_mdp_mixer_pipe_unstage(pipe);
+ pipe->mixer = mixer;
+ }
}
pipe->flags = req->flags;
@@ -418,25 +437,28 @@
int num_planes,
u32 flags)
{
- int i;
+ int i, rc = 0;
+
+ if ((num_planes <= 0) || (num_planes > MAX_PLANES))
+ return -EINVAL;
memset(data, 0, sizeof(*data));
for (i = 0; i < num_planes; i++) {
data->p[i].flags = flags;
- mdss_mdp_get_img(&planes[i], &data->p[i]);
- if (data->p[0].len == 0)
+ rc = mdss_mdp_get_img(&planes[i], &data->p[i]);
+ if (rc) {
+ pr_err("failed to map buf p=%d flags=%x\n", i, flags);
+ while (i > 0) {
+ i--;
+ mdss_mdp_put_img(&data->p[i]);
+ }
break;
+ }
}
- if (i != num_planes) {
- for (; i >= 0; i--)
- mdss_mdp_put_img(&data->p[i]);
- return -ENOMEM;
- }
+ data->num_planes = i;
- data->num_planes = num_planes;
-
- return 0;
+ return rc;
}
static inline int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
@@ -479,9 +501,22 @@
int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
{
struct msm_fb_data_type *mfd = ctl->mfd;
+ struct mdss_mdp_pipe *pipe;
int ret;
mutex_lock(&mfd->ov_lock);
+ mutex_lock(&mfd->lock);
+ list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ if (pipe->params_changed || pipe->back_buf.num_planes) {
+ ret = mdss_mdp_pipe_queue_data(pipe, &pipe->back_buf);
+ if (IS_ERR_VALUE(ret)) {
+ pr_warn("Unable to queue data for pnum=%d\n",
+ pipe->num);
+ mdss_mdp_overlay_free_buf(&pipe->back_buf);
+ }
+ }
+ }
+ mutex_unlock(&mfd->lock);
if (mfd->kickoff_fnc)
ret = mfd->kickoff_fnc(ctl);
@@ -580,6 +615,13 @@
unset_ndx |= pipe->ndx;
cnt++;
}
+
+ if (cnt == 0 && !list_empty(&mfd->pipes_cleanup)) {
+ pr_warn("overlay release on fb%d called without commit!",
+ mfd->index);
+ cnt++;
+ }
+
mutex_unlock(&mfd->lock);
if (unset_ndx) {
@@ -628,32 +670,29 @@
ret = mdss_mdp_overlay_get_buf(mfd, &src_data, &req->data, 1, flgs);
if (ret) {
pr_err("src_data pmem error\n");
- goto rotate_done;
+ return ret;
}
ret = mdss_mdp_overlay_get_buf(mfd, &dst_data, &req->dst_data, 1, flgs);
if (ret) {
pr_err("dst_data pmem error\n");
- goto rotate_done;
+ goto dst_buf_fail;
}
ret = mdss_mdp_rotator_queue(rot, &src_data, &dst_data);
- if (ret) {
+ if (ret)
pr_err("rotator queue error session id=%x\n", req->id);
- goto rotate_done;
- }
-rotate_done:
mdss_mdp_overlay_free_buf(&dst_data);
+dst_buf_fail:
mdss_mdp_overlay_free_buf(&src_data);
- return 0;
+ return ret;
}
static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
- struct mdss_mdp_ctl *ctl;
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_data *src_data;
int ret;
@@ -679,12 +718,7 @@
ret = mdss_mdp_overlay_get_buf(mfd, src_data, &req->data, 1, flags);
if (IS_ERR_VALUE(ret)) {
pr_err("src_data pmem error\n");
- } else {
- ret = mdss_mdp_pipe_queue_data(pipe, src_data);
- if (IS_ERR_VALUE(ret))
- mdss_mdp_overlay_free_buf(src_data);
}
- ctl = pipe->mixer->ctl;
mdss_mdp_pipe_unmap(pipe);
return ret;
@@ -1291,12 +1325,21 @@
mfd->ctl = ctl;
}
+ pm_runtime_get_sync(&mfd->pdev->dev);
+
rc = mdss_mdp_ctl_start(mfd->ctl);
if (rc == 0) {
atomic_inc(&ov_active_panels);
+
+ if (mfd->vsync_pending) {
+ mfd->vsync_pending = 0;
+ mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
+ }
} else {
mdss_mdp_ctl_destroy(mfd->ctl);
mfd->ctl = NULL;
+
+ pm_runtime_put(&mfd->pdev->dev);
}
return rc;
@@ -1329,6 +1372,8 @@
if (atomic_dec_return(&ov_active_panels) == 0)
mdss_mdp_rotator_release_all();
+
+ pm_runtime_put(&mfd->pdev->dev);
}
return rc;
@@ -1369,6 +1414,9 @@
return rc;
}
+ pm_runtime_set_suspended(&mfd->pdev->dev);
+ pm_runtime_enable(&mfd->pdev->dev);
+
kobject_uevent(&dev->kobj, KOBJ_ADD);
pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index ee48f31..851d608 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -844,9 +844,6 @@
int mdss_mdp_pp_init(struct device *dev)
{
int ret = 0;
- int i;
- u32 offset;
- uint32_t data[ENHIST_LUT_ENTRIES];
mutex_lock(&mdss_pp_mutex);
if (!mdss_pp_res) {
@@ -856,20 +853,6 @@
pr_err("%s mdss_pp_res allocation failed!", __func__);
ret = -ENOMEM;
}
-
- for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
- data[i] = i;
-
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- /* Initialize Histogram LUT for all DSPPs */
- for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
- offset = MDSS_MDP_REG_DSPP_OFFSET(i) +
- MDSS_MDP_REG_DSPP_HIST_LUT_BASE;
- mdss_pp_res->enhist_disp_cfg[i].data = data;
- pp_update_hist_lut(offset,
- &mdss_pp_res->enhist_disp_cfg[i]);
- }
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
}
mutex_unlock(&mdss_pp_mutex);
return ret;
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 7ffae9d..41f7c29 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -20,6 +20,7 @@
#define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D
#define DRM_KGSL_GEM_CREATE_FD 0x0E
#define DRM_KGSL_GEM_GET_ION_FD 0x0F
+#define DRM_KGSL_GEM_CREATE_FROM_ION 0x10
#define DRM_IOCTL_KGSL_GEM_CREATE \
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create)
@@ -80,6 +81,10 @@
DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_ION_FD, \
struct drm_kgsl_gem_get_ion_fd)
+#define DRM_IOCTL_KGSL_GEM_CREATE_FROM_ION \
+DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FROM_ION, \
+struct drm_kgsl_gem_create_from_ion)
+
/* Maximum number of sub buffers per GEM object */
#define DRM_KGSL_GEM_MAX_BUFFERS 2
@@ -199,4 +204,9 @@
uint32_t handle;
};
+struct drm_kgsl_gem_create_from_ion {
+ uint32_t ion_fd;
+ uint32_t handle;
+};
+
#endif
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index 5ff1cfb..f27ceca 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -89,6 +89,8 @@
* readings from bms are not available.
* @delta_rbatt_mohm: the resistance to be added towards lower soc to
* compensate for battery capacitance.
+ * @rbatt_capacitve_mohm: the resistance to be added to compensate for
+ * battery capacitance
*/
struct bms_battery_data {
@@ -100,6 +102,7 @@
struct sf_lut *rbatt_sf_lut;
int default_rbatt_mohm;
int delta_rbatt_mohm;
+ int rbatt_capacitive_mohm;
};
#if defined(CONFIG_PM8921_BMS) || \
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 3ebf091..aed549e 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -29,6 +29,8 @@
(((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
+#define WCD9XXX_SUPPLY_BUCK_NAME "cdc-vdd-buck"
+
#define SITAR_VERSION_1P0 0
#define SITAR_VERSION_1P1 1
#define SITAR_IS_1P0(ver) \
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index 9c44e8b..412341a 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -196,4 +196,85 @@
#define WCD9XXX_A_MAD_ANA_CTRL (0x150)
#define WCD9XXX_A_MAD_ANA_CTRL__POR (0xF1)
+
+#define WCD9XXX_A_CDC_CLK_OTHR_CTL (0x30C)
+#define WCD9XXX_A_CDC_CLK_OTHR_CTL__POR (0x00)
+
+/* Class H related common registers */
+#define WCD9XXX_A_BUCK_MODE_1 (0x181)
+#define WCD9XXX_A_BUCK_MODE_1__POR (0x21)
+#define WCD9XXX_A_BUCK_MODE_2 (0x182)
+#define WCD9XXX_A_BUCK_MODE_2__POR (0xFF)
+#define WCD9XXX_A_BUCK_MODE_3 (0x183)
+#define WCD9XXX_A_BUCK_MODE_3__POR (0xCC)
+#define WCD9XXX_A_BUCK_MODE_4 (0x184)
+#define WCD9XXX_A_BUCK_MODE_4__POR (0x3A)
+#define WCD9XXX_A_BUCK_MODE_5 (0x185)
+#define WCD9XXX_A_BUCK_MODE_5__POR (0x00)
+#define WCD9XXX_A_BUCK_CTRL_VCL_1 (0x186)
+#define WCD9XXX_A_BUCK_CTRL_VCL_1__POR (0x48)
+#define WCD9XXX_A_BUCK_CTRL_VCL_2 (0x187)
+#define WCD9XXX_A_BUCK_CTRL_VCL_2__POR (0xA3)
+#define WCD9XXX_A_BUCK_CTRL_VCL_3 (0x188)
+#define WCD9XXX_A_BUCK_CTRL_VCL_3__POR (0x82)
+#define WCD9XXX_A_BUCK_CTRL_CCL_1 (0x189)
+#define WCD9XXX_A_BUCK_CTRL_CCL_1__POR (0xAB)
+#define WCD9XXX_A_BUCK_CTRL_CCL_2 (0x18A)
+#define WCD9XXX_A_BUCK_CTRL_CCL_2__POR (0xDC)
+#define WCD9XXX_A_BUCK_CTRL_CCL_3 (0x18B)
+#define WCD9XXX_A_BUCK_CTRL_CCL_3__POR (0x6A)
+#define WCD9XXX_A_BUCK_CTRL_CCL_4 (0x18C)
+#define WCD9XXX_A_BUCK_CTRL_CCL_4__POR (0x58)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_1 (0x18D)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_1__POR (0x50)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_2 (0x18E)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_2__POR (0x64)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_3 (0x18F)
+#define WCD9XXX_A_BUCK_CTRL_PWM_DRVR_3__POR (0x77)
+#define WCD9XXX_A_BUCK_TMUX_A_D (0x190)
+#define WCD9XXX_A_BUCK_TMUX_A_D__POR (0x00)
+#define WCD9XXX_A_NCP_EN (0x192)
+#define WCD9XXX_A_NCP_EN__POR (0xFE)
+#define WCD9XXX_A_NCP_STATIC (0x194)
+#define WCD9XXX_A_NCP_STATIC__POR (0x28)
+#define WCD9XXX_A_NCP_BUCKREF (0x191)
+#define WCD9XXX_A_NCP_BUCKREF__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_B1_CTL (0x320)
+#define WCD9XXX_A_CDC_CLSH_B1_CTL__POR (0xE4)
+#define WCD9XXX_A_CDC_CLSH_B2_CTL (0x321)
+#define WCD9XXX_A_CDC_CLSH_B2_CTL__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_B3_CTL (0x322)
+#define WCD9XXX_A_CDC_CLSH_B3_CTL__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS (0x323)
+#define WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD (0x324)
+#define WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD__POR (0x12)
+#define WCD9XXX_A_CDC_CLSH_IDLE_EAR_THSD (0x325)
+#define WCD9XXX_A_CDC_CLSH_IDLE_EAR_THSD__POR (0x0C)
+#define WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD (0x326)
+#define WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR (0x18)
+#define WCD9XXX_A_CDC_CLSH_FCLKONLY_EAR_THSD (0x327)
+#define WCD9XXX_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR (0x23)
+#define WCD9XXX_A_CDC_CLSH_K_ADDR (0x328)
+#define WCD9XXX_A_CDC_CLSH_K_ADDR__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_K_DATA (0x329)
+#define WCD9XXX_A_CDC_CLSH_K_DATA__POR (0xA4)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L (0x32A)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L__POR (0xD7)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U (0x32B)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U__POR (0x05)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_L (0x32C)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_L__POR (0x60)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_U (0x32D)
+#define WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_U__POR (0x09)
+#define WCD9XXX_A_CDC_CLSH_V_PA_HD_EAR (0x32E)
+#define WCD9XXX_A_CDC_CLSH_V_PA_HD_EAR__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_V_PA_HD_HPH (0x32F)
+#define WCD9XXX_A_CDC_CLSH_V_PA_HD_HPH__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_V_PA_MIN_EAR (0x330)
+#define WCD9XXX_A_CDC_CLSH_V_PA_MIN_EAR__POR (0x00)
+#define WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH (0x331)
+#define WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH__POR (0x00)
+
+
#endif
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index 471f10a..f0c4915 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -49,6 +49,10 @@
(AUDIO_MAX_COMMON_IOCTL_NUM+21), unsigned)
#define AUDIO_SET_LSM_CAL _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+22), unsigned)
+#define AUDIO_SET_ADM_CUSTOM_TOPOLOGY _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+23), unsigned)
+#define AUDIO_SET_ASM_CUSTOM_TOPOLOGY _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
#define AUDIO_MAX_ACDB_IOCTL (AUDIO_MAX_COMMON_IOCTL_NUM+30)
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 3ec966b..32f71a1 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -166,6 +166,7 @@
#define MDP_BACKEND_COMPOSITION 0x00040000
#define MDP_BORDERFILL_SUPPORTED 0x00010000
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
+#define MDP_OV_PIPE_FORCE_DMA 0x00004000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
#define MDP_TRANSP_NOP 0xffffffff
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index a3347c4..1849cee 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1149,6 +1149,23 @@
*/
int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
uint32_t *low_threshold, uint32_t *high_threshold);
+/**
+ * qpnp_vadc_iadc_sync_request() - Performs Voltage ADC read and
+ * locks the peripheral. When performing simultaneous
+ * voltage and current request the VADC peripheral is
+ * prepared for conversion and the IADC sync conversion
+ * is done from the IADC peripheral.
+ * @channel: Input channel to perform the voltage ADC read.
+ */
+int32_t qpnp_vadc_iadc_sync_request(enum qpnp_vadc_channels channel);
+/**
+ * qpnp_vadc_iadc_sync_complete_request() - Reads the ADC result and
+ * unlocks the peripheral.
+ * @result: Structure pointer of type adc_chan_result
+ * in which the ADC read results are stored.
+ */
+int32_t qpnp_vadc_iadc_sync_complete_request(
+ enum qpnp_vadc_channels channel, struct qpnp_vadc_result *result);
#else
static inline int32_t qpnp_vadc_read(uint32_t channel,
struct qpnp_vadc_result *result)
@@ -1218,6 +1235,13 @@
static inline int32_t qpnp_adc_tm_scale_voltage_therm_pu2(
uint32_t reg, int64_t *result)
{ return -ENXIO; }
+static inline int32_t qpnp_vadc_iadc_sync_request(
+ enum qpnp_vadc_channels channel)
+{ return -ENXIO; }
+static inline int32_t qpnp_vadc_iadc_sync_complete_request(
+ enum qpnp_vadc_channels channel,
+ struct qpnp_vadc_result *result)
+{ return -ENXIO; }
#endif
/* Public API */
@@ -1226,7 +1250,7 @@
/**
* qpnp_iadc_read() - Performs ADC read on the current channel.
* @channel: Input channel to perform the ADC read.
- * @result: Current across rsens in mV.
+ * @result: Current across rsense in mA.
*/
int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
struct qpnp_iadc_result *result);
@@ -1245,7 +1269,6 @@
* type qpnp_iadc_calib.
*/
int32_t qpnp_iadc_get_gain_and_offset(struct qpnp_iadc_calib *result);
-
/**
* qpnp_iadc_is_ready() - Clients can use this API to check if the
* device is ready to use.
@@ -1253,15 +1276,34 @@
* has not occured.
*/
int32_t qpnp_iadc_is_ready(void);
+/**
+ * qpnp_iadc_vadc_sync_read() - Performs synchronous VADC and IADC read.
+ * The api is to be used only by the BMS to perform
+ * simultaneous VADC and IADC measurement for battery voltage
+ * and current.
+ * @i_channel: Input battery current channel to perform the IADC read.
+ * @i_result: Current across the rsense in mA.
+ * @v_channel: Input battery voltage channel to perform VADC read.
+ * @v_result: Voltage on the vbatt channel with units in mV.
+ */
+int32_t qpnp_iadc_vadc_sync_read(
+ enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
+ enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result);
#else
static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
struct qpnp_iadc_result *result)
{ return -ENXIO; }
+static inline int32_t qpnp_iadc_get_rsense(int32_t *rsense)
+{ return -ENXIO; }
static inline int32_t qpnp_iadc_get_gain_and_offset(struct qpnp_iadc_calib
*result)
{ return -ENXIO; }
static inline int32_t qpnp_iadc_is_ready(void)
{ return -ENXIO; }
+static inline int32_t qpnp_iadc_vadc_sync_read(
+ enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
+ enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
+{ return -ENXIO; }
#endif
/* Public API */
@@ -1323,8 +1365,6 @@
{ return -ENXIO; }
static inline int32_t qpnp_adc_tm_is_ready(void)
{ return -ENXIO; }
-static inline int32_t qpnp_iadc_get_rsense(int32_t *rsense)
-{ return -ENXIO; }
#endif
#endif
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index 2b39f69..478734f 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -54,6 +54,7 @@
#define USB_CDC_OBEX_TYPE 0x15
#define USB_CDC_NCM_TYPE 0x1a
#define USB_CDC_MBB_TYPE 0x1b /* mbb_desc */
+#define USB_CDC_EXT_MBB_TYPE 0x1c
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct usb_cdc_header_desc {
@@ -203,6 +204,17 @@
__u8 bmNetworkCapabilities;
} __packed;
+/* "Extended MBIM Functional Descriptor" */
+struct usb_cdc_ext_mbb_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdMbbExtendedVersion;
+ __u8 bMaxOutstandingCmdMsges;
+ __le16 wMTU;
+} __packed;
+
/*-------------------------------------------------------------------------*/
/*
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 268aa48..4fb20f6 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -349,9 +349,8 @@
/* to log submission/completion events*/
void (*log_urb)(struct urb *urb, char *event, unsigned extra);
void (*dump_regs)(struct usb_hcd *);
- void (*enable_ulpi_control)(struct usb_hcd *hcd, u32 linestate);
- void (*disable_ulpi_control)(struct usb_hcd *hcd);
void (*set_autosuspend_delay)(struct usb_device *);
+ void (*reset_sof_bug_handler)(struct usb_hcd *hcd, u32 val);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
diff --git a/include/linux/usb/rmnet_ctrl_qti.h b/include/linux/usb/rmnet_ctrl_qti.h
new file mode 100644
index 0000000..5038396
--- /dev/null
+++ b/include/linux/usb/rmnet_ctrl_qti.h
@@ -0,0 +1,12 @@
+#ifndef __LINUX_USB_U_RMNET_CTRL_QTI_H
+#define __LINUX_USB_U_RMNET_CTRL_QTI_H
+
+#include <linux/ioctl.h>
+
+#define MAX_QTI_PKT_SIZE 2048
+
+#define FRMNET_CTRL_IOCTL_MAGIC 'r'
+#define FRMNET_CTRL_GET_LINE_STATE _IOR(FRMNET_CTRL_IOCTL_MAGIC, 2, int)
+
+
+#endif /* __LINUX_USB_U_RMNET_CTRL_QTI_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index badbd8e..e909195 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
+ Copyright (c) 2000-2001, 2010-2013 The Linux Foundation. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -63,6 +63,7 @@
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3
+#define BT_SECURITY_VERY_HIGH 4
#define BT_DEFER_SETUP 7
#define BT_FLUSHABLE 8
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 4555b08..cad737a 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -6215,6 +6215,22 @@
#define VOICE_CMD_GET_PARAM 0x0001133E
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
+/* Set Q6 topologies */
+#define ASM_CMD_ADD_TOPOLOGIES 0x00010DBE
+#define ADM_CMD_ADD_TOPOLOGIES 0x00010335
+
+/* structure used for both ioctls */
+struct cmd_set_topologies {
+ struct apr_hdr hdr;
+ u32 payload_addr_lsw;
+ /* LSW of parameter data payload address.*/
+ u32 payload_addr_msw;
+ /* MSW of parameter data payload address.*/
+ u32 mem_map_handle;
+ /* Memory map handle returned by mem map command */
+ u32 payload_size;
+ /* Size in bytes of the variable payload in shared memory */
+} __packed;
/* SRS TRUMEDIA start */
/* topology */
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 15d3585..198773c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
+ Copyright (c) 2000-2001, 2010-2013 The Linux Foundation. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -2046,7 +2046,7 @@
sizeof(cp), &cp);
goto unlock;
} else if (!(lmp_ssp_capable(conn)) && conn->auth_initiator &&
- (conn->pending_sec_level == BT_SECURITY_HIGH)) {
+ (conn->pending_sec_level == BT_SECURITY_VERY_HIGH)) {
conn->pending_sec_level = BT_SECURITY_MEDIUM;
}
@@ -2669,6 +2669,12 @@
BT_DBG("Conn pending sec level is %d, ssp is %d, key len is %d",
conn->pending_sec_level, conn->ssp_mode, key->pin_len);
}
+ if (conn && (conn->ssp_mode == 0) &&
+ (conn->pending_sec_level == BT_SECURITY_VERY_HIGH) &&
+ (key->pin_len != 16)) {
+ BT_DBG("Security is high ignoring this key");
+ goto not_found;
+ }
if (key->key_type == 0x04 && conn && conn->auth_type != 0xff &&
(conn->auth_type & 0x01)) {
@@ -2853,14 +2859,14 @@
conn->ssp_mode = (ev->features[0] & 0x01);
/*In case if remote device ssp supported/2.0 device
- reduce the security level to MEDIUM if it is HIGH*/
+ reduce the security level to MEDIUM if it is VERY HIGH*/
if (!conn->ssp_mode && conn->auth_initiator &&
- (conn->pending_sec_level == BT_SECURITY_HIGH))
+ (conn->pending_sec_level == BT_SECURITY_VERY_HIGH))
conn->pending_sec_level = BT_SECURITY_MEDIUM;
if (conn->ssp_mode && conn->auth_initiator &&
conn->io_capability != 0x03) {
- conn->pending_sec_level = BT_SECURITY_HIGH;
+ conn->pending_sec_level = BT_SECURITY_VERY_HIGH;
conn->auth_type = HCI_AT_DEDICATED_BONDING_MITM;
}
}
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6eab6d0..fd9088a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (c) 2000-2001, 2010-2012 The Linux Foundation. All rights reserved.
+ Copyright (c) 2000-2001, 2010-2013 The Linux Foundation. All rights reserved.
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
@@ -610,6 +610,7 @@
{
if (sk->sk_type == SOCK_RAW) {
switch (l2cap_pi(sk)->sec_level) {
+ case BT_SECURITY_VERY_HIGH:
case BT_SECURITY_HIGH:
return HCI_AT_DEDICATED_BONDING_MITM;
case BT_SECURITY_MEDIUM:
@@ -621,12 +622,14 @@
if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
- if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+ if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH ||
+ l2cap_pi(sk)->sec_level == BT_SECURITY_VERY_HIGH)
return HCI_AT_NO_BONDING_MITM;
else
return HCI_AT_NO_BONDING;
} else {
switch (l2cap_pi(sk)->sec_level) {
+ case BT_SECURITY_VERY_HIGH:
case BT_SECURITY_HIGH:
return HCI_AT_GENERAL_BONDING_MITM;
case BT_SECURITY_MEDIUM:
@@ -7533,7 +7536,8 @@
if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ * 5);
- } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+ } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH ||
+ l2cap_pi(sk)->sec_level == BT_SECURITY_VERY_HIGH)
__l2cap_sock_close(sk, ECONNREFUSED);
} else {
if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index dc4bf2f..d1914ea 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -262,6 +262,7 @@
__u8 auth_type;
switch (d->sec_level) {
+ case BT_SECURITY_VERY_HIGH:
case BT_SECURITY_HIGH:
auth_type = HCI_AT_GENERAL_BONDING_MITM;
break;
@@ -2163,7 +2164,8 @@
set_bit(RFCOMM_SEC_PENDING, &d->flags);
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
continue;
- } else if (d->sec_level == BT_SECURITY_HIGH) {
+ } else if (d->sec_level == BT_SECURITY_HIGH ||
+ d->sec_level == BT_SECURITY_VERY_HIGH) {
__rfcomm_dlc_close(d, ECONNREFUSED);
continue;
}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 66cc1f0..216068f 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -707,12 +707,13 @@
break;
}
- if (sec.level > BT_SECURITY_HIGH) {
+ if (sec.level > BT_SECURITY_VERY_HIGH) {
err = -EINVAL;
break;
}
rfcomm_pi(sk)->sec_level = sec.level;
+ BT_DBG("set to %d", sec.level);
break;
case BT_DEFER_SETUP:
@@ -763,6 +764,7 @@
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT;
break;
case BT_SECURITY_HIGH:
+ case BT_SECURITY_VERY_HIGH:
opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT |
RFCOMM_LM_SECURE;
break;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 517779f..4a83020 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -213,6 +213,7 @@
static __u8 seclevel_to_authreq(__u8 level)
{
switch (level) {
+ case BT_SECURITY_VERY_HIGH:
case BT_SECURITY_HIGH:
return SMP_AUTH_MITM | SMP_AUTH_BONDING;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index df34213..155585a 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -298,6 +298,9 @@
config SND_SOC_WCD9306
tristate
+config SND_SOC_MSM8X10_WCD
+ tristate
+
config SND_SOC_WL1273
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 11338aa..a09dab3 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -51,8 +51,9 @@
snd-soc-wcd9304-objs := wcd9304.o wcd9304-tables.o
snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
snd-soc-cs8427-objs := cs8427.o
-snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o
-snd-soc-wcd9306-objs := wcd9xxx-resmgr.o wcd9306.o wcd9306-tables.o wcd9xxx-mbhc.o
+snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o wcd9xxx-common.o
+snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o
+snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
@@ -163,7 +164,8 @@
obj-$(CONFIG_SND_SOC_WCD9310) += snd-soc-wcd9310.o
obj-$(CONFIG_SND_SOC_CS8427) += snd-soc-cs8427.o
obj-$(CONFIG_SND_SOC_WCD9320) += snd-soc-wcd9320.o
-obj-$(CONFIG_SND_SOC_WCD9306) += snd-soc-wcd9306.o
+obj-$(CONFIG_SND_SOC_WCD9306) += snd-soc-wcd9306.o wcd9xxx-resmgr.o wcd9xxx-mbhc.o
+obj-$(CONFIG_SND_SOC_MSM8X10_WCD) += snd-soc-msm8x10-wcd.o wcd9xxx-resmgr.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
diff --git a/sound/soc/codecs/msm8x10-wcd-tables.c b/sound/soc/codecs/msm8x10-wcd-tables.c
new file mode 100644
index 0000000..7e0263d
--- /dev/null
+++ b/sound/soc/codecs/msm8x10-wcd-tables.c
@@ -0,0 +1,794 @@
+/* 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 <msm8x10_wcd_registers.h>
+#include "msm8x10-wcd.h"
+
+const u8 msm8x10_wcd_reg_readable[MSM8X10_WCD_CACHE_SIZE] = {
+ [MSM8X10_WCD_A_CHIP_CTL] = 1,
+ [MSM8X10_WCD_A_CHIP_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_TLMM_MODE_SELECT] = 1,
+ [MSM8X10_WCD_A_MODE_LOCK] = 0,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_0] = 1,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_1] = 1,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_2] = 1,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_3] = 1,
+ [MSM8X10_WCD_A_CHIP_VERSION] = 1,
+ [MSM8X10_WCD_A_ANALOG_SLAVE_ID] = 1,
+ [MSM8X10_WCD_A_PIN_CTL_OE] = 1,
+ [MSM8X10_WCD_A_PIN_CTL_DATA] = 1,
+ [MSM8X10_WCD_A_PIN_STATUS] = 1,
+ [MSM8X10_WCD_A_HDRIVE_CTL] = 1,
+ [MSM8X10_WCD_A_HDRIVE_I2C_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RST_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TOP_CLK_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_ANA_CLK_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DIG_CLK_CTL] = 1,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL0] = 1,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL1] = 1,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL2] = 1,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL3] = 1,
+ [MSM8X10_WCD_A_QFUSE_CTL] = 1,
+ [MSM8X10_WCD_A_QFUSE_STATUS] = 1,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT0] = 1,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT1] = 1,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT2] = 1,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT3] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_TX1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_TX2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_CTL] = 1,
+ [MSM8X10_WCD_A_DIGITAL_DEBUG_CTL] = 1,
+ [MSM8X10_WCD_A_ANALOG_DEBUG_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_CTL] = 1,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA0] = 1,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA1] = 1,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA2] = 1,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA3] = 1,
+ [MSM8X10_WCD_A_SPARE_0] = 1,
+ [MSM8X10_WCD_A_SPARE_1] = 1,
+ [MSM8X10_WCD_A_SPARE_2] = 1,
+ [MSM8X10_WCD_A_INTR_MODE] = 1,
+ [MSM8X10_WCD_A_INTR_MASK0] = 1,
+ [MSM8X10_WCD_A_INTR_MASK1] = 1,
+ [MSM8X10_WCD_A_INTR_MASK2] = 1,
+ [MSM8X10_WCD_A_INTR_STATUS0] = 1,
+ [MSM8X10_WCD_A_INTR_STATUS1] = 1,
+ [MSM8X10_WCD_A_INTR_STATUS2] = 1,
+ [MSM8X10_WCD_A_INTR_CLEAR0] = 0,
+ [MSM8X10_WCD_A_INTR_CLEAR1] = 0,
+ [MSM8X10_WCD_A_INTR_CLEAR2] = 0,
+ [MSM8X10_WCD_A_INTR_TEST0] = 1,
+ [MSM8X10_WCD_A_INTR_TEST1] = 1,
+ [MSM8X10_WCD_A_INTR_TEST2] = 1,
+ [MSM8X10_WCD_A_INTR_SET0] = 1,
+ [MSM8X10_WCD_A_INTR_SET1] = 1,
+ [MSM8X10_WCD_A_INTR_SET2] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_EN_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_FIR_B1_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_FIR_B2_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B1_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B2_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B3_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B4_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B5_STATUS] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_CLK_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_INT_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_DEBUG_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_MBHC_SPARE] = 1,
+ [MSM8X10_WCD_A_BIAS_REF_CTL] = 1,
+ [MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL] = 1,
+ [MSM8X10_WCD_A_BIAS_PRECHRG_CTL] = 1,
+ [MSM8X10_WCD_A_BIAS_CURR_CTL_1] = 1,
+ [MSM8X10_WCD_A_BIAS_CURR_CTL_2] = 1,
+ [MSM8X10_WCD_A_BIAS_OSC_BG_CTL] = 1,
+ [MSM8X10_WCD_A_MICB_CFILT_1_CTL] = 1,
+ [MSM8X10_WCD_A_MICB_CFILT_1_VAL] = 1,
+ [MSM8X10_WCD_A_MICB_CFILT_1_PRECHRG] = 1,
+ [MSM8X10_WCD_A_MICB_1_CTL] = 1,
+ [MSM8X10_WCD_A_MICB_1_INT_RBIAS] = 1,
+ [MSM8X10_WCD_A_MICB_1_MBHC] = 1,
+ [MSM8X10_WCD_A_MBHC_INSERT_DETECT] = 1,
+ [MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS] = 1,
+ [MSM8X10_WCD_A_TX_COM_BIAS] = 1,
+ [MSM8X10_WCD_A_MBHC_SCALING_MUX_1] = 1,
+ [MSM8X10_WCD_A_MBHC_SCALING_MUX_2] = 1,
+ [MSM8X10_WCD_A_RESERVED_MAD_ANA_CTRL] = 1,
+ [MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1] = 1,
+ [MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_2] = 1,
+ [MSM8X10_WCD_A_TX_1_EN] = 1,
+ [MSM8X10_WCD_A_TX_2_EN] = 1,
+ [MSM8X10_WCD_A_TX_1_2_ADC_CH1] = 1,
+ [MSM8X10_WCD_A_TX_1_2_ADC_CH2] = 1,
+ [MSM8X10_WCD_A_TX_1_2_ATEST_REFCTRL] = 1,
+ [MSM8X10_WCD_A_TX_1_2_TEST_CTL] = 1,
+ [MSM8X10_WCD_A_TX_1_2_TEST_BLOCK_EN] = 1,
+ [MSM8X10_WCD_A_TX_1_2_TXFE_CLKDIV] = 1,
+ [MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH1] = 1,
+ [MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH2] = 1,
+ [MSM8X10_WCD_A_TX_3_EN] = 1,
+ [MSM8X10_WCD_A_TX_1_2_TEST_EN] = 1,
+ [MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL] = 1,
+ [MSM8X10_WCD_A_TX_7_MBHC_SAR_ERR] = 1,
+ [MSM8X10_WCD_A_CP_EN] = 1,
+ [MSM8X10_WCD_A_CP_CLK] = 1,
+ [MSM8X10_WCD_A_CP_STATIC] = 1,
+ [MSM8X10_WCD_A_CP_DCC1] = 1,
+ [MSM8X10_WCD_A_CP_DCC3] = 1,
+ [MSM8X10_WCD_A_CP_ATEST] = 1,
+ [MSM8X10_WCD_A_CP_DTEST] = 1,
+ [MSM8X10_WCD_A_RX_AUX_SW_CTL] = 1,
+ [MSM8X10_WCD_A_RX_PA_AUX_IN_CONN] = 1,
+ [MSM8X10_WCD_A_RX_COM_TIMER_DIV] = 1,
+ [MSM8X10_WCD_A_RX_COM_OCP_CTL] = 1,
+ [MSM8X10_WCD_A_RX_COM_OCP_COUNT] = 1,
+ [MSM8X10_WCD_A_RX_COM_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_RX_COM_BIAS] = 1,
+ [MSM8X10_WCD_A_RX_HPH_AUTO_CHOP] = 1,
+ [MSM8X10_WCD_A_RX_HPH_CHOP_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_PA] = 1,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_LDO] = 1,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_CNP] = 1,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP] = 1,
+ [MSM8X10_WCD_A_RX_HPH_OCP_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_CNP_EN] = 1,
+ [MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_GAIN] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_TEST] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_PA_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_ATEST] = 1,
+ [MSM8X10_WCD_A_RX_HPH_L_STATUS] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_GAIN] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_TEST] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_PA_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_ATEST] = 1,
+ [MSM8X10_WCD_A_RX_HPH_R_STATUS] = 1,
+ [MSM8X10_WCD_A_RX_EAR_BIAS_PA] = 1,
+ [MSM8X10_WCD_A_RX_EAR_BIAS_CMBUFF] = 1,
+ [MSM8X10_WCD_A_RX_EAR_EN] = 1,
+ [MSM8X10_WCD_A_RX_EAR_GAIN] = 1,
+ [MSM8X10_WCD_A_RX_EAR_CMBUFF] = 1,
+ [MSM8X10_WCD_A_RX_EAR_ICTL] = 1,
+ [MSM8X10_WCD_A_RX_EAR_CCOMP] = 1,
+ [MSM8X10_WCD_A_RX_EAR_VCM] = 1,
+ [MSM8X10_WCD_A_RX_EAR_CNP] = 1,
+ [MSM8X10_WCD_A_RX_EAR_DAC_CTL_ATEST] = 1,
+ [MSM8X10_WCD_A_RX_EAR_STATUS] = 1,
+ [MSM8X10_WCD_A_RX_LINE_BIAS_PA] = 1,
+ [MSM8X10_WCD_A_RX_BUCK_BIAS1] = 1,
+ [MSM8X10_WCD_A_RX_BUCK_BIAS2] = 1,
+ [MSM8X10_WCD_A_RX_LINE_COM] = 1,
+ [MSM8X10_WCD_A_RX_LINE_CNP_EN] = 1,
+ [MSM8X10_WCD_A_RX_LINE_CNP_WG_CTL] = 1,
+ [MSM8X10_WCD_A_RX_LINE_CNP_WG_TIME] = 1,
+ [MSM8X10_WCD_A_RX_LINE_1_GAIN] = 1,
+ [MSM8X10_WCD_A_RX_LINE_1_TEST] = 1,
+ [MSM8X10_WCD_A_RX_LINE_1_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_RX_LINE_1_STATUS] = 1,
+ [MSM8X10_WCD_A_RX_LINE_CNP_DBG] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_EN] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_GAIN] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_DAC_CTL] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_OCP_CTL] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_CLIP_DET] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_IEC] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_DAC] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_PA] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_PWRSTG] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_LDO] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_INT] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_PA] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_STATUS_OCP] = 1,
+ [MSM8X10_WCD_A_SPKR_DRV_STATUS_PA] = 1,
+ [MSM8X10_WCD_A_RC_OSC_FREQ] = 1,
+ [MSM8X10_WCD_A_RC_OSC_TEST] = 1,
+ [MSM8X10_WCD_A_RC_OSC_STATUS] = 1,
+ [MSM8X10_WCD_A_RC_OSC_TUNER] = 1,
+ [MSM8X10_WCD_A_MBHC_HPH] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_OTHR_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_MCLK_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_PDM_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLK_SD_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_GAIN_THRESH_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_TIMER_B1_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_TIMER_B2_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_CLSG_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_TIMER] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_CFG] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_MUX_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_MUX_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_CLK_FS_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_CLK_FS_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX1_DMIC_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TX2_DMIC_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B5_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B6_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B7_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B8_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_TIMER_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_COEF_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B3_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B4_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_CONN_TX_I2S_SD1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_TOP_GAIN_UPDATE] = 1,
+ [MSM8X10_WCD_A_CDC_TOP_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DEBUG_DESER1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DEBUG_DESER2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DEBUG_B1_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DEBUG_B2_CTL] = 1,
+ [MSM8X10_WCD_A_CDC_DEBUG_B3_CTL] = 1,
+};
+
+const u8 msm8x10_wcd_reset_reg_defaults[MSM8X10_WCD_CACHE_SIZE] = {
+ [MSM8X10_WCD_A_CHIP_CTL] = MSM8X10_WCD_A_CHIP_CTL__POR,
+ [MSM8X10_WCD_A_CHIP_STATUS] = MSM8X10_WCD_A_CHIP_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_TLMM_MODE_SELECT] =
+ MSM8X10_WCD_A_CDC_TLMM_MODE_SELECT__POR,
+ [MSM8X10_WCD_A_MODE_LOCK] = MSM8X10_WCD_A_MODE_LOCK__POR,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_0] = MSM8X10_WCD_A_CHIP_ID_BYTE_0__POR,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_1] = MSM8X10_WCD_A_CHIP_ID_BYTE_1__POR,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_2] = MSM8X10_WCD_A_CHIP_ID_BYTE_2__POR,
+ [MSM8X10_WCD_A_CHIP_ID_BYTE_3] = MSM8X10_WCD_A_CHIP_ID_BYTE_3__POR,
+ [MSM8X10_WCD_A_CHIP_VERSION] = MSM8X10_WCD_A_CHIP_VERSION__POR,
+ [MSM8X10_WCD_A_ANALOG_SLAVE_ID] = MSM8X10_WCD_A_ANALOG_SLAVE_ID__POR,
+ [MSM8X10_WCD_A_PIN_CTL_OE] = MSM8X10_WCD_A_PIN_CTL_OE__POR,
+ [MSM8X10_WCD_A_PIN_CTL_DATA] = MSM8X10_WCD_A_PIN_CTL_DATA__POR,
+ [MSM8X10_WCD_A_PIN_STATUS] = MSM8X10_WCD_A_PIN_STATUS__POR,
+ [MSM8X10_WCD_A_HDRIVE_CTL] = MSM8X10_WCD_A_HDRIVE_CTL__POR,
+ [MSM8X10_WCD_A_HDRIVE_I2C_CTL] = MSM8X10_WCD_A_HDRIVE_I2C_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RST_CTL] = MSM8X10_WCD_A_CDC_RST_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TOP_CLK_CTL] = MSM8X10_WCD_A_CDC_TOP_CLK_CTL__POR,
+ [MSM8X10_WCD_A_CDC_ANA_CLK_CTL] = MSM8X10_WCD_A_CDC_ANA_CLK_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DIG_CLK_CTL] = MSM8X10_WCD_A_CDC_DIG_CLK_CTL__POR,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL0] =
+ MSM8X10_WCD_A_PROCESS_MONITOR_CTL0__POR,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL1] =
+ MSM8X10_WCD_A_PROCESS_MONITOR_CTL1__POR,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL2] =
+ MSM8X10_WCD_A_PROCESS_MONITOR_CTL2__POR,
+ [MSM8X10_WCD_A_PROCESS_MONITOR_CTL3] =
+ MSM8X10_WCD_A_PROCESS_MONITOR_CTL3__POR,
+ [MSM8X10_WCD_A_QFUSE_CTL] = MSM8X10_WCD_A_QFUSE_CTL__POR,
+ [MSM8X10_WCD_A_QFUSE_STATUS] = MSM8X10_WCD_A_QFUSE_STATUS__POR,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT0] = MSM8X10_WCD_A_QFUSE_DATA_OUT0__POR,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT1] = MSM8X10_WCD_A_QFUSE_DATA_OUT1__POR,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT2] = MSM8X10_WCD_A_QFUSE_DATA_OUT2__POR,
+ [MSM8X10_WCD_A_QFUSE_DATA_OUT3] = MSM8X10_WCD_A_QFUSE_DATA_OUT3__POR,
+ [MSM8X10_WCD_A_CDC_CONN_TX1_CTL] = MSM8X10_WCD_A_CDC_CONN_TX1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_TX2_CTL] = MSM8X10_WCD_A_CDC_CONN_TX2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_CTL] = MSM8X10_WCD_A_CDC_CONN_RX1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_CTL] = MSM8X10_WCD_A_CDC_CONN_RX2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_CTL] = MSM8X10_WCD_A_CDC_CONN_RX3_CTL__POR,
+ [MSM8X10_WCD_A_DIGITAL_DEBUG_CTL] =
+ MSM8X10_WCD_A_DIGITAL_DEBUG_CTL__POR,
+ [MSM8X10_WCD_A_ANALOG_DEBUG_CTL] = MSM8X10_WCD_A_ANALOG_DEBUG_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_CTL] = MSM8X10_WCD_A_CDC_RX1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_CTL] = MSM8X10_WCD_A_CDC_RX2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_CTL] = MSM8X10_WCD_A_CDC_RX3_CTL__POR,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA0] = MSM8X10_WCD_A_DEM_BYPASS_DATA0__POR,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA1] = MSM8X10_WCD_A_DEM_BYPASS_DATA1__POR,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA2] = MSM8X10_WCD_A_DEM_BYPASS_DATA2__POR,
+ [MSM8X10_WCD_A_DEM_BYPASS_DATA3] = MSM8X10_WCD_A_DEM_BYPASS_DATA3__POR,
+ [MSM8X10_WCD_A_SPARE_0] = MSM8X10_WCD_A_SPARE_0__POR,
+ [MSM8X10_WCD_A_SPARE_1] = MSM8X10_WCD_A_SPARE_1__POR,
+ [MSM8X10_WCD_A_SPARE_2] = MSM8X10_WCD_A_SPARE_2__POR,
+ [MSM8X10_WCD_A_INTR_MODE] = MSM8X10_WCD_A_INTR_MODE__POR,
+ [MSM8X10_WCD_A_INTR_MASK0] = MSM8X10_WCD_A_INTR_MASK0__POR,
+ [MSM8X10_WCD_A_INTR_MASK1] = MSM8X10_WCD_A_INTR_MASK1__POR,
+ [MSM8X10_WCD_A_INTR_MASK2] = MSM8X10_WCD_A_INTR_MASK2__POR,
+ [MSM8X10_WCD_A_INTR_STATUS0] = MSM8X10_WCD_A_INTR_STATUS0__POR,
+ [MSM8X10_WCD_A_INTR_STATUS1] = MSM8X10_WCD_A_INTR_STATUS1__POR,
+ [MSM8X10_WCD_A_INTR_STATUS2] = MSM8X10_WCD_A_INTR_STATUS2__POR,
+ [MSM8X10_WCD_A_INTR_CLEAR0] = MSM8X10_WCD_A_INTR_CLEAR0__POR,
+ [MSM8X10_WCD_A_INTR_CLEAR1] = MSM8X10_WCD_A_INTR_CLEAR1__POR,
+ [MSM8X10_WCD_A_INTR_CLEAR2] = MSM8X10_WCD_A_INTR_CLEAR2__POR,
+ [MSM8X10_WCD_A_INTR_TEST0] = MSM8X10_WCD_A_INTR_TEST0__POR,
+ [MSM8X10_WCD_A_INTR_TEST1] = MSM8X10_WCD_A_INTR_TEST1__POR,
+ [MSM8X10_WCD_A_INTR_TEST2] = MSM8X10_WCD_A_INTR_TEST2__POR,
+ [MSM8X10_WCD_A_INTR_SET0] = MSM8X10_WCD_A_INTR_SET0__POR,
+ [MSM8X10_WCD_A_INTR_SET1] = MSM8X10_WCD_A_INTR_SET1__POR,
+ [MSM8X10_WCD_A_INTR_SET2] = MSM8X10_WCD_A_INTR_SET2__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_EN_CTL] = MSM8X10_WCD_A_CDC_MBHC_EN_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_FIR_B1_CFG] =
+ MSM8X10_WCD_A_CDC_MBHC_FIR_B1_CFG__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_FIR_B2_CFG] =
+ MSM8X10_WCD_A_CDC_MBHC_FIR_B2_CFG__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B1_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B2_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B3_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B4_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B5_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_TIMER_B6_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_TIMER_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B1_STATUS] =
+ MSM8X10_WCD_A_CDC_MBHC_B1_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B2_STATUS] =
+ MSM8X10_WCD_A_CDC_MBHC_B2_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B3_STATUS] =
+ MSM8X10_WCD_A_CDC_MBHC_B3_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B4_STATUS] =
+ MSM8X10_WCD_A_CDC_MBHC_B4_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B5_STATUS] =
+ MSM8X10_WCD_A_CDC_MBHC_B5_STATUS__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B1_CTL] = MSM8X10_WCD_A_CDC_MBHC_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_B2_CTL] = MSM8X10_WCD_A_CDC_MBHC_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B1_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B2_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B3_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B4_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B5_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B6_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B7_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B7_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B8_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B8_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B9_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B9_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B10_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B10_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B11_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B11_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_VOLT_B12_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_VOLT_B12_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_CLK_CTL] = MSM8X10_WCD_A_CDC_MBHC_CLK_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_INT_CTL] = MSM8X10_WCD_A_CDC_MBHC_INT_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_DEBUG_CTL] =
+ MSM8X10_WCD_A_CDC_MBHC_DEBUG_CTL__POR,
+ [MSM8X10_WCD_A_CDC_MBHC_SPARE] = MSM8X10_WCD_A_CDC_MBHC_SPARE__POR,
+ [MSM8X10_WCD_A_BIAS_REF_CTL] = MSM8X10_WCD_A_BIAS_REF_CTL__POR,
+ [MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL] =
+ MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL__POR,
+ [MSM8X10_WCD_A_BIAS_PRECHRG_CTL] = MSM8X10_WCD_A_BIAS_PRECHRG_CTL__POR,
+ [MSM8X10_WCD_A_BIAS_CURR_CTL_1] = MSM8X10_WCD_A_BIAS_CURR_CTL_1__POR,
+ [MSM8X10_WCD_A_BIAS_CURR_CTL_2] = MSM8X10_WCD_A_BIAS_CURR_CTL_2__POR,
+ [MSM8X10_WCD_A_BIAS_OSC_BG_CTL] = MSM8X10_WCD_A_BIAS_OSC_BG_CTL__POR,
+ [MSM8X10_WCD_A_MICB_CFILT_1_CTL] = MSM8X10_WCD_A_MICB_CFILT_1_CTL__POR,
+ [MSM8X10_WCD_A_MICB_CFILT_1_VAL] = MSM8X10_WCD_A_MICB_CFILT_1_VAL__POR,
+ [MSM8X10_WCD_A_MICB_CFILT_1_PRECHRG] =
+ MSM8X10_WCD_A_MICB_CFILT_1_PRECHRG__POR,
+ [MSM8X10_WCD_A_MICB_1_CTL] = MSM8X10_WCD_A_MICB_1_CTL__POR,
+ [MSM8X10_WCD_A_MICB_1_INT_RBIAS] = MSM8X10_WCD_A_MICB_1_INT_RBIAS__POR,
+ [MSM8X10_WCD_A_MICB_1_MBHC] = MSM8X10_WCD_A_MICB_1_MBHC__POR,
+ [MSM8X10_WCD_A_MBHC_INSERT_DETECT] =
+ MSM8X10_WCD_A_MBHC_INSERT_DETECT__POR,
+ [MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS] =
+ MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS__POR,
+ [MSM8X10_WCD_A_TX_COM_BIAS] = MSM8X10_WCD_A_TX_COM_BIAS__POR,
+ [MSM8X10_WCD_A_MBHC_SCALING_MUX_1] =
+ MSM8X10_WCD_A_MBHC_SCALING_MUX_1__POR,
+ [MSM8X10_WCD_A_MBHC_SCALING_MUX_2] =
+ MSM8X10_WCD_A_MBHC_SCALING_MUX_2__POR,
+ [MSM8X10_WCD_A_RESERVED_MAD_ANA_CTRL] =
+ MSM8X10_WCD_A_RESERVED_MAD_ANA_CTRL__POR,
+ [MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1] =
+ MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1__POR,
+ [MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_2] =
+ MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_2__POR,
+ [MSM8X10_WCD_A_TX_1_EN] = MSM8X10_WCD_A_TX_1_EN__POR,
+ [MSM8X10_WCD_A_TX_2_EN] = MSM8X10_WCD_A_TX_2_EN__POR,
+ [MSM8X10_WCD_A_TX_1_2_ADC_CH1] = MSM8X10_WCD_A_TX_1_2_ADC_CH1__POR,
+ [MSM8X10_WCD_A_TX_1_2_ADC_CH2] = MSM8X10_WCD_A_TX_1_2_ADC_CH2__POR,
+ [MSM8X10_WCD_A_TX_1_2_ATEST_REFCTRL] =
+ MSM8X10_WCD_A_TX_1_2_ATEST_REFCTRL__POR,
+ [MSM8X10_WCD_A_TX_1_2_TEST_CTL] =
+ MSM8X10_WCD_A_TX_1_2_TEST_CTL__POR,
+ [MSM8X10_WCD_A_TX_1_2_TEST_BLOCK_EN] =
+ MSM8X10_WCD_A_TX_1_2_TEST_BLOCK_EN__POR,
+ [MSM8X10_WCD_A_TX_1_2_TXFE_CLKDIV] =
+ MSM8X10_WCD_A_TX_1_2_TXFE_CLKDIV__POR,
+ [MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH1] =
+ MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH1__POR,
+ [MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH2] =
+ MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH2__POR,
+ [MSM8X10_WCD_A_TX_3_EN] = MSM8X10_WCD_A_TX_3_EN__POR,
+ [MSM8X10_WCD_A_TX_1_2_TEST_EN] = MSM8X10_WCD_A_TX_1_2_TEST_EN__POR,
+ [MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL] =
+ MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL__POR,
+ [MSM8X10_WCD_A_TX_7_MBHC_SAR_ERR] =
+ MSM8X10_WCD_A_TX_7_MBHC_SAR_ERR__POR,
+ [MSM8X10_WCD_A_CP_EN] = MSM8X10_WCD_A_CP_EN__POR,
+ [MSM8X10_WCD_A_CP_CLK] = MSM8X10_WCD_A_CP_CLK__POR,
+ [MSM8X10_WCD_A_CP_STATIC] = MSM8X10_WCD_A_CP_STATIC__POR,
+ [MSM8X10_WCD_A_CP_DCC1] = MSM8X10_WCD_A_CP_DCC1__POR,
+ [MSM8X10_WCD_A_CP_DCC3] = MSM8X10_WCD_A_CP_DCC3__POR,
+ [MSM8X10_WCD_A_CP_ATEST] = MSM8X10_WCD_A_CP_ATEST__POR,
+ [MSM8X10_WCD_A_CP_DTEST] = MSM8X10_WCD_A_CP_DTEST__POR,
+ [MSM8X10_WCD_A_RX_AUX_SW_CTL] = MSM8X10_WCD_A_RX_AUX_SW_CTL__POR,
+ [MSM8X10_WCD_A_RX_PA_AUX_IN_CONN] =
+ MSM8X10_WCD_A_RX_PA_AUX_IN_CONN__POR,
+ [MSM8X10_WCD_A_RX_COM_TIMER_DIV] = MSM8X10_WCD_A_RX_COM_TIMER_DIV__POR,
+ [MSM8X10_WCD_A_RX_COM_OCP_CTL] = MSM8X10_WCD_A_RX_COM_OCP_CTL__POR,
+ [MSM8X10_WCD_A_RX_COM_OCP_COUNT] = MSM8X10_WCD_A_RX_COM_OCP_COUNT__POR,
+ [MSM8X10_WCD_A_RX_COM_DAC_CTL] = MSM8X10_WCD_A_RX_COM_DAC_CTL__POR,
+ [MSM8X10_WCD_A_RX_COM_BIAS] = MSM8X10_WCD_A_RX_COM_BIAS__POR,
+ [MSM8X10_WCD_A_RX_HPH_AUTO_CHOP] = MSM8X10_WCD_A_RX_HPH_AUTO_CHOP__POR,
+ [MSM8X10_WCD_A_RX_HPH_CHOP_CTL] = MSM8X10_WCD_A_RX_HPH_CHOP_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_PA] = MSM8X10_WCD_A_RX_HPH_BIAS_PA__POR,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_LDO] = MSM8X10_WCD_A_RX_HPH_BIAS_LDO__POR,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_CNP] = MSM8X10_WCD_A_RX_HPH_BIAS_CNP__POR,
+ [MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP] =
+ MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP__POR,
+ [MSM8X10_WCD_A_RX_HPH_OCP_CTL] = MSM8X10_WCD_A_RX_HPH_OCP_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_CNP_EN] = MSM8X10_WCD_A_RX_HPH_CNP_EN__POR,
+ [MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL] =
+ MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME] =
+ MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_GAIN] = MSM8X10_WCD_A_RX_HPH_L_GAIN__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_TEST] = MSM8X10_WCD_A_RX_HPH_L_TEST__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_PA_CTL] = MSM8X10_WCD_A_RX_HPH_L_PA_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_DAC_CTL] =
+ MSM8X10_WCD_A_RX_HPH_L_DAC_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_ATEST] = MSM8X10_WCD_A_RX_HPH_L_ATEST__POR,
+ [MSM8X10_WCD_A_RX_HPH_L_STATUS] = MSM8X10_WCD_A_RX_HPH_L_STATUS__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_GAIN] = MSM8X10_WCD_A_RX_HPH_R_GAIN__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_TEST] = MSM8X10_WCD_A_RX_HPH_R_TEST__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_PA_CTL] = MSM8X10_WCD_A_RX_HPH_R_PA_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_DAC_CTL] = MSM8X10_WCD_A_RX_HPH_R_DAC_CTL__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_ATEST] = MSM8X10_WCD_A_RX_HPH_R_ATEST__POR,
+ [MSM8X10_WCD_A_RX_HPH_R_STATUS] = MSM8X10_WCD_A_RX_HPH_R_STATUS__POR,
+ [MSM8X10_WCD_A_RX_EAR_BIAS_PA] = MSM8X10_WCD_A_RX_EAR_BIAS_PA__POR,
+ [MSM8X10_WCD_A_RX_EAR_BIAS_CMBUFF] =
+ MSM8X10_WCD_A_RX_EAR_BIAS_CMBUFF__POR,
+ [MSM8X10_WCD_A_RX_EAR_EN] = MSM8X10_WCD_A_RX_EAR_EN__POR,
+ [MSM8X10_WCD_A_RX_EAR_GAIN] = MSM8X10_WCD_A_RX_EAR_GAIN__POR,
+ [MSM8X10_WCD_A_RX_EAR_CMBUFF] = MSM8X10_WCD_A_RX_EAR_CMBUFF__POR,
+ [MSM8X10_WCD_A_RX_EAR_ICTL] = MSM8X10_WCD_A_RX_EAR_ICTL__POR,
+ [MSM8X10_WCD_A_RX_EAR_CCOMP] = MSM8X10_WCD_A_RX_EAR_CCOMP__POR,
+ [MSM8X10_WCD_A_RX_EAR_VCM] = MSM8X10_WCD_A_RX_EAR_VCM__POR,
+ [MSM8X10_WCD_A_RX_EAR_CNP] = MSM8X10_WCD_A_RX_EAR_CNP__POR,
+ [MSM8X10_WCD_A_RX_EAR_DAC_CTL_ATEST] =
+ MSM8X10_WCD_A_RX_EAR_DAC_CTL_ATEST__POR,
+ [MSM8X10_WCD_A_RX_EAR_STATUS] = MSM8X10_WCD_A_RX_EAR_STATUS__POR,
+ [MSM8X10_WCD_A_RX_LINE_BIAS_PA] =
+ MSM8X10_WCD_A_RX_LINE_BIAS_PA__POR,
+ [MSM8X10_WCD_A_RX_BUCK_BIAS1] = MSM8X10_WCD_A_RX_BUCK_BIAS1__POR,
+ [MSM8X10_WCD_A_RX_BUCK_BIAS2] = MSM8X10_WCD_A_RX_BUCK_BIAS2__POR,
+ [MSM8X10_WCD_A_RX_LINE_COM] = MSM8X10_WCD_A_RX_LINE_COM__POR,
+ [MSM8X10_WCD_A_RX_LINE_CNP_EN] = MSM8X10_WCD_A_RX_LINE_CNP_EN__POR,
+ [MSM8X10_WCD_A_RX_LINE_CNP_WG_CTL] =
+ MSM8X10_WCD_A_RX_LINE_CNP_WG_CTL__POR,
+ [MSM8X10_WCD_A_RX_LINE_CNP_WG_TIME] =
+ MSM8X10_WCD_A_RX_LINE_CNP_WG_TIME__POR,
+ [MSM8X10_WCD_A_RX_LINE_1_GAIN] = MSM8X10_WCD_A_RX_LINE_1_GAIN__POR,
+ [MSM8X10_WCD_A_RX_LINE_1_TEST] = MSM8X10_WCD_A_RX_LINE_1_TEST__POR,
+ [MSM8X10_WCD_A_RX_LINE_1_DAC_CTL] =
+ MSM8X10_WCD_A_RX_LINE_1_DAC_CTL__POR,
+ [MSM8X10_WCD_A_RX_LINE_1_STATUS] =
+ MSM8X10_WCD_A_RX_LINE_1_STATUS__POR,
+ [MSM8X10_WCD_A_RX_LINE_CNP_DBG] = MSM8X10_WCD_A_RX_LINE_CNP_DBG__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_EN] = MSM8X10_WCD_A_SPKR_DRV_EN__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_GAIN] = MSM8X10_WCD_A_SPKR_DRV_GAIN__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_DAC_CTL] = MSM8X10_WCD_A_SPKR_DRV_DAC_CTL__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_OCP_CTL] = MSM8X10_WCD_A_SPKR_DRV_OCP_CTL__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_CLIP_DET] =
+ MSM8X10_WCD_A_SPKR_DRV_CLIP_DET__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_IEC] = MSM8X10_WCD_A_SPKR_DRV_IEC__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_DAC] = MSM8X10_WCD_A_SPKR_DRV_DBG_DAC__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_PA] = MSM8X10_WCD_A_SPKR_DRV_DBG_PA__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_DBG_PWRSTG] =
+ MSM8X10_WCD_A_SPKR_DRV_DBG_PWRSTG__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_LDO] =
+ MSM8X10_WCD_A_SPKR_DRV_BIAS_LDO__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_INT] =
+ MSM8X10_WCD_A_SPKR_DRV_BIAS_INT__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_BIAS_PA] = MSM8X10_WCD_A_SPKR_DRV_BIAS_PA__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_STATUS_OCP] =
+ MSM8X10_WCD_A_SPKR_DRV_STATUS_OCP__POR,
+ [MSM8X10_WCD_A_SPKR_DRV_STATUS_PA] =
+ MSM8X10_WCD_A_SPKR_DRV_STATUS_PA__POR,
+ [MSM8X10_WCD_A_RC_OSC_FREQ] = MSM8X10_WCD_A_RC_OSC_FREQ__POR,
+ [MSM8X10_WCD_A_RC_OSC_TEST] = MSM8X10_WCD_A_RC_OSC_TEST__POR,
+ [MSM8X10_WCD_A_RC_OSC_STATUS] = MSM8X10_WCD_A_RC_OSC_STATUS__POR,
+ [MSM8X10_WCD_A_RC_OSC_TUNER] = MSM8X10_WCD_A_RC_OSC_TUNER__POR,
+ [MSM8X10_WCD_A_MBHC_HPH] = MSM8X10_WCD_A_MBHC_HPH__POR,
+ [MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_OTHR_CTL] = MSM8X10_WCD_A_CDC_CLK_OTHR_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_MCLK_CTL] = MSM8X10_WCD_A_CDC_CLK_MCLK_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_PDM_CTL] = MSM8X10_WCD_A_CDC_CLK_PDM_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLK_SD_CTL] = MSM8X10_WCD_A_CDC_CLK_SD_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B1_CTL] = MSM8X10_WCD_A_CDC_RX1_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B1_CTL] = MSM8X10_WCD_A_CDC_RX2_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B1_CTL] = MSM8X10_WCD_A_CDC_RX3_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B2_CTL] = MSM8X10_WCD_A_CDC_RX1_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B2_CTL] = MSM8X10_WCD_A_CDC_RX2_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B2_CTL] = MSM8X10_WCD_A_CDC_RX3_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B3_CTL] = MSM8X10_WCD_A_CDC_RX1_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B3_CTL] = MSM8X10_WCD_A_CDC_RX2_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B3_CTL] = MSM8X10_WCD_A_CDC_RX3_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B4_CTL] = MSM8X10_WCD_A_CDC_RX1_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B4_CTL] = MSM8X10_WCD_A_CDC_RX2_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B4_CTL] = MSM8X10_WCD_A_CDC_RX3_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B5_CTL] = MSM8X10_WCD_A_CDC_RX1_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B5_CTL] = MSM8X10_WCD_A_CDC_RX2_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B5_CTL] = MSM8X10_WCD_A_CDC_RX3_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_B6_CTL] = MSM8X10_WCD_A_CDC_RX1_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_B6_CTL] = MSM8X10_WCD_A_CDC_RX2_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_B6_CTL] = MSM8X10_WCD_A_CDC_RX3_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B1_CTL] =
+ MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B1_CTL] =
+ MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B1_CTL] =
+ MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL] =
+ MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL] =
+ MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL] =
+ MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B3_CTL] =
+ MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B4_CTL] =
+ MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_GAIN_THRESH_CTL] =
+ MSM8X10_WCD_A_CDC_CLSG_GAIN_THRESH_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_TIMER_B1_CFG] =
+ MSM8X10_WCD_A_CDC_CLSG_TIMER_B1_CFG__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_TIMER_B2_CFG] =
+ MSM8X10_WCD_A_CDC_CLSG_TIMER_B2_CFG__POR,
+ [MSM8X10_WCD_A_CDC_CLSG_CTL] = MSM8X10_WCD_A_CDC_CLSG_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_TIMER] =
+ MSM8X10_WCD_A_CDC_TX1_VOL_CTL_TIMER__POR,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_TIMER] =
+ MSM8X10_WCD_A_CDC_TX2_VOL_CTL_TIMER__POR,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN] =
+ MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN__POR,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN] =
+ MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN__POR,
+ [MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG] =
+ MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG__POR,
+ [MSM8X10_WCD_A_CDC_TX2_VOL_CTL_CFG] =
+ MSM8X10_WCD_A_CDC_TX2_VOL_CTL_CFG__POR,
+ [MSM8X10_WCD_A_CDC_TX1_MUX_CTL] =
+ MSM8X10_WCD_A_CDC_TX1_MUX_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX2_MUX_CTL] =
+ MSM8X10_WCD_A_CDC_TX2_MUX_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX1_CLK_FS_CTL] =
+ MSM8X10_WCD_A_CDC_TX1_CLK_FS_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX2_CLK_FS_CTL] =
+ MSM8X10_WCD_A_CDC_TX2_CLK_FS_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX1_DMIC_CTL] =
+ MSM8X10_WCD_A_CDC_TX1_DMIC_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TX2_DMIC_CTL] =
+ MSM8X10_WCD_A_CDC_TX2_DMIC_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B1_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B2_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B3_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B4_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B5_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B5_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B5_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B6_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B6_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B6_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B7_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B7_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B7_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B7_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_B8_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B8_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_B8_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_B8_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_CTL] = MSM8X10_WCD_A_CDC_IIR1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_CTL] = MSM8X10_WCD_A_CDC_IIR2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_GAIN_TIMER_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_GAIN_TIMER_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_GAIN_TIMER_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_COEF_B1_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_COEF_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL] =
+ MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL] =
+ MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX2_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_RX3_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_RX3_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ1_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B3_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ1_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ1_B4_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ1_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ2_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B2_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ2_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B3_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ2_B3_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_EQ2_B4_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_EQ2_B4_CTL__POR,
+ [MSM8X10_WCD_A_CDC_CONN_TX_I2S_SD1_CTL] =
+ MSM8X10_WCD_A_CDC_CONN_TX_I2S_SD1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_TOP_GAIN_UPDATE] =
+ MSM8X10_WCD_A_CDC_TOP_GAIN_UPDATE__POR,
+ [MSM8X10_WCD_A_CDC_TOP_CTL] = MSM8X10_WCD_A_CDC_TOP_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DEBUG_DESER1_CTL] =
+ MSM8X10_WCD_A_CDC_DEBUG_DESER1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DEBUG_DESER2_CTL] =
+ MSM8X10_WCD_A_CDC_DEBUG_DESER2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DEBUG_B1_CTL] =
+ MSM8X10_WCD_A_CDC_DEBUG_B1_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DEBUG_B2_CTL] =
+ MSM8X10_WCD_A_CDC_DEBUG_B2_CTL__POR,
+ [MSM8X10_WCD_A_CDC_DEBUG_B3_CTL] =
+ MSM8X10_WCD_A_CDC_DEBUG_B3_CTL__POR,
+};
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
new file mode 100644
index 0000000..4bcea07
--- /dev/null
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -0,0 +1,2427 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include "msm8x10-wcd.h"
+#include "wcd9xxx-resmgr.h"
+#include "msm8x10_wcd_registers.h"
+
+#define MSM8X10_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+#define MSM8X10_WCD_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+
+#define NUM_DECIMATORS 2
+#define NUM_INTERPOLATORS 3
+#define BITS_PER_REG 8
+#define MSM8X10_WCD_TX_PORT_NUMBER 4
+
+#define MSM8X10_WCD_I2S_MASTER_MODE_MASK 0x08
+#define MSM8X10_DINO_CODEC_BASE_ADDR 0xFE043000
+
+#define MAX_MSM8X10_WCD_DEVICE 2
+#define CODEC_DT_MAX_PROP_SIZE 40
+#define MSM8X10_WCD_I2C_GSBI_SLAVE_ID "2-000d"
+
+enum {
+ MSM8X10_WCD_I2C_TOP_LEVEL = 0,
+ MSM8X10_WCD_I2C_ANALOG,
+ MSM8X10_WCD_I2C_DIGITAL_1,
+ MSM8X10_WCD_I2C_DIGITAL_2,
+};
+
+enum {
+ AIF1_PB = 0,
+ AIF1_CAP,
+ NUM_CODEC_DAIS,
+};
+
+enum {
+ RX_MIX1_INP_SEL_ZERO = 0,
+ RX_MIX1_INP_SEL_IIR1,
+ RX_MIX1_INP_SEL_IIR2,
+ RX_MIX1_INP_SEL_RX1,
+ RX_MIX1_INP_SEL_RX2,
+ RX_MIX1_INP_SEL_RX3,
+};
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver msm8x10_wcd_i2s_dai[];
+static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR1 = 0,
+ IIR2,
+ IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+struct hpf_work {
+ struct msm8x10_wcd_priv *msm8x10_wcd;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+struct msm8x10_wcd_priv {
+ struct snd_soc_codec *codec;
+ u32 adc_count;
+ u32 rx_bias_count;
+ s32 dmic_1_2_clk_cnt;
+
+ /* resmgr module */
+ struct wcd9xxx_resmgr resmgr;
+ /* mbhc module */
+ struct wcd9xxx_mbhc mbhc;
+};
+
+
+static unsigned short rx_digital_gain_reg[] = {
+ MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL,
+ MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL,
+ MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL,
+};
+
+static unsigned short tx_digital_gain_reg[] = {
+ MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN,
+ MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN,
+};
+
+struct msm8x10_wcd_i2c {
+ struct i2c_client *client;
+ struct i2c_msg xfer_msg[2];
+ struct mutex xfer_lock;
+ int mod_id;
+};
+
+static char *msm8x10_wcd_supplies[] = {
+ "cdc-vdd-mic-bias", "cdc-vdda-h", "cdc-vdd-1p2", "cdc-vdd-px",
+ "cdc-vdda-cp",
+};
+
+static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x10_wcd_regulator *vreg, const char *vreg_name);
+static int msm8x10_wcd_dt_parse_micbias_info(struct device *dev,
+ struct msm8x10_wcd_micbias_setting *micbias);
+static struct msm8x10_wcd_pdata *msm8x10_wcd_populate_dt_pdata(
+ struct device *dev);
+
+struct msm8x10_wcd_i2c msm8x10_wcd_modules[MAX_MSM8X10_WCD_DEVICE];
+
+
+static int get_i2c_msm8x10_wcd_device_info(u16 reg,
+ struct msm8x10_wcd_i2c **msm8x10_wcd)
+{
+ int rtn = 0;
+ int value = ((reg & 0x0f00) >> 8) & 0x000f;
+ pr_debug("%s: reg(0x%x) value(%d)\n", __func__, reg, value);
+ switch (value) {
+ case 0:
+ case 1:
+ *msm8x10_wcd = &msm8x10_wcd_modules[value];
+ break;
+ default:
+ rtn = -EINVAL;
+ break;
+ }
+ return rtn;
+}
+
+static int msm8x10_wcd_abh_write_device(u16 reg, u8 *value, u32 bytes)
+{
+ u32 temp = ((u32)(*value)) & 0x000000FF;
+ u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
+ iowrite32(temp, ioremap(MSM8X10_DINO_CODEC_BASE_ADDR + offset, 4));
+ return 0;
+}
+
+static int msm8x10_wcd_abh_read_device(u16 reg, u32 bytes, u8 *value)
+{
+ u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
+ *value = (u8)ioread32(ioremap(MSM8X10_DINO_CODEC_BASE_ADDR +
+ offset, 4));
+ return 0;
+}
+
+static int msm8x10_wcd_i2c_write_device(u16 reg, u8 *value, u32 bytes)
+{
+
+ struct i2c_msg *msg;
+ int ret;
+ u8 reg_addr = 0;
+ u8 data[bytes + 1];
+ struct msm8x10_wcd_i2c *msm8x10_wcd;
+
+ ret = get_i2c_msm8x10_wcd_device_info(reg, &msm8x10_wcd);
+ if (!ret) {
+ pr_err("%s: Invalid register address\n", __func__);
+ return ret;
+ }
+
+ if (msm8x10_wcd == NULL || msm8x10_wcd->client == NULL) {
+ pr_err("%s: Failed to get device info\n", __func__);
+ return -ENODEV;
+ }
+ reg_addr = (u8)reg;
+ msg = &msm8x10_wcd->xfer_msg[0];
+ msg->addr = msm8x10_wcd->client->addr;
+ msg->len = bytes + 1;
+ msg->flags = 0;
+ data[0] = reg;
+ data[1] = *value;
+ msg->buf = data;
+ ret = i2c_transfer(msm8x10_wcd->client->adapter,
+ msm8x10_wcd->xfer_msg, 1);
+ /* Try again if the write fails */
+ if (ret != 1) {
+ ret = i2c_transfer(msm8x10_wcd->client->adapter,
+ msm8x10_wcd->xfer_msg, 1);
+ if (ret != 1) {
+ pr_err("failed to write the device\n");
+ return ret;
+ }
+ }
+ pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
+ return 0;
+}
+
+
+int msm8x10_wcd_i2c_read_device(u32 reg, u32 bytes, u8 *dest)
+{
+ struct i2c_msg *msg;
+ int ret = 0;
+ u8 reg_addr = 0;
+ struct msm8x10_wcd_i2c *msm8x10_wcd;
+ u8 i = 0;
+
+ ret = get_i2c_msm8x10_wcd_device_info(reg, &msm8x10_wcd);
+ if (!ret) {
+ pr_err("%s: Invalid register address\n", __func__);
+ return ret;
+ }
+
+ if (msm8x10_wcd == NULL || msm8x10_wcd->client == NULL) {
+ pr_err("%s: Failed to get device info\n", __func__);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < bytes; i++) {
+ reg_addr = (u8)reg++;
+ msg = &msm8x10_wcd->xfer_msg[0];
+ msg->addr = msm8x10_wcd->client->addr;
+ msg->len = 1;
+ msg->flags = 0;
+ msg->buf = ®_addr;
+
+ msg = &msm8x10_wcd->xfer_msg[1];
+ msg->addr = msm8x10_wcd->client->addr;
+ msg->len = 1;
+ msg->flags = I2C_M_RD;
+ msg->buf = dest++;
+ ret = i2c_transfer(msm8x10_wcd->client->adapter,
+ msm8x10_wcd->xfer_msg, 2);
+
+ /* Try again if read fails first time */
+ if (ret != 2) {
+ ret = i2c_transfer(msm8x10_wcd->client->adapter,
+ msm8x10_wcd->xfer_msg, 2);
+ if (ret != 2) {
+ pr_err("failed to read msm8x10_wcd register\n");
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_reg_read(struct msm8x10_wcd *msm8x10_wcd, u16 reg)
+{
+ u8 val;
+ int ret = -EINVAL;
+
+ /* check if use I2C interface for Helicon or AHB for Dino */
+ mutex_lock(&msm8x10_wcd->io_lock);
+ if (MSM8X10_WCD_IS_HELICON_REG(reg))
+ ret = msm8x10_wcd_i2c_read_device(reg, 1, &val);
+ else if (MSM8X10_WCD_IS_DINO_REG(reg))
+ ret = msm8x10_wcd_abh_read_device(reg, 1, &val);
+ mutex_unlock(&msm8x10_wcd->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+
+
+static int msm8x10_wcd_reg_write(struct msm8x10_wcd *msm8x10_wcd, u16 reg,
+ u8 val)
+{
+ int ret = -EINVAL;
+
+ /* check if use I2C interface for Helicon or AHB for Dino */
+ mutex_lock(&msm8x10_wcd->io_lock);
+ if (MSM8X10_WCD_IS_HELICON_REG(reg))
+ ret = msm8x10_wcd_i2c_write_device(reg, &val, 1);
+ else if (MSM8X10_WCD_IS_DINO_REG(reg))
+ ret = msm8x10_wcd_abh_write_device(reg, &val, 1);
+ mutex_unlock(&msm8x10_wcd->io_lock);
+
+ return ret;
+}
+
+static bool msm8x10_wcd_is_digital_gain_register(unsigned int reg)
+{
+ bool rtn = false;
+ switch (reg) {
+ case MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL:
+ case MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL:
+ case MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL:
+ case MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN:
+ case MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN:
+ rtn = true;
+ break;
+ default:
+ break;
+ }
+ return rtn;
+}
+
+static int msm8x10_wcd_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ /*
+ * Registers lower than 0x100 are top level registers which can be
+ * written by the Taiko core driver.
+ */
+
+ if ((reg >= MSM8X10_WCD_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+ return 1;
+
+ /* IIR Coeff registers are not cacheable */
+ if ((reg >= MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL) &&
+ (reg <= MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL))
+ return 1;
+
+ /*
+ * Digital gain register is not cacheable so we have to write
+ * the setting even it is the same
+ */
+ if (msm8x10_wcd_is_digital_gain_register(reg))
+ return 1;
+
+ /* HPH status registers */
+ if (reg == MSM8X10_WCD_A_RX_HPH_L_STATUS ||
+ reg == MSM8X10_WCD_A_RX_HPH_R_STATUS)
+ return 1;
+
+ if (reg == MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS)
+ return 1;
+
+ return 0;
+}
+
+static int msm8x10_wcd_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ return msm8x10_wcd_reg_readable[reg];
+}
+
+static int msm8x10_wcd_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+
+ if (reg == SND_SOC_NOPM)
+ return 0;
+
+ BUG_ON(reg > MSM8X10_WCD_MAX_REGISTER);
+
+ if (!msm8x10_wcd_volatile(codec, reg)) {
+ ret = snd_soc_cache_write(codec, reg, value);
+ if (ret != 0)
+ dev_err(codec->dev, "Cache write to %x failed: %d\n",
+ reg, ret);
+ }
+
+ return msm8x10_wcd_reg_write(codec->control_data, reg, value);
+}
+
+static unsigned int msm8x10_wcd_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned int val;
+ int ret;
+
+ if (reg == SND_SOC_NOPM)
+ return 0;
+
+ BUG_ON(reg > MSM8X10_WCD_MAX_REGISTER);
+
+ if (!msm8x10_wcd_volatile(codec, reg) &&
+ msm8x10_wcd_readable(codec, reg) &&
+ reg < codec->driver->reg_cache_size) {
+ ret = snd_soc_cache_read(codec, reg, &val);
+ if (ret >= 0) {
+ return val;
+ } else
+ dev_err(codec->dev, "Cache read from %x failed: %d\n",
+ reg, ret);
+ }
+
+ val = msm8x10_wcd_reg_read(codec->control_data, reg);
+ return val;
+}
+
+
+static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
+ struct msm8x10_wcd_regulator *vreg, const char *vreg_name)
+{
+ int len, ret = 0;
+ const __be32 *prop;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ struct device_node *regnode = NULL;
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
+ vreg_name);
+ regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+
+ if (!regnode) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ vreg->name = vreg_name;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-voltage", vreg_name);
+ prop = of_get_property(dev->of_node, prop_name, &len);
+
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "%s %s property\n",
+ prop ? "invalid format" : "no", prop_name);
+ return -ENODEV;
+ } else {
+ vreg->min_uV = be32_to_cpup(&prop[0]);
+ vreg->max_uV = be32_to_cpup(&prop[1]);
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-current", vreg_name);
+
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ vreg->optimum_uA = prop_val;
+
+ dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
+ vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+ return 0;
+}
+
+static int msm8x10_wcd_dt_parse_micbias_info(struct device *dev,
+ struct msm8x10_wcd_micbias_setting *micbias)
+{
+ int ret = 0;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-ldoh-v");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->ldoh_v = (u8)prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-cfilt1-mv");
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt1_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias1-cfilt-sel");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->bias1_cfilt_sel = (u8)prop_val;
+
+ /* micbias external cap */
+ micbias->bias1_cap_mode =
+ (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
+ MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+
+ dev_dbg(dev, "ldoh_v %u cfilt1_mv %u\n",
+ (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv);
+ dev_dbg(dev, "bias1_cfilt_sel %u\n", (u32)micbias->bias1_cfilt_sel);
+ dev_dbg(dev, "bias1_ext_cap %d\n", micbias->bias1_cap_mode);
+
+ return 0;
+}
+
+static struct msm8x10_wcd_pdata *msm8x10_wcd_populate_dt_pdata(
+ struct device *dev)
+{
+ struct msm8x10_wcd_pdata *pdata;
+ int ret, i;
+ char **codec_supplies;
+ u32 num_of_supplies = 0;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "could not allocate memory for platform data\n");
+ return NULL;
+ }
+ if ((!strcmp(dev_name(dev), MSM8X10_WCD_I2C_GSBI_SLAVE_ID))) {
+ codec_supplies = msm8x10_wcd_supplies;
+ num_of_supplies = ARRAY_SIZE(msm8x10_wcd_supplies);
+ } else {
+ dev_err(dev, "%s unsupported device %s\n",
+ __func__, dev_name(dev));
+ goto err;
+ }
+
+ if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+ dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
+ __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
+
+ goto err;
+ }
+
+ for (i = 0; i < num_of_supplies; i++) {
+ ret = msm8x10_wcd_dt_parse_vreg_info(dev, &pdata->regulator[i],
+ codec_supplies[i]);
+ if (ret)
+ goto err;
+ }
+
+ ret = msm8x10_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
+ if (ret)
+ goto err;
+
+ pdata->reset_gpio = of_get_named_gpio(dev->of_node,
+ "qcom,cdc-reset-gpio", 0);
+ if (pdata->reset_gpio < 0) {
+ dev_err(dev, "Looking up %s property in node %s failed %d\n",
+ "qcom, cdc-reset-gpio", dev->of_node->full_name,
+ pdata->reset_gpio);
+ goto err;
+ }
+ dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
+ return pdata;
+err:
+ devm_kfree(dev, pdata);
+ return NULL;
+}
+
+static int msm8x10_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* Enable charge pump clock*/
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_OTHR_CTL,
+ 0x01, 0x01);
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLSG_CTL,
+ 0x08, 0x08);
+ usleep_range(200, 300);
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CP_STATIC,
+ 0x10, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL,
+ 0x01, 0x01);
+ usleep_range(20, 100);
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CP_STATIC, 0x08, 0x08);
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CP_STATIC, 0x10, 0x10);
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_CLSG_CTL, 0x08, 0x00);
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_CLK_OTHR_CTL, 0x01,
+ 0x00);
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CP_STATIC, 0x08, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ear_pa_gain = snd_soc_read(codec, MSM8X10_WCD_A_RX_EAR_GAIN);
+
+ ear_pa_gain = ear_pa_gain >> 5;
+
+ if (ear_pa_gain == 0x00) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (ear_pa_gain == 0x04) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+ return 0;
+}
+
+static int msm8x10_wcd_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ ear_pa_gain = 0x00;
+ break;
+ case 1:
+ ear_pa_gain = 0x80;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_RX_EAR_GAIN,
+ 0xE0, ear_pa_gain);
+ return 0;
+}
+
+static int msm8x10_wcd_get_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
+ (1 << band_idx);
+
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm8x10_wcd_put_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ /* Mask first 5 bits, 6-8 are reserved */
+ snd_soc_update_bits(codec, (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx),
+ (1 << band_idx), (value << band_idx));
+
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx, value);
+ return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx)
+{
+ /* Address does not automatically update if reading */
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ return ((snd_soc_read(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 24)) &
+ 0x3FFFFFFF;
+}
+
+static int msm8x10_wcd_get_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+ ucontrol->value.integer.value[1] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+ ucontrol->value.integer.value[2] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+ ucontrol->value.integer.value[3] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+ ucontrol->value.integer.value[4] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[1],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[2],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[3],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[4]);
+ return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx, uint32_t value)
+{
+ /* Mask top 3 bits, 6-8 are reserved */
+ /* Update address manually each time */
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
+ (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_write(codec,
+ (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
+ (value >> 24) & 0x3F);
+
+}
+
+static int msm8x10_wcd_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+ ucontrol->value.integer.value[0]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+ ucontrol->value.integer.value[1]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+ ucontrol->value.integer.value[2]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+ ucontrol->value.integer.value[3]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+ ucontrol->value.integer.value[4]);
+
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+ return 0;
+}
+
+static const char * const msm8x10_wcd_ear_pa_gain_text[] = {
+ "POS_6_DB", "POS_2_DB"};
+static const struct soc_enum msm8x10_wcd_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, msm8x10_wcd_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+ "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX1_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX2_B4_CTL, 0, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
+
+static const struct snd_kcontrol_new msm8x10_wcd_snd_controls[] = {
+
+ SOC_ENUM_EXT("EAR PA Gain", msm8x10_wcd_ear_pa_gain_enum[0],
+ msm8x10_wcd_pa_gain_get, msm8x10_wcd_pa_gain_put),
+
+ SOC_SINGLE_TLV("LINEOUT1 Volume", MSM8X10_WCD_A_RX_LINE_1_GAIN,
+ 0, 12, 1, line_gain),
+
+ SOC_SINGLE_TLV("HPHL Volume", MSM8X10_WCD_A_RX_HPH_L_GAIN,
+ 0, 12, 1, line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", MSM8X10_WCD_A_RX_HPH_R_GAIN,
+ 0, 12, 1, line_gain),
+
+ SOC_SINGLE_S8_TLV("RX1 Digital Volume",
+ MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX2 Digital Volume",
+ MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX3 Digital Volume",
+ MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("DEC1 Volume",
+ MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC2 Volume",
+ MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP4 Volume",
+ MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE("MICBIAS1 CAPLESS Switch",
+ MSM8X10_WCD_A_MICB_1_CTL, 4, 1, 1),
+
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+
+ SOC_SINGLE("TX1 HPF Switch", MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX2 HPF Switch", MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 3, 1, 0),
+
+ SOC_SINGLE("RX1 HPF Switch", MSM8X10_WCD_A_CDC_RX1_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX2 HPF Switch", MSM8X10_WCD_A_CDC_RX2_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX3 HPF Switch", MSM8X10_WCD_A_CDC_RX3_B5_CTL, 2, 1, 0),
+
+ SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+ SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+ SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+
+ SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+ msm8x10_wcd_get_iir_enable_audio_mixer,
+ msm8x10_wcd_put_iir_enable_audio_mixer),
+
+ SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+ msm8x10_wcd_get_iir_band_audio_mixer,
+ msm8x10_wcd_put_iir_band_audio_mixer),
+
+};
+
+static const char * const rx_mix1_text[] = {
+ "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
+};
+
+static const char * const rx_mix2_text[] = {
+ "ZERO", "IIR1", "IIR2"
+};
+
+static const char * const dec_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "DMIC1", "DMIC2"
+};
+
+
+static const char * const anc_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
+ "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
+};
+
+static const char * const anc1_fb_mux_text[] = {
+ "ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
+static const char * const iir1_inp1_text[] = {
+ "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text);
+
+static const struct soc_enum rx1_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
+
+static const struct soc_enum dec1_mux_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL, 0, 5, dec_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL, 3, 5, dec_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL, 0, 6,
+ iir1_inp1_text);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static int msm8x10_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *w = wlist->widgets[0];
+ struct snd_soc_codec *codec = w->codec;
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int dec_mux, decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ u16 tx_mux_ctl_reg;
+ u8 adc_dmic_sel = 0x0;
+ int ret = 0;
+
+ if (ucontrol->value.enumerated.item[0] > e->max - 1)
+ return -EINVAL;
+
+ dec_mux = ucontrol->value.enumerated.item[0];
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "12"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+ , __func__, w->name, decimator, dec_mux);
+
+ switch (decimator) {
+ case 1:
+ case 2:
+ if (dec_mux == 1)
+ adc_dmic_sel = 0x1;
+ else
+ adc_dmic_sel = 0x0;
+ break;
+ default:
+ pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_mux_ctl_reg = MSM8X10_WCD_A_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+#define MSM8X10_WCD_DEC_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = snd_soc_dapm_get_enum_double, \
+ .put = msm8x10_wcd_put_dec_enum, \
+ .private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+ MSM8X10_WCD_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+ MSM8X10_WCD_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const struct snd_kcontrol_new dac1_switch[] = {
+ SOC_DAPM_SINGLE("Switch", MSM8X10_WCD_A_RX_EAR_EN, 5, 1, 0)
+};
+static const struct snd_kcontrol_new hphl_switch[] = {
+ SOC_DAPM_SINGLE("Switch", MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+/* virtual port entries */
+static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+
+ ucontrol->value.integer.value[0] = widget->value;
+ return 0;
+}
+
+static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+
+ ucontrol->value.enumerated.item[0] = widget->value;
+ return 0;
+}
+
+static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+
+static const char *const slim_rx_mux_text[] = {
+ "ZERO", "AIF1_PB"
+};
+
+static const struct soc_enum slim_rx_mux_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
+
+static const struct snd_kcontrol_new slim_rx_mux[MSM8X10_WCD_RX_MAX] = {
+ SOC_DAPM_ENUM_EXT("I2S RX1 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("I2S RX2 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("I2S RX3 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+};
+
+static const struct snd_kcontrol_new aif_cap_mixer[] = {
+ SOC_SINGLE_EXT("I2S TX1", SND_SOC_NOPM, MSM8X10_WCD_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("I2S TX2", SND_SOC_NOPM, MSM8X10_WCD_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("I2S TX3", SND_SOC_NOPM, MSM8X10_WCD_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("I2S TX4", SND_SOC_NOPM, MSM8X10_WCD_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+
+static void msm8x10_wcd_codec_enable_adc_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct msm8x10_wcd_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s %d\n", __func__, enable);
+
+ if (enable) {
+ taiko->adc_count++;
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 0x20, 0x20);
+ } else {
+ taiko->adc_count--;
+ if (!taiko->adc_count)
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
+ 0x20, 0x0);
+ }
+}
+
+static int msm8x10_wcd_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 adc_reg;
+ u8 init_bit_shift;
+
+ pr_debug("%s %d\n", __func__, event);
+ adc_reg = MSM8X10_WCD_A_TX_1_2_TEST_CTL;
+
+ if (w->reg == MSM8X10_WCD_A_TX_1_EN)
+ init_bit_shift = 7;
+ else if (adc_reg == MSM8X10_WCD_A_TX_2_EN)
+ init_bit_shift = 6;
+ else {
+ pr_err("%s: Error, invalid adc register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ msm8x10_wcd_codec_enable_adc_block(codec, 1);
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+ 1 << init_bit_shift);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msm8x10_wcd_codec_enable_adc_block(codec, 0);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_codec_enable_lineout(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 lineout_gain_reg;
+
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+
+ switch (w->shift) {
+ case 0:
+ lineout_gain_reg = MSM8X10_WCD_A_RX_LINE_1_GAIN;
+ break;
+ default:
+ pr_err("%s: Error, incorrect lineout register value\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
+ __func__, w->name);
+ usleep_range(16000, 16100);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+ return 0;
+}
+
+static int msm8x10_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+ u8 dmic_clk_en;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ unsigned int dmic;
+ int ret;
+
+ ret = kstrtouint(strpbrk(w->name, "12"), 10, &dmic);
+ if (ret < 0) {
+ pr_err("%s: Invalid DMIC line on the codec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 1:
+ case 2:
+ dmic_clk_en = 0x01;
+ dmic_clk_cnt = &(msm8x10_wcd->dmic_1_2_clk_cnt);
+ dmic_clk_reg = MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL;
+ pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+ break;
+ default:
+ pr_err("%s: Invalid DMIC Selection\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1)
+ snd_soc_update_bits(codec, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_update_bits(codec, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+ u16 micb_int_reg;
+ u8 cfilt_sel_val = 0;
+ char *internal1_text = "Internal1";
+ char *internal2_text = "Internal2";
+ char *internal3_text = "Internal3";
+ enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
+
+ pr_debug("%s %d\n", __func__, event);
+ switch (w->reg) {
+ case MSM8X10_WCD_A_MICB_1_CTL:
+ micb_int_reg = MSM8X10_WCD_A_MICB_1_INT_RBIAS;
+ cfilt_sel_val =
+ msm8x10_wcd->resmgr.pdata->micbias.bias1_cfilt_sel;
+ e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
+ e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
+ e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
+ break;
+ default:
+ pr_err("%s: Error, invalid micbias register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Let MBHC module know so micbias switch to be off */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
+
+ /* Get cfilt */
+ wcd9xxx_resmgr_cfilt_get(&msm8x10_wcd->resmgr, cfilt_sel_val);
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+ else if (strnstr(w->name, internal3_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(20000, 20100);
+ /* Let MBHC module know so micbias is on */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* Let MBHC module know so micbias switch to be off */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
+ else if (strnstr(w->name, internal3_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
+
+ /* Put cfilt */
+ wcd9xxx_resmgr_cfilt_put(&msm8x10_wcd->resmgr, cfilt_sel_val);
+ break;
+ }
+
+ return 0;
+}
+
+#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+
+static int msm8x10_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0;
+ u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ u8 dec_hpf_cut_of_freq;
+ int offset;
+
+ pr_debug("%s %d\n", __func__, event);
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "12"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
+ if (w->reg == MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
+ dec_reset_reg = MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL;
+ offset = 0;
+ } else {
+ pr_err("%s: Error, incorrect dec\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_vol_ctl_reg = MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG +
+ 32 * (decimator - 1);
+ tx_mux_ctl_reg = MSM8X10_WCD_A_CDC_TX1_MUX_CTL +
+ 32 * (decimator - 1);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Enableable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
+ 1 << w->shift);
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+ dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+ /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ CF_MIN_3DB_150HZ << 4);
+ }
+
+ /* enable HPF */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* Disable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+ /* apply the digital gain after the decimator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
+ snd_soc_write(codec,
+ tx_digital_gain_reg[w->shift + offset],
+ snd_soc_read(codec,
+ tx_digital_gain_reg[w->shift + offset])
+ );
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+ break;
+ }
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+static int msm8x10_wcd_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* apply the digital gain after the interpolator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write(codec,
+ rx_digital_gain_reg[w->shift],
+ snd_soc_read(codec,
+ rx_digital_gain_reg[w->shift])
+ );
+ break;
+ }
+ return 0;
+}
+
+
+/* The register address is the same as other codec so it can use resmgr */
+static int msm8x10_wcd_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd9xxx_resmgr_enable_rx_bias(&msm8x10_wcd->resmgr, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd9xxx_resmgr_enable_rx_bias(&msm8x10_wcd->resmgr, 0);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+ enum wcd9xxx_notify_event e_pre_on, e_post_off;
+
+ pr_debug("%s: %s event = %d\n", __func__, w->name, event);
+ if (w->shift == 5) {
+ e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+ e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+ } else if (w->shift == 4) {
+ e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
+ e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+ } else {
+ pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Let MBHC module know PA is turning on */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ usleep_range(10000, 10100);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ /* Let MBHC module know PA turned off */
+ wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
+
+ /*
+ * 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.
+ */
+ pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
+ w->name);
+ usleep_range(10000, 10100);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_lineout_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int msm8x10_wcd_spk_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+ return 0;
+}
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ {"RX_I2S_CLK", NULL, "CDC_CONN"},
+ {"I2S RX1", NULL, "RX_I2S_CLK"},
+ {"I2S RX2", NULL, "RX_I2S_CLK"},
+ {"I2S RX3", NULL, "RX_I2S_CLK"},
+
+ {"I2S TX1", NULL, "TX_I2S_CLK"},
+ {"I2S TX2", NULL, "TX_I2S_CLK"},
+ {"I2S TX3", NULL, "TX_I2S_CLK"},
+ {"I2S TX4", NULL, "TX_I2S_CLK"},
+
+ {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
+
+ {"AIF1_CAP Mixer", "I2S TX1", "I2S TX1 MUX"},
+ {"AIF1_CAP Mixer", "I2S TX2", "I2S TX2 MUX"},
+ {"AIF1_CAP Mixer", "I2S TX3", "I2S TX3 MUX"},
+ {"AIF1_CAP Mixer", "I2S TX4", "I2S TX4 MUX"},
+
+ {"I2S TX1 MUX", NULL, "DEC1 MUX"},
+ {"I2S TX2 MUX", NULL, "DEC2 MUX"},
+ {"I2S TX3 MUX", NULL, "RX1 MIX1"},
+ {"I2S TX4 MUX", "RMIX2", "RX1 MIX2"},
+ {"I2S TX4 MUX", "RMIX3", "RX1 MIX3"},
+
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR PA"},
+ {"EAR PA", NULL, "DAC1"},
+ {"DAC1", NULL, "CP"},
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL"},
+ {"HEADPHONE", NULL, "HPHR"},
+
+ {"HPHL", NULL, "HPHL DAC"},
+
+ {"HPHR", NULL, "HPHR DAC"},
+ {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+
+ {"HPHL DAC", NULL, "CP"},
+
+ {"HPHR DAC", NULL, "CP"},
+
+ {"DAC1", "Switch", "RX1 CHAIN"},
+ {"HPHL DAC", "Switch", "RX1 CHAIN"},
+ {"HPHR DAC", NULL, "RX2 CHAIN"},
+
+ {"LINEOUT1", NULL, "LINEOUT1 PA"},
+ {"SPK_OUT", NULL, "SPK PA"},
+
+ {"LINEOUT1 PA", NULL, "CP"},
+ {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
+
+ {"LINEOUT1 DAC", "RX2 INPUT", "RX2 MIX1"},
+ {"LINEOUT1 DAC", "RX3 INPUT", "RX3 MIX1"},
+
+ {"SPK PA", NULL, "SPK DAC"},
+ {"SPK DAC", NULL, "RX7 MIX2"},
+
+ {"RX1 CHAIN", NULL, "RX1 MIX2"},
+ {"RX2 CHAIN", NULL, "RX2 MIX2"},
+
+ {"LINEOUT1 DAC", NULL, "RX_BIAS"},
+ {"SPK DAC", NULL, "RX_BIAS"},
+
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+ {"RX1 MIX2", NULL, "RX1 MIX1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
+ {"RX2 MIX2", NULL, "RX2 MIX1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
+
+ {"I2S RX1 MUX", "AIF1_PB", "AIF1 PB"},
+ {"I2S RX2 MUX", "AIF1_PB", "AIF1 PB"},
+ {"I2S RX3 MUX", "AIF1_PB", "AIF1 PB"},
+
+ {"I2S RX1", NULL, "I2S RX1 MUX"},
+ {"I2S RX2", NULL, "I2S RX2 MUX"},
+ {"I2S RX3", NULL, "I2S RX3 MUX"},
+
+ {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
+ {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
+ {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
+
+ {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX2 MIX1 INP2", "IIR1", "IIR1"},
+
+ {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
+ {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
+ {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
+ {"RX3 MIX1 INP2", "IIR1", "IIR1"},
+
+ /* Decimator Inputs */
+ {"DEC1 MUX", "DMIC1", "DMIC1"},
+ {"DEC1 MUX", "DMIC2", "DMIC2"},
+ {"DEC1 MUX", "ADC1", "ADC1"},
+ {"DEC1 MUX", "ADC2", "ADC2"},
+ {"DEC1 MUX", NULL, "CDC_CONN"},
+
+ {"DEC2 MUX", "DMIC1", "DMIC1"},
+ {"DEC2 MUX", "DMIC2", "DMIC2"},
+ {"DEC2 MUX", "ADC1", "ADC1"},
+ {"DEC2 MUX", "ADC2", "ADC2"},
+ {"DEC2 MUX", NULL, "CDC_CONN"},
+
+ /* ADC Connections */
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2", NULL, "AMIC2"},
+
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+
+ /* There is no LDO_H in Helicon */
+ {"MIC BIAS1 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS1 Internal2", NULL, "LDO_H"},
+ {"MIC BIAS1 External", NULL, "LDO_H"},
+};
+
+
+static int msm8x10_wcd_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm8x10_wcd *msm8x10_wcd_core =
+ dev_get_drvdata(dai->codec->dev);
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+ if ((msm8x10_wcd_core != NULL) &&
+ (msm8x10_wcd_core->dev != NULL))
+ pm_runtime_get_sync(msm8x10_wcd_core->dev);
+
+ return 0;
+}
+
+static void msm8x10_wcd_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm8x10_wcd *msm8x10_wcd_core =
+ dev_get_drvdata(dai->codec->dev);
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+ if ((msm8x10_wcd_core != NULL) &&
+ (msm8x10_wcd_core->dev != NULL)) {
+ pm_runtime_mark_last_busy(msm8x10_wcd_core->dev);
+ pm_runtime_put(msm8x10_wcd_core->dev);
+ }
+}
+
+int msm8x10_wcd_mclk_enable(struct snd_soc_codec *codec,
+ int mclk_enable, bool dapm)
+{
+ struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
+ dapm);
+
+ WCD9XXX_BCL_LOCK(&msm8x10_wcd->resmgr);
+ if (mclk_enable) {
+ wcd9xxx_resmgr_get_bandgap(&msm8x10_wcd->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ wcd9xxx_resmgr_get_clk_block(&msm8x10_wcd->resmgr,
+ WCD9XXX_CLK_MCLK);
+ } else {
+ /* Put clock and BG */
+ wcd9xxx_resmgr_put_clk_block(&msm8x10_wcd->resmgr,
+ WCD9XXX_CLK_MCLK);
+ wcd9xxx_resmgr_put_bandgap(&msm8x10_wcd->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ }
+ WCD9XXX_BCL_UNLOCK(&msm8x10_wcd->resmgr);
+
+ return 0;
+}
+
+static int msm8x10_wcd_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int msm8x10_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int msm8x10_wcd_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int msm8x10_wcd_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int msm8x10_wcd_set_interpolator_rate(struct snd_soc_dai *dai,
+ u8 rx_fs_rate_reg_val, u32 sample_rate)
+{
+ return 0;
+}
+
+static int msm8x10_wcd_set_decimator_rate(struct snd_soc_dai *dai,
+ u8 tx_fs_rate_reg_val, u32 sample_rate)
+{
+ return 0;
+}
+
+static int msm8x10_wcd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ u8 tx_fs_rate, rx_fs_rate;
+ int ret;
+
+ pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+ dai->name, dai->id, params_rate(params),
+ params_channels(params));
+
+ switch (params_rate(params)) {
+ case 8000:
+ tx_fs_rate = 0x00;
+ rx_fs_rate = 0x00;
+ break;
+ case 16000:
+ tx_fs_rate = 0x01;
+ rx_fs_rate = 0x20;
+ break;
+ case 32000:
+ tx_fs_rate = 0x02;
+ rx_fs_rate = 0x40;
+ break;
+ case 48000:
+ tx_fs_rate = 0x03;
+ rx_fs_rate = 0x60;
+ break;
+ case 96000:
+ tx_fs_rate = 0x04;
+ rx_fs_rate = 0x80;
+ break;
+ case 192000:
+ tx_fs_rate = 0x05;
+ rx_fs_rate = 0xA0;
+ break;
+ default:
+ pr_err("%s: Invalid sampling rate %d\n", __func__,
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ switch (substream->stream) {
+ case SNDRV_PCM_STREAM_CAPTURE:
+ ret = msm8x10_wcd_set_decimator_rate(dai, tx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ pr_err("%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ case SNDRV_PCM_STREAM_PLAYBACK:
+ ret = msm8x10_wcd_set_interpolator_rate(dai, rx_fs_rate,
+ params_rate(params));
+ if (ret < 0) {
+ pr_err("%s: set decimator rate failed %d\n", __func__,
+ ret);
+ return ret;
+ }
+ break;
+ default:
+ pr_err("%s: Invalid stream type %d\n", __func__,
+ substream->stream);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm8x10_wcd_dai_ops = {
+ .startup = msm8x10_wcd_startup,
+ .shutdown = msm8x10_wcd_shutdown,
+ .hw_params = msm8x10_wcd_hw_params,
+ .set_sysclk = msm8x10_wcd_set_dai_sysclk,
+ .set_fmt = msm8x10_wcd_set_dai_fmt,
+ .set_channel_map = msm8x10_wcd_set_channel_map,
+ .get_channel_map = msm8x10_wcd_get_channel_map,
+};
+
+static struct snd_soc_dai_driver msm8x10_wcd_i2s_dai[] = {
+ {
+ .name = "msm8x10_wcd_i2s_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = MSM8X10_WCD_RATES,
+ .formats = MSM8X10_WCD_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &msm8x10_wcd_dai_ops,
+ },
+ {
+ .name = "msm8x10_wcd_i2s_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = MSM8X10_WCD_RATES,
+ .formats = MSM8X10_WCD_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &msm8x10_wcd_dai_ops,
+ },
+};
+
+static int msm8x10_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ pr_debug("%s: Sleeping 20ms after enabling EAR PA\n",
+ __func__);
+ msleep(20);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ pr_debug("%s: Sleeping 20ms after disabling EAR PA\n",
+ __func__);
+ msleep(20);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8x10_wcd_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+
+ SND_SOC_DAPM_PGA_E("EAR PA", MSM8X10_WCD_A_RX_EAR_EN, 4, 0, NULL, 0,
+ msm8x10_wcd_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MIXER("DAC1", MSM8X10_WCD_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch)),
+
+ SND_SOC_DAPM_AIF_IN("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
+ AIF1_PB, 0),
+
+ SND_SOC_DAPM_MUX("I2S RX1 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX1, 0,
+ &slim_rx_mux[MSM8X10_WCD_RX1]),
+ SND_SOC_DAPM_MUX("I2S RX2 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX2, 0,
+ &slim_rx_mux[MSM8X10_WCD_RX2]),
+ SND_SOC_DAPM_MUX("I2S RX3 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX3, 0,
+ &slim_rx_mux[MSM8X10_WCD_RX3]),
+
+ SND_SOC_DAPM_MIXER("I2S RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I2S RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I2S RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I2S RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("I2S RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Headphone */
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL", MSM8X10_WCD_A_RX_HPH_CNP_EN,
+ 5, 0, NULL, 0,
+ msm8x10_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("HPHL DAC", MSM8X10_WCD_A_RX_HPH_L_DAC_CTL,
+ 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+ SND_SOC_DAPM_PGA_E("HPHR", MSM8X10_WCD_A_RX_HPH_CNP_EN,
+ 4, 0, NULL, 0,
+ msm8x10_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, MSM8X10_WCD_A_RX_HPH_R_DAC_CTL,
+ 7, 0,
+ msm8x10_wcd_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", MSM8X10_WCD_A_RX_LINE_CNP_EN,
+ 0, 0, NULL, 0, msm8x10_wcd_codec_enable_lineout,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_PGA_E("SPK PA", MSM8X10_WCD_A_SPKR_DRV_EN,
+ 7, 0 , NULL, 0, msm8x10_wcd_codec_enable_spk_pa,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL,
+ MSM8X10_WCD_A_RX_LINE_1_DAC_CTL, 7, 0,
+ msm8x10_wcd_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x10_wcd_spk_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX2",
+ MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+ 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX2",
+ MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+ 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1",
+ MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+ 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", MSM8X10_WCD_A_CDC_RX1_B6_CTL,
+ 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", MSM8X10_WCD_A_CDC_RX2_B6_CTL,
+ 5, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp3_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp1_mux),
+
+ SND_SOC_DAPM_SUPPLY("CP", MSM8X10_WCD_A_CP_EN, 0, 0,
+ msm8x10_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+ msm8x10_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", MSM8X10_WCD_A_CDC_CLK_OTHR_CTL,
+ 2, 0, NULL, 0),
+
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External",
+ MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
+ msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1",
+ MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
+ msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2",
+ MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
+ msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
+ msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
+ msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX",
+ MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, msm8x10_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC2 MUX",
+ MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, msm8x10_wcd_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_AIF_OUT("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
+ AIF1_CAP, 0),
+
+ SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+ aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x10_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ msm8x10_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR1", MSM8X10_WCD_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL, 4,
+ 0, NULL, 0),
+};
+
+static const struct msm8x10_wcd_reg_mask_val msm8x10_wcd_reg_defaults[] = {
+
+ /* set MCLk to 9.6 */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CHIP_CTL, 0x0A),
+
+ /* EAR PA deafults */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_EAR_CMBUFF, 0x05),
+
+ /* RX deafults */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX1_B5_CTL, 0x78),
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX2_B5_CTL, 0x78),
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX3_B5_CTL, 0x78),
+
+ /* RX1 and RX2 defaults */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX1_B6_CTL, 0xA0),
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX2_B6_CTL, 0xA0),
+
+ /* RX3 to RX7 defaults */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX3_B6_CTL, 0x80),
+
+ /* Reduce HPH DAC bias to 70% */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_HPH_BIAS_PA, 0x7A),
+ /*Reduce EAR DAC bias to 70% */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_EAR_BIAS_PA, 0x76),
+ /* Reduce LINE DAC bias to 70% */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_LINE_BIAS_PA, 0x78),
+
+
+ /* Disable TX7 internal biasing path which can cause leakage */
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
+};
+
+static void msm8x10_wcd_update_reg_defaults(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(msm8x10_wcd_reg_defaults); i++)
+ snd_soc_write(codec, msm8x10_wcd_reg_defaults[i].reg,
+ msm8x10_wcd_reg_defaults[i].val);
+}
+
+static const struct msm8x10_wcd_reg_mask_val
+ msm8x10_wcd_codec_reg_init_val[] = {
+ /* Initialize current threshold to 350MA
+ * number of wait and run cycles to 4096
+ */
+ {MSM8X10_WCD_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
+ {MSM8X10_WCD_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+ /* Initialize gain registers to use register gain */
+ {MSM8X10_WCD_A_RX_HPH_L_GAIN, 0x20, 0x20},
+ {MSM8X10_WCD_A_RX_HPH_R_GAIN, 0x20, 0x20},
+ {MSM8X10_WCD_A_RX_LINE_1_GAIN, 0x20, 0x20},
+
+ /*enable HPF filter for TX paths */
+ {MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+ {MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+
+ /* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
+ {MSM8X10_WCD_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
+ {MSM8X10_WCD_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
+
+ /* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
+ {MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
+
+};
+
+static void msm8x10_wcd_codec_init_reg(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(msm8x10_wcd_codec_reg_init_val); i++)
+ snd_soc_update_bits(codec,
+ msm8x10_wcd_codec_reg_init_val[i].reg,
+ msm8x10_wcd_codec_reg_init_val[i].mask,
+ msm8x10_wcd_codec_reg_init_val[i].val);
+}
+
+int msm8x10_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct msm8x10_wcd_mbhc_config *mbhc_cfg)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(msm8x10_wcd_hs_detect);
+
+static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
+{
+ msm8x10_wcd_codec_init_reg(codec);
+
+ msm8x10_wcd_update_reg_defaults(codec);
+
+ dev_dbg(codec->dev, "%s()\n", __func__);
+
+ return 0;
+}
+
+static int msm8x10_wcd_codec_remove(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_msm8x10_wcd = {
+ .probe = msm8x10_wcd_codec_probe,
+ .remove = msm8x10_wcd_codec_remove,
+
+ .read = msm8x10_wcd_read,
+ .write = msm8x10_wcd_write,
+
+ .readable_register = msm8x10_wcd_readable,
+ .volatile_register = msm8x10_wcd_volatile,
+
+ .reg_cache_size = MSM8X10_WCD_CACHE_SIZE,
+ .reg_cache_default = msm8x10_wcd_reset_reg_defaults,
+ .reg_word_size = 1,
+
+ .controls = msm8x10_wcd_snd_controls,
+ .num_controls = ARRAY_SIZE(msm8x10_wcd_snd_controls),
+ .dapm_widgets = msm8x10_wcd_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm8x10_wcd_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static int __devinit msm8x10_wcd_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int ret;
+ struct msm8x10_wcd_pdata *pdata;
+ if (client->dev.of_node) {
+ dev_dbg(&client->dev, "%s:Platform data from device tree\n",
+ __func__);
+ pdata = msm8x10_wcd_populate_dt_pdata(&client->dev);
+ client->dev.platform_data = pdata;
+ } else {
+ dev_dbg(&client->dev, "%s:Platform data from board file\n",
+ __func__);
+ pdata = client->dev.platform_data;
+ }
+
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_dev_msm8x10_wcd,
+ msm8x10_wcd_i2s_dai, ARRAY_SIZE(msm8x10_wcd_i2s_dai));
+ dev_dbg(&client->dev, "%s:ret = 0x%x\n", __func__, ret);
+
+ return ret;
+}
+
+static int __devexit msm8x10_wcd_i2c_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static struct i2c_device_id msm8x10_wcd_id_table[] = {
+ {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_TOP_LEVEL},
+ {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_ANALOG},
+ {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_DIGITAL_1},
+ {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_DIGITAL_2},
+ {}
+};
+
+static struct of_device_id msm8x10_wcd_of_match[] = {
+ { .compatible = "qcom,msm8x10-wcd-i2c",},
+ { },
+};
+
+
+static struct i2c_driver msm8x10_wcd_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "msm8x10-wcd-i2c-core",
+ .of_match_table = msm8x10_wcd_of_match
+ },
+ .id_table = msm8x10_wcd_id_table,
+ .probe = msm8x10_wcd_i2c_probe,
+ .remove = __devexit_p(msm8x10_wcd_i2c_remove),
+};
+
+static int __init msm8x10_wcd_codec_init(void)
+{
+ int ret;
+
+ pr_debug("%s:\n", __func__);
+ ret = i2c_add_driver(&msm8x10_wcd_i2c_driver);
+ if (ret != 0)
+ pr_err("%s: Failed to add msm8x10 wcd I2C driver - error code %d\n",
+ __func__, ret);
+ return ret;
+}
+
+static void __exit msm8x10_wcd_codec_exit(void)
+{
+ i2c_del_driver(&msm8x10_wcd_i2c_driver);
+}
+
+
+module_init(msm8x10_wcd_codec_init);
+module_exit(msm8x10_wcd_codec_exit);
+
+MODULE_DESCRIPTION("MSM8x10 Audio codec driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(i2c, msm8x10_wcd_id_table);
+
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
new file mode 100644
index 0000000..365d526
--- /dev/null
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -0,0 +1,226 @@
+/* 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.
+ */
+#ifndef MSM8X10_WCD_H
+#define MSM8X10_WCD_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include "wcd9xxx-mbhc.h"
+#include "wcd9xxx-resmgr.h"
+
+#define MSM8X10_WCD_NUM_REGISTERS 0x600
+#define MSM8X10_WCD_MAX_REGISTER (MSM8X10_WCD_NUM_REGISTERS-1)
+#define MSM8X10_WCD_CACHE_SIZE MSM8X10_WCD_NUM_REGISTERS
+#define MSM8X10_WCD_NUM_IRQ_REGS 3
+#define MAX_REGULATOR 7
+#define MSM8X10_WCD_REG_VAL(reg, val) {reg, 0, val}
+
+#define MSM8X10_WCD_IS_DINO_REG(reg) \
+ (((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
+#define MSM8X10_WCD_IS_HELICON_REG(reg) \
+ (((reg >= 0x000) && (reg <= 0x1FF)) ? 1 : 0)
+extern const u8 msm8x10_wcd_reg_readable[MSM8X10_WCD_CACHE_SIZE];
+extern const u8 msm8x10_wcd_reset_reg_defaults[MSM8X10_WCD_CACHE_SIZE];
+struct msm8x10_wcd_codec_dai_data {
+ u32 rate;
+ u32 *ch_num;
+ u32 ch_act;
+ u32 ch_tot;
+};
+
+enum msm8x10_wcd_pid_current {
+ MSM8X10_WCD_PID_MIC_2P5_UA,
+ MSM8X10_WCD_PID_MIC_5_UA,
+ MSM8X10_WCD_PID_MIC_10_UA,
+ MSM8X10_WCD_PID_MIC_20_UA,
+};
+
+struct msm8x10_wcd_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+enum msm8x10_wcd_mbhc_analog_pwr_cfg {
+ MSM8X10_WCD_ANALOG_PWR_COLLAPSED = 0,
+ MSM8X10_WCD_ANALOG_PWR_ON,
+ MSM8X10_WCD_NUM_ANALOG_PWR_CONFIGS,
+};
+
+/* Number of input and output Slimbus port */
+enum {
+ MSM8X10_WCD_RX1 = 0,
+ MSM8X10_WCD_RX2,
+ MSM8X10_WCD_RX3,
+ MSM8X10_WCD_RX_MAX,
+};
+
+enum {
+ MSM8X10_WCD_TX1 = 0,
+ MSM8X10_WCD_TX2,
+ MSM8X10_WCD_TX3,
+ MSM8X10_WCD_TX4,
+ MSM8X10_WCD_TX_MAX,
+};
+
+enum {
+ /* INTR_REG 0 */
+ MSM8X10_WCD_IRQ_RESERVED_0 = 0,
+ MSM8X10_WCD_IRQ_MBHC_REMOVAL,
+ MSM8X10_WCD_IRQ_MBHC_SHORT_TERM,
+ MSM8X10_WCD_IRQ_MBHC_PRESS,
+ MSM8X10_WCD_IRQ_MBHC_RELEASE,
+ MSM8X10_WCD_IRQ_MBHC_POTENTIAL,
+ MSM8X10_WCD_IRQ_MBHC_INSERTION,
+ MSM8X10_WCD_IRQ_MBHC_HS_DET,
+ /* INTR_REG 1 */
+ MSM8X10_WCD_IRQ_PA_STARTUP,
+ MSM8X10_WCD_IRQ_BG_PRECHARGE,
+ MSM8X10_WCD_IRQ_RESERVED_1,
+ MSM8X10_WCD_IRQ_EAR_PA_OCPL_FAULT,
+ MSM8X10_WCD_IRQ_EAR_PA_STARTUP,
+ MSM8X10_WCD_IRQ_SPKR_PA_OCPL_FAULT,
+ MSM8X10_WCD_IRQ_SPKR_CLIP_FAULT,
+ MSM8X10_WCD_IRQ_RESERVED_2,
+ /* INTR_REG 2 */
+ MSM8X10_WCD_IRQ_HPH_L_PA_STARTUP,
+ MSM8X10_WCD_IRQ_HPH_R_PA_STARTUP,
+ MSM8X10_WCD_IRQ_HPH_PA_OCPL_FAULT,
+ MSM8X10_WCD_IRQ_HPH_PA_OCPR_FAULT,
+ MSM8X10_WCD_IRQ_RESERVED_3,
+ MSM8X10_WCD_IRQ_RESERVED_4,
+ MSM8X10_WCD_IRQ_RESERVED_5,
+ MSM8X10_WCD_IRQ_RESERVED_6,
+ MSM8X10_WCD_NUM_IRQS,
+};
+
+/*
+ * Each micbias can be assigned to one of three cfilters
+ * Vbatt_min >= .15V + ldoh_v
+ * ldoh_v >= .15v + cfiltx_mv
+ * If ldoh_v = 1.95 160 mv < cfiltx_mv < 1800 mv
+ * If ldoh_v = 2.35 200 mv < cfiltx_mv < 2200 mv
+ * If ldoh_v = 2.75 240 mv < cfiltx_mv < 2600 mv
+ * If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
+ */
+struct msm8x10_wcd_micbias_setting {
+ u8 ldoh_v;
+ u32 cfilt1_mv; /* in mv */
+ /*
+ * Different WCD9xxx series codecs may not
+ * have 4 mic biases. If a codec has fewer
+ * mic biases, some of these properties will
+ * not be used.
+ */
+ u8 bias1_cfilt_sel;
+ u8 bias1_cap_mode;
+};
+
+struct msm8x10_wcd_ocp_setting {
+ unsigned int use_pdata:1; /* 0 - use sys default as recommended */
+ unsigned int num_attempts:4; /* up to 15 attempts */
+ unsigned int run_time:4; /* in duty cycle */
+ unsigned int wait_time:4; /* in duty cycle */
+ unsigned int hph_ocp_limit:3; /* Headphone OCP current limit */
+};
+
+struct msm8x10_wcd_regulator {
+ const char *name;
+ int min_uV;
+ int max_uV;
+ int optimum_uA;
+ struct regulator *regulator;
+};
+
+struct msm8x10_wcd_pdata {
+ int irq;
+ int irq_base;
+ int num_irqs;
+ int reset_gpio;
+ void *msm8x10_wcd_ahb_base_vaddr;
+ struct msm8x10_wcd_micbias_setting micbias;
+ struct msm8x10_wcd_ocp_setting ocp;
+ struct msm8x10_wcd_regulator regulator[MAX_REGULATOR];
+ u32 mclk_rate;
+};
+
+enum msm8x10_wcd_micbias_num {
+ MSM8X10_WCD_MICBIAS1 = 0,
+};
+
+struct msm8x10_wcd_mbhc_config {
+ struct snd_soc_jack *headset_jack;
+ struct snd_soc_jack *button_jack;
+ bool read_fw_bin;
+ /*
+ * void* calibration contains:
+ * struct msm8x10_wcd_mbhc_general_cfg generic;
+ * struct msm8x10_wcd_mbhc_plug_detect_cfg plug_det;
+ * struct msm8x10_wcd_mbhc_plug_type_cfg plug_type;
+ * struct msm8x10_wcd_mbhc_btn_detect_cfg btn_det;
+ * struct msm8x10_wcd_mbhc_imped_detect_cfg imped_det;
+ * Note: various size depends on btn_det->num_btn
+ */
+ void *calibration;
+ enum msm8x10_wcd_micbias_num micbias;
+ int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
+ unsigned int mclk_rate;
+ unsigned int gpio;
+ unsigned int gpio_irq;
+ int gpio_level_insert;
+ bool detect_extn_cable;
+ /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
+ bool (*swap_gnd_mic) (struct snd_soc_codec *);
+};
+
+enum msm8x10_wcd_pm_state {
+ MSM8X10_WCD_PM_SLEEPABLE,
+ MSM8X10_WCD_PM_AWAKE,
+ MSM8X10_WCD_PM_ASLEEP,
+};
+
+struct msm8x10_wcd {
+ struct device *dev;
+ struct mutex io_lock;
+ struct mutex xfer_lock;
+ struct mutex irq_lock;
+ u8 version;
+
+ int reset_gpio;
+
+ u32 num_of_supplies;
+ struct regulator_bulk_data *supplies;
+
+ enum msm8x10_wcd_pm_state pm_state;
+ struct mutex pm_lock;
+ /* pm_wq notifies change of pm_state */
+ wait_queue_head_t pm_wq;
+ struct pm_qos_request pm_qos_req;
+ int wlock_holders;
+
+ u8 idbyte[4];
+
+ unsigned int irq_base;
+ unsigned int irq;
+ u8 irq_masks_cur[MSM8X10_WCD_NUM_IRQ_REGS];
+ u8 irq_masks_cache[MSM8X10_WCD_NUM_IRQ_REGS];
+ bool irq_level_high[MSM8X10_WCD_NUM_IRQS];
+ int num_irqs;
+ u32 mclk_rate;
+};
+
+extern int msm8x10_wcd_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+ bool dapm);
+extern int msm8x10_wcd_hs_detect(struct snd_soc_codec *codec,
+ struct msm8x10_wcd_mbhc_config *mbhc_cfg);
+
+#endif
diff --git a/sound/soc/codecs/msm8x10_wcd_registers.h b/sound/soc/codecs/msm8x10_wcd_registers.h
new file mode 100644
index 0000000..a10f31f
--- /dev/null
+++ b/sound/soc/codecs/msm8x10_wcd_registers.h
@@ -0,0 +1,641 @@
+ /* 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.
+ */
+#ifndef MSM8X10_WCD_REGISTERS_H
+#define MSM8X10_WCD_REGISTERS_H
+
+#define MSM8X10_WCD_A_CHIP_CTL (0x000)
+#define MSM8X10_WCD_A_CHIP_CTL__POR (0x04)
+#define MSM8X10_WCD_A_CHIP_STATUS (0x001)
+#define MSM8X10_WCD_A_CHIP_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TLMM_MODE_SELECT (0x002)
+#define MSM8X10_WCD_A_CDC_TLMM_MODE_SELECT__POR (0x00)
+#define MSM8X10_WCD_A_MODE_LOCK (0x003)
+#define MSM8X10_WCD_A_MODE_LOCK__POR (0x00)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_0 (0x004)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_0__POR (0x00)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_1 (0x005)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_1__POR (0x00)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_2 (0x006)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_2__POR (0x04)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_3 (0x007)
+#define MSM8X10_WCD_A_CHIP_ID_BYTE_3__POR (0x01)
+#define MSM8X10_WCD_A_CHIP_VERSION (0x008)
+#define MSM8X10_WCD_A_CHIP_VERSION__POR (0x00)
+#define MSM8X10_WCD_A_ANALOG_SLAVE_ID (0x00C)
+#define MSM8X10_WCD_A_ANALOG_SLAVE_ID__POR (0x77)
+#define MSM8X10_WCD_A_PIN_CTL_OE (0x010)
+#define MSM8X10_WCD_A_PIN_CTL_OE__POR (0x07)
+#define MSM8X10_WCD_A_PIN_CTL_DATA (0x012)
+#define MSM8X10_WCD_A_PIN_CTL_DATA__POR (0x00)
+#define MSM8X10_WCD_A_PIN_STATUS (0x014)
+#define MSM8X10_WCD_A_PIN_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_HDRIVE_CTL (0x018)
+#define MSM8X10_WCD_A_HDRIVE_CTL__POR (0x01)
+#define MSM8X10_WCD_A_HDRIVE_I2C_CTL (0x019)
+#define MSM8X10_WCD_A_HDRIVE_I2C_CTL__POR (0x01)
+#define MSM8X10_WCD_A_CDC_RST_CTL (0x020)
+#define MSM8X10_WCD_A_CDC_RST_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TOP_CLK_CTL (0x022)
+#define MSM8X10_WCD_A_CDC_TOP_CLK_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_ANA_CLK_CTL (0x023)
+#define MSM8X10_WCD_A_CDC_ANA_CLK_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_DIG_CLK_CTL (0x024)
+#define MSM8X10_WCD_A_CDC_DIG_CLK_CTL__POR (0x00)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL0 (0x030)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL0__POR (0x80)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL1 (0x031)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL1__POR (0x00)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL2 (0x032)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL2__POR (0x00)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL3 (0x033)
+#define MSM8X10_WCD_A_PROCESS_MONITOR_CTL3__POR (0x01)
+#define MSM8X10_WCD_A_QFUSE_CTL (0x034)
+#define MSM8X10_WCD_A_QFUSE_CTL__POR (0x00)
+#define MSM8X10_WCD_A_QFUSE_STATUS (0x035)
+#define MSM8X10_WCD_A_QFUSE_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT0 (0x036)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT0__POR (0x00)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT1 (0x037)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT1__POR (0x00)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT2 (0x038)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT2__POR (0x00)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT3 (0x039)
+#define MSM8X10_WCD_A_QFUSE_DATA_OUT3__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_TX1_CTL (0x040)
+#define MSM8X10_WCD_A_CDC_CONN_TX1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_TX2_CTL (0x041)
+#define MSM8X10_WCD_A_CDC_CONN_TX2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL (0x042)
+#define MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL__POR (0x01)
+#define MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL (0x043)
+#define MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_CTL (0x044)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_CTL (0x045)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_CTL (0x046)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_DIGITAL_DEBUG_CTL (0x048)
+#define MSM8X10_WCD_A_DIGITAL_DEBUG_CTL__POR (0x00)
+#define MSM8X10_WCD_A_ANALOG_DEBUG_CTL (0x049)
+#define MSM8X10_WCD_A_ANALOG_DEBUG_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_CTL (0x050)
+#define MSM8X10_WCD_A_CDC_RX1_CTL__POR (0x7C)
+#define MSM8X10_WCD_A_CDC_RX2_CTL (0x058)
+#define MSM8X10_WCD_A_CDC_RX2_CTL__POR (0x7C)
+#define MSM8X10_WCD_A_CDC_RX3_CTL (0x060)
+#define MSM8X10_WCD_A_CDC_RX3_CTL__POR (0x7C)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA0 (0x070)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA0__POR (0x00)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA1 (0x071)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA1__POR (0x00)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA2 (0x072)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA2__POR (0x00)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA3 (0x073)
+#define MSM8X10_WCD_A_DEM_BYPASS_DATA3__POR (0x00)
+#define MSM8X10_WCD_A_SPARE_0 (0x080)
+#define MSM8X10_WCD_A_SPARE_0__POR (0x00)
+#define MSM8X10_WCD_A_SPARE_1 (0x082)
+#define MSM8X10_WCD_A_SPARE_1__POR (0x00)
+#define MSM8X10_WCD_A_SPARE_2 (0x084)
+#define MSM8X10_WCD_A_SPARE_2__POR (0x00)
+#define MSM8X10_WCD_A_INTR_MODE (0x090)
+#define MSM8X10_WCD_A_INTR_MODE__POR (0x00)
+#define MSM8X10_WCD_A_INTR_MASK0 (0x094)
+#define MSM8X10_WCD_A_INTR_MASK0__POR (0xFF)
+#define MSM8X10_WCD_A_INTR_MASK1 (0x095)
+#define MSM8X10_WCD_A_INTR_MASK1__POR (0xFF)
+#define MSM8X10_WCD_A_INTR_MASK2 (0x096)
+#define MSM8X10_WCD_A_INTR_MASK2__POR (0x3F)
+#define MSM8X10_WCD_A_INTR_STATUS0 (0x098)
+#define MSM8X10_WCD_A_INTR_STATUS0__POR (0x00)
+#define MSM8X10_WCD_A_INTR_STATUS1 (0x099)
+#define MSM8X10_WCD_A_INTR_STATUS1__POR (0x00)
+#define MSM8X10_WCD_A_INTR_STATUS2 (0x09A)
+#define MSM8X10_WCD_A_INTR_STATUS2__POR (0x00)
+#define MSM8X10_WCD_A_INTR_CLEAR0 (0x09C)
+#define MSM8X10_WCD_A_INTR_CLEAR0__POR (0x00)
+#define MSM8X10_WCD_A_INTR_CLEAR1 (0x09D)
+#define MSM8X10_WCD_A_INTR_CLEAR1__POR (0x00)
+#define MSM8X10_WCD_A_INTR_CLEAR2 (0x09E)
+#define MSM8X10_WCD_A_INTR_CLEAR2__POR (0x00)
+#define MSM8X10_WCD_A_INTR_TEST0 (0x0A4)
+#define MSM8X10_WCD_A_INTR_TEST0__POR (0x00)
+#define MSM8X10_WCD_A_INTR_TEST1 (0x0A5)
+#define MSM8X10_WCD_A_INTR_TEST1__POR (0x00)
+#define MSM8X10_WCD_A_INTR_TEST2 (0x0A6)
+#define MSM8X10_WCD_A_INTR_TEST2__POR (0x00)
+#define MSM8X10_WCD_A_INTR_SET0 (0x0A8)
+#define MSM8X10_WCD_A_INTR_SET0__POR (0x00)
+#define MSM8X10_WCD_A_INTR_SET1 (0x0A9)
+#define MSM8X10_WCD_A_INTR_SET1__POR (0x00)
+#define MSM8X10_WCD_A_INTR_SET2 (0x0AA)
+#define MSM8X10_WCD_A_INTR_SET2__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_EN_CTL (0x0C0)
+#define MSM8X10_WCD_A_CDC_MBHC_EN_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_FIR_B1_CFG (0x0C1)
+#define MSM8X10_WCD_A_CDC_MBHC_FIR_B1_CFG__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_FIR_B2_CFG (0x0C2)
+#define MSM8X10_WCD_A_CDC_MBHC_FIR_B2_CFG__POR (0x06)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B1_CTL (0x0C3)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B1_CTL__POR (0x03)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B2_CTL (0x0C4)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B2_CTL__POR (0x09)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B3_CTL (0x0C5)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B3_CTL__POR (0x1E)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B4_CTL (0x0C6)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B4_CTL__POR (0x45)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B5_CTL (0x0C7)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B5_CTL__POR (0x04)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B6_CTL (0x0C8)
+#define MSM8X10_WCD_A_CDC_MBHC_TIMER_B6_CTL__POR (0x78)
+#define MSM8X10_WCD_A_CDC_MBHC_B1_STATUS (0x0C9)
+#define MSM8X10_WCD_A_CDC_MBHC_B1_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_B2_STATUS (0x0CA)
+#define MSM8X10_WCD_A_CDC_MBHC_B2_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_B3_STATUS (0x0CB)
+#define MSM8X10_WCD_A_CDC_MBHC_B3_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_B4_STATUS (0x0CC)
+#define MSM8X10_WCD_A_CDC_MBHC_B4_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_B5_STATUS (0x0CD)
+#define MSM8X10_WCD_A_CDC_MBHC_B5_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_B1_CTL (0x0CE)
+#define MSM8X10_WCD_A_CDC_MBHC_B1_CTL__POR (0xC0)
+#define MSM8X10_WCD_A_CDC_MBHC_B2_CTL (0x0CF)
+#define MSM8X10_WCD_A_CDC_MBHC_B2_CTL__POR (0x5D)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B1_CTL (0x0D0)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B2_CTL (0x0D1)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B3_CTL (0x0D2)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B4_CTL (0x0D3)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B5_CTL (0x0D4)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B5_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B6_CTL (0x0D5)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B7_CTL (0x0D6)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B7_CTL__POR (0xFF)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B8_CTL (0x0D7)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B8_CTL__POR (0x07)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B9_CTL (0x0D8)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B9_CTL__POR (0xFF)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B10_CTL (0x0D9)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B10_CTL__POR (0x7F)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B11_CTL (0x0DA)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B11_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B12_CTL (0x0DB)
+#define MSM8X10_WCD_A_CDC_MBHC_VOLT_B12_CTL__POR (0x80)
+#define MSM8X10_WCD_A_CDC_MBHC_CLK_CTL (0x0DC)
+#define MSM8X10_WCD_A_CDC_MBHC_CLK_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_INT_CTL (0x0DD)
+#define MSM8X10_WCD_A_CDC_MBHC_INT_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_DEBUG_CTL (0x0DE)
+#define MSM8X10_WCD_A_CDC_MBHC_DEBUG_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_MBHC_SPARE (0x0DF)
+#define MSM8X10_WCD_A_CDC_MBHC_SPARE__POR (0x00)
+#define MSM8X10_WCD_A_BIAS_REF_CTL (0x100)
+#define MSM8X10_WCD_A_BIAS_REF_CTL__POR (0x1C)
+#define MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL (0x101)
+#define MSM8X10_WCD_A_BIAS_CENTRAL_BG_CTL__POR (0x50)
+#define MSM8X10_WCD_A_BIAS_PRECHRG_CTL (0x102)
+#define MSM8X10_WCD_A_BIAS_PRECHRG_CTL__POR (0x07)
+#define MSM8X10_WCD_A_BIAS_CURR_CTL_1 (0x103)
+#define MSM8X10_WCD_A_BIAS_CURR_CTL_1__POR (0x52)
+#define MSM8X10_WCD_A_BIAS_CURR_CTL_2 (0x104)
+#define MSM8X10_WCD_A_BIAS_CURR_CTL_2__POR (0x00)
+#define MSM8X10_WCD_A_BIAS_OSC_BG_CTL (0x105)
+#define MSM8X10_WCD_A_BIAS_OSC_BG_CTL__POR (0x16)
+#define MSM8X10_WCD_A_MICB_CFILT_1_CTL (0x128)
+#define MSM8X10_WCD_A_MICB_CFILT_1_CTL__POR (0x40)
+#define MSM8X10_WCD_A_MICB_CFILT_1_VAL (0x129)
+#define MSM8X10_WCD_A_MICB_CFILT_1_VAL__POR (0x80)
+#define MSM8X10_WCD_A_MICB_CFILT_1_PRECHRG (0x12A)
+#define MSM8X10_WCD_A_MICB_CFILT_1_PRECHRG__POR (0x00)
+#define MSM8X10_WCD_A_MICB_1_CTL (0x12B)
+#define MSM8X10_WCD_A_MICB_1_CTL__POR (0x02)
+#define MSM8X10_WCD_A_MICB_1_INT_RBIAS (0x12C)
+#define MSM8X10_WCD_A_MICB_1_INT_RBIAS__POR (0x00)
+#define MSM8X10_WCD_A_MICB_1_MBHC (0x12D)
+#define MSM8X10_WCD_A_MICB_1_MBHC__POR (0x00)
+#define MSM8X10_WCD_A_MBHC_INSERT_DETECT (0x14A)
+#define MSM8X10_WCD_A_MBHC_INSERT_DETECT__POR (0x00)
+#define MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS (0x14B)
+#define MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_TX_COM_BIAS (0x14C)
+#define MSM8X10_WCD_A_TX_COM_BIAS__POR (0xF0)
+#define MSM8X10_WCD_A_MBHC_SCALING_MUX_1 (0x14E)
+#define MSM8X10_WCD_A_MBHC_SCALING_MUX_1__POR (0x00)
+#define MSM8X10_WCD_A_MBHC_SCALING_MUX_2 (0x14F)
+#define MSM8X10_WCD_A_MBHC_SCALING_MUX_2__POR (0x80)
+#define MSM8X10_WCD_A_RESERVED_MAD_ANA_CTRL (0x150)
+#define MSM8X10_WCD_A_RESERVED_MAD_ANA_CTRL__POR (0xF1)
+#define MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1 (0x151)
+#define MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1__POR (0x00)
+#define MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_2 (0x152)
+#define MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_2__POR (0x80)
+#define MSM8X10_WCD_A_TX_1_EN (0x153)
+#define MSM8X10_WCD_A_TX_1_EN__POR (0x02)
+#define MSM8X10_WCD_A_TX_2_EN (0x154)
+#define MSM8X10_WCD_A_TX_2_EN__POR (0x02)
+#define MSM8X10_WCD_A_TX_1_2_ADC_CH1 (0x155)
+#define MSM8X10_WCD_A_TX_1_2_ADC_CH1__POR (0x44)
+#define MSM8X10_WCD_A_TX_1_2_ADC_CH2 (0x156)
+#define MSM8X10_WCD_A_TX_1_2_ADC_CH2__POR (0x44)
+#define MSM8X10_WCD_A_TX_1_2_ATEST_REFCTRL (0x157)
+#define MSM8X10_WCD_A_TX_1_2_ATEST_REFCTRL__POR (0x00)
+#define MSM8X10_WCD_A_TX_1_2_TEST_CTL (0x158)
+#define MSM8X10_WCD_A_TX_1_2_TEST_CTL__POR (0x38)
+#define MSM8X10_WCD_A_TX_1_2_TEST_BLOCK_EN (0x159)
+#define MSM8X10_WCD_A_TX_1_2_TEST_BLOCK_EN__POR (0xFC)
+#define MSM8X10_WCD_A_TX_1_2_TXFE_CLKDIV (0x15A)
+#define MSM8X10_WCD_A_TX_1_2_TXFE_CLKDIV__POR (0x55)
+#define MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH1 (0x15B)
+#define MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH1__POR (0x00)
+#define MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH2 (0x15C)
+#define MSM8X10_WCD_A_TX_1_2_SAR_ERR_CH2__POR (0x00)
+#define MSM8X10_WCD_A_TX_3_EN (0x15D)
+#define MSM8X10_WCD_A_TX_3_EN__POR (0x00)
+#define MSM8X10_WCD_A_TX_1_2_TEST_EN (0x15E)
+#define MSM8X10_WCD_A_TX_1_2_TEST_EN__POR (0xCC)
+#define MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL (0x171)
+#define MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL__POR (0x10)
+#define MSM8X10_WCD_A_TX_7_MBHC_SAR_ERR (0x175)
+#define MSM8X10_WCD_A_TX_7_MBHC_SAR_ERR__POR (0x00)
+#define MSM8X10_WCD_A_CP_EN (0x192)
+#define MSM8X10_WCD_A_CP_EN__POR (0xE6)
+#define MSM8X10_WCD_A_CP_CLK (0x193)
+#define MSM8X10_WCD_A_CP_CLK__POR (0x29)
+#define MSM8X10_WCD_A_CP_STATIC (0x194)
+#define MSM8X10_WCD_A_CP_STATIC__POR (0x10)
+#define MSM8X10_WCD_A_CP_DCC1 (0x195)
+#define MSM8X10_WCD_A_CP_DCC1__POR (0x52)
+#define MSM8X10_WCD_A_CP_DCC3 (0x196)
+#define MSM8X10_WCD_A_CP_DCC3__POR (0x01)
+#define MSM8X10_WCD_A_CP_ATEST (0x197)
+#define MSM8X10_WCD_A_CP_ATEST__POR (0x00)
+#define MSM8X10_WCD_A_CP_DTEST (0x198)
+#define MSM8X10_WCD_A_CP_DTEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_AUX_SW_CTL (0x19B)
+#define MSM8X10_WCD_A_RX_AUX_SW_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_PA_AUX_IN_CONN (0x19C)
+#define MSM8X10_WCD_A_RX_PA_AUX_IN_CONN__POR (0x00)
+#define MSM8X10_WCD_A_RX_COM_TIMER_DIV (0x19E)
+#define MSM8X10_WCD_A_RX_COM_TIMER_DIV__POR (0xE8)
+#define MSM8X10_WCD_A_RX_COM_OCP_CTL (0x19F)
+#define MSM8X10_WCD_A_RX_COM_OCP_CTL__POR (0x1F)
+#define MSM8X10_WCD_A_RX_COM_OCP_COUNT (0x1A0)
+#define MSM8X10_WCD_A_RX_COM_OCP_COUNT__POR (0x77)
+#define MSM8X10_WCD_A_RX_COM_DAC_CTL (0x1A1)
+#define MSM8X10_WCD_A_RX_COM_DAC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_COM_BIAS (0x1A2)
+#define MSM8X10_WCD_A_RX_COM_BIAS__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_AUTO_CHOP (0x1A4)
+#define MSM8X10_WCD_A_RX_HPH_AUTO_CHOP__POR (0x38)
+#define MSM8X10_WCD_A_RX_HPH_CHOP_CTL (0x1A5)
+#define MSM8X10_WCD_A_RX_HPH_CHOP_CTL__POR (0x34)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_PA (0x1A6)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_PA__POR (0x5A)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_LDO (0x1A7)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_LDO__POR (0x87)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_CNP (0x1A8)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_CNP__POR (0x8A)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP (0x1A9)
+#define MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP__POR (0x2A)
+#define MSM8X10_WCD_A_RX_HPH_OCP_CTL (0x1AA)
+#define MSM8X10_WCD_A_RX_HPH_OCP_CTL__POR (0x69)
+#define MSM8X10_WCD_A_RX_HPH_CNP_EN (0x1AB)
+#define MSM8X10_WCD_A_RX_HPH_CNP_EN__POR (0x80)
+#define MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL (0x1AC)
+#define MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL__POR (0xDE)
+#define MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME (0x1AD)
+#define MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME__POR (0x15)
+#define MSM8X10_WCD_A_RX_HPH_L_GAIN (0x1AE)
+#define MSM8X10_WCD_A_RX_HPH_L_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_L_TEST (0x1AF)
+#define MSM8X10_WCD_A_RX_HPH_L_TEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_L_PA_CTL (0x1B0)
+#define MSM8X10_WCD_A_RX_HPH_L_PA_CTL__POR (0x40)
+#define MSM8X10_WCD_A_RX_HPH_L_DAC_CTL (0x1B1)
+#define MSM8X10_WCD_A_RX_HPH_L_DAC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_L_ATEST (0x1B2)
+#define MSM8X10_WCD_A_RX_HPH_L_ATEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_L_STATUS (0x1B3)
+#define MSM8X10_WCD_A_RX_HPH_L_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_R_GAIN (0x1B4)
+#define MSM8X10_WCD_A_RX_HPH_R_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_R_TEST (0x1B5)
+#define MSM8X10_WCD_A_RX_HPH_R_TEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_R_PA_CTL (0x1B6)
+#define MSM8X10_WCD_A_RX_HPH_R_PA_CTL__POR (0x40)
+#define MSM8X10_WCD_A_RX_HPH_R_DAC_CTL (0x1B7)
+#define MSM8X10_WCD_A_RX_HPH_R_DAC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_R_ATEST (0x1B8)
+#define MSM8X10_WCD_A_RX_HPH_R_ATEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_HPH_R_STATUS (0x1B9)
+#define MSM8X10_WCD_A_RX_HPH_R_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_RX_EAR_BIAS_PA (0x1BA)
+#define MSM8X10_WCD_A_RX_EAR_BIAS_PA__POR (0x56)
+#define MSM8X10_WCD_A_RX_EAR_BIAS_CMBUFF (0x1BB)
+#define MSM8X10_WCD_A_RX_EAR_BIAS_CMBUFF__POR (0xA0)
+#define MSM8X10_WCD_A_RX_EAR_EN (0x1BC)
+#define MSM8X10_WCD_A_RX_EAR_EN__POR (0x00)
+#define MSM8X10_WCD_A_RX_EAR_GAIN (0x1BD)
+#define MSM8X10_WCD_A_RX_EAR_GAIN__POR (0x02)
+#define MSM8X10_WCD_A_RX_EAR_CMBUFF (0x1BE)
+#define MSM8X10_WCD_A_RX_EAR_CMBUFF__POR (0x05)
+#define MSM8X10_WCD_A_RX_EAR_ICTL (0x1BF)
+#define MSM8X10_WCD_A_RX_EAR_ICTL__POR (0x40)
+#define MSM8X10_WCD_A_RX_EAR_CCOMP (0x1C0)
+#define MSM8X10_WCD_A_RX_EAR_CCOMP__POR (0x08)
+#define MSM8X10_WCD_A_RX_EAR_VCM (0x1C1)
+#define MSM8X10_WCD_A_RX_EAR_VCM__POR (0x03)
+#define MSM8X10_WCD_A_RX_EAR_CNP (0x1C2)
+#define MSM8X10_WCD_A_RX_EAR_CNP__POR (0xF2)
+#define MSM8X10_WCD_A_RX_EAR_DAC_CTL_ATEST (0x1C3)
+#define MSM8X10_WCD_A_RX_EAR_DAC_CTL_ATEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_EAR_STATUS (0x1C5)
+#define MSM8X10_WCD_A_RX_EAR_STATUS__POR (0x04)
+#define MSM8X10_WCD_A_RX_LINE_BIAS_PA (0x1C6)
+#define MSM8X10_WCD_A_RX_LINE_BIAS_PA__POR (0x58)
+#define MSM8X10_WCD_A_RX_BUCK_BIAS1 (0x1C7)
+#define MSM8X10_WCD_A_RX_BUCK_BIAS1__POR (0x42)
+#define MSM8X10_WCD_A_RX_BUCK_BIAS2 (0x1C8)
+#define MSM8X10_WCD_A_RX_BUCK_BIAS2__POR (0x84)
+#define MSM8X10_WCD_A_RX_LINE_COM (0x1C9)
+#define MSM8X10_WCD_A_RX_LINE_COM__POR (0x80)
+#define MSM8X10_WCD_A_RX_LINE_CNP_EN (0x1CA)
+#define MSM8X10_WCD_A_RX_LINE_CNP_EN__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_CNP_WG_CTL (0x1CB)
+#define MSM8X10_WCD_A_RX_LINE_CNP_WG_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_CNP_WG_TIME (0x1CC)
+#define MSM8X10_WCD_A_RX_LINE_CNP_WG_TIME__POR (0x04)
+#define MSM8X10_WCD_A_RX_LINE_1_GAIN (0x1CD)
+#define MSM8X10_WCD_A_RX_LINE_1_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_1_TEST (0x1CE)
+#define MSM8X10_WCD_A_RX_LINE_1_TEST__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_1_DAC_CTL (0x1CF)
+#define MSM8X10_WCD_A_RX_LINE_1_DAC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_1_STATUS (0x1D0)
+#define MSM8X10_WCD_A_RX_LINE_1_STATUS__POR (0x00)
+#define MSM8X10_WCD_A_RX_LINE_CNP_DBG (0x1DD)
+#define MSM8X10_WCD_A_RX_LINE_CNP_DBG__POR (0x00)
+#define MSM8X10_WCD_A_SPKR_DRV_EN (0x1DF)
+#define MSM8X10_WCD_A_SPKR_DRV_EN__POR (0x6F)
+#define MSM8X10_WCD_A_SPKR_DRV_GAIN (0x1E0)
+#define MSM8X10_WCD_A_SPKR_DRV_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_SPKR_DRV_DAC_CTL (0x1E1)
+#define MSM8X10_WCD_A_SPKR_DRV_DAC_CTL__POR (0x04)
+#define MSM8X10_WCD_A_SPKR_DRV_OCP_CTL (0x1E2)
+#define MSM8X10_WCD_A_SPKR_DRV_OCP_CTL__POR (0x98)
+#define MSM8X10_WCD_A_SPKR_DRV_CLIP_DET (0x1E3)
+#define MSM8X10_WCD_A_SPKR_DRV_CLIP_DET__POR (0x01)
+#define MSM8X10_WCD_A_SPKR_DRV_IEC (0x1E4)
+#define MSM8X10_WCD_A_SPKR_DRV_IEC__POR (0x00)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_DAC (0x1E5)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_DAC__POR (0x05)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_PA (0x1E6)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_PA__POR (0x18)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_PWRSTG (0x1E7)
+#define MSM8X10_WCD_A_SPKR_DRV_DBG_PWRSTG__POR (0x00)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_LDO (0x1E8)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_LDO__POR (0x45)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_INT (0x1E9)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_INT__POR (0xA5)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_PA (0x1EA)
+#define MSM8X10_WCD_A_SPKR_DRV_BIAS_PA__POR (0x55)
+#define MSM8X10_WCD_A_SPKR_DRV_STATUS_OCP (0x1EB)
+#define MSM8X10_WCD_A_SPKR_DRV_STATUS_OCP__POR (0x00)
+#define MSM8X10_WCD_A_SPKR_DRV_STATUS_PA (0x1EC)
+#define MSM8X10_WCD_A_SPKR_DRV_STATUS_PA__POR (0x00)
+#define MSM8X10_WCD_A_RC_OSC_FREQ (0x1FA)
+#define MSM8X10_WCD_A_RC_OSC_FREQ__POR (0x46)
+#define MSM8X10_WCD_A_RC_OSC_TEST (0x1FB)
+#define MSM8X10_WCD_A_RC_OSC_TEST__POR (0x0A)
+#define MSM8X10_WCD_A_RC_OSC_STATUS (0x1FC)
+#define MSM8X10_WCD_A_RC_OSC_STATUS__POR (0x18)
+#define MSM8X10_WCD_A_RC_OSC_TUNER (0x1FD)
+#define MSM8X10_WCD_A_RC_OSC_TUNER__POR (0x00)
+#define MSM8X10_WCD_A_MBHC_HPH (0x1FE)
+#define MSM8X10_WCD_A_MBHC_HPH__POR (0x44)
+#define MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL (0x400)
+#define MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL (0x404)
+#define MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL (0x408)
+#define MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL (0x40C)
+#define MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL__POR (0x10)
+#define MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL (0x410)
+#define MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL__POR (0x10)
+#define MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL (0x414)
+#define MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL (0x418)
+#define MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_OTHR_CTL (0x41C)
+#define MSM8X10_WCD_A_CDC_CLK_OTHR_CTL__POR (0x04)
+#define MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL (0x420)
+#define MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_MCLK_CTL (0x424)
+#define MSM8X10_WCD_A_CDC_CLK_MCLK_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_PDM_CTL (0x428)
+#define MSM8X10_WCD_A_CDC_CLK_PDM_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLK_SD_CTL (0x42C)
+#define MSM8X10_WCD_A_CDC_CLK_SD_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_B1_CTL (0x440)
+#define MSM8X10_WCD_A_CDC_RX1_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_B1_CTL (0x460)
+#define MSM8X10_WCD_A_CDC_RX2_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_B1_CTL (0x480)
+#define MSM8X10_WCD_A_CDC_RX3_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_B2_CTL (0x444)
+#define MSM8X10_WCD_A_CDC_RX1_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_B2_CTL (0x464)
+#define MSM8X10_WCD_A_CDC_RX2_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_B2_CTL (0x484)
+#define MSM8X10_WCD_A_CDC_RX3_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_B3_CTL (0x448)
+#define MSM8X10_WCD_A_CDC_RX1_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_B3_CTL (0x468)
+#define MSM8X10_WCD_A_CDC_RX2_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_B3_CTL (0x488)
+#define MSM8X10_WCD_A_CDC_RX3_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_B4_CTL (0x44C)
+#define MSM8X10_WCD_A_CDC_RX1_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_B4_CTL (0x46C)
+#define MSM8X10_WCD_A_CDC_RX2_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_B4_CTL (0x48C)
+#define MSM8X10_WCD_A_CDC_RX3_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_B5_CTL (0x450)
+#define MSM8X10_WCD_A_CDC_RX1_B5_CTL__POR (0x68)
+#define MSM8X10_WCD_A_CDC_RX2_B5_CTL (0x470)
+#define MSM8X10_WCD_A_CDC_RX2_B5_CTL__POR (0x68)
+#define MSM8X10_WCD_A_CDC_RX3_B5_CTL (0x490)
+#define MSM8X10_WCD_A_CDC_RX3_B5_CTL__POR (0x68)
+#define MSM8X10_WCD_A_CDC_RX1_B6_CTL (0x454)
+#define MSM8X10_WCD_A_CDC_RX1_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_B6_CTL (0x474)
+#define MSM8X10_WCD_A_CDC_RX2_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_B6_CTL (0x494)
+#define MSM8X10_WCD_A_CDC_RX3_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B1_CTL (0x458)
+#define MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B1_CTL (0x478)
+#define MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B1_CTL (0x498)
+#define MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL (0x45C)
+#define MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL (0x47C)
+#define MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL (0x49C)
+#define MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL (0x4A0)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR (0x07)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B2_CTL (0x4A4)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR (0x13)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B3_CTL (0x4A8)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR (0x1B)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B4_CTL (0x4AC)
+#define MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR (0x7F)
+#define MSM8X10_WCD_A_CDC_CLSG_GAIN_THRESH_CTL (0x4B0)
+#define MSM8X10_WCD_A_CDC_CLSG_GAIN_THRESH_CTL__POR (0x26)
+#define MSM8X10_WCD_A_CDC_CLSG_TIMER_B1_CFG (0x4B4)
+#define MSM8X10_WCD_A_CDC_CLSG_TIMER_B1_CFG__POR (0x0A)
+#define MSM8X10_WCD_A_CDC_CLSG_TIMER_B2_CFG (0x4B8)
+#define MSM8X10_WCD_A_CDC_CLSG_TIMER_B2_CFG__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CLSG_CTL (0x4BC)
+#define MSM8X10_WCD_A_CDC_CLSG_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_TIMER (0x4C0)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_TIMER__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_TIMER (0x4E0)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_TIMER__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN (0x4C4)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN (0x4E4)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG (0x4C8)
+#define MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_CFG (0x4E8)
+#define MSM8X10_WCD_A_CDC_TX2_VOL_CTL_CFG__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX1_MUX_CTL (0x4CC)
+#define MSM8X10_WCD_A_CDC_TX1_MUX_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX2_MUX_CTL (0x4EC)
+#define MSM8X10_WCD_A_CDC_TX2_MUX_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX1_CLK_FS_CTL (0x4D0)
+#define MSM8X10_WCD_A_CDC_TX1_CLK_FS_CTL__POR (0x03)
+#define MSM8X10_WCD_A_CDC_TX2_CLK_FS_CTL (0x4F0)
+#define MSM8X10_WCD_A_CDC_TX2_CLK_FS_CTL__POR (0x03)
+#define MSM8X10_WCD_A_CDC_TX1_DMIC_CTL (0x4D4)
+#define MSM8X10_WCD_A_CDC_TX1_DMIC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TX2_DMIC_CTL (0x4F4)
+#define MSM8X10_WCD_A_CDC_TX2_DMIC_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL (0x500)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B1_CTL (0x540)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL (0x504)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B2_CTL (0x544)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL (0x508)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B3_CTL (0x548)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL (0x50C)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B4_CTL (0x54C)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B5_CTL (0x510)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B5_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B5_CTL (0x550)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B5_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B6_CTL (0x514)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B6_CTL (0x554)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B6_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B7_CTL (0x518)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B7_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B7_CTL (0x558)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B7_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B8_CTL (0x51C)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_B8_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B8_CTL (0x55C)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_B8_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_CTL (0x520)
+#define MSM8X10_WCD_A_CDC_IIR1_CTL__POR (0x40)
+#define MSM8X10_WCD_A_CDC_IIR2_CTL (0x560)
+#define MSM8X10_WCD_A_CDC_IIR2_CTL__POR (0x40)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_TIMER_CTL (0x524)
+#define MSM8X10_WCD_A_CDC_IIR1_GAIN_TIMER_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_TIMER_CTL (0x564)
+#define MSM8X10_WCD_A_CDC_IIR2_GAIN_TIMER_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL (0x528)
+#define MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_COEF_B1_CTL (0x568)
+#define MSM8X10_WCD_A_CDC_IIR2_COEF_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL (0x52C)
+#define MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL (0x56C)
+#define MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL (0x580)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL (0x584)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL (0x588)
+#define MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL (0x58C)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B2_CTL (0x590)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL (0x594)
+#define MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL (0x598)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_B2_CTL (0x59C)
+#define MSM8X10_WCD_A_CDC_CONN_RX3_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL (0x5A4)
+#define MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL (0x5A8)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B2_CTL (0x5AC)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B3_CTL (0x5B0)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B4_CTL (0x5B4)
+#define MSM8X10_WCD_A_CDC_CONN_EQ1_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B1_CTL (0x5B8)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B2_CTL (0x5BC)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B3_CTL (0x5C0)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B3_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B4_CTL (0x5C4)
+#define MSM8X10_WCD_A_CDC_CONN_EQ2_B4_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_CONN_TX_I2S_SD1_CTL (0x5C8)
+#define MSM8X10_WCD_A_CDC_CONN_TX_I2S_SD1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TOP_GAIN_UPDATE (0x5D0)
+#define MSM8X10_WCD_A_CDC_TOP_GAIN_UPDATE__POR (0x00)
+#define MSM8X10_WCD_A_CDC_TOP_CTL (0x5D8)
+#define MSM8X10_WCD_A_CDC_TOP_CTL__POR (0x01)
+#define MSM8X10_WCD_A_CDC_DEBUG_DESER1_CTL (0x5E0)
+#define MSM8X10_WCD_A_CDC_DEBUG_DESER1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_DEBUG_DESER2_CTL (0x5E4)
+#define MSM8X10_WCD_A_CDC_DEBUG_DESER2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_DEBUG_B1_CTL (0x5E8)
+#define MSM8X10_WCD_A_CDC_DEBUG_B1_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_DEBUG_B2_CTL (0x5EC)
+#define MSM8X10_WCD_A_CDC_DEBUG_B2_CTL__POR (0x00)
+#define MSM8X10_WCD_A_CDC_DEBUG_B3_CTL (0x5F0)
+#define MSM8X10_WCD_A_CDC_DEBUG_B3_CTL__POR (0x00)
+#endif
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 28be822..6f601c1 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -36,6 +36,7 @@
#include <linux/gpio.h>
#include "wcd9320.h"
#include "wcd9xxx-resmgr.h"
+#include "wcd9xxx-common.h"
static atomic_t kp_taiko_priv;
static int spkr_drv_wrnd_param_set(const char *val,
@@ -69,6 +70,7 @@
#define TAIKO_SLIM_IRQ_PORT_CLOSED (1 << 2)
#define TAIKO_MCLK_CLK_12P288MHZ 12288000
#define TAIKO_MCLK_CLK_9P6HZ 9600000
+
enum {
AIF1_PB = 0,
AIF1_CAP,
@@ -233,6 +235,10 @@
struct wcd9xxx_resmgr resmgr;
/* mbhc module */
struct wcd9xxx_mbhc mbhc;
+
+ /* class h specific data */
+ struct wcd9xxx_clsh_cdc_data clsh_d;
+
};
static const u32 comp_shift[] = {
@@ -354,73 +360,6 @@
return 0;
}
-static int taiko_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- pr_debug("%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TAIKO_A_CDC_CLSH_B1_CTL, 0x01, 0x01);
- break;
- case SND_SOC_DAPM_PRE_PMD:
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x80, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_CDC_CLSH_B1_CTL, 0x01, 0x00);
- break;
- }
- return 0;
-}
-
-static int taiko_codec_enable_class_h(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- pr_debug("%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_POST_PMU:
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x02);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_4, 0xFF, 0xFF);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x04, 0x04);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x04, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_1, 0x80, 0x80);
- usleep_range(1000, 1000);
- break;
- }
- return 0;
-}
-
-static int taiko_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- pr_debug("%s %s %d\n", __func__, w->name, event);
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, w->reg, 0x01, 0x01);
- snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
- break;
-
- case SND_SOC_DAPM_POST_PMU:
- usleep_range(1000, 1000);
- break;
-
- case SND_SOC_DAPM_PRE_PMD:
- snd_soc_update_bits(codec, w->reg, 0x01, 0x00);
- snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
- break;
- }
- return 0;
-}
-
-
static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -905,6 +844,17 @@
static const struct soc_enum cf_rxmix7_enum =
SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 1, 3, cf_text);
+static const char * const class_h_dsm_text[] = {
+ "ZERO", "DSM_HPHL_RX1", "DSM_SPKR_RX7"
+};
+
+static const struct soc_enum class_h_dsm_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_CLSH_CTL, 4, 3, class_h_dsm_text);
+
+static const struct snd_kcontrol_new class_h_dsm_mux =
+ SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
+
+
static const struct snd_kcontrol_new taiko_snd_controls[] = {
SOC_ENUM_EXT("EAR PA Gain", taiko_ear_pa_gain_enum[0],
@@ -1842,11 +1792,12 @@
if (enable) {
taiko->adc_count++;
- snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
+ 0x2, 0x2);
} else {
taiko->adc_count--;
if (!taiko->adc_count)
- snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL,
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
0x2, 0x0);
}
}
@@ -1934,6 +1885,7 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
u16 lineout_gain_reg;
pr_debug("%s %d %s\n", __func__, event, w->name);
@@ -1962,11 +1914,19 @@
snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
break;
case SND_SOC_DAPM_POST_PMU:
- pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
+ wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+ pr_debug("%s: sleeping 3 ms after %s PA turn on\n",
__func__, w->name);
- usleep_range(16000, 16000);
+ usleep_range(3000, 3000);
break;
case SND_SOC_DAPM_POST_PMD:
+ wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
break;
}
@@ -2169,45 +2129,44 @@
{
struct snd_soc_codec *codec = w->codec;
struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
- u16 micb_int_reg;
+ u16 micb_int_reg = 0, micb_ctl_reg = 0;
u8 cfilt_sel_val = 0;
char *internal1_text = "Internal1";
char *internal2_text = "Internal2";
char *internal3_text = "Internal3";
enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
- pr_debug("%s %d\n", __func__, event);
- switch (w->reg) {
- case TAIKO_A_MICB_1_CTL:
+ pr_debug("%s: w->name %s event %d\n", __func__, w->name, event);
+ if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1"))) {
+ micb_ctl_reg = TAIKO_A_MICB_1_CTL;
micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
cfilt_sel_val = taiko->resmgr.pdata->micbias.bias1_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
- break;
- case TAIKO_A_MICB_2_CTL:
+ } else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2"))) {
+ micb_ctl_reg = TAIKO_A_MICB_2_CTL;
micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
cfilt_sel_val = taiko->resmgr.pdata->micbias.bias2_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_2_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_2_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_2_OFF;
- break;
- case TAIKO_A_MICB_3_CTL:
+ } else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3"))) {
+ micb_ctl_reg = TAIKO_A_MICB_2_CTL;
micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
cfilt_sel_val = taiko->resmgr.pdata->micbias.bias3_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_3_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_3_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_3_OFF;
- break;
- case TAIKO_A_MICB_4_CTL:
+ } else if (strnstr(w->name, "MIC BIAS4", sizeof("MIC BIAS4"))) {
+ micb_ctl_reg = TAIKO_A_MICB_2_CTL;
micb_int_reg = taiko->resmgr.reg_addr->micb_4_int_rbias;
cfilt_sel_val = taiko->resmgr.pdata->micbias.bias4_cfilt_sel;
e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_4_ON;
e_post_on = WCD9XXX_EVENT_POST_MICBIAS_4_ON;
e_post_off = WCD9XXX_EVENT_POST_MICBIAS_4_OFF;
- break;
- default:
- pr_err("%s: Error, invalid micbias register\n", __func__);
+ } else {
+ pr_err("%s: Error, invalid micbias %s\n", __func__, w->name);
return -EINVAL;
}
@@ -2226,6 +2185,16 @@
else if (strnstr(w->name, internal3_text, 30))
snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+ if (micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
+ WCD9XXX_BCL_LOCK(&taiko->resmgr);
+ wcd9xxx_resmgr_add_cond_update_bits(&taiko->resmgr,
+ WCD9XXX_COND_HPH_MIC,
+ micb_ctl_reg, w->shift,
+ false);
+ WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+ } else
+ snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+ 1 << w->shift);
break;
case SND_SOC_DAPM_POST_PMU:
usleep_range(20000, 20000);
@@ -2233,6 +2202,16 @@
wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_on);
break;
case SND_SOC_DAPM_POST_PMD:
+ if (micb_ctl_reg == TAIKO_A_MICB_2_CTL) {
+ WCD9XXX_BCL_LOCK(&taiko->resmgr);
+ wcd9xxx_resmgr_rm_cond_update_bits(&taiko->resmgr,
+ WCD9XXX_COND_HPH_MIC,
+ micb_ctl_reg, 7, false);
+ WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+ } else
+ snd_soc_update_bits(codec, micb_ctl_reg, 1 << w->shift,
+ 0);
+
/* Let MBHC module know so micbias switch to be off */
wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
@@ -2496,18 +2475,52 @@
}
return 0;
}
-static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
+
+static int taiko_hphl_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
pr_debug("%s %s %d\n", __func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x02, 0x02);
+ wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
+ WCD9XXX_CLSH_STATE_HPHL,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
break;
case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x02, 0x00);
+ }
+ return 0;
+}
+
+static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x04, 0x04);
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
+ WCD9XXX_CLSH_STATE_HPHR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL,
+ 0x04, 0x00);
snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
break;
}
@@ -2520,14 +2533,17 @@
struct snd_soc_codec *codec = w->codec;
struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
enum wcd9xxx_notify_event e_pre_on, e_post_off;
+ u8 req_clsh_state;
pr_debug("%s: %s event = %d\n", __func__, w->name, event);
if (w->shift == 5) {
e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
+ req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
} else if (w->shift == 4) {
e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+ req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
} else {
pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
return -EINVAL;
@@ -2540,29 +2556,27 @@
break;
case SND_SOC_DAPM_POST_PMU:
- usleep_range(10000, 10000);
+ wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
+ req_clsh_state,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x20, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x04);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
- usleep_range(10, 10);
+ usleep_range(5000, 5000);
break;
case SND_SOC_DAPM_POST_PMD:
/* Let MBHC module know PA turned off */
wcd9xxx_resmgr_notifier_call(&taiko->resmgr, e_post_off);
- /*
- * 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.
- */
+ wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
+ req_clsh_state,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+
pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
w->name);
- usleep_range(10000, 10000);
+ usleep_range(5000, 5000);
break;
}
return 0;
@@ -2579,11 +2593,16 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
pr_debug("%s %s %d\n", __func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ wcd9xxx_clsh_fsm(codec, &taiko->clsh_d,
+ WCD9XXX_CLSH_STATE_LO,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
break;
@@ -2738,15 +2757,11 @@
{"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
{"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
- /* Change Pump */
- {"CP", NULL, "CLASS_H_CLK"},
-
/* Earpiece (RX MIX1) */
{"EAR", NULL, "EAR PA"},
{"EAR PA", NULL, "EAR_PA_MIXER"},
{"EAR_PA_MIXER", NULL, "DAC1"},
- {"DAC1", NULL, "CLASS_H_EAR"},
- {"CLASS_H_EAR", NULL, "CP"},
+ {"DAC1", NULL, "RX_BIAS"},
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
@@ -2758,15 +2773,11 @@
{"HPHL", NULL, "HPHL_PA_MIXER"},
{"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+ {"HPHL DAC", NULL, "RX_BIAS"},
{"HPHR", NULL, "HPHR_PA_MIXER"},
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
-
- {"HPHL DAC", NULL, "CLASS_H_HPH_L"},
- {"CLASS_H_HPH_L", NULL, "CP"},
-
- {"HPHR DAC", NULL, "CLASS_H_HPH_R"},
- {"CLASS_H_HPH_R", NULL, "CP"},
+ {"HPHR DAC", NULL, "RX_BIAS"},
{"ANC", NULL, "ANC1 MUX"},
{"ANC", NULL, "ANC2 MUX"},
@@ -2781,8 +2792,8 @@
{"ANC", NULL, "CDC_CONN"},
- {"DAC1", "Switch", "RX1 CHAIN"},
- {"HPHL DAC", "Switch", "RX1 CHAIN"},
+ {"DAC1", "Switch", "CLASS_H_DSM MUX"},
+ {"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
{"HPHR DAC", NULL, "RX2 CHAIN"},
{"LINEOUT1", NULL, "LINEOUT1 PA"},
@@ -2791,30 +2802,20 @@
{"LINEOUT4", NULL, "LINEOUT4 PA"},
{"SPK_OUT", NULL, "SPK PA"},
- {"LINEOUT1 PA", NULL, "CP"},
{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
- {"LINEOUT2 PA", NULL, "CP"},
{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
- {"LINEOUT3 PA", NULL, "CP"},
{"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
{"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
- {"LINEOUT4 PA", NULL, "CP"},
{"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
{"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
- {"CP", NULL, "CLASS_H_LINEOUTS_PA"},
- {"CLASS_H_LINEOUTS_PA", NULL, "CLASS_H_CLK"},
-
-
-
{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
-
{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
{"RDAC5 MUX", "DEM4", "RX4 MIX1"},
@@ -2831,12 +2832,13 @@
{"SPK DAC", NULL, "RX7 MIX2"},
{"SPK DAC", NULL, "VDD_SPKDRV"},
+ {"CLASS_H_DSM MUX", "DSM_HPHL_RX1", "RX1 CHAIN"},
+
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
{"RX1 CHAIN", NULL, "ANC"},
{"RX2 CHAIN", NULL, "ANC"},
- {"CLASS_H_CLK", NULL, "RX_BIAS"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
{"LINEOUT3 DAC", NULL, "RX_BIAS"},
@@ -3967,24 +3969,81 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
pr_debug("%s %s %d\n", __func__, w->name, event);
switch (event) {
- break;
case SND_SOC_DAPM_POST_PMU:
-
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_5, 0x02, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x20, 0x00);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x04, 0x04);
- snd_soc_update_bits(codec, TAIKO_A_BUCK_MODE_3, 0x08, 0x00);
+ wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
usleep_range(5000, 5000);
break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_DISABLE,
+ WCD9XXX_CLSH_EVENT_POST_PA);
+ usleep_range(5000, 5000);
+ }
+ return 0;
+}
+
+static int taiko_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd9xxx_clsh_fsm(codec, &taiko_p->clsh_d,
+ WCD9XXX_CLSH_STATE_EAR,
+ WCD9XXX_CLSH_REQ_ENABLE,
+ WCD9XXX_CLSH_EVENT_PRE_DAC);
+ break;
+ }
+
+ return 0;
+}
+
+static int taiko_codec_dsm_mux_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u8 reg_val, zoh_mux_val = 0x00;
+
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ reg_val = snd_soc_read(codec, TAIKO_A_CDC_CONN_CLSH_CTL);
+
+ if ((reg_val & 0x30) == 0x10)
+ zoh_mux_val = 0x04;
+ else if ((reg_val & 0x30) == 0x20)
+ zoh_mux_val = 0x08;
+
+ if (zoh_mux_val != 0x00)
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CONN_CLSH_CTL,
+ 0x0C, zoh_mux_val);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_CLSH_CTL,
+ 0x0C, 0x00);
+ break;
}
return 0;
}
+
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
*/
@@ -3993,10 +4052,12 @@
SND_SOC_DAPM_OUTPUT("EAR"),
SND_SOC_DAPM_PGA_E("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0,
- taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
+ taiko_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
- ARRAY_SIZE(dac1_switch)),
+ SND_SOC_DAPM_MIXER_E("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch), taiko_codec_ear_dac_event,
+ SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
AIF1_PB, 0, taiko_codec_enable_slimrx,
@@ -4036,8 +4097,9 @@
SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MIXER("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
- hphl_switch, ARRAY_SIZE(hphl_switch)),
+ SND_SOC_DAPM_MIXER_E("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch), taiko_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
@@ -4173,36 +4235,20 @@
SND_SOC_DAPM_MUX("RDAC7 MUX", SND_SOC_NOPM, 0, 0,
&rx_dac7_mux),
- SND_SOC_DAPM_SUPPLY("CLASS_H_CLK", TAIKO_A_CDC_CLK_OTHR_CTL, 0, 0,
- taiko_codec_enable_class_h_clk, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_EAR", TAIKO_A_CDC_CLSH_B1_CTL, 4, 0,
- taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_L", TAIKO_A_CDC_CLSH_B1_CTL, 3, 0,
- taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_HPH_R", TAIKO_A_CDC_CLSH_B1_CTL, 2, 0,
- taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CLASS_H_LINEOUTS_PA", SND_SOC_NOPM, 0, 0,
- taiko_codec_enable_class_h, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
- taiko_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_MUX_E("CLASS_H_DSM MUX", SND_SOC_NOPM, 0, 0,
+ &class_h_dsm_mux, taiko_codec_dsm_mux_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", TAIKO_A_CDC_CLK_OTHR_CTL, 5, 0,
+ SND_SOC_DAPM_SUPPLY("CDC_I2S_RX_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 5, 0,
NULL, 0),
/* TX */
- SND_SOC_DAPM_SUPPLY("CDC_CONN", TAIKO_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", WCD9XXX_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
0),
SND_SOC_DAPM_SUPPLY("LDO_H", TAIKO_A_LDO_H_MODE_1, 7, 0,
@@ -4220,15 +4266,18 @@
SND_SOC_DAPM_INPUT("AMIC1"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAIKO_A_MICB_1_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAIKO_A_MICB_1_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAIKO_A_MICB_1_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -4311,31 +4360,38 @@
SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
SND_SOC_DAPM_INPUT("AMIC2"),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAIKO_A_MICB_2_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAIKO_A_MICB_2_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAIKO_A_MICB_2_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAIKO_A_MICB_2_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAIKO_A_MICB_3_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAIKO_A_MICB_3_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAIKO_A_MICB_3_CTL, 7, 0,
- taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TAIKO_A_MICB_4_CTL, 7,
- 0, taiko_codec_enable_micbias,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", SND_SOC_NOPM, 7, 0,
+ taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", SND_SOC_NOPM, 7,
+ 0, taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
@@ -4511,84 +4567,6 @@
return IRQ_HANDLED;
}
-static const struct taiko_reg_mask_val taiko_1_0_class_h_ear[] = {
-
- /* CLASS-H EAR IDLE_THRESHOLD Table */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_IDLE_EAR_THSD, 0x26),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD, 0x2C),
-
- /* CLASS-H EAR I_PA_FACT Table. */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L, 0xA9),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U, 0x07),
-
- /* CLASS-H EAR Voltage Headroom , Voltage Min. */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_HD_EAR, 0x0D),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_MIN_EAR, 0x3A),
-
- /* CLASS-H EAR K values --chnages from load. */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_ADDR, 0x08),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x1B),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x2D),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x36),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x37),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- /** end of Ear PA load 32 */
-};
-
-static const struct taiko_reg_mask_val taiko_1_0_class_h_hph[] = {
-
- /* CLASS-H HPH IDLE_THRESHOLD Table */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_IDLE_HPH_THSD, 0x13),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x19),
-
- /* CLASS-H HPH I_PA_FACT Table */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L, 0x9A),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U, 0x06),
-
- /* CLASS-H HPH Voltage Headroom , Voltage Min */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_HD_HPH, 0x0D),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_V_PA_MIN_HPH, 0x1D),
-
- /* CLASS-H HPH K values --chnages from load .*/
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_ADDR, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0xAE),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x01),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x1C),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x25),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x27),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_K_DATA, 0x00),
-};
-
-static int taiko_config_ear_class_h(struct snd_soc_codec *codec, u32 ear_load)
-{
- u32 i;
-
- if (ear_load != 32)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(taiko_1_0_class_h_ear); i++)
- snd_soc_write(codec, taiko_1_0_class_h_ear[i].reg,
- taiko_1_0_class_h_ear[i].val);
- return 0;
-}
-
-static int taiko_config_hph_class_h(struct snd_soc_codec *codec, u32 hph_load)
-{
- u32 i;
- if (hph_load != 16)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(taiko_1_0_class_h_hph); i++)
- snd_soc_write(codec, taiko_1_0_class_h_hph[i].reg,
- taiko_1_0_class_h_hph[i].val);
- return 0;
-}
-
static int taiko_handle_pdata(struct taiko_priv *taiko)
{
struct snd_soc_codec *codec = taiko->codec;
@@ -4727,14 +4705,11 @@
0x00 : 0x16);
snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
- taiko_config_ear_class_h(codec, 32);
- taiko_config_hph_class_h(codec, 16);
-
done:
return rc;
}
-static const struct taiko_reg_mask_val taiko_reg_defaults[] = {
+static const struct wcd9xxx_reg_mask_val taiko_reg_defaults[] = {
/* set MCLk to 9.6 */
TAIKO_REG_VAL(TAIKO_A_CHIP_CTL, 0x02),
@@ -4743,24 +4718,6 @@
/* EAR PA deafults */
TAIKO_REG_VAL(TAIKO_A_RX_EAR_CMBUFF, 0x05),
- /* BUCK and NCP defaults for EAR and HS */
- TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_1, 0x5B),
-
- /* CLASS-H defaults for EAR and HS */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_BUCK_NCP_VARS, 0x00),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_BUCK_NCP_VARS, 0x04),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x01),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x05),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B2_CTL, 0x35),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B3_CTL, 0x30),
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B3_CTL, 0x3B),
-
- /*
- * For CLASS-H, Enable ANC delay buffer,
- * set HPHL and EAR PA ref gain to 0 DB.
- */
- TAIKO_REG_VAL(TAIKO_A_CDC_CLSH_B1_CTL, 0x26),
-
/* RX deafults */
TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
@@ -4782,25 +4739,31 @@
TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
};
-static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
+static const struct wcd9xxx_reg_mask_val taiko_1_0_reg_defaults[] = {
/*
* The following only need to be written for Taiko 1.0 parts.
* Taiko 2.0 will have appropriate defaults for these registers.
*/
/* BUCK default */
- TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x50),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x50),
+
+ /* Required defaults for class H operation */
+ TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xF4),
+ TAIKO_REG_VAL(TAIKO_A_BIAS_CURR_CTL_2, 0x08),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_1, 0x5B),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_3, 0x60),
/* Choose max non-overlap time for NCP */
TAIKO_REG_VAL(TAIKO_A_NCP_CLK, 0xFC),
/* Use 25mV/50mV for deltap/m to reduce ripple */
- TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_VCL_1, 0x08),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x08),
/*
* Set DISABLE_MODE_SEL<1:0> to 0b10 (disable PWM in auto mode).
* Note that the other bits of this register will be changed during
* Rx PA bring up.
*/
- TAIKO_REG_VAL(TAIKO_A_BUCK_MODE_3, 0xCE),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
/* Reduce HPH DAC bias to 70% */
TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
/*Reduce EAR DAC bias to 70% */
@@ -4829,7 +4792,7 @@
* Don't update TAIKO_A_CHIP_CTL, TAIKO_A_BUCK_CTRL_CCL_1 and
* TAIKO_A_RX_EAR_CMBUFF as those are updated in taiko_reg_defaults
*/
-static const struct taiko_reg_mask_val taiko_2_0_reg_defaults[] = {
+static const struct wcd9xxx_reg_mask_val taiko_2_0_reg_defaults[] = {
TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_GAIN, 0x2),
TAIKO_REG_VAL(TAIKO_A_CDC_TX_2_GAIN, 0x2),
TAIKO_REG_VAL(TAIKO_A_CDC_TX_1_2_ADC_IB, 0x44),
@@ -4839,9 +4802,9 @@
TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_GAIN, 0x2),
TAIKO_REG_VAL(TAIKO_A_CDC_TX_6_GAIN, 0x2),
TAIKO_REG_VAL(TAIKO_A_CDC_TX_5_6_ADC_IB, 0x44),
- TAIKO_REG_VAL(TAIKO_A_BUCK_MODE_3, 0xCE),
- TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_VCL_1, 0x8),
- TAIKO_REG_VAL(TAIKO_A_BUCK_CTRL_CCL_4, 0x51),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_MODE_3, 0xCE),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_VCL_1, 0x8),
+ TAIKO_REG_VAL(WCD9XXX_A_BUCK_CTRL_CCL_4, 0x51),
TAIKO_REG_VAL(TAIKO_A_NCP_DTEST, 0x10),
TAIKO_REG_VAL(TAIKO_A_RX_HPH_CHOP_CTL, 0xA4),
TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x7A),
@@ -4902,7 +4865,7 @@
}
}
-static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
+static const struct wcd9xxx_reg_mask_val taiko_codec_reg_init_val[] = {
/* Initialize current threshold to 350MA
* number of wait and run cycles to 4096
*/
@@ -4920,9 +4883,6 @@
{TAIKO_A_RX_LINE_4_GAIN, 0x20, 0x20},
{TAIKO_A_SPKR_DRV_GAIN, 0x04, 0x04},
- /* CLASS H config */
- {TAIKO_A_CDC_CONN_CLSH_CTL, 0x3C, 0x14},
-
/* Use 16 bit sample size for TX1 to TX6 */
{TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
{TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
@@ -5072,6 +5032,24 @@
return 0;
}
+static int taiko_codec_get_buck_mv(struct snd_soc_codec *codec)
+{
+ int buck_volt = WCD9XXX_CDC_BUCK_UNSUPPORTED;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx_pdata *pdata = taiko->resmgr.pdata;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (!strncmp(pdata->regulator[i].name,
+ WCD9XXX_SUPPLY_BUCK_NAME,
+ sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
+ buck_volt = pdata->regulator[i].min_uV;
+ break;
+ }
+ }
+ return buck_volt;
+}
+
static int taiko_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -5103,8 +5081,10 @@
tx_hpf_corner_freq_callback);
}
+
snd_soc_codec_set_drvdata(codec, taiko);
+
/* codec resmgr module init */
wcd9xxx = codec->control_data;
pdata = dev_get_platdata(codec->dev->parent);
@@ -5115,6 +5095,9 @@
return ret;
}
+ taiko->clsh_d.buck_mv = taiko_codec_get_buck_mv(codec);
+ wcd9xxx_clsh_init(&taiko->clsh_d);
+
/* init and start mbhc */
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec);
if (ret) {
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
index aea31db..89a0b9f 100644
--- a/sound/soc/codecs/wcd9320.h
+++ b/sound/soc/codecs/wcd9320.h
@@ -41,12 +41,6 @@
TAIKO_PID_MIC_20_UA,
};
-struct taiko_reg_mask_val {
- u16 reg;
- u8 mask;
- u8 val;
-};
-
enum taiko_mbhc_analog_pwr_cfg {
TAIKO_ANALOG_PWR_COLLAPSED = 0,
TAIKO_ANALOG_PWR_ON,
diff --git a/sound/soc/codecs/wcd9xxx-common.c b/sound/soc/codecs/wcd9xxx-common.c
new file mode 100644
index 0000000..dbf2e39
--- /dev/null
+++ b/sound/soc/codecs/wcd9xxx-common.c
@@ -0,0 +1,591 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include "wcd9xxx-common.h"
+
+#define CLSH_COMPUTE_EAR 0x01
+#define CLSH_COMPUTE_HPH_L 0x02
+#define CLSH_COMPUTE_HPH_R 0x03
+
+#define BUCK_VREF_2V 0xFF
+#define BUCK_VREF_1P8V 0xE6
+
+#define NCP_FCLK_LEVEL_8 0x08
+#define NCP_FCLK_LEVEL_5 0x05
+
+#define BUCK_SETTLE_TIME_US 50
+#define NCP_SETTLE_TIME_US 50
+
+static inline void wcd9xxx_enable_clsh_block(
+ struct snd_soc_codec *codec,
+ bool on)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
+ 0x01, on ? 0x01 : 0x00);
+}
+
+static inline void wcd9xxx_enable_anc_delay(
+ struct snd_soc_codec *codec,
+ bool on)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
+ 0x02, on ? 0x02 : 0x00);
+}
+
+static inline void wcd9xxx_enable_ncp(
+ struct snd_soc_codec *codec,
+ bool on)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
+ 0x01, on ? 0x01 : 0x00);
+}
+
+static inline void wcd9xxx_enable_buck(
+ struct snd_soc_codec *codec,
+ bool on)
+{
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
+ 0x80, on ? 0x80 : 0x00);
+}
+
+static int cdc_lo_count;
+
+static void (*clsh_state_fp[NUM_CLSH_STATES])
+ (struct snd_soc_codec *,
+ struct wcd9xxx_clsh_cdc_data *,
+ u8 req_state, bool req_type);
+
+static const char *state_to_str(u8 state)
+{
+ if (state == WCD9XXX_CLSH_STATE_IDLE)
+ return "STATE_IDLE";
+ else if (state == WCD9XXX_CLSH_STATE_EAR)
+ return "STATE_EAR";
+ else if (state == WCD9XXX_CLSH_STATE_HPHL)
+ return "STATE_HPH_L";
+ else if (state == WCD9XXX_CLSH_STATE_HPHR)
+ return "STATE_HPH_R";
+ else if (state == (WCD9XXX_CLSH_STATE_HPHL
+ | WCD9XXX_CLSH_STATE_HPHR))
+ return "STATE_HPH_L_R";
+ else if (state == WCD9XXX_CLSH_STATE_LO)
+ return "STATE_LO";
+
+ return "UNKNOWN_STATE";
+}
+
+static void wcd9xxx_cfg_clsh_buck(
+ struct snd_soc_codec *codec)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_BUCK_CTRL_CCL_4, 0x0B, 0x00},
+ {WCD9XXX_A_BUCK_CTRL_CCL_1, 0xF0, 0x50},
+ {WCD9XXX_A_BUCK_CTRL_CCL_3, 0x03, 0x00},
+ {WCD9XXX_A_BUCK_CTRL_CCL_3, 0x0B, 0x00},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
+ reg_set[i].val);
+
+ dev_dbg(codec->dev, "%s: Programmed buck parameters", __func__);
+}
+
+static void wcd9xxx_cfg_clsh_param_common(
+ struct snd_soc_codec *codec)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 0, 0},
+ {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, 0x3 << 2, 1 << 2},
+ {WCD9XXX_A_CDC_CLSH_BUCK_NCP_VARS, (0x1 << 4), 0},
+ {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 0), 0x01},
+ {WCD9XXX_A_CDC_CLSH_B2_CTL, (0x3 << 2), (0x01 << 2)},
+ {WCD9XXX_A_CDC_CLSH_B2_CTL, (0xf << 4), (0x03 << 4)},
+ {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 4), (0x03 << 4)},
+ {WCD9XXX_A_CDC_CLSH_B3_CTL, (0xf << 0), (0x0B)},
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 5), (0x01 << 5)},
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 1), (0x01 << 1)},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
+ reg_set[i].val);
+
+ dev_dbg(codec->dev, "%s: Programmed class H controller common parameters",
+ __func__);
+}
+
+static void wcd9xxx_chargepump_request(
+ struct snd_soc_codec *codec, bool on)
+{
+ static int cp_count;
+
+ if (on && (++cp_count == 1)) {
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
+ 0x01, 0x01);
+ dev_info(codec->dev, "%s: Charge Pump enabled, count = %d\n",
+ __func__, cp_count);
+ }
+
+ else if (!on) {
+ if (--cp_count < 0) {
+ dev_dbg(codec->dev, "%s: Unbalanced disable for charge pump\n",
+ __func__);
+ if (snd_soc_read(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL)
+ & 0x01) {
+ dev_info(codec->dev, "%s: Actual chargepump is ON\n",
+ __func__);
+ }
+ cp_count = 0;
+ WARN_ON(1);
+ }
+
+ if (cp_count == 0) {
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLK_OTHR_CTL,
+ 0x01, 0x00);
+ dev_dbg(codec->dev, "%s: Charge pump disabled, count = %d\n",
+ __func__, cp_count);
+ }
+ }
+}
+
+static inline void wcd9xxx_clsh_computation_request(
+ struct snd_soc_codec *codec, int compute_pa, bool on)
+{
+ u8 reg_val, reg_mask;
+
+ switch (compute_pa) {
+ case CLSH_COMPUTE_EAR:
+ reg_mask = 0x10;
+ reg_val = (on ? 0x10 : 0x00);
+ break;
+ case CLSH_COMPUTE_HPH_L:
+ reg_mask = 0x08;
+ reg_val = (on ? 0x08 : 0x00);
+ break;
+ case CLSH_COMPUTE_HPH_R:
+ reg_mask = 0x04;
+ reg_val = (on ? 0x04 : 0x00);
+ break;
+ default:
+ dev_dbg(codec->dev, "%s: class h computation PA request incorrect\n",
+ __func__);
+ return;
+ }
+
+ snd_soc_update_bits(codec, WCD9XXX_A_CDC_CLSH_B1_CTL,
+ reg_mask, reg_val);
+
+}
+
+static void wcd9xxx_enable_buck_mode(struct snd_soc_codec *codec,
+ u8 buck_vref)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x03},
+ {WCD9XXX_A_BUCK_MODE_4, 0xFF, buck_vref},
+ {WCD9XXX_A_BUCK_MODE_1, 0x04, 0x04},
+ {WCD9XXX_A_BUCK_MODE_1, 0x08, 0x00},
+ {WCD9XXX_A_BUCK_MODE_3, 0x04, 0x00},
+ {WCD9XXX_A_BUCK_MODE_3, 0x08, 0x00},
+ {WCD9XXX_A_BUCK_MODE_1, 0x80, 0x80},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg,
+ reg_set[i].mask, reg_set[i].val);
+
+ dev_dbg(codec->dev, "%s: Done\n", __func__);
+ usleep_range(BUCK_SETTLE_TIME_US, BUCK_SETTLE_TIME_US);
+}
+
+static void wcd9xxx_clsh_enable_post_pa(struct snd_soc_codec *codec)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_BUCK_MODE_5, 0x02, 0x00},
+ {WCD9XXX_A_NCP_STATIC, 0x20, 0x00},
+ {WCD9XXX_A_BUCK_MODE_3, 0x04, 0x04},
+ {WCD9XXX_A_BUCK_MODE_3, 0x08, 0x08},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg,
+ reg_set[i].mask, reg_set[i].val);
+
+ dev_dbg(codec->dev, "%s: completed clsh mode settings after PA enable\n",
+ __func__);
+
+}
+
+static void wcd9xxx_set_fclk_enable_ncp(struct snd_soc_codec *codec,
+ u8 fclk_level)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_NCP_STATIC, 0x20, 0x20},
+ {WCD9XXX_A_NCP_EN, 0x01, 0x01},
+ };
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
+ 0x010, 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
+ 0x0F, fclk_level);
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg,
+ reg_set[i].mask, reg_set[i].val);
+
+ usleep_range(NCP_SETTLE_TIME_US, NCP_SETTLE_TIME_US);
+
+ dev_dbg(codec->dev, "%s: set ncp done\n", __func__);
+}
+
+static void wcd9xxx_cfg_clsh_param_ear(struct snd_soc_codec *codec)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 7), 0},
+ {WCD9XXX_A_CDC_CLSH_V_PA_HD_EAR, (0x3f << 0), 0x0D},
+ {WCD9XXX_A_CDC_CLSH_V_PA_MIN_EAR, (0x3f << 0), 0x3A},
+
+ /* Under assumption that EAR load is 10.7ohm */
+ {WCD9XXX_A_CDC_CLSH_IDLE_EAR_THSD, (0x3f << 0), 0x26},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_EAR_THSD, (0x3f << 0), 0x2C},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_L, 0xff, 0xA9},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_EAR_U, 0xff, 0x07},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, (0x1 << 7), 0},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, (0xf << 0), 0x08},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1b},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x2d},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x36},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x37},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg,
+ reg_set[i].mask, reg_set[i].val);
+
+ dev_dbg(codec->dev, "%s: Programmed Class H controller EAR specific params\n",
+ __func__);
+}
+
+static void wcd9xxx_cfg_clsh_param_hph(struct snd_soc_codec *codec)
+{
+ int i;
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, (0x1 << 6), 0},
+ {WCD9XXX_A_CDC_CLSH_V_PA_HD_HPH, 0x3f, 0x0D},
+ {WCD9XXX_A_CDC_CLSH_V_PA_MIN_HPH, 0x3f, 0x1D},
+
+ /* Under assumption that HPH load is 16ohm per channel */
+ {WCD9XXX_A_CDC_CLSH_IDLE_HPH_THSD, 0x3f, 0x13},
+ {WCD9XXX_A_CDC_CLSH_FCLKONLY_HPH_THSD, 0x1f, 0x19},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_L, 0xff, 0x97},
+ {WCD9XXX_A_CDC_CLSH_I_PA_FACT_HPH_U, 0xff, 0x05},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, (0x1 << 7), 0},
+ {WCD9XXX_A_CDC_CLSH_K_ADDR, 0x0f, 0},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0xAE},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x01},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x1C},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x24},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x25},
+ {WCD9XXX_A_CDC_CLSH_K_DATA, 0xff, 0x00},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg, reg_set[i].mask,
+ reg_set[i].val);
+ dev_dbg(codec->dev, "%s: Programmed Class H controller HPH specific params\n",
+ __func__);
+}
+
+static void wcd9xxx_clsh_turnoff_postpa
+ (struct snd_soc_codec *codec)
+{
+
+ int i;
+
+ const struct wcd9xxx_reg_mask_val reg_set[] = {
+ {WCD9XXX_A_NCP_EN, 0x01, 0x00},
+ {WCD9XXX_A_BUCK_MODE_1, 0x80, 0x00},
+ {WCD9XXX_A_CDC_CLSH_B1_CTL, 0x10, 0x00},
+ };
+
+ wcd9xxx_chargepump_request(codec, false);
+
+ for (i = 0; i < ARRAY_SIZE(reg_set); i++)
+ snd_soc_update_bits(codec, reg_set[i].reg,
+ reg_set[i].mask, reg_set[i].val);
+
+ wcd9xxx_enable_clsh_block(codec, false);
+
+ dev_dbg(codec->dev, "%s: Done\n", __func__);
+}
+
+static void wcd9xxx_clsh_state_idle(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+ dev_dbg(codec->dev, "%s: wrong transition, cannot enable IDLE state\n",
+ __func__);
+ } else {
+ if (req_state == WCD9XXX_CLSH_STATE_EAR) {
+ wcd9xxx_clsh_turnoff_postpa(codec);
+ } else if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_L, false);
+ wcd9xxx_clsh_turnoff_postpa(codec);
+ } else if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_R, false);
+ wcd9xxx_clsh_turnoff_postpa(codec);
+ } else if (req_state == WCD9XXX_CLSH_STATE_LO) {
+ wcd9xxx_enable_ncp(codec, false);
+ wcd9xxx_enable_buck(codec, false);
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_ear(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+ wcd9xxx_cfg_clsh_buck(codec);
+ wcd9xxx_cfg_clsh_param_common(codec);
+ wcd9xxx_cfg_clsh_param_ear(codec);
+ wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_chargepump_request(codec, true);
+ wcd9xxx_enable_anc_delay(codec, true);
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_EAR, true);
+ wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
+ wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+
+ dev_dbg(codec->dev, "%s: Enabled ear mode class h\n", __func__);
+ } else {
+ dev_dbg(codec->dev, "%s: stub fallback to ear\n", __func__);
+ }
+}
+
+static void wcd9xxx_clsh_state_hph_l(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+ wcd9xxx_cfg_clsh_buck(codec);
+ wcd9xxx_cfg_clsh_param_common(codec);
+ wcd9xxx_cfg_clsh_param_hph(codec);
+ wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_chargepump_request(codec, true);
+ wcd9xxx_enable_anc_delay(codec, true);
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_L, true);
+ wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
+ wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+
+ dev_dbg(codec->dev, "%s: Done\n", __func__);
+ } else {
+ if (req_state == WCD9XXX_CLSH_STATE_HPHR) {
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_R, false);
+ } else {
+ dev_dbg(codec->dev, "%s: stub fallback to hph_l\n",
+ __func__);
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_hph_r(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+
+ wcd9xxx_cfg_clsh_buck(codec);
+ wcd9xxx_cfg_clsh_param_common(codec);
+ wcd9xxx_cfg_clsh_param_hph(codec);
+ wcd9xxx_enable_clsh_block(codec, true);
+ wcd9xxx_chargepump_request(codec, true);
+ wcd9xxx_enable_anc_delay(codec, true);
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_R, true);
+ wcd9xxx_enable_buck_mode(codec, BUCK_VREF_2V);
+ wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_8);
+
+ dev_dbg(codec->dev, "%s: Done\n", __func__);
+ } else {
+ if (req_state == WCD9XXX_CLSH_STATE_HPHL) {
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_L, false);
+ } else {
+ dev_dbg(codec->dev, "%s: stub fallback to hph_r\n",
+ __func__);
+ }
+ }
+}
+
+static void wcd9xxx_clsh_state_hph_st(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_L, true);
+ wcd9xxx_clsh_computation_request(codec,
+ CLSH_COMPUTE_HPH_R, true);
+ } else {
+ dev_dbg(codec->dev, "%s: stub fallback to hph_st\n", __func__);
+ }
+}
+
+static void wcd9xxx_clsh_state_lo(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ if (is_enable) {
+ if (++cdc_lo_count > 1)
+ return;
+
+ wcd9xxx_enable_buck_mode(codec, BUCK_VREF_1P8V);
+ wcd9xxx_set_fclk_enable_ncp(codec, NCP_FCLK_LEVEL_5);
+
+ if (clsh_d->buck_mv == WCD9XXX_CDC_BUCK_MV_1P8) {
+ wcd9xxx_enable_buck(codec, false);
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_STATIC,
+ 0x20, 0x01);
+ wcd9xxx_enable_ncp(codec, true);
+ msleep(NCP_SETTLE_TIME_US);
+
+ } else {
+ snd_soc_update_bits(codec, WCD9XXX_A_NCP_EN,
+ 0x40, 0x00);
+ wcd9xxx_enable_ncp(codec, true);
+ msleep(NCP_SETTLE_TIME_US);
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
+ 0x01, 0x01);
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_5,
+ 0xFB, (0x02 << 2));
+ }
+ snd_soc_update_bits(codec, WCD9XXX_A_BUCK_MODE_1,
+ 0x04, 0x00);
+ } else {
+ dev_dbg(codec->dev, "%s: stub fallback to lineout\n", __func__);
+ }
+}
+
+static void wcd9xxx_clsh_state_err(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *clsh_d,
+ u8 req_state, bool is_enable)
+{
+ dev_dbg(codec->dev, "%s Wrong request for class H state machine requested to %s %s"
+ , __func__, is_enable ? "enable" : "disable",
+ state_to_str(req_state));
+ WARN_ON(1);
+}
+
+void wcd9xxx_clsh_fsm(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *cdc_clsh_d,
+ u8 req_state, bool req_type, u8 clsh_event)
+{
+ u8 old_state, new_state;
+
+ switch (clsh_event) {
+
+ case WCD9XXX_CLSH_EVENT_PRE_DAC:
+
+ /* PRE_DAC event should be used only for Enable */
+ BUG_ON(req_type != WCD9XXX_CLSH_REQ_ENABLE);
+
+ old_state = cdc_clsh_d->state;
+ new_state = old_state | req_state;
+
+ (*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
+ req_state, req_type);
+ cdc_clsh_d->state = new_state;
+ dev_info(codec->dev, "%s: ClassH state transition from %s to %s\n",
+ __func__, state_to_str(old_state),
+ state_to_str(cdc_clsh_d->state));
+
+ break;
+
+ case WCD9XXX_CLSH_EVENT_POST_PA:
+
+ if (req_type == WCD9XXX_CLSH_REQ_DISABLE) {
+ if (req_state == WCD9XXX_CLSH_STATE_LO
+ && --cdc_lo_count > 0)
+ break;
+
+ old_state = cdc_clsh_d->state;
+ new_state = old_state & (~req_state);
+
+ if (new_state < NUM_CLSH_STATES) {
+ (*clsh_state_fp[new_state]) (codec, cdc_clsh_d,
+ req_state, req_type);
+ cdc_clsh_d->state = new_state;
+ dev_info(codec->dev, "%s: ClassH state transition from %s to %s\n",
+ __func__, state_to_str(old_state),
+ state_to_str(cdc_clsh_d->state));
+
+ } else {
+ dev_dbg(codec->dev, "%s: wrong new state = %x\n",
+ __func__, new_state);
+ }
+
+
+ } else if (req_state != WCD9XXX_CLSH_STATE_LO) {
+ wcd9xxx_clsh_enable_post_pa(codec);
+ }
+
+ break;
+ }
+
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_clsh_fsm);
+
+void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh)
+{
+ int i;
+ clsh->state = WCD9XXX_CLSH_STATE_IDLE;
+
+ for (i = 0; i < NUM_CLSH_STATES; i++)
+ clsh_state_fp[i] = wcd9xxx_clsh_state_err;
+
+ clsh_state_fp[WCD9XXX_CLSH_STATE_IDLE] = wcd9xxx_clsh_state_idle;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_EAR] = wcd9xxx_clsh_state_ear;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHL] =
+ wcd9xxx_clsh_state_hph_l;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPHR] =
+ wcd9xxx_clsh_state_hph_r;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_HPH_ST] =
+ wcd9xxx_clsh_state_hph_st;
+ clsh_state_fp[WCD9XXX_CLSH_STATE_LO] = wcd9xxx_clsh_state_lo;
+
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_clsh_init);
+
+MODULE_DESCRIPTION("WCD9XXX Common");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
new file mode 100644
index 0000000..743ab0c
--- /dev/null
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -0,0 +1,68 @@
+/* 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.
+ */
+
+#ifndef WCD9XXX_CODEC_COMMON
+
+#define WCD9XXX_CODEC_COMMON
+
+#define WCD9XXX_CLSH_REQ_ENABLE true
+#define WCD9XXX_CLSH_REQ_DISABLE false
+
+#define WCD9XXX_CLSH_EVENT_PRE_DAC 0x01
+#define WCD9XXX_CLSH_EVENT_POST_PA 0x02
+
+/* Basic states for Class H state machine.
+ * represented as a bit mask within a u8 data type
+ * bit 0: EAR mode
+ * bit 1: HPH Left mode
+ * bit 2: HPH Right mode
+ * bit 3: Lineout mode
+ * bit 4: Ultrasound mode
+ */
+#define WCD9XXX_CLSH_STATE_IDLE 0x00
+#define WCD9XXX_CLSH_STATE_EAR (0x01 << 0)
+#define WCD9XXX_CLSH_STATE_HPHL (0x01 << 1)
+#define WCD9XXX_CLSH_STATE_HPHR (0x01 << 2)
+#define WCD9XXX_CLSH_STATE_LO (0x01 << 3)
+#define NUM_CLSH_STATES ((0x01 << 4) - 1)
+
+/* Derived State: Bits 1 and 2 should be set for Headphone stereo */
+#define WCD9XXX_CLSH_STATE_HPH_ST (WCD9XXX_CLSH_STATE_HPHL | \
+ WCD9XXX_CLSH_STATE_HPHR)
+
+
+struct wcd9xxx_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+/* Class H data that the codec driver will maintain */
+struct wcd9xxx_clsh_cdc_data {
+ u8 state;
+ int buck_mv;
+};
+
+
+enum wcd9xxx_buck_volt {
+ WCD9XXX_CDC_BUCK_UNSUPPORTED = 0,
+ WCD9XXX_CDC_BUCK_MV_1P8 = 1800000,
+ WCD9XXX_CDC_BUCK_MV_2P15 = 2150000,
+};
+
+extern void wcd9xxx_clsh_fsm(struct snd_soc_codec *codec,
+ struct wcd9xxx_clsh_cdc_data *cdc_clsh_d,
+ u8 req_state, bool req_type, u8 clsh_event);
+
+extern void wcd9xxx_clsh_init(struct wcd9xxx_clsh_cdc_data *clsh);
+
+#endif
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index c1a1aa1..b3549cc 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -83,6 +83,7 @@
#define VDDIO_MICBIAS_MV 1800
#define WCD9XXX_HPHL_STATUS_READY_WAIT_US 1000
+#define WCD9XXX_MUX_SWITCH_READY_WAIT_US 100
#define WCD9XXX_MEAS_DELTA_MAX_MV 50
#define WCD9XXX_GM_SWAP_THRES_MIN_MV 150
#define WCD9XXX_GM_SWAP_THRES_MAX_MV 500
@@ -373,8 +374,14 @@
}
}
-static void wcd9xxx_jack_report(struct snd_soc_jack *jack, int status, int mask)
+static void wcd9xxx_jack_report(struct wcd9xxx_mbhc *mbhc,
+ struct snd_soc_jack *jack, int status, int mask)
{
+ if (jack == &mbhc->headset_jack)
+ wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
+ WCD9XXX_COND_HPH_MIC,
+ status & SND_JACK_MICROPHONE);
+
snd_soc_jack_report_no_dapm(jack, status, mask);
}
@@ -387,7 +394,7 @@
codec = mbhc->codec;
if (mbhc->hph_status & jack_status) {
mbhc->hph_status &= ~jack_status;
- wcd9xxx_jack_report(&mbhc->headset_jack,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status, WCD9XXX_JACK_MASK);
snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
0x00);
@@ -617,14 +624,14 @@
else if (mbhc->buttons_pressed) {
pr_debug("%s: release of button press%d\n",
__func__, jack_type);
- wcd9xxx_jack_report(&mbhc->button_jack, 0,
+ wcd9xxx_jack_report(mbhc, &mbhc->button_jack, 0,
mbhc->buttons_pressed);
mbhc->buttons_pressed &=
~WCD9XXX_JACK_BUTTON_MASK;
}
pr_debug("%s: Reporting removal %d(%x)\n", __func__,
jack_type, mbhc->hph_status);
- wcd9xxx_jack_report(&mbhc->headset_jack, mbhc->hph_status,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack, mbhc->hph_status,
WCD9XXX_JACK_MASK);
wcd9xxx_set_and_turnoff_hph_padac(mbhc);
hphrocp_off_report(mbhc, SND_JACK_OC_HPHR);
@@ -637,7 +644,7 @@
if (mbhc->hph_status && mbhc->hph_status != jack_type) {
pr_debug("%s: Reporting removal (%x)\n",
__func__, mbhc->hph_status);
- wcd9xxx_jack_report(&mbhc->headset_jack,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
0, WCD9XXX_JACK_MASK);
mbhc->hph_status = 0;
}
@@ -657,7 +664,7 @@
}
pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
jack_type, mbhc->hph_status);
- wcd9xxx_jack_report(&mbhc->headset_jack,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status, WCD9XXX_JACK_MASK);
wcd9xxx_clr_and_turnon_hph_padac(mbhc);
}
@@ -1605,6 +1612,14 @@
pr_debug("%s: enter, removal interrupt\n", __func__);
WCD9XXX_BCL_LOCK(mbhc->resmgr);
+ /*
+ * While we don't know whether MIC is there or not, let the resmgr know
+ * so micbias can be disabled temporarily
+ */
+ if (mbhc->current_plug == PLUG_TYPE_HEADSET)
+ wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
+ WCD9XXX_COND_HPH_MIC, false);
+
vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
mbhc->mbhc_micbias_switched);
if (vddio)
@@ -1623,6 +1638,10 @@
*/
if (vddio && (mbhc->current_plug == PLUG_TYPE_HEADSET))
__wcd9xxx_switch_micbias(mbhc, 1, true, true);
+
+ if (mbhc->current_plug == PLUG_TYPE_HEADSET)
+ wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
+ WCD9XXX_COND_HPH_MIC, true);
WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
return IRQ_HANDLED;
@@ -1678,7 +1697,7 @@
pr_debug("%s: STA: %d, DCE: %d\n", __func__, sta_mv, dce_mv);
pr_debug("%s: Reporting long button press event\n", __func__);
- wcd9xxx_jack_report(&mbhc->button_jack, mbhc->buttons_pressed,
+ wcd9xxx_jack_report(mbhc, &mbhc->button_jack, mbhc->buttons_pressed,
mbhc->buttons_pressed);
pr_debug("%s: leave\n", __func__);
@@ -2356,7 +2375,7 @@
if (ret == 0) {
pr_debug("%s: Reporting long button release event\n",
__func__);
- wcd9xxx_jack_report(&mbhc->button_jack, 0,
+ wcd9xxx_jack_report(mbhc, &mbhc->button_jack, 0,
mbhc->buttons_pressed);
} else {
if (wcd9xxx_is_fake_press(mbhc)) {
@@ -2369,12 +2388,14 @@
} else {
pr_debug("%s: Reporting btn press\n",
__func__);
- wcd9xxx_jack_report(&mbhc->button_jack,
+ wcd9xxx_jack_report(mbhc,
+ &mbhc->button_jack,
mbhc->buttons_pressed,
mbhc->buttons_pressed);
pr_debug("%s: Reporting btn release\n",
__func__);
- wcd9xxx_jack_report(&mbhc->button_jack,
+ wcd9xxx_jack_report(mbhc,
+ &mbhc->button_jack,
0, mbhc->buttons_pressed);
}
}
@@ -2413,7 +2434,7 @@
WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
mbhc->hphlocp_cnt = 0;
mbhc->hph_status |= SND_JACK_OC_HPHL;
- wcd9xxx_jack_report(&mbhc->headset_jack,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status,
WCD9XXX_JACK_MASK);
}
@@ -2442,7 +2463,7 @@
WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
mbhc->hphrocp_cnt = 0;
mbhc->hph_status |= SND_JACK_OC_HPHR;
- wcd9xxx_jack_report(&mbhc->headset_jack,
+ wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status, WCD9XXX_JACK_MASK);
}
@@ -2515,6 +2536,7 @@
static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc)
{
u8 cfilt_mode;
+ u16 reg0, reg1;
struct snd_soc_codec *codec = mbhc->codec;
pr_debug("%s: enter\n", __func__);
@@ -2544,15 +2566,28 @@
snd_soc_write(codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0x78);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
- /* DCE measurement for 0 volts */
+ /* Pull down micbias to ground */
+ reg0 = snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg);
+ snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 1, 1);
+ /* Disconnect override from micbias */
+ reg1 = snd_soc_read(codec, WCD9XXX_A_MAD_ANA_CTRL);
+ snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
+ /* Connect the MUX to micbias */
+ snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
+ usleep_range(WCD9XXX_MUX_SWITCH_READY_WAIT_US,
+ WCD9XXX_MUX_SWITCH_READY_WAIT_US +
+ WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ /* DCE measurement for 0 voltage */
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
- snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
- snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x81);
- usleep_range(100, 100);
- snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04);
- usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce);
- mbhc->mbhc_data.dce_z = wcd9xxx_read_dce_result(codec);
+ mbhc->mbhc_data.dce_z = __wcd9xxx_codec_sta_dce(mbhc, 1, true, false);
+ /* STA measurement for 0 voltage */
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
+ mbhc->mbhc_data.sta_z = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
+ /* Restore registers */
+ snd_soc_write(codec, mbhc->mbhc_bias_regs.ctl_reg, reg0);
+ snd_soc_write(codec, WCD9XXX_A_MAD_ANA_CTRL, reg1);
/* DCE measurment for MB voltage */
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
@@ -2563,17 +2598,10 @@
usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce);
mbhc->mbhc_data.dce_mb = wcd9xxx_read_dce_result(codec);
- /* STA measuremnt for 0 volts */
+ /* STA Measurement for MB Voltage */
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
- snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x81);
- usleep_range(100, 100);
- snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
- usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta);
- mbhc->mbhc_data.sta_z = wcd9xxx_read_sta_result(codec);
-
- /* STA Measurement for MB Voltage */
snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
usleep_range(100, 100);
snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 17edd4a..2011346 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -94,6 +94,14 @@
"WCD9XXX_EVENT_LAST",
};
+struct wcd9xxx_resmgr_cond_entry {
+ unsigned short reg;
+ int shift;
+ bool invert;
+ enum wcd9xxx_resmgr_cond cond;
+ struct list_head list;
+};
+
static enum wcd9xxx_clock_type wcd9xxx_save_clock(struct wcd9xxx_resmgr
*resmgr);
static void wcd9xxx_restore_clock(struct wcd9xxx_resmgr *resmgr,
@@ -640,6 +648,93 @@
return rc;
}
+void wcd9xxx_resmgr_cond_trigger_cond(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond)
+{
+ struct list_head *l;
+ struct wcd9xxx_resmgr_cond_entry *e;
+ bool set;
+
+ pr_debug("%s: enter\n", __func__);
+ WCD9XXX_BCL_ASSERT_LOCKED(resmgr);
+ set = !!test_bit(cond, &resmgr->cond_flags);
+ list_for_each(l, &resmgr->update_bit_cond_h) {
+ e = list_entry(l, struct wcd9xxx_resmgr_cond_entry, list);
+ if (e->cond == cond)
+ snd_soc_update_bits(resmgr->codec, e->reg,
+ 1 << e->shift,
+ (set ? !e->invert : e->invert)
+ << e->shift);
+ }
+ pr_debug("%s: leave\n", __func__);
+}
+
+void wcd9xxx_resmgr_cond_update_cond(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond, bool set)
+{
+ WCD9XXX_BCL_ASSERT_LOCKED(resmgr);
+ if ((set && !test_and_set_bit(cond, &resmgr->cond_flags)) ||
+ (!set && test_and_clear_bit(cond, &resmgr->cond_flags))) {
+ pr_debug("%s: Resource %d condition changed to %s\n", __func__,
+ cond, set ? "set" : "clear");
+ wcd9xxx_resmgr_cond_trigger_cond(resmgr, cond);
+ }
+}
+
+int wcd9xxx_resmgr_add_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond,
+ unsigned short reg, int shift,
+ bool invert)
+{
+ struct wcd9xxx_resmgr_cond_entry *entry;
+
+ WCD9XXX_BCL_ASSERT_LOCKED(resmgr);
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->cond = cond;
+ entry->reg = reg;
+ entry->shift = shift;
+ entry->invert = invert;
+ list_add_tail(&entry->list, &resmgr->update_bit_cond_h);
+
+ wcd9xxx_resmgr_cond_trigger_cond(resmgr, cond);
+
+ return 0;
+}
+
+/*
+ * wcd9xxx_resmgr_rm_cond_update_bits :
+ * Clear bit and remove from the conditional bit update list
+ */
+int wcd9xxx_resmgr_rm_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond,
+ unsigned short reg, int shift,
+ bool invert)
+{
+ struct list_head *l, *next;
+ struct wcd9xxx_resmgr_cond_entry *e = NULL;
+
+ pr_debug("%s: enter\n", __func__);
+ WCD9XXX_BCL_ASSERT_LOCKED(resmgr);
+ list_for_each_safe(l, next, &resmgr->update_bit_cond_h) {
+ e = list_entry(l, struct wcd9xxx_resmgr_cond_entry, list);
+ if (e->reg == reg && e->shift == shift && e->invert == invert) {
+ snd_soc_update_bits(resmgr->codec, e->reg,
+ 1 << e->shift,
+ e->invert << e->shift);
+ list_del(&e->list);
+ kfree(e);
+ return 0;
+ }
+ }
+ pr_err("%s: Cannot find update bit entry reg 0x%x, shift %d\n",
+ __func__, e ? e->reg : 0, e ? e->shift : 0);
+
+ return -EINVAL;
+}
+
int wcd9xxx_resmgr_register_notifier(struct wcd9xxx_resmgr *resmgr,
struct notifier_block *nblock)
{
@@ -669,6 +764,8 @@
resmgr->pdata = pdata;
resmgr->reg_addr = reg_addr;
+ INIT_LIST_HEAD(&resmgr->update_bit_cond_h);
+
BLOCKING_INIT_NOTIFIER_HEAD(&resmgr->notifier);
mutex_init(&resmgr->codec_resource_lock);
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.h b/sound/soc/codecs/wcd9xxx-resmgr.h
index 6c30eeb..53c48f6 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.h
+++ b/sound/soc/codecs/wcd9xxx-resmgr.h
@@ -125,6 +125,9 @@
/* Notifier needs mbhc pointer with resmgr */
struct wcd9xxx_mbhc *mbhc;
+ unsigned long cond_flags;
+ struct list_head update_bit_cond_h;
+
/*
* Currently, only used for mbhc purpose, to protect
* concurrent execution of mbhc threaded irq handlers and
@@ -189,4 +192,18 @@
void wcd9xxx_resmgr_notifier_call(struct wcd9xxx_resmgr *resmgr,
const enum wcd9xxx_notify_event e);
+enum wcd9xxx_resmgr_cond {
+ WCD9XXX_COND_HPH_MIC = 1,
+};
+int wcd9xxx_resmgr_rm_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond,
+ unsigned short reg, int shift,
+ bool invert);
+int wcd9xxx_resmgr_add_cond_update_bits(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond,
+ unsigned short reg, int shift,
+ bool invert);
+void wcd9xxx_resmgr_cond_update_cond(struct wcd9xxx_resmgr *resmgr,
+ enum wcd9xxx_resmgr_cond cond, bool set);
+
#endif /* __WCD9XXX_COMMON_H__ */
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 41e4c60..22bc9e1 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. 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
@@ -155,7 +155,8 @@
};
static int voip_get_media_type(uint32_t mode, uint32_t rate_type,
- unsigned int samp_rate);
+ unsigned int samp_rate,
+ uint32_t *media_type);
static int voip_get_rate_type(uint32_t mode,
uint32_t rate,
uint32_t *rate_type);
@@ -934,12 +935,12 @@
goto done;
}
prtd->rate_type = rate_type;
- media_type = voip_get_media_type(prtd->mode,
- prtd->rate_type,
- prtd->play_samp_rate);
- if (media_type < 0) {
+ ret = voip_get_media_type(prtd->mode,
+ prtd->rate_type,
+ prtd->play_samp_rate,
+ &media_type);
+ if (ret < 0) {
pr_err("fail at getting media_type\n");
- ret = -EINVAL;
goto done;
}
pr_debug(" media_type=%d, rate_type=%d\n", media_type,
@@ -1210,49 +1211,50 @@
}
static int voip_get_media_type(uint32_t mode, uint32_t rate_type,
- unsigned int samp_rate)
+ unsigned int samp_rate,
+ uint32_t *media_type)
{
- uint32_t media_type;
+ int ret = 0;
pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
mode, samp_rate);
switch (mode) {
case MODE_AMR:
- media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
+ *media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
break;
case MODE_AMR_WB:
- media_type = VSS_MEDIA_ID_AMR_WB_MODEM;
+ *media_type = VSS_MEDIA_ID_AMR_WB_MODEM;
break;
case MODE_PCM:
if (samp_rate == 8000)
- media_type = VSS_MEDIA_ID_PCM_NB;
+ *media_type = VSS_MEDIA_ID_PCM_NB;
else
- media_type = VSS_MEDIA_ID_PCM_WB;
+ *media_type = VSS_MEDIA_ID_PCM_WB;
break;
case MODE_IS127: /* EVRC-A */
- media_type = VSS_MEDIA_ID_EVRC_MODEM;
+ *media_type = VSS_MEDIA_ID_EVRC_MODEM;
break;
case MODE_4GV_NB: /* EVRC-B */
- media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+ *media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
break;
case MODE_4GV_WB: /* EVRC-WB */
- media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+ *media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
break;
case MODE_G711:
case MODE_G711A:
if (rate_type == MVS_G711A_MODE_MULAW)
- media_type = VSS_MEDIA_ID_G711_MULAW;
+ *media_type = VSS_MEDIA_ID_G711_MULAW;
else
- media_type = VSS_MEDIA_ID_G711_ALAW;
+ *media_type = VSS_MEDIA_ID_G711_ALAW;
break;
default:
pr_debug(" input mode is not supported\n");
- media_type = -EINVAL;
+ ret = -EINVAL;
}
- pr_debug("%s: media_type is 0x%x\n", __func__, media_type);
+ pr_debug("%s: media_type is 0x%x\n", __func__, *media_type);
- return media_type;
+ return ret;
}
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index b7f8714..7c5e599 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1041,18 +1041,18 @@
btn_low[0] = -50;
btn_high[0] = 20;
btn_low[1] = 21;
- btn_high[1] = 63;
- btn_low[2] = 64;
- btn_high[2] = 106;
- btn_low[3] = 107;
- btn_high[3] = 146;
- btn_low[4] = 146;
- btn_high[4] = 186;
- btn_low[5] = 187;
- btn_high[5] = 221;
- btn_low[6] = 222;
- btn_high[6] = 253;
- btn_low[7] = 254;
+ btn_high[1] = 61;
+ btn_low[2] = 62;
+ btn_high[2] = 104;
+ btn_low[3] = 105;
+ btn_high[3] = 148;
+ btn_low[4] = 149;
+ btn_high[4] = 189;
+ btn_low[5] = 190;
+ btn_high[5] = 228;
+ btn_low[6] = 229;
+ btn_high[6] = 269;
+ btn_low[7] = 270;
btn_high[7] = 500;
n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
n_ready[0] = 80;
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 58fdc1b..b71132e 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -66,6 +66,12 @@
/* VocProc dev cfg cal*/
struct acdb_atomic_cal_block vocproc_dev_cal;
+ /* Custom topology */
+ struct acdb_atomic_cal_block adm_custom_topology;
+ struct acdb_atomic_cal_block asm_custom_topology;
+ atomic_t valid_adm_custom_top;
+ atomic_t valid_asm_custom_top;
+
/* AFE cal */
struct acdb_atomic_cal_block afe_cal[MAX_AUDPROC_TYPES];
@@ -134,6 +140,106 @@
atomic_set(&acdb_data.asm_topology, topology);
}
+void reset_custom_topology_flags(void)
+{
+ atomic_set(&acdb_data.valid_adm_custom_top, 1);
+ atomic_set(&acdb_data.valid_asm_custom_top, 1);
+}
+
+void get_adm_custom_topology(struct acdb_cal_block *cal_block)
+{
+ pr_debug("%s\n", __func__);
+
+ if (cal_block == NULL) {
+ pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+ goto done;
+ }
+
+ if (atomic_read(&acdb_data.valid_adm_custom_top) == 0) {
+ cal_block->cal_size = 0;
+ goto done;
+ }
+ atomic_set(&acdb_data.valid_adm_custom_top, 0);
+
+ cal_block->cal_size =
+ atomic_read(&acdb_data.adm_custom_topology.cal_size);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.adm_custom_topology.cal_paddr);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.adm_custom_topology.cal_kvaddr);
+done:
+ return;
+}
+
+void store_adm_custom_topology(struct cal_block *cal_block)
+{
+ pr_debug("%s,\n", __func__);
+
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
+ __func__, cal_block->cal_offset,
+ (long)atomic64_read(&acdb_data.mem_len));
+ goto done;
+ }
+
+ atomic_set(&acdb_data.adm_custom_topology.cal_size,
+ cal_block->cal_size);
+ atomic_set(&acdb_data.adm_custom_topology.cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.adm_custom_topology.cal_kvaddr,
+ cal_block->cal_offset +
+ atomic64_read(&acdb_data.kvaddr));
+done:
+ return;
+}
+
+void get_asm_custom_topology(struct acdb_cal_block *cal_block)
+{
+ pr_debug("%s\n", __func__);
+
+ if (cal_block == NULL) {
+ pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+ goto done;
+ }
+
+ if (atomic_read(&acdb_data.valid_asm_custom_top) == 0) {
+ cal_block->cal_size = 0;
+ goto done;
+ }
+ atomic_set(&acdb_data.valid_asm_custom_top, 0);
+
+ cal_block->cal_size =
+ atomic_read(&acdb_data.asm_custom_topology.cal_size);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.asm_custom_topology.cal_paddr);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.asm_custom_topology.cal_kvaddr);
+done:
+ return;
+}
+
+void store_asm_custom_topology(struct cal_block *cal_block)
+{
+ pr_debug("%s,\n", __func__);
+
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
+ __func__, cal_block->cal_offset,
+ (long)atomic64_read(&acdb_data.mem_len));
+ goto done;
+ }
+
+ atomic_set(&acdb_data.asm_custom_topology.cal_size,
+ cal_block->cal_size);
+ atomic_set(&acdb_data.asm_custom_topology.cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.asm_custom_topology.cal_kvaddr,
+ cal_block->cal_offset +
+ atomic64_read(&acdb_data.kvaddr));
+done:
+ return;
+}
+
void get_voice_cal_allocation(struct acdb_cal_block *cal_block)
{
cal_block->cal_size = ACDB_TOTAL_VOICE_ALLOCATION;
@@ -672,6 +778,8 @@
__func__);
}
+ atomic_set(&acdb_data.valid_adm_custom_top, 1);
+ atomic_set(&acdb_data.valid_asm_custom_top, 1);
atomic_inc(&usage_count);
return result;
}
@@ -925,6 +1033,12 @@
case AUDIO_SET_LSM_CAL:
store_lsm_cal((struct cal_block *)data);
goto done;
+ case AUDIO_SET_ADM_CUSTOM_TOPOLOGY:
+ store_adm_custom_topology((struct cal_block *)data);
+ goto done;
+ case AUDIO_SET_ASM_CUSTOM_TOPOLOGY:
+ store_asm_custom_topology((struct cal_block *)data);
+ goto done;
default:
pr_err("ACDB=> ACDB ioctl not found!\n");
}
@@ -998,6 +1112,8 @@
memset(&acdb_data, 0, sizeof(acdb_data));
mutex_init(&acdb_data.acdb_mutex);
atomic_set(&usage_count, 0);
+ atomic_set(&acdb_data.valid_adm_custom_top, 1);
+ atomic_set(&acdb_data.valid_asm_custom_top, 1);
return misc_register(&acdb_misc);
}
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.h b/sound/soc/msm/qdsp6v2/audio_acdb.h
index 8528e3c..0b6110d 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.h
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.h
@@ -46,6 +46,9 @@
uint32_t get_adm_rx_topology(void);
uint32_t get_adm_tx_topology(void);
uint32_t get_asm_topology(void);
+void reset_custom_topology_flags(void);
+void get_adm_custom_topology(struct acdb_cal_block *cal_block);
+void get_asm_custom_topology(struct acdb_cal_block *cal_block);
void get_voice_cal_allocation(struct acdb_cal_block *cal_block);
void get_lsm_cal(struct acdb_cal_block *cal_block);
void get_anc_cal(struct acdb_cal_block *cal_block);
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 145f095..1969fe8 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -30,6 +30,15 @@
#define AUDIO_OCMEM_BUF_SIZE (512 * SZ_1K)
+#define _BIT_MASK_\
+ ((1 << OCMEM_STATE_EXIT) |\
+ (1 << OCMEM_STATE_GROW) |\
+ (1 << OCMEM_STATE_SHRINK))
+
+#define set_bit_pos(x, y) (atomic_set(&x, (atomic_read(&x) | (1 << y))))
+#define clear_bit_pos(x, y) (atomic_set(&x, (atomic_read(&x) & (~(1 << y)))))
+#define test_bit_pos(x, y) ((atomic_read(&x)) & (1 << y))
+
static int enable_ocmem_audio_voice = 1;
module_param(enable_ocmem_audio_voice, int,
S_IRUGO | S_IWUSR | S_IWGRP);
@@ -48,6 +57,8 @@
OCMEM_STATE_MAP_FAIL,
OCMEM_STATE_UNMAP_FAIL,
OCMEM_STATE_EXIT,
+ OCMEM_STATE_SSR,
+ OCMEM_STATE_DISABLE,
};
static void audio_ocmem_process_workdata(struct work_struct *work);
@@ -74,6 +85,7 @@
atomic_t audio_cond;
atomic_t audio_exit;
spinlock_t audio_lock;
+ struct mutex protect_lock;
struct workqueue_struct *audio_ocmem_workqueue;
struct workqueue_struct *voice_ocmem_workqueue;
bool ocmem_en;
@@ -81,7 +93,6 @@
static struct audio_ocmem_prv audio_ocmem_lcl;
-
static int audio_ocmem_client_cb(struct notifier_block *this,
unsigned long event1, void *data)
{
@@ -97,7 +108,9 @@
switch (event1) {
case OCMEM_MAP_DONE:
pr_debug("%s: map done\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_COMPL);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_TRANSITION);
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_COMPL);
break;
case OCMEM_MAP_FAIL:
pr_debug("%s: map fail\n", __func__);
@@ -105,7 +118,9 @@
break;
case OCMEM_UNMAP_DONE:
pr_debug("%s: unmap done\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state,
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_TRANSITION);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
OCMEM_STATE_UNMAP_COMPL);
break;
case OCMEM_UNMAP_FAIL:
@@ -115,13 +130,13 @@
break;
case OCMEM_ALLOC_GROW:
rbuf = data;
- if (rbuf->len == AUDIO_OCMEM_BUF_SIZE) {
+ if ((rbuf->len == AUDIO_OCMEM_BUF_SIZE)) {
audio_ocmem_lcl.buf = data;
pr_debug("%s: Alloc grow request received buf->addr: 0x%08lx\n",
__func__,
(audio_ocmem_lcl.buf)->addr);
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_GROW);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_GROW);
} else {
pr_debug("%s: Alloc grow request with size: %ld",
__func__,
@@ -132,19 +147,33 @@
break;
case OCMEM_ALLOC_SHRINK:
pr_debug("%s: Alloc shrink request received\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_SHRINK);
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_SHRINK);
break;
default:
pr_err("%s: Invalid event[%ld]\n", __func__, event1);
break;
}
spin_unlock_irqrestore(&audio_ocmem_lcl.audio_lock, flags);
- if (!vwait && (atomic_read(&audio_ocmem_lcl.audio_cond))) {
atomic_set(&audio_ocmem_lcl.audio_cond, 0);
wake_up(&audio_ocmem_lcl.audio_wait);
- }
return rc;
}
+int get_state_to_process(atomic_t *state)
+{
+
+ if (test_bit_pos((*state), OCMEM_STATE_SHRINK)) {
+ pr_debug("%s: returning shrink state\n", __func__);
+ return OCMEM_STATE_SHRINK;
+ } else if (test_bit_pos((*state), OCMEM_STATE_GROW)) {
+ pr_debug("%s: returning grow state\n", __func__);
+ return OCMEM_STATE_GROW;
+ } else if (test_bit_pos((*state), OCMEM_STATE_EXIT)) {
+ pr_debug("%s: returning exit state\n", __func__);
+ return OCMEM_STATE_EXIT;
+ } else
+ return -EINVAL;
+
+}
/**
* audio_ocmem_enable() - Exercise OCMEM for audio
@@ -159,36 +188,12 @@
{
int ret;
int i, j;
+ int state_bit;
struct ocmem_buf *buf = NULL;
struct avcs_cmd_rsp_get_low_power_segments_info_t *lp_segptr;
pr_debug("%s\n", __func__);
- /* Non-blocking ocmem allocate (asynchronous) */
- buf = ocmem_allocate_nb(cid, AUDIO_OCMEM_BUF_SIZE);
- if (IS_ERR_OR_NULL(buf)) {
- pr_err("%s: failed: %d\n", __func__, cid);
- return -ENOMEM;
- }
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_ALLOC);
-
- audio_ocmem_lcl.buf = buf;
- atomic_set(&audio_ocmem_lcl.audio_exit, 0);
- atomic_set(&audio_ocmem_lcl.audio_cond, 1);
- pr_debug("%s: buf->len: %ld\n", __func__, buf->len);
- if (!buf->len) {
- pr_debug("%s: buf.len is 0, waiting for ocmem region\n",
- __func__);
- wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- (atomic_read(&audio_ocmem_lcl.audio_cond) == 0) ||
- (atomic_read(&audio_ocmem_lcl.audio_exit) == 1));
- if (atomic_read(&audio_ocmem_lcl.audio_exit)) {
- pr_err("%s: audio playback ended while waiting for ocmem\n",
- __func__);
- ret = -EINVAL;
- goto fail_cmd;
- }
- }
- pr_debug("%s: buf->len: %ld\n", __func__, (audio_ocmem_lcl.buf)->len);
+ atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_DEFAULT);
if (audio_ocmem_lcl.lp_memseg_ptr == NULL) {
/* Retrieve low power segments */
ret = core_get_low_power_segments(
@@ -213,6 +218,42 @@
(uint32_t)audio_ocmem_lcl.mlist.chunks[j].ddr_paddr,
(uint32_t)audio_ocmem_lcl.mlist.chunks[j].size);
}
+ /* Non-blocking ocmem allocate (asynchronous) */
+ buf = ocmem_allocate_nb(cid, AUDIO_OCMEM_BUF_SIZE);
+ if (IS_ERR_OR_NULL(buf)) {
+ pr_err("%s: failed: %d\n", __func__, cid);
+ return -ENOMEM;
+ }
+
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_ALLOC);
+
+ audio_ocmem_lcl.buf = buf;
+ atomic_set(&audio_ocmem_lcl.audio_exit, 0);
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+ pr_debug("%s: buf->len: %ld\n", __func__, buf->len);
+ if (!buf->len) {
+ pr_debug("%s: buf.len is 0, waiting for ocmem region\n",
+ __func__);
+ mutex_unlock(&audio_ocmem_lcl.protect_lock);
+ wait_event_interruptible(audio_ocmem_lcl.audio_wait,
+ (atomic_read(&audio_ocmem_lcl.audio_cond) == 0) ||
+ (atomic_read(&audio_ocmem_lcl.audio_exit) == 1));
+ if (atomic_read(&audio_ocmem_lcl.audio_exit)) {
+ ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
+ if (ret) {
+ pr_err("%s: ocmem_free failed, state[%d]\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_state));
+ }
+ pr_info("%s: audio playback ended while waiting for ocmem\n",
+ __func__);
+ ret = 0;
+ goto fail_cmd;
+ }
+ clear_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_GROW);
+ mutex_trylock(&audio_ocmem_lcl.protect_lock);
+ }
+ pr_debug("%s: buf->len: %ld\n", __func__, (audio_ocmem_lcl.buf)->len);
/* vote for ocmem bus bandwidth */
ret = msm_bus_scale_client_update_request(
@@ -221,7 +262,7 @@
if (ret)
pr_err("%s: failed to vote for bus bandwidth\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_TRANSITION);
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_TRANSITION);
pr_debug("%s: buf->addr: 0x%08lx, len: %ld, audio_state[0x%x]\n",
__func__,
@@ -236,16 +277,25 @@
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
}
+ wait_event_interruptible(audio_ocmem_lcl.audio_wait,
+ test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL) != 0);
+ atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+
+ mutex_unlock(&audio_ocmem_lcl.protect_lock);
pr_debug("%s: audio_cond[%d] audio_state[0x%x]\n", __func__,
atomic_read(&audio_ocmem_lcl.audio_cond),
atomic_read(&audio_ocmem_lcl.audio_state));
- while ((atomic_read(&audio_ocmem_lcl.audio_state) !=
- OCMEM_STATE_EXIT)) {
+
+ while ((test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_DISABLE)) == 0) {
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- atomic_read(&audio_ocmem_lcl.audio_cond) == 0);
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _BIT_MASK_) != 0);
- switch (atomic_read(&audio_ocmem_lcl.audio_state)) {
+ state_bit = get_state_to_process(&audio_ocmem_lcl.audio_state);
+ switch (state_bit) {
case OCMEM_STATE_MAP_COMPL:
pr_debug("%s: audio_cond[0x%x], audio_state[0x%x]\n",
__func__, atomic_read(&audio_ocmem_lcl.audio_cond),
@@ -258,6 +308,10 @@
pr_debug("%s: ocmem shrink request process\n",
__func__);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_TRANSITION);
ret = ocmem_unmap(cid, audio_ocmem_lcl.buf,
&audio_ocmem_lcl.mlist);
if (ret) {
@@ -267,12 +321,9 @@
goto fail_cmd;
}
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_UNMAP_TRANSITION);
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- atomic_read(&audio_ocmem_lcl.audio_cond) == 0);
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_UNMAP_COMPL);
+ test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_COMPL) != 0);
ret = ocmem_shrink(cid, audio_ocmem_lcl.buf, 0);
if (ret) {
pr_err("%s: ocmem_shrink failed, state[%d]\n",
@@ -281,11 +332,18 @@
goto fail_cmd;
}
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_SHRINK);
+ pr_debug("%s:shrink process complete\n", __func__);
break;
case OCMEM_STATE_GROW:
pr_debug("%s: ocmem grow request process\n",
__func__);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_COMPL);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_TRANSITION);
ret = ocmem_map(cid, audio_ocmem_lcl.buf,
&audio_ocmem_lcl.mlist);
if (ret) {
@@ -294,14 +352,102 @@
atomic_read(&audio_ocmem_lcl.audio_state));
goto fail_cmd;
}
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_MAP_TRANSITION);
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- atomic_read(&audio_ocmem_lcl.audio_cond) == 0);
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_MAP_COMPL);
+ test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL) != 0);
+
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_GROW);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
break;
+ case OCMEM_STATE_EXIT:
+ if (test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL)) {
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_TRANSITION);
+ ret = ocmem_unmap(cid, audio_ocmem_lcl.buf,
+ &audio_ocmem_lcl.mlist);
+ if (ret) {
+ pr_err("%s: ocmem_unmap failed, state[0x%x]\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_state));
+ goto fail_cmd;
+ }
+ wait_event_interruptible(
+ audio_ocmem_lcl.audio_wait,
+ test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_COMPL) != 0);
+ }
+
+ if (test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_SHRINK)) {
+ pr_debug("%s: SHRINK while exiting\n",
+ __func__);
+ ret = ocmem_shrink(cid, audio_ocmem_lcl.buf,
+ 0);
+ if (ret) {
+ pr_err("%s: ocmem_shrink failed, state[0x%x]\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_state));
+ goto fail_cmd;
+ }
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_SHRINK);
+
+ }
+
+ pr_debug("%s: calling ocmem free\n", __func__);
+ ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
+ if (ret == -EAGAIN) {
+ pr_debug("%s: received EAGAIN\n", __func__);
+ if (test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_SHRINK)) {
+ ret = ocmem_shrink(cid,
+ audio_ocmem_lcl.buf,
+ 0);
+ if (ret) {
+ pr_err("%s: ocmem_shrink failed, state[0x%x]\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_state));
+ goto fail_cmd;
+ }
+ pr_debug("calling free after EAGAIN");
+ ret = ocmem_free(OCMEM_LP_AUDIO,
+ audio_ocmem_lcl.buf);
+ if (ret) {
+ pr_err("%s: ocmem_free failed\n",
+ __func__);
+ goto fail_cmd;
+ }
+ } else {
+ pr_debug("%s: shrink callback already processed\n",
+ __func__);
+ goto fail_cmd;
+ }
+ } else if (ret) {
+ pr_err("%s: ocmem_free failed, state[0x%x], ret:%d\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_state),
+ ret);
+ goto fail_cmd;
+ }
+ pr_debug("%s: ocmem_free success\n", __func__);
+ msm_bus_scale_client_update_request(
+ audio_ocmem_lcl.audio_ocmem_bus_client,
+ 0);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_DISABLE);
+ break;
+
+
+ case -EINVAL:
+ pr_info("%s: audio_cond[%d] audio_state[0x%x]\n",
+ __func__,
+ atomic_read(&audio_ocmem_lcl.audio_cond),
+ atomic_read(&audio_ocmem_lcl.audio_state));
+ break;
}
}
ret = 0;
@@ -320,64 +466,17 @@
*/
int audio_ocmem_disable(int cid)
{
- int ret;
- int cur_state;
-
- pr_debug("%s: disable\n", __func__);
- cur_state = atomic_read(&audio_ocmem_lcl.audio_state);
- if (atomic_cmpxchg(&audio_ocmem_lcl.audio_cond, 1, 0)) {
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_EXIT);
- wake_up(&audio_ocmem_lcl.audio_wait);
- }
pr_debug("%s: audio_cond[0x%x], audio_state[0x%x]\n", __func__,
atomic_read(&audio_ocmem_lcl.audio_cond),
atomic_read(&audio_ocmem_lcl.audio_state));
- switch (cur_state) {
- case OCMEM_STATE_MAP_COMPL:
- atomic_set(&audio_ocmem_lcl.audio_cond, 1);
- ret = ocmem_unmap(cid, audio_ocmem_lcl.buf,
- &audio_ocmem_lcl.mlist);
- if (ret) {
- pr_err("%s: ocmem_unmap failed, state[%d]\n",
- __func__,
- atomic_read(&audio_ocmem_lcl.audio_state));
- goto fail_cmd;
- }
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_EXIT);
+ wake_up(&audio_ocmem_lcl.audio_wait);
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_EXIT);
-
- wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- atomic_read(&audio_ocmem_lcl.audio_cond) == 0);
- case OCMEM_STATE_UNMAP_COMPL:
- case OCMEM_STATE_MAP_FAIL:
- case OCMEM_STATE_MAP_TRANSITION:
- case OCMEM_STATE_ALLOC:
- ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
- if (ret) {
- pr_err("%s: ocmem_free failed, state[%d]\n",
- __func__,
- atomic_read(&audio_ocmem_lcl.audio_state));
- goto fail_cmd;
- }
- pr_debug("%s: state=%d", __func__,
- atomic_read(&audio_ocmem_lcl.audio_state));
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_EXIT);
- pr_debug("%s: ocmem_free success\n", __func__);
- break;
-
- default:
- pr_debug("%s:error: state=%d", __func__,
- atomic_read(&audio_ocmem_lcl.audio_state));
- break;
-
- }
- msm_bus_scale_client_update_request(
- audio_ocmem_lcl.audio_ocmem_bus_client,
- 0);
+ mutex_unlock(&audio_ocmem_lcl.protect_lock);
+ pr_debug("%s: exit\n", __func__);
return 0;
-fail_cmd:
- return ret;
}
static void voice_ocmem_process_workdata(struct work_struct *work)
@@ -497,6 +596,10 @@
container_of(work, struct audio_ocmem_workdata, work);
en = audio_ocm_work->en;
+ mutex_lock(&audio_ocmem_lcl.protect_lock);
+ /* if previous work waiting for ocmem - signal it to exit */
+ atomic_set(&audio_ocmem_lcl.audio_exit, 1);
+ pr_debug("%s: acquired mutex for %d\n", __func__, en);
switch (audio_ocm_work->id) {
case AUDIO:
cid = OCMEM_LP_AUDIO;
@@ -548,9 +651,6 @@
workdata->id = id;
workdata->en = enable;
- /* if previous work waiting for ocmem - signal it to exit */
- atomic_set(&audio_ocmem_lcl.audio_exit, 1);
-
INIT_WORK(&workdata->work, audio_ocmem_process_workdata);
queue_work(audio_ocmem_lcl.audio_ocmem_workqueue,
&workdata->work);
@@ -611,6 +711,7 @@
atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_DEFAULT);
atomic_set(&audio_ocmem_lcl.audio_exit, 0);
spin_lock_init(&audio_ocmem_lcl.audio_lock);
+ mutex_init(&audio_ocmem_lcl.protect_lock);
audio_ocmem_lcl.ocmem_en = true;
/* populate platform data */
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 49f1d70..b5ce28f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-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
@@ -140,7 +140,8 @@
};
static int voip_get_media_type(uint32_t mode,
- unsigned int samp_rate);
+ unsigned int samp_rate,
+ unsigned int *media_type);
static int voip_get_rate_type(uint32_t mode,
uint32_t rate,
uint32_t *rate_type);
@@ -782,11 +783,11 @@
goto done;
}
prtd->rate_type = rate_type;
- media_type = voip_get_media_type(prtd->mode,
- prtd->play_samp_rate);
- if (media_type < 0) {
+ ret = voip_get_media_type(prtd->mode,
+ prtd->play_samp_rate,
+ &media_type);
+ if (ret < 0) {
pr_err("fail at getting media_type\n");
- ret = -EINVAL;
goto done;
}
pr_debug(" media_type=%d, rate_type=%d\n", media_type,
@@ -1058,42 +1059,43 @@
}
static int voip_get_media_type(uint32_t mode,
- unsigned int samp_rate)
+ unsigned int samp_rate,
+ unsigned int *media_type)
{
- uint32_t media_type;
+ int ret = 0;
pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
mode, samp_rate);
switch (mode) {
case MODE_AMR:
- media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
+ *media_type = VSS_MEDIA_ID_AMR_NB_MODEM;
break;
case MODE_AMR_WB:
- media_type = VSS_MEDIA_ID_AMR_WB_MODEM;
+ *media_type = VSS_MEDIA_ID_AMR_WB_MODEM;
break;
case MODE_PCM:
if (samp_rate == 8000)
- media_type = VSS_MEDIA_ID_PCM_NB;
+ *media_type = VSS_MEDIA_ID_PCM_NB;
else
- media_type = VSS_MEDIA_ID_PCM_WB;
+ *media_type = VSS_MEDIA_ID_PCM_WB;
break;
case MODE_IS127: /* EVRC-A */
- media_type = VSS_MEDIA_ID_EVRC_MODEM;
+ *media_type = VSS_MEDIA_ID_EVRC_MODEM;
break;
case MODE_4GV_NB: /* EVRC-B */
- media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
+ *media_type = VSS_MEDIA_ID_4GV_NB_MODEM;
break;
case MODE_4GV_WB: /* EVRC-WB */
- media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
+ *media_type = VSS_MEDIA_ID_4GV_WB_MODEM;
break;
default:
pr_debug(" input mode is not supported\n");
- media_type = -EINVAL;
+ ret = -EINVAL;
}
- pr_debug("%s: media_type is 0x%x\n", __func__, media_type);
+ pr_debug("%s: media_type is 0x%x\n", __func__, *media_type);
- return media_type;
+ return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index bc11304..685deef 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -46,8 +46,11 @@
/* 0 - (MAX_AUDPROC_TYPES -1): audproc handles */
/* (MAX_AUDPROC_TYPES -1) - (2 * MAX_AUDPROC_TYPES -1): audvol handles */
- atomic_t mem_map_cal_handles[(2 * MAX_AUDPROC_TYPES)];
+/* + 1 for custom ADM topology */
+ atomic_t mem_map_cal_handles[(2 * MAX_AUDPROC_TYPES) + 1];
atomic_t mem_map_cal_index;
+
+ int set_custom_topology;
};
static struct adm_ctl this_adm;
@@ -309,6 +312,8 @@
atomic_set(&this_adm.copp_stat[i], 0);
}
this_adm.apr = NULL;
+ reset_custom_topology_flags();
+ this_adm.set_custom_topology = 1;
}
pr_debug("Resetting calibration blocks");
for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
@@ -350,6 +355,7 @@
case ADM_CMD_DEVICE_CLOSE_V5:
case ADM_CMD_SHARED_MEM_UNMAP_REGIONS:
case ADM_CMD_MATRIX_MAP_ROUTINGS_V5:
+ case ADM_CMD_ADD_TOPOLOGIES:
pr_debug("%s: Basic callback received, wake up.\n",
__func__);
atomic_set(&this_adm.copp_stat[index], 1);
@@ -435,6 +441,87 @@
return 0;
}
+void send_adm_custom_topology(int port_id)
+{
+ struct acdb_cal_block cal_block;
+ struct cmd_set_topologies adm_top;
+ int index;
+ int result;
+ int size = 4096;
+
+ get_adm_custom_topology(&cal_block);
+ if (cal_block.cal_size == 0) {
+ pr_debug("%s: no cal to send addr= 0x%x\n",
+ __func__, cal_block.cal_paddr);
+ goto done;
+ }
+
+ index = afe_get_port_index(port_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %#x\n",
+ __func__, index, port_id);
+ goto done;
+ }
+
+ if (this_adm.set_custom_topology) {
+ /* specific index 4 for adm topology memory */
+ atomic_set(&this_adm.mem_map_cal_index, 4);
+
+ /* Only call this once */
+ this_adm.set_custom_topology = 0;
+
+ result = adm_memory_map_regions(port_id, &cal_block.cal_paddr,
+ 0, &size, 1);
+ if (result < 0) {
+ pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block.cal_paddr,
+ cal_block.cal_size);
+ goto done;
+ }
+ }
+
+
+ adm_top.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(20), APR_PKT_VER);
+ adm_top.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(adm_top));
+ adm_top.hdr.src_svc = APR_SVC_ADM;
+ adm_top.hdr.src_domain = APR_DOMAIN_APPS;
+ adm_top.hdr.src_port = port_id;
+ adm_top.hdr.dest_svc = APR_SVC_ADM;
+ adm_top.hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_top.hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+ adm_top.hdr.token = port_id;
+ adm_top.hdr.opcode = ADM_CMD_ADD_TOPOLOGIES;
+ adm_top.payload_addr_lsw = cal_block.cal_paddr;
+ adm_top.payload_addr_msw = 0;
+ adm_top.mem_map_handle = atomic_read(&this_adm.mem_map_cal_handles[4]);
+ adm_top.payload_size = cal_block.cal_size;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ pr_debug("%s: Sending ADM_CMD_ADD_TOPOLOGIES payload = 0x%x, size = %d\n",
+ __func__, adm_top.payload_addr_lsw,
+ adm_top.payload_size);
+ result = apr_send_pkt(this_adm.apr, (uint32_t *)&adm_top);
+ if (result < 0) {
+ pr_err("%s: Set topologies failed port = 0x%x payload = 0x%x\n",
+ __func__, port_id, cal_block.cal_paddr);
+ goto done;
+ }
+ /* Wait for the callback */
+ result = wait_event_timeout(this_adm.wait[index],
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!result) {
+ pr_err("%s: Set topologies timed out port = 0x%x, payload = 0x%x\n",
+ __func__, port_id, cal_block.cal_paddr);
+ goto done;
+ }
+
+done:
+ return;
+}
+
static int send_adm_cal_block(int port_id, struct acdb_cal_block *aud_cal)
{
s32 result = 0;
@@ -684,6 +771,7 @@
rtac_set_adm_handle(this_adm.apr);
}
+ send_adm_custom_topology(port_id);
/* Create a COPP if port id are not enabled */
if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
@@ -1154,6 +1242,7 @@
{
int i = 0;
this_adm.apr = NULL;
+ this_adm.set_custom_topology = 1;
for (i = 0; i < AFE_MAX_PORTS; i++) {
atomic_set(&this_adm.copp_id[i], RESET_COPP_ID);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 3d8d5eb..b832c41 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -106,6 +106,9 @@
static int out_cold_index;
static char *out_buffer;
static char *in_buffer;
+static int set_custom_topology;
+static int topology_map_handle;
+
static int audio_output_latency_dbgfs_open(struct inode *inode,
struct file *file)
{
@@ -341,6 +344,90 @@
return;
}
+void send_asm_custom_topology(struct audio_client *ac)
+{
+ struct acdb_cal_block cal_block;
+ struct cmd_set_topologies asm_top;
+ struct audio_buffer *buf;
+ struct asm_buffer_node *buf_node = NULL;
+ struct list_head *ptr, *next;
+ int result;
+ int size = 4096;
+
+ get_asm_custom_topology(&cal_block);
+ if (cal_block.cal_size == 0) {
+ pr_debug("%s: no cal to send addr= 0x%x\n",
+ __func__, cal_block.cal_paddr);
+ goto done;
+ }
+
+ if (set_custom_topology) {
+ /* Only call this once */
+ set_custom_topology = 0;
+
+ /* Use first asm buf to map memory */
+ buf = kzalloc(sizeof(struct audio_buffer), GFP_KERNEL);
+ if (!buf) {
+ pr_debug("%s: could not allocate temp memory\n",
+ __func__);
+ goto done;
+ }
+ buf[0].phys = cal_block.cal_paddr;
+ ac->port[0].buf = buf;
+
+ result = q6asm_memory_map_regions(ac, 0, size, 1, 1);
+ if (result < 0) {
+ pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
+ __func__, cal_block.cal_paddr,
+ cal_block.cal_size);
+ goto done;
+ }
+
+ list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+ buf_node = list_entry(ptr, struct asm_buffer_node,
+ list);
+ if (buf_node->buf_addr_lsw == cal_block.cal_paddr) {
+ topology_map_handle = buf_node->mmap_hdl;
+ break;
+ }
+ }
+
+ kfree(buf);
+ }
+
+ q6asm_add_hdr(ac, &asm_top.hdr, APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(asm_top)), TRUE);
+
+ asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES;
+ asm_top.payload_addr_lsw = cal_block.cal_paddr;
+ asm_top.payload_addr_msw = 0;
+ asm_top.mem_map_handle = topology_map_handle;
+ asm_top.payload_size = cal_block.cal_size;
+
+ pr_debug("%s: Sending ASM_CMD_ADD_TOPOLOGIES payload = 0x%x, size = %d, map handle = 0x%x\n",
+ __func__, asm_top.payload_addr_lsw,
+ asm_top.payload_size, asm_top.mem_map_handle);
+
+ result = apr_send_pkt(ac->apr, (uint32_t *) &asm_top);
+ if (result < 0) {
+ pr_err("%s: Set topologies failed payload = 0x%x\n",
+ __func__, cal_block.cal_paddr);
+ goto done;
+ }
+
+ result = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (result < 0) {
+ pr_err("%s: Set topologies failed payload = 0x%x\n",
+ __func__, cal_block.cal_paddr);
+ goto done;
+ }
+
+
+done:
+ return;
+}
+
int q6asm_audio_client_buf_free(unsigned int dir,
struct audio_client *ac)
{
@@ -563,6 +650,8 @@
atomic_set(&ac->cmd_state, 0);
atomic_set(&ac->nowait_cmd_cnt, 0);
+ send_asm_custom_topology(ac);
+
pr_debug("%s: session[%d]\n", __func__, ac->session);
return ac;
@@ -822,6 +911,8 @@
apr_reset(this_mmap.apr);
atomic_set(&this_mmap.ref_cnt, 0);
this_mmap.apr = NULL;
+ reset_custom_topology_flags();
+ set_custom_topology = 1;
return 0;
}
sid = (data->token >> 8) & 0x0F;
@@ -956,6 +1047,8 @@
(uint32_t *)data->payload, ac->priv);
apr_reset(ac->apr);
ac->apr = NULL;
+ reset_custom_topology_flags();
+ set_custom_topology = 1;
return 0;
}
@@ -997,6 +1090,7 @@
case ASM_STREAM_CMD_OPEN_READWRITE_V2:
case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+ case ASM_CMD_ADD_TOPOLOGIES:
pr_debug("%s:Payload = [0x%x]stat[0x%x]\n",
__func__, payload[0], payload[1]);
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
@@ -3564,6 +3658,7 @@
{
pr_debug("%s\n", __func__);
memset(session, 0, sizeof(session));
+ set_custom_topology = 1;
config_debug_fs_init();