Merge "msm: msm_bus: Enable bus driver to get pdata from device tree"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 104d6a2..032c814 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -459,6 +459,11 @@
- qcom,taiko-mclk-clk-freq : Master clock value given to codec. Some WCD9XXX
codec can run at different mclk values. Mclk value can be 9.6MHz or 12.288MHz.
This element represents the value for MCLK provided to codec.
+- prim-i2s-gpio-ws : Specifies gpio assigned for primary WS I2S pin.
+- prim-i2s-gpio-din : Specifies gpio assigned for primary DIN I2S pin.
+- prim-i2s-gpio-dout : Specifies gpio assigned for primary DOUT I2S pin.
+- prim-i2s-gpio-sclk : Specifies gpio assigned for primary SCLK I2S pin.
+- prim-i2s-gpio-mclk : Specifies gpio assigned for MCLK I2S pin.
Example:
@@ -494,6 +499,11 @@
"DMIC6", "MIC BIAS4 External",
"MIC BIAS4 External", "Digital Mic6";
qcom,taiko-mclk-clk-freq = <12288000>;
+ prim-i2s-gpio-ws = <&msmgpio 12 0>;
+ prim-i2s-gpio-din = <&msmgpio 13 0>;
+ prim-i2s-gpio-dout = <&msmgpio 14 0>;
+ prim-i2s-gpio-sclk = <&msmgpio 15 0>;
+ prim-i2s-gpio-mclk = <&msmgpio 71 0>;
};
* msm-adsp-loader
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 015822f..8b7b31b 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -147,6 +147,10 @@
- qcom,descriptor-fifo-offset: descriptor fifo offset address
- qcom,descriptor-fifo-size: descriptor fifo size
+Optional Properties for Subnode:
+- qcom,reset-bam-on-connect: If present then BAM is RESET before connecting
+ pipe. This may be required if BAM peripheral is also reset before connect.
+
Optional properties :
- qcom,ignore-core-reset-ack: If present then BAM ignores ACK from USB core
while performing PIPE RESET
@@ -193,6 +197,7 @@
qcom,data-fifo-size = <0x4000>;
qcom,descriptor-fifo-offset = <0xf4000>;
qcom,descriptor-fifo-size = <0x1400>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe3 {
diff --git a/Documentation/mmc/mmc-dev-attrs.txt b/Documentation/mmc/mmc-dev-attrs.txt
index 43453d0..d96b431 100644
--- a/Documentation/mmc/mmc-dev-attrs.txt
+++ b/Documentation/mmc/mmc-dev-attrs.txt
@@ -25,14 +25,14 @@
running parallel lmdd write and lmdd read operations and calculating
the max number of packed writes requests.
- min_sectors_to_check_bkops_status This attribute is used to
- determine whether the status bit that indicates the need for BKOPS
- should be checked. The value is stored in this attribute represents
- the minimum number of sectors that needs to be changed in the device
- (written or discarded) in order to require the status-bit of BKOPS
- to be checked. The value can modified via sysfs by writing the
- required value to:
- /sys/block/<block_dev_name>/min_sectors_to_check_bkops_status
+ bkops_check_threshold This attribute is used to determine whether
+ the status bit that indicates the need for BKOPS should be checked.
+ The value should be given in percentages of the card size.
+ This value is used to calculate the minimum number of sectors that
+ needs to be changed in the device (written or discarded) in order to
+ require the status-bit of BKOPS to be checked.
+ The value can modified via sysfs by writing the required value to:
+ /sys/block/<block_dev_name>/bkops_check_threshold
SD and MMC Device Attributes
============================
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 81f8c09..98ed0bf 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -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
@@ -121,6 +121,7 @@
atmel,panel-coords = <0 0 1080 1920>;
atmel,display-coords = <0 0 1080 1920>;
atmel,i2c-pull-up;
+ atmel,no-force-update;
atmel,cfg_1 {
atmel,family-id = <0xa2>;
atmel,variant-id = <0x00>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 6a9a071..9be99af 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -99,6 +99,8 @@
usb_otg: usb@f9a55000 {
compatible = "qcom,hsusb-otg";
+ status = "disabled";
+
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0 0 140 0>;
interrupt-names = "core_irq", "async_irq";
@@ -1114,6 +1116,7 @@
qcom,data-fifo-size = <0x1800>;
qcom,descriptor-fifo-offset = <0xf4000>;
qcom,descriptor-fifo-size = <0x1400>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe3 {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 75a0ae5..2fbff6d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -81,7 +81,7 @@
vbus_otg-supply = <&usb_vbus>;
qcom,hsusb-otg-phy-type = <2>;
- qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-mode = <3>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-disable-reset;
};
@@ -470,6 +470,11 @@
"DMIC6", "MIC BIAS4 External",
"MIC BIAS4 External", "Digital Mic6";
qcom,taiko-mclk-clk-freq = <12288000>;
+ prim-i2s-gpio-ws = <&msmgpio 12 0>;
+ prim-i2s-gpio-din = <&msmgpio 13 0>;
+ prim-i2s-gpio-dout = <&msmgpio 14 0>;
+ prim-i2s-gpio-sclk = <&msmgpio 15 0>;
+ prim-i2s-gpio-mclk = <&msmgpio 71 0>;
};
qcom,msm-adsp-loader {
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 1fadd28..136cb5a 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -1,7 +1,6 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
CONFIG_LOCALVERSION="-perf"
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
@@ -217,7 +216,7 @@
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=m
+CONFIG_CFG80211=y
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 87f72f6..eb3c315 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -1,6 +1,5 @@
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_RCU_FAST_NO_HZ=y
CONFIG_IKCONFIG=y
@@ -219,7 +218,7 @@
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=m
+CONFIG_CFG80211=y
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 0b003fd..decd8f2 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -238,6 +238,7 @@
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
+CONFIG_EXT3_FS=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 989d80e..afb9ab6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -346,6 +346,7 @@
select MSM_RUN_QUEUE_STATS
select MIGHT_HAVE_CACHE_L2X0
select ARM_HAS_SG_CHAIN
+ select CPU_HAS_L2_PMU
config ARCH_MSM9625
bool "MSM9625"
@@ -482,6 +483,7 @@
select ARCH_MSM_CORTEXMP
select MIGHT_HAVE_CACHE_L2X0
select ARM_HAS_SG_CHAIN
+ select CPU_HAS_L2_PMU
config MSM_VIC
bool
@@ -1566,6 +1568,16 @@
to perform QMI message marshaling and transport them over IPC
Router.
+config MSM_TEST_QMI_CLIENT
+ depends on MSM_QMI_INTERFACE
+ bool "MSM TEST QMI CLIENT"
+ help
+ The sample QMI client provides a test code for QMI usage. The
+ test_service client driver uses QMI interface library to send
+ and receive QMI messages over IPC Router. The test code sends
+ a synchronous QMI request to the test_service and handles the
+ QMI responses.
+
config MSM_ONCRPCROUTER_DEBUG
depends on MSM_ONCRPCROUTER
default y
@@ -2740,4 +2752,9 @@
stand alone power collapse operation. Selecting this option
ensures that they are always off.
+config MSM_UARTDM_Core_v14
+ bool "Use MSM BLSP based HSUART Core v1.4"
+ depends on SERIAL_MSM_HS
+ help
+ Select if BLSP based UART Core v.14 or higher is present.
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9d9550e..2d617a9 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -33,8 +33,12 @@
obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
+ifdef CONFIG_HW_PERF_EVENTS
+obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9615) += pmu.o perf_event_msm_pl310.o
+endif
ifndef CONFIG_MSM_SMP
obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o
@@ -134,6 +138,7 @@
obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
obj-$(CONFIG_MSM_IPC_ROUTER_SECURITY)+= msm_ipc_router_security.o
obj-$(CONFIG_MSM_QMI_INTERFACE) += msm_qmi_interface.o
+obj-$(CONFIG_MSM_TEST_QMI_CLIENT) += kernel_test_service_v01.o test_qmi_client.o
obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index db77a34..e8c7680 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -122,7 +122,7 @@
[3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 },
[4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 },
[5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 },
- [6] = { { 702000, HFPLL, 1, 0x1A }, 1050000, 1050000, 4 },
+ [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 },
[7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 },
[8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 },
[9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 },
@@ -137,18 +137,18 @@
static struct acpu_level tbl_slow[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
- { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 975000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 975000 },
- { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 1000000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 1000000 },
- { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 1025000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 1025000 },
- { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 1075000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 1075000 },
- { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 1100000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1100000 },
- { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1125000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 975000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 975000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(5), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(5), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(5), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(5), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(5), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1125000 },
{ 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
{ 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
@@ -163,18 +163,18 @@
static struct acpu_level tbl_nom[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 },
- { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 925000 },
- { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 950000 },
- { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 975000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 975000 },
- { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 1025000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 1025000 },
- { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 1050000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1050000 },
- { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1075000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1075000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(5), 950000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(5), 975000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 975000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(5), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1025000 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(5), 1050000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1050000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(5), 1075000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1075000 },
{ 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1125000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1125000 },
{ 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1150000 },
@@ -189,18 +189,18 @@
static struct acpu_level tbl_fast[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 850000 },
- { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 900000 },
- { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 },
- { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 975000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 975000 },
- { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 1000000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1000000 },
- { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1025000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 875000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(5), 900000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(5), 925000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(5), 975000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 975000 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(5), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1000000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(5), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1025000 },
{ 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1075000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
{ 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1100000 },
@@ -215,18 +215,18 @@
static struct acpu_level tbl_faster[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 850000 },
- { 0, { 432000, HFPLL, 2, 0x20 }, L2(6), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 0, { 540000, HFPLL, 2, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 900000 },
- { 0, { 648000, HFPLL, 1, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 },
- { 0, { 756000, HFPLL, 1, 0x1C }, L2(6), 962500 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 962500 },
- { 0, { 864000, HFPLL, 1, 0x20 }, L2(6), 975000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 975000 },
- { 0, { 972000, HFPLL, 1, 0x24 }, L2(6), 1000000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1000000 },
+ { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 875000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 0, { 540000, HFPLL, 2, 0x28 }, L2(5), 900000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 },
+ { 0, { 648000, HFPLL, 1, 0x18 }, L2(5), 925000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 },
+ { 0, { 756000, HFPLL, 1, 0x1C }, L2(5), 962500 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 962500 },
+ { 0, { 864000, HFPLL, 1, 0x20 }, L2(5), 975000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 975000 },
+ { 0, { 972000, HFPLL, 1, 0x24 }, L2(5), 1000000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1000000 },
{ 0, { 1080000, HFPLL, 1, 0x28 }, L2(15), 1050000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1050000 },
{ 0, { 1188000, HFPLL, 1, 0x2C }, L2(15), 1075000 },
@@ -241,12 +241,12 @@
static struct acpu_level tbl_PVS0_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 950000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 1000000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1037500 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1037500 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1075000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1087500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1125000 },
@@ -259,12 +259,12 @@
static struct acpu_level tbl_PVS1_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 950000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 975000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 1000000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1012500 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 975000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1000000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1012500 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1037500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1050000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1087500 },
@@ -277,12 +277,12 @@
static struct acpu_level tbl_PVS2_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 925000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 937500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 950000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 975000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 925000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 937500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 950000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 975000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
@@ -295,12 +295,12 @@
static struct acpu_level tbl_PVS3_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 900000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 900000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 900000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 925000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 950000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 900000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 900000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 925000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 950000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 975000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 987500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
@@ -313,12 +313,12 @@
static struct acpu_level tbl_PVS4_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 950000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 962500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 975000 },
@@ -331,12 +331,12 @@
static struct acpu_level tbl_PVS5_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 937500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 950000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 962500 },
@@ -349,12 +349,12 @@
static struct acpu_level tbl_PVS6_1700MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 937500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 950000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 962500 },
@@ -367,12 +367,12 @@
static struct acpu_level tbl_PVS0_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 950000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 950000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 962500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 975000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 1000000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 950000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 962500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 975000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1000000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1025000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1037500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1062500 },
@@ -386,12 +386,12 @@
static struct acpu_level tbl_PVS1_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 925000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 937500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 950000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 975000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 925000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 937500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 950000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 975000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 1000000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 1012500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1037500 },
@@ -405,12 +405,12 @@
static struct acpu_level tbl_PVS2_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 900000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 900000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 912500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 925000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 950000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 900000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 912500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 925000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 950000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 975000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 987500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1012500 },
@@ -424,12 +424,12 @@
static struct acpu_level tbl_PVS3_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 900000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 900000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 900000 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 912500 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 937500 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 900000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 900000 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 912500 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 937500 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 962500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 975000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 1000000 },
@@ -443,12 +443,12 @@
static struct acpu_level tbl_PVS4_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 950000 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 962500 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 975000 },
@@ -462,12 +462,12 @@
static struct acpu_level tbl_PVS5_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 937500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 950000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 962500 },
@@ -481,12 +481,12 @@
static struct acpu_level tbl_PVS6_2000MHz[] __initdata = {
{ 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 },
- { 1, { 486000, HFPLL, 2, 0x24 }, L2(6), 875000 },
- { 1, { 594000, HFPLL, 1, 0x16 }, L2(6), 875000 },
- { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 },
- { 1, { 810000, HFPLL, 1, 0x1E }, L2(6), 887500 },
- { 1, { 918000, HFPLL, 1, 0x22 }, L2(6), 900000 },
- { 1, { 1026000, HFPLL, 1, 0x26 }, L2(6), 925000 },
+ { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 },
+ { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 },
+ { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 },
+ { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 },
+ { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 },
+ { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 },
{ 1, { 1134000, HFPLL, 1, 0x2A }, L2(15), 937500 },
{ 1, { 1242000, HFPLL, 1, 0x2E }, L2(15), 950000 },
{ 1, { 1350000, HFPLL, 1, 0x32 }, L2(15), 962500 },
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index f6dd2ea..aef937a 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -183,6 +183,8 @@
/* Initial PM8XXX MPP configurations */
static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
+ /* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
+ PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
/*MPP9 is used to detect docking station connection/removal on Liquid*/
PM8921_MPP_INIT(9, D_INPUT, PM8921_MPP_DIG_LEVEL_S4, DIN_TO_INT),
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 1a8e7e4..a6f0e32 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -299,7 +299,6 @@
};
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
- REGULATOR_SUPPLY("ext_ddr3", NULL),
REGULATOR_SUPPLY("vbus", "msm_ehci_host.0"),
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index f782dfe..90315b5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -3538,20 +3538,6 @@
}
-static void enable_ddr3_regulator(void)
-{
- static struct regulator *ext_ddr3;
-
- /* Use MPP7 output state as a flag for PCDDR3 presence. */
- if (gpio_get_value_cansleep(PM8921_MPP_PM_TO_SYS(7)) > 0) {
- ext_ddr3 = regulator_get(NULL, "ext_ddr3");
- if (IS_ERR(ext_ddr3) || ext_ddr3 == NULL)
- pr_err("Could not get MPP7 regulator\n");
- else
- regulator_enable(ext_ddr3);
- }
-}
-
static void enable_avc_i2c_bus(void)
{
int avc_i2c_en_mpp = PM8921_MPP_PM_TO_SYS(8);
@@ -3656,7 +3642,6 @@
ARRAY_SIZE(common_i2s_devices));
}
- enable_ddr3_regulator();
rpmrs_level =
msm_rpmrs_levels[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT];
msm_hsic_pdata.swfi_latency = rpmrs_level.latency_us;
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 2f2eb2c..ce6ca92 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.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
@@ -75,6 +75,18 @@
CLK_DUMMY("bus_clk", NULL, "msm_sdcc.2", OFF),
CLK_DUMMY("core_clk", NULL, "f9928000.spi", OFF),
CLK_DUMMY("iface_clk", NULL, "f9928000.spi", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fda64000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fda64000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fda44000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fda44000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fd928000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fd928000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fdb10000.qcom,iommu", OFF),
+ CLK_DUMMY("alt_core_clk", NULL, "fdb10000.qcom,iommu", OFF),
+ CLK_DUMMY("iface_clk", NULL, "fdc84000.qcom,iommu", OFF),
+ CLK_DUMMY("alt_core_clk", NULL, "fdc84000.qcom,iommu", OFF),
+ CLK_DUMMY("core_clk", NULL, "fdc84000.qcom,iommu", OFF),
};
static struct clock_init_data msm_dummy_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index a5fded4..c0402ef 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -182,6 +182,8 @@
static struct pm8xxx_mpp_init pm8917_mpps[] __initdata = {
PM8917_MPP_INIT(PM8XXX_AMUX_MPP_3, A_INPUT,
PM8XXX_MPP_AIN_AMUX_CH8, DIN_TO_INT),
+ /* Configure MPP01 for USB ID detection */
+ PM8917_MPP_INIT(1, D_INPUT, PM8921_MPP_DIG_LEVEL_S4, DIN_TO_INT),
};
void __init msm8930_pm8038_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 3785fb2..61b4e13 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.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
@@ -1558,7 +1558,6 @@
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
.phy_type = SNPS_28NM_INTEGRATED_PHY,
- .pmic_id_irq = PM8038_USB_ID_IN_IRQ(PM8038_IRQ_BASE),
.power_budget = 750,
#ifdef CONFIG_MSM_BUS_SCALING
.bus_scale_table = &usb_bus_scale_pdata,
@@ -2870,6 +2869,16 @@
msm_clock_init(&msm8930_pm8917_clock_init_data);
else
msm_clock_init(&msm8930_clock_init_data);
+
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
+ /* MPP01 IRQ number */
+ msm_otg_pdata.pmic_id_irq =
+ PM8921_MPP_IRQ(PM8917_IRQ_BASE, 1);
+ } else {
+ msm_otg_pdata.pmic_id_irq =
+ PM8038_USB_ID_IN_IRQ(PM8038_IRQ_BASE);
+ }
+
msm_otg_pdata.phy_init_seq = hsusb_phy_init_seq;
if (msm8930_mhl_display_enabled()) {
mhl_platform_data.mhl_enabled = true;
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index fdad2e5..6672f49 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -88,7 +88,12 @@
static struct gpiomux_setting gpio_i2c_config = {
.func = GPIOMUX_FUNC_3,
- .drv = GPIOMUX_DRV_8MA,
+ /*
+ * Please keep I2C GPIOs drive-strength at minimum (2ma). It is a
+ * workaround for HW issue of glitches caused by rapid GPIO current-
+ * change.
+ */
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
};
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 2392f57..d6b8a97 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -254,6 +254,8 @@
ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
{"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+ {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
};
static struct pm8xxx_adc_properties pm8018_adc_data = {
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 4465440..2f75470 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -142,6 +142,34 @@
},
},
{
+ .gpio = 16, /* Sec mi2s ws */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
+ [GPIOMUX_ACTIVE] = &mi2s_active_cfg,
+ },
+ },
+ {
+ .gpio = 17, /* Sec mi2s din */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
+ [GPIOMUX_ACTIVE] = &mi2s_active_cfg,
+ },
+ },
+ {
+ .gpio = 18, /* Sec mi2s dout */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
+ [GPIOMUX_ACTIVE] = &mi2s_active_cfg,
+ },
+ },
+ {
+ .gpio = 19, /* Sec mi2s clk */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
+ [GPIOMUX_ACTIVE] = &mi2s_active_cfg,
+ },
+ },
+ {
.gpio = 71, /* mi2s mclk */
.settings = {
[GPIOMUX_SUSPENDED] = &mi2s_suspend_cfg,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 1b0ac74..43a03a0 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.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
@@ -5281,6 +5281,7 @@
"fda64000.qcom,iommu"),
CLK_LOOKUP("core_clk", camss_jpeg_jpeg_axi_clk.c,
"fda64000.qcom,iommu"),
+ CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda64000.qcom,iommu"),
CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda1c000.qcom,jpeg"),
CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda20000.qcom,jpeg"),
CLK_LOOKUP("bus_clk0", camss_jpeg_jpeg_axi_clk.c, "fda24000.qcom,jpeg"),
@@ -5297,8 +5298,9 @@
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
"fda24000.qcom,jpeg"),
CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_vfe_cpp_ahb_clk.c, "fda44000.qcom,iommu"),
- CLK_LOOKUP("core_clk", camss_vfe_cpp_clk.c, "fda44000.qcom,iommu"),
+ CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda44000.qcom,iommu"),
+ CLK_LOOKUP("core_clk", camss_vfe_vfe_axi_clk.c, "fda44000.qcom,iommu"),
+ CLK_LOOKUP("alt_core_clk", camss_top_ahb_clk.c, "fda44000.qcom,iommu"),
CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdss_dsi_clk_ctrl"),
CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd923400.qcom,mdss_edp"),
@@ -5451,56 +5453,6 @@
CLK_LOOKUP("krait3_m_clk", krait3_m_clk, ""),
};
-static struct pll_config_regs gpll0_regs __initdata = {
- .l_reg = (void __iomem *)GPLL0_L_REG,
- .m_reg = (void __iomem *)GPLL0_M_REG,
- .n_reg = (void __iomem *)GPLL0_N_REG,
- .config_reg = (void __iomem *)GPLL0_USER_CTL_REG,
- .mode_reg = (void __iomem *)GPLL0_MODE_REG,
- .base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL0 at 600 MHz, main output enabled. */
-static struct pll_config gpll0_config __initdata = {
- .l = 0x1f,
- .m = 0x1,
- .n = 0x4,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .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),
-};
-
-static struct pll_config_regs gpll1_regs __initdata = {
- .l_reg = (void __iomem *)GPLL1_L_REG,
- .m_reg = (void __iomem *)GPLL1_M_REG,
- .n_reg = (void __iomem *)GPLL1_N_REG,
- .config_reg = (void __iomem *)GPLL1_USER_CTL_REG,
- .mode_reg = (void __iomem *)GPLL1_MODE_REG,
- .base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL1 at 480 MHz, main output enabled. */
-static struct pll_config gpll1_config __initdata = {
- .l = 0x19,
- .m = 0x0,
- .n = 0x1,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
static struct pll_config_regs mmpll0_regs __initdata = {
.l_reg = (void __iomem *)MMPLL0_L_REG,
.m_reg = (void __iomem *)MMPLL0_M_REG,
@@ -5605,9 +5557,6 @@
.main_output_mask = BIT(0),
};
-#define PLL_AUX_OUTPUT_BIT 1
-#define PLL_AUX2_OUTPUT_BIT 2
-
#define PWR_ON_MASK BIT(31)
#define EN_REST_WAIT_MASK (0xF << 20)
#define EN_FEW_WAIT_MASK (0xF << 16)
@@ -5627,24 +5576,11 @@
u32 regval, status;
int ret;
- if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
- & gpll0_clk_src.status_mask))
- configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
-
- if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
- & gpll1_clk_src.status_mask))
- configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
-
configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
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);
- /* Enable GPLL0's aux outputs. */
- regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
- regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
- writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
-
/* Vote for GPLL0 to turn on. Needed by acpuclock. */
regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
regval |= BIT(0);
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index f4c045c..151f192 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2125,10 +2125,14 @@
"msm-dai-q6-mi2s.0"),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c,
"msm-dai-q6-mi2s.0"),
- 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_sec_clk_src.c,
+ "msm-dai-q6-mi2s.1"),
+ CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c,
+ "msm-dai-q6-mi2s.1"),
+ CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c,
+ "msm-dai-q6-mi2s.1"),
+ CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c,
+ "msm-dai-q6-mi2s.1"),
CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index cf456f7..3c60fa6 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1667,7 +1667,7 @@
},
{
.name = "l2_irq",
- .start = MSM8625_INT_L2CC_INTR,
+ .start = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
.flags = IORESOURCE_IRQ,
},
};
@@ -2096,7 +2096,7 @@
msm_cpr_init();
if (!cpu_is_msm8625() && !cpu_is_msm8625q())
- pl310_resources[1].start = INT_L2CC_INTR;
+ pl310_resources[1].start = SC_SICL2PERFMONIRPTREQ;
platform_device_register(&pl310_erp_device);
diff --git a/arch/arm/mach-msm/include/mach/irqs-7xxx.h b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
index c90b4ee..97ca682 100644
--- a/arch/arm/mach-msm/include/mach/irqs-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
@@ -75,7 +75,7 @@
/* 22-31 are reserved except 7x27a*/
#if defined(CONFIG_ARCH_MSM7X27A)
#define INT_L2CC_EM (32 + 22)
-#define INT_L2CC_INTR (32 + 23)
+#define SC_SICL2PERFMONIRPTREQ (32 + 23)
#define INT_CE_IRQ (32 + 24)
#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
index a83dd2e..7083390 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -83,7 +83,7 @@
#define MSM8625_INT_UART2DM_IRQ (GIC_SPI_START + 32 + 20)
#define MSM8625_INT_UART2DM_RX (GIC_SPI_START + 32 + 21)
#define MSM8625_INT_L2CC_EM (GIC_SPI_START + 32 + 22)
-#define MSM8625_INT_L2CC_INTR (GIC_SPI_START + 32 + 23)
+#define MSM8625_INT_SC_SICL2PERFMONIRPTREQ (GIC_SPI_START + 32 + 23)
#define MSM8625_INT_CE_IRQ (GIC_SPI_START + 32 + 24)
#define MSM8625_INT_CPR_IRQ0 (GIC_SPI_START + 32 + 25)
#define MSM8625_INT_CPR_IRQ1 (GIC_SPI_START + 32 + 26)
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
index e1fc0cd..5fc87e0 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -48,4 +48,5 @@
/* ID used for virtual devices */
#define PSEUDO_ACDB_ID 0xFFFF
+int is_acdb_enabled(void);
#endif /* _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H */
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index a000c3e..d61d07d 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -77,6 +77,8 @@
#define SPS_BAM_OPT_IRQ_WAKEUP (1UL << 3)
/* Ignore external block pipe reset */
#define SPS_BAM_NO_EXT_P_RST (1UL << 4)
+/* Don't enable local clock gating */
+#define SPS_BAM_NO_LOCAL_CLK_GATING (1UL << 5)
/* BAM device management flags */
@@ -1253,13 +1255,13 @@
*
* @tb_sel - testbus selection
*
- * @pre_level - prescreening level
+ * @desc_sel - selection of descriptors
*
* @return 0 on success, negative value on error
*
*/
int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
- u32 tb_sel, u8 pre_level);
+ u32 tb_sel, u8 desc_sel);
#else
static inline int sps_register_bam_device(const struct sps_bam_props
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.c b/arch/arm/mach-msm/kernel_test_service_v01.c
new file mode 100644
index 0000000..498e046
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.c
@@ -0,0 +1,254 @@
+/* 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/qmi_encdec.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define PING_REQ1_TLV_TYPE 0x1
+#define PING_RESP1_TLV_TYPE 0x2
+#define PING_OPT1_TLV_TYPE 0x10
+#define PING_OPT2_TLV_TYPE 0x11
+
+#define DATA_REQ1_TLV_TYPE 0x1
+#define DATA_RESP1_TLV_TYPE 0x2
+#define DATA_OPT1_TLV_TYPE 0x10
+#define DATA_OPT2_TLV_TYPE 0x11
+
+static struct elem_info test_name_type_v01_ei[] = {
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ .offset = offsetof(struct test_name_type_v01,
+ name_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = TEST_MAX_NAME_SIZE_V01,
+ .elem_size = sizeof(char),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ .offset = offsetof(struct test_name_type_v01,
+ name),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info test_ping_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 4,
+ .elem_size = sizeof(char),
+ .is_array = STATIC_ARRAY,
+ .tlv_type = PING_REQ1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_req_msg_v01,
+ ping),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_req_msg_v01,
+ client_name_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct test_name_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_req_msg_v01,
+ client_name),
+ .ei_array = test_name_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info test_ping_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_RESP1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_resp_msg_v01,
+ pong_valid),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = 4,
+ .elem_size = sizeof(char),
+ .is_array = STATIC_ARRAY,
+ .tlv_type = PING_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_ping_resp_msg_v01,
+ pong),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_OPT2_TLV_TYPE,
+ .offset = offsetof(struct test_ping_resp_msg_v01,
+ service_name_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct test_name_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = PING_OPT2_TLV_TYPE,
+ .offset = offsetof(struct test_ping_resp_msg_v01,
+ service_name),
+ .ei_array = test_name_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info test_data_req_msg_v01_ei[] = {
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_REQ1_TLV_TYPE,
+ .offset = offsetof(struct test_data_req_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = TEST_MED_DATA_SIZE_V01,
+ .elem_size = sizeof(uint8_t),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = DATA_REQ1_TLV_TYPE,
+ .offset = offsetof(struct test_data_req_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_data_req_msg_v01,
+ client_name_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct test_name_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_data_req_msg_v01,
+ client_name),
+ .ei_array = test_name_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+struct elem_info test_data_resp_msg_v01_ei[] = {
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct qmi_response_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_RESP1_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ resp),
+ .ei_array = get_qmi_response_type_v01_ei(),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ data_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(uint32_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ data_len),
+ },
+ {
+ .data_type = QMI_UNSIGNED_1_BYTE,
+ .elem_len = TEST_MED_DATA_SIZE_V01,
+ .elem_size = sizeof(uint8_t),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = DATA_OPT1_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ data),
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(uint8_t),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT2_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ service_name_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct test_name_type_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = DATA_OPT2_TLV_TYPE,
+ .offset = offsetof(struct test_data_resp_msg_v01,
+ service_name),
+ .ei_array = test_name_type_v01_ei,
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
diff --git a/arch/arm/mach-msm/kernel_test_service_v01.h b/arch/arm/mach-msm/kernel_test_service_v01.h
new file mode 100644
index 0000000..79c1845
--- /dev/null
+++ b/arch/arm/mach-msm/kernel_test_service_v01.h
@@ -0,0 +1,73 @@
+/* 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_QMI_TEST_SERVICE_V01_H
+#define MSM_QMI_TEST_SERVICE_V01_H
+
+#include <mach/msm_qmi_interface.h>
+
+#define TEST_MED_DATA_SIZE_V01 8192
+#define TEST_MAX_NAME_SIZE_V01 255
+
+#define TEST_PING_REQ_MSG_ID_V01 0x20
+#define TEST_DATA_REQ_MSG_ID_V01 0x21
+
+#define TEST_PING_REQ_MAX_MSG_LEN_V01 266
+#define TEST_DATA_REQ_MAX_MSG_LEN_V01 8456
+
+struct test_name_type_v01 {
+ uint32_t name_len;
+ char name[TEST_MAX_NAME_SIZE_V01];
+};
+
+struct test_ping_req_msg_v01 {
+ char ping[4];
+
+ uint8_t client_name_valid;
+ struct test_name_type_v01 client_name;
+};
+
+struct test_ping_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+
+ uint8_t pong_valid;
+ char pong[4];
+
+ uint8_t service_name_valid;
+ struct test_name_type_v01 service_name;
+};
+
+struct test_data_req_msg_v01 {
+ uint32_t data_len;
+ uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+ uint8_t client_name_valid;
+ struct test_name_type_v01 client_name;
+};
+
+struct test_data_resp_msg_v01 {
+ struct qmi_response_type_v01 resp;
+
+ uint8_t data_valid;
+ uint32_t data_len;
+ uint8_t data[TEST_MED_DATA_SIZE_V01];
+
+ uint8_t service_name_valid;
+ struct test_name_type_v01 service_name;
+};
+
+extern struct elem_info test_ping_req_msg_v01_ei[];
+extern struct elem_info test_data_req_msg_v01_ei[];
+extern struct elem_info test_ping_resp_msg_v01_ei[];
+extern struct elem_info test_data_resp_msg_v01_ei[];
+
+#endif
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index aaac476..06c0606 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -101,7 +101,7 @@
static uint16_t msm_bypassed_apps_irqs[] = {
MSM8625_INT_CPR_IRQ0,
- MSM8625_INT_L2CC_INTR,
+ MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
};
/* Check IRQ falls into bypassed list are not */
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index 2a4422e..6aa14a6 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,8 @@
#define SCM_SET_REGSAVE_CMD 0x2
#define SCM_SVC_SEC_WDOG_DIS 0x7
+static struct workqueue_struct *wdog_wq;
+
struct msm_watchdog_data {
unsigned int __iomem phys_base;
size_t size;
@@ -213,7 +215,7 @@
work_data.wdog_dd = wdog_dd;
init_completion(&work_data.complete);
INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work);
- schedule_work_on(0, &work_data.work);
+ queue_work_on(0, wdog_wq, &work_data.work);
wait_for_completion(&work_data.complete);
mutex_unlock(&wdog_dd->disable_lock);
} else {
@@ -288,8 +290,8 @@
/* Check again before scheduling *
* Could have been changed on other cpu */
if (enable)
- schedule_delayed_work_on(0, &wdog_dd->dogwork_struct,
- delay_time);
+ queue_delayed_work_on(0, wdog_wq,
+ &wdog_dd->dogwork_struct, delay_time);
}
static int msm_watchdog_remove(struct platform_device *pdev)
@@ -303,7 +305,7 @@
work_data.wdog_dd = wdog_dd;
init_completion(&work_data.complete);
INIT_WORK_ONSTACK(&work_data.work, wdog_disable_work);
- schedule_work_on(0, &work_data.work);
+ queue_work_on(0, wdog_wq, &work_data.work);
wait_for_completion(&work_data.complete);
}
mutex_unlock(&wdog_dd->disable_lock);
@@ -311,6 +313,7 @@
if (wdog_dd->irq_ppi)
free_percpu(wdog_dd->wdog_cpu_dd);
printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
+ destroy_workqueue(wdog_wq);
kfree(wdog_dd);
return 0;
}
@@ -425,7 +428,8 @@
atomic_notifier_chain_register(&panic_notifier_list,
&wdog_dd->panic_blk);
mutex_init(&wdog_dd->disable_lock);
- schedule_delayed_work_on(0, &wdog_dd->dogwork_struct, delay_time);
+ queue_delayed_work_on(0, wdog_wq, &wdog_dd->dogwork_struct,
+ delay_time);
__raw_writel(1, wdog_dd->base + WDT0_EN);
__raw_writel(1, wdog_dd->base + WDT0_RST);
wdog_dd->last_pet = sched_clock();
@@ -509,6 +513,12 @@
int ret;
struct msm_watchdog_data *wdog_dd;
+ wdog_wq = alloc_workqueue("wdog", WQ_HIGHPRI, 0);
+ if (!wdog_wq) {
+ pr_err("Failed to allocate watchdog workqueue\n");
+ return -EIO;
+ }
+
if (!pdev->dev.of_node || !enable)
return -ENODEV;
wdog_dd = kzalloc(sizeof(struct msm_watchdog_data), GFP_KERNEL);
@@ -522,9 +532,10 @@
cpumask_clear(&wdog_dd->alive_mask);
INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);
INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);
- schedule_work_on(0, &wdog_dd->init_dogwork_struct);
+ queue_work_on(0, wdog_wq, &wdog_dd->init_dogwork_struct);
return 0;
err:
+ destroy_workqueue(wdog_wq);
kzfree(wdog_dd);
return ret;
}
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index 40a2f98..e2a580f 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -22,6 +22,9 @@
#include <asm/pmu.h>
#include <asm/hardware/cache-l2x0.h>
+#include <mach/socinfo.h>
+
+static u32 rev1;
/*
* Store dynamic PMU type after registration,
@@ -110,6 +113,30 @@
#define COUNTER_ADDR(idx) (l2x0_base + L2X0_EVENT_CNT0_VAL - 4*idx)
+static u32 l2x0_read_intr_mask(void)
+{
+ return readl_relaxed(l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_write_intr_mask(u32 val)
+{
+ writel_relaxed(val, l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_enable_counter_interrupt(void)
+{
+ u32 intr_mask = l2x0_read_intr_mask();
+ intr_mask |= L2X0_INTR_MASK_ECNTR;
+ l2x0_write_intr_mask(intr_mask);
+}
+
+static void l2x0_disable_counter_interrupt(void)
+{
+ u32 intr_mask = l2x0_read_intr_mask();
+ intr_mask &= ~L2X0_INTR_MASK_ECNTR;
+ l2x0_write_intr_mask(intr_mask);
+}
+
static void l2x0_clear_interrupts(u32 flags)
{
writel_relaxed(flags, l2x0_base + L2X0_INTR_CLEAR);
@@ -190,10 +217,8 @@
raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
- /*
- * TODO: Enable counter interrupt,
- * once we know it works on this chip.
- */
+ if (!rev1)
+ l2x0_enable_counter_interrupt();
val = l2x0pmu_read_ctrl();
@@ -214,10 +239,8 @@
val &= ~L2X0_EVENT_CNT_ENABLE_MASK;
l2x0pmu_write_ctrl(val);
- /*
- * TODO: Disable counter interrupt,
- * once we know it works on this chip.
- */
+ if (!rev1)
+ l2x0_disable_counter_interrupt();
raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
}
@@ -401,6 +424,9 @@
static int __init register_pmu_driver(void)
{
+ if (machine_is_msm9625())
+ rev1 = 1;
+
return platform_driver_register(&l2x0pmu_driver);
}
device_initcall(register_pmu_driver);
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index c903b72..affb451 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. 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
@@ -680,7 +680,7 @@
struct pil_priv *priv;
int id;
void __iomem *addr;
- size_t len;
+ char buf[sizeof(priv->info->name)];
/* Ignore users who don't make any sense */
WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
@@ -703,9 +703,8 @@
addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
priv->info = (struct pil_image_info __iomem *)addr;
- len = min(strlen(desc->name), sizeof(priv->info->name));
- memset_io(priv->info->name, 0, sizeof(priv->info->name));
- memcpy_toio(priv->info->name, desc->name, len);
+ strncpy(buf, desc->name, sizeof(buf));
+ __iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index f0b83f9..cb191fc 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -137,6 +137,21 @@
.resource = msm8625_cpu_pmu_resource,
.num_resources = ARRAY_SIZE(msm8625_cpu_pmu_resource),
};
+
+static struct resource msm8625_l2_pmu_resource[] = {
+ {
+ .start = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+ .end = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device msm8625_l2_pmu_device = {
+ .name = "l2-arm-pmu",
+ .id = ARM_PMU_DEVICE_L2CC,
+ .resource = msm8625_l2_pmu_resource,
+ .num_resources = ARRAY_SIZE(msm8625_l2_pmu_resource),
+};
#endif
static struct platform_device *pmu_devices[] = {
@@ -168,6 +183,7 @@
#ifdef CONFIG_ARCH_MSM8625
if (cpu_is_msm8625()) {
pmu_devices[0] = &msm8625_cpu_pmu_device;
+ pmu_devices[1] = &msm8625_l2_pmu_device;
msm8625_cpu_pmu_device.dev.platform_data = &multicore_data;
}
#endif
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index d7a4607..681b41c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1301,6 +1301,15 @@
}
EXPORT_SYMBOL(acdb_get_calibration_data);
+int is_acdb_enabled()
+{
+ if (acdb_data.handle != NULL)
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(is_acdb_enabled);
+
static u8 check_device_info_already_present(
struct dev_evt_msg device_info,
struct acdb_cache_node *acdb_cache_free_node)
@@ -1522,7 +1531,7 @@
result = -EINVAL;
goto done;
} else
- MM_DBG("AUDPP is calibrated with IIR parameters");
+ MM_DBG("AUDPP is calibrated with IIR parameters\n");
}
result = acdb_fill_audpp_mbadrc();
if (!IS_ERR_VALUE(result)) {
@@ -2270,13 +2279,9 @@
if (ret == 1) {
MM_DBG("got device ready call back for another "\
"audplay task sessions on same COPP\n");
- /*stream_id is used to keep track of number of active*/
- /*sessions active on this device*/
- acdb_cache_free_node->stream_id++;
mutex_unlock(&acdb_data.acdb_mutex);
goto done;
}
- acdb_cache_free_node->stream_id++;
}
update_acdb_data_struct(acdb_cache_free_node);
acdb_data.device_cb_compl = 1;
@@ -2317,6 +2322,9 @@
}
goto done;
}
+ /*stream_id is used to keep track of number of active*/
+ /*sessions active on this device*/
+ acdb_cache_rx.stream_id++;
acdb_data.acdb_state |= AUDPP_READY;
acdb_data.audpp_cb_compl = 1;
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 6f3bf91..fee7404 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -39,6 +39,7 @@
#include "audmgr.h"
+#include <mach/qdsp5/audio_acdb_def.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
#include <mach/qdsp5/qdsp5audpp.h>
@@ -298,19 +299,20 @@
if (!audio_copp->status)
return;
- audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
+ if (!is_acdb_enabled()) {
+ audpp_dsp_set_mbadrc(COMMON_OBJ_ID, audio_copp->mbadrc_enable,
&audio_copp->mbadrc);
- audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
+ audpp_dsp_set_eq(COMMON_OBJ_ID, audio_copp->eq_enable,
&audio_copp->eq);
-
- audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
+ audpp_dsp_set_rx_iir(COMMON_OBJ_ID, audio_copp->rx_iir_enable,
&audio_copp->iir);
- audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
+ audpp_dsp_set_vol_pan(COMMON_OBJ_ID, &audio_copp->vol_pan);
- audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
+ audpp_dsp_set_qconcert_plus(COMMON_OBJ_ID,
audio_copp->qconcert_plus_enable,
&audio_copp->qconcert_plus);
+ }
audio_enable_srs_trumedia(audio_copp, true);
}
EXPORT_SYMBOL(audio_commit_pending_pp_params);
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 7b2090d..c5787fd 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -2,7 +2,7 @@
*
* pcm audio input device
*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_pcm_in.c,
* Copyright (C) 2008 Google, Inc.
@@ -42,6 +42,7 @@
#include "audmgr.h"
+#include <mach/qdsp5/audio_acdb_def.h>
#include <mach/qdsp5/qdsp5audpreproc.h>
#include <mach/qdsp5/qdsp5audpreproccmdi.h>
#include <mach/qdsp5/qdsp5audpreprocmsg.h>
@@ -346,6 +347,8 @@
case AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG: {
MM_INFO("PARAM CFG DONE\n");
audio->running = 1;
+ if (is_acdb_enabled())
+ break;
audio_dsp_set_tx_agc(audio);
audio_dsp_set_ns(audio);
audio_dsp_set_iir(audio);
@@ -914,6 +917,12 @@
mutex_lock(&audio->lock);
switch (cmd) {
case AUDIO_ENABLE_AUDPRE:
+
+ if (is_acdb_enabled()) {
+ MM_INFO("Audpp is supported via acdb\n");
+ rc = -EFAULT;
+ break;
+ }
if (copy_from_user(&enable_mask, (void *) arg,
sizeof(enable_mask))) {
rc = -EFAULT;
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 73ebdf6..8e7a1f5 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -855,6 +855,12 @@
r = PTR_ERR(smd_pkt_devp->pil);
pr_err("%s failed on smd_pkt_dev id:%d - subsystem_get failed for %s\n",
__func__, smd_pkt_devp->i, peripheral);
+ /*
+ * Sleep inorder to reduce the frequency of
+ * retry by user-space modules and to avoid
+ * possible watchdog bite.
+ */
+ msleep((smd_pkt_devp->open_modem_wait * 1000));
goto release_pd;
}
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
new file mode 100644
index 0000000..d070e37
--- /dev/null
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -0,0 +1,344 @@
+/* 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/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/qmi_encdec.h>
+
+#include <asm/uaccess.h>
+
+#include <mach/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define TEST_SERVICE_SVC_ID 0x0000000f
+#define TEST_SERVICE_INS_ID 1
+
+static int test_rep_cnt = 10;
+module_param_named(rep_cnt, test_rep_cnt, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_data_sz = 50;
+module_param_named(data_sz, test_data_sz, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_clnt_debug_mask;
+module_param_named(debug_mask, test_clnt_debug_mask,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define D(x...) do { \
+ if (test_clnt_debug_mask) \
+ pr_debug(x); \
+} while (0)
+
+/* Variable to initiate the test through debugfs interface */
+static struct dentry *test_dent;
+
+/* Test client port for IPC Router */
+static struct qmi_handle *test_clnt;
+static int test_clnt_reset;
+
+/* Reader thread to receive responses & indications */
+static void test_clnt_recv_msg(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_recv_msg, test_clnt_recv_msg);
+static void test_clnt_svc_arrive(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_arrive, test_clnt_svc_arrive);
+static void test_clnt_svc_exit(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_exit, test_clnt_svc_exit);
+static struct workqueue_struct *test_clnt_workqueue;
+
+/* Variable to hold the test result */
+static int test_res;
+
+static int test_qmi_ping_pong_send_sync_msg(void)
+{
+ struct test_ping_req_msg_v01 req;
+ struct test_ping_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+ int rc;
+
+ memcpy(req.ping, "ping", sizeof(req.ping));
+ req.client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_ping_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+ resp_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+ resp_desc.ei_array = test_ping_resp_msg_v01_ei;
+
+ rc = qmi_send_req_wait(test_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp), 0);
+ if (rc < 0) {
+ pr_err("%s: send req failed %d\n", __func__, rc);
+ return rc;
+ }
+
+ D("%s: Received %s response\n", __func__, resp.pong);
+ return rc;
+}
+
+static int test_qmi_data_send_sync_msg(unsigned int data_len)
+{
+ struct test_data_req_msg_v01 *req;
+ struct test_data_resp_msg_v01 *resp;
+ struct msg_desc req_desc, resp_desc;
+ int rc, i;
+
+ req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+ if (!req) {
+ pr_err("%s: Data req msg alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+ if (!resp) {
+ pr_err("%s: Data resp msg alloc failed\n", __func__);
+ kfree(req);
+ return -ENOMEM;
+ }
+
+ req->data_len = data_len;
+ for (i = 0; i < data_len; i = i + sizeof(int))
+ memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+ req->client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_data_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ resp_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ resp_desc.ei_array = test_data_resp_msg_v01_ei;
+
+ rc = qmi_send_req_wait(test_clnt, &req_desc, req, sizeof(*req),
+ &resp_desc, resp, sizeof(*resp), 0);
+ if (rc < 0) {
+ pr_err("%s: send req failed\n", __func__);
+ goto data_send_err;
+ }
+
+ D("%s: data_valid %d\n", __func__, resp->data_valid);
+ D("%s: data_len %d\n", __func__, resp->data_len);
+data_send_err:
+ kfree(resp);
+ kfree(req);
+ return rc;
+}
+
+static void test_clnt_recv_msg(struct work_struct *work)
+{
+ int rc;
+
+ rc = qmi_recv_msg(test_clnt);
+ if (rc < 0)
+ pr_err("%s: Error receiving message\n", __func__);
+}
+
+static void test_clnt_notify(struct qmi_handle *handle,
+ enum qmi_event_type event, void *notify_priv)
+{
+ switch (event) {
+ case QMI_RECV_MSG:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_recv_msg, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static void test_clnt_svc_arrive(struct work_struct *work)
+{
+ int rc;
+
+ D("%s begins\n", __func__);
+
+ /* Create a Local client port for QMI communication */
+ test_clnt = qmi_handle_create(test_clnt_notify, NULL);
+ if (!test_clnt) {
+ pr_err("%s: QMI client handle alloc failed\n", __func__);
+ return;
+ }
+
+ D("%s: Lookup server name\n", __func__);
+ rc = qmi_connect_to_service(test_clnt, TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_INS_ID);
+ if (rc < 0) {
+ pr_err("%s: Server not found\n", __func__);
+ qmi_handle_destroy(test_clnt);
+ test_clnt = NULL;
+ return;
+ }
+ test_clnt_reset = 0;
+ D("%s complete\n", __func__);
+}
+
+static void test_clnt_svc_exit(struct work_struct *work)
+{
+ D("%s begins\n", __func__);
+
+ qmi_handle_destroy(test_clnt);
+ test_clnt_reset = 1;
+ test_clnt = NULL;
+
+ D("%s complete\n", __func__);
+}
+
+static int test_clnt_svc_event_notify(struct notifier_block *this,
+ unsigned long code,
+ void *_cmd)
+{
+ D("%s: event %ld\n", __func__, code);
+ switch (code) {
+ case QMI_SERVER_ARRIVE:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_svc_arrive, 0);
+ break;
+ case QMI_SERVER_EXIT:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_svc_exit, 0);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int test_qmi_open(struct inode *ip, struct file *fp)
+{
+ if (!test_clnt) {
+ pr_err("%s Test client is not initialized\n", __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static ssize_t test_qmi_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ char _buf[16];
+ snprintf(_buf, sizeof(_buf), "%d\n", test_res);
+ test_res = 0;
+ return simple_read_from_buffer(buf, count, pos,
+ _buf, strnlen(_buf, 16));
+}
+
+static int test_qmi_release(struct inode *ip, struct file *fp)
+{
+ return 0;
+}
+
+static ssize_t test_qmi_write(struct file *fp, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ unsigned char cmd[64];
+ int len;
+ int i;
+
+ if (count < 1)
+ return 0;
+
+ len = min(count, (sizeof(cmd) - 1));
+
+ if (copy_from_user(cmd, buf, len))
+ return -EFAULT;
+
+ cmd[len] = 0;
+ if (cmd[len-1] == '\n') {
+ cmd[len-1] = 0;
+ len--;
+ }
+
+ if (!strncmp(cmd, "ping_pong", sizeof(cmd))) {
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_ping_pong_send_sync_msg();
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ }
+ }
+ } else if (!strncmp(cmd, "data", sizeof(cmd))) {
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_data_send_sync_msg(test_data_sz);
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ }
+ }
+ } else {
+ test_res = -EINVAL;
+ }
+ return count;
+}
+
+static struct notifier_block test_clnt_nb = {
+ .notifier_call = test_clnt_svc_event_notify,
+};
+
+static const struct file_operations debug_ops = {
+ .owner = THIS_MODULE,
+ .open = test_qmi_open,
+ .read = test_qmi_read,
+ .write = test_qmi_write,
+ .release = test_qmi_release,
+};
+
+static int __init test_qmi_init(void)
+{
+ int rc;
+
+ test_clnt_workqueue = create_singlethread_workqueue("test_clnt");
+ if (!test_clnt_workqueue)
+ return -EFAULT;
+
+ rc = qmi_svc_event_notifier_register(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_INS_ID, &test_clnt_nb);
+ if (rc < 0) {
+ pr_err("%s: notifier register failed\n", __func__);
+ destroy_workqueue(test_clnt_workqueue);
+ return rc;
+ }
+
+ test_dent = debugfs_create_file("test_qmi_client", 0444, 0,
+ NULL, &debug_ops);
+ if (IS_ERR(test_dent)) {
+ pr_err("%s: unable to create debugfs %ld\n",
+ __func__, IS_ERR(test_dent));
+ test_dent = NULL;
+ qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_INS_ID, &test_clnt_nb);
+ destroy_workqueue(test_clnt_workqueue);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void __exit test_qmi_exit(void)
+{
+ qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_INS_ID, &test_clnt_nb);
+ destroy_workqueue(test_clnt_workqueue);
+ debugfs_remove(test_dent);
+}
+
+module_init(test_qmi_init);
+module_exit(test_qmi_exit);
+
+MODULE_DESCRIPTION("TEST QMI Client Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0b395c5..79f20a4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -321,4 +321,8 @@
extern struct diag_bridge_dev *diag_bridge;
extern struct diagchar_dev *driver;
+
+extern int wrap_enabled;
+extern uint16_t wrap_count;
+
#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6a7f55f..f6c26c3 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -84,11 +84,23 @@
static int token_list[MAX_PROC] = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9};
#define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
-/* This macro gets the next delayed respose id. Once it reaches
- DIAGPKT_MAX_DELAYED_RSP, it stays at DIAGPKT_MAX_DELAYED_RSP */
-#define DIAGPKT_NEXT_DELAYED_RSP_ID(x) \
-((x < DIAGPKT_MAX_DELAYED_RSP) ? x++ : DIAGPKT_MAX_DELAYED_RSP)
+/* returns the next delayed rsp id - rollsover the id if wrapping is
+ enabled. */
+uint16_t diagpkt_next_delayed_rsp_id(uint16_t rspid)
+{
+ if (rspid < DIAGPKT_MAX_DELAYED_RSP)
+ rspid++;
+ else {
+ if (wrap_enabled) {
+ rspid = 1;
+ wrap_count++;
+ } else
+ rspid = DIAGPKT_MAX_DELAYED_RSP;
+ }
+ delayed_rsp_id = rspid;
+ return delayed_rsp_id;
+}
#define COPY_USER_SPACE_OR_EXIT(buf, data, length) \
do { \
@@ -534,7 +546,7 @@
if ((delay_params.rsp_ptr) &&
(delay_params.size == sizeof(delayed_rsp_id)) &&
(delay_params.num_bytes_ptr)) {
- interim_rsp_id = DIAGPKT_NEXT_DELAYED_RSP_ID(
+ interim_rsp_id = diagpkt_next_delayed_rsp_id(
delayed_rsp_id);
if (copy_to_user((void *)delay_params.rsp_ptr,
&interim_rsp_id, sizeof(uint16_t)))
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6b4c337..0bd26cf 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -51,6 +51,8 @@
struct diag_master_table entry;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+int wrap_enabled;
+uint16_t wrap_count;
void encode_rsp_and_send(int buf_length)
{
@@ -896,6 +898,23 @@
return 0;
}
}
+ /* Return the Delayed Response Wrap Status */
+ else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ (*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
+ memcpy(driver->apps_rsp_buf, buf, 4);
+ driver->apps_rsp_buf[4] = wrap_enabled;
+ encode_rsp_and_send(4);
+ return 0;
+ }
+ /* Wrap the Delayed Rsp ID */
+ else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ (*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
+ wrap_enabled = true;
+ memcpy(driver->apps_rsp_buf, buf, 4);
+ driver->apps_rsp_buf[4] = wrap_count;
+ encode_rsp_and_send(5);
+ return 0;
+ }
/* Check for ID for NO MODEM present */
else if (chk_polling_response()) {
/* respond to 0x0 command */
@@ -1449,6 +1468,8 @@
int success;
int i;
+ wrap_enabled = 0;
+ wrap_count = 0;
diag_debug_buf_idx = 0;
driver->read_len_legacy = 0;
driver->use_device_tree = has_device_tree();
diff --git a/drivers/hwmon/pm8xxx-adc-scale.c b/drivers/hwmon/pm8xxx-adc-scale.c
index 4a1f58c..56c352a 100644
--- a/drivers/hwmon/pm8xxx-adc-scale.c
+++ b/drivers/hwmon/pm8xxx-adc-scale.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -271,172 +271,174 @@
};
static const struct pm8xxx_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
- {696483, -40960},
- {649148, -39936},
- {605368, -38912},
- {564809, -37888},
- {527215, -36864},
- {492322, -35840},
- {460007, -34816},
- {429982, -33792},
- {402099, -32768},
- {376192, -31744},
- {352075, -30720},
- {329714, -29696},
- {308876, -28672},
- {289480, -27648},
- {271417, -26624},
- {254574, -25600},
- {238903, -24576},
- {224276, -23552},
- {210631, -22528},
- {197896, -21504},
- {186007, -20480},
- {174899, -19456},
- {164521, -18432},
- {154818, -17408},
- {145744, -16384},
- {137265, -15360},
- {129307, -14336},
- {121866, -13312},
- {114896, -12288},
- {108365, -11264},
- {102252, -10240},
- {96499, -9216},
- {91111, -8192},
- {86055, -7168},
- {81308, -6144},
- {76857, -5120},
- {72660, -4096},
- {68722, -3072},
- {65020, -2048},
- {61538, -1024},
- {58261, 0},
- {55177, 1024},
- {52274, 2048},
- {49538, 3072},
- {46962, 4096},
- {44531, 5120},
- {42243, 6144},
- {40083, 7168},
- {38045, 8192},
- {36122, 9216},
- {34308, 10240},
- {32592, 11264},
- {30972, 12288},
- {29442, 13312},
- {27995, 14336},
- {26624, 15360},
- {25333, 16384},
- {24109, 17408},
- {22951, 18432},
- {21854, 19456},
- {20807, 20480},
- {19831, 21504},
- {18899, 22528},
- {18016, 23552},
- {17178, 24576},
- {16384, 25600},
- {15631, 26624},
- {14916, 27648},
- {14237, 28672},
- {13593, 29696},
- {12976, 30720},
- {12400, 31744},
- {11848, 32768},
- {11324, 33792},
- {10825, 34816},
- {10354, 35840},
- {9900, 36864},
- {9471, 37888},
- {9062, 38912},
- {8674, 39936},
- {8306, 40960},
- {7951, 41984},
- {7616, 43008},
- {7296, 44032},
- {6991, 45056},
- {6701, 46080},
- {6424, 47104},
- {6160, 48128},
- {5908, 49152},
- {5667, 50176},
- {5439, 51200},
- {5219, 52224},
- {5010, 53248},
- {4810, 54272},
- {4619, 55296},
- {4440, 56320},
- {4263, 57344},
- {4097, 58368},
- {3938, 59392},
- {3785, 60416},
- {3637, 61440},
- {3501, 62464},
- {3368, 63488},
- {3240, 64512},
- {3118, 65536},
- {2998, 66560},
- {2889, 67584},
- {2782, 68608},
- {2680, 69632},
- {2581, 70656},
- {2490, 71680},
- {2397, 72704},
- {2310, 73728},
- {2227, 74752},
- {2147, 75776},
- {2064, 76800},
- {1998, 77824},
- {1927, 78848},
- {1860, 79872},
- {1795, 80896},
- {1736, 81920},
- {1673, 82944},
- {1615, 83968},
- {1560, 84992},
- {1507, 86016},
- {1456, 87040},
- {1407, 88064},
- {1360, 89088},
- {1314, 90112},
- {1271, 91136},
- {1228, 92160},
- {1189, 93184},
- {1150, 94208},
- {1112, 95232},
- {1076, 96256},
- {1042, 97280},
- {1008, 98304},
- {976, 99328},
- {945, 100352},
- {915, 101376},
+ {374682, -40960},
+ {360553, -39936},
+ {346630, -38912},
+ {332940, -37888},
+ {319510, -36864},
+ {306363, -35840},
+ {293521, -34816},
+ {281001, -33792},
+ {268818, -32768},
+ {256987, -31744},
+ {245516, -30720},
+ {234413, -29696},
+ {223685, -28672},
+ {213333, -27648},
+ {203360, -26624},
+ {193763, -25600},
+ {184541, -24576},
+ {175691, -23552},
+ {167205, -22528},
+ {159079, -21504},
+ {151304, -20480},
+ {143872, -19456},
+ {136775, -18432},
+ {130001, -17408},
+ {123542, -16384},
+ {117387, -15360},
+ {111526, -14336},
+ {105946, -13312},
+ {100639, -12288},
+ {95592, -11264},
+ {90795, -10240},
+ {86238, -9216},
+ {81909, -8192},
+ {77800, -7168},
+ {73899, -6144},
+ {70197, -5120},
+ {66685, -4096},
+ {63354, -3072},
+ {60194, -2048},
+ {57198, -1024},
+ {54356, 0},
+ {51662, 1024},
+ {49108, 2048},
+ {46687, 3072},
+ {44391, 4096},
+ {42215, 5120},
+ {40151, 6144},
+ {38195, 7168},
+ {36340, 8192},
+ {34582, 9216},
+ {32914, 10240},
+ {31333, 11264},
+ {29833, 12288},
+ {28410, 13312},
+ {27061, 14336},
+ {25781, 15360},
+ {24566, 16384},
+ {23413, 17408},
+ {22319, 18432},
+ {21280, 19456},
+ {20294, 20480},
+ {19358, 21504},
+ {18469, 22528},
+ {17624, 23552},
+ {16822, 24576},
+ {16060, 25600},
+ {15335, 26624},
+ {14646, 27648},
+ {13992, 28672},
+ {13369, 29696},
+ {12777, 30720},
+ {12214, 31744},
+ {11678, 32768},
+ {11168, 33792},
+ {10682, 34816},
+ {10220, 35840},
+ {9780, 36864},
+ {9361, 37888},
+ {8962, 38912},
+ {8582, 39936},
+ {8219, 40960},
+ {7874, 41984},
+ {7545, 43008},
+ {7231, 44032},
+ {6931, 45056},
+ {6646, 46080},
+ {6373, 47104},
+ {6113, 48128},
+ {5865, 49152},
+ {5628, 50176},
+ {5402, 51200},
+ {5185, 52224},
+ {4979, 53248},
+ {4782, 54272},
+ {4593, 55296},
+ {4413, 56320},
+ {4241, 57344},
+ {4076, 58368},
+ {3919, 59392},
+ {3768, 60416},
+ {3624, 61440},
+ {3486, 62464},
+ {3354, 63488},
+ {3227, 64512},
+ {3106, 65536},
+ {2990, 66560},
+ {2879, 67584},
+ {2773, 68608},
+ {2671, 69632},
+ {2573, 70656},
+ {2479, 71680},
+ {2390, 72704},
+ {2303, 73728},
+ {2221, 74752},
+ {2142, 75776},
+ {2066, 76800},
+ {1993, 77824},
+ {1923, 78848},
+ {1855, 79872},
+ {1791, 80896},
+ {1729, 81920},
+ {1669, 82944},
+ {1612, 83968},
+ {1557, 84992},
+ {1504, 86016},
+ {1453, 87040},
+ {1404, 88064},
+ {1357, 89088},
+ {1312, 90112},
+ {1269, 91136},
+ {1227, 92160},
+ {1187, 93184},
+ {1148, 94208},
+ {1111, 95232},
+ {1075, 96256},
+ {1040, 97280},
+ {1007, 98304},
+ {975, 99328},
+ {944, 100352},
+ {914, 101376},
{886, 102400},
- {859, 103424},
- {832, 104448},
- {807, 105472},
- {782, 106496},
- {756, 107520},
- {735, 108544},
+ {858, 103424},
+ {831, 104448},
+ {806, 105472},
+ {781, 106496},
+ {757, 107520},
+ {734, 108544},
{712, 109568},
- {691, 110592},
+ {690, 110592},
{670, 111616},
{650, 112640},
- {631, 113664},
+ {630, 113664},
{612, 114688},
{594, 115712},
- {577, 116736},
- {560, 117760},
- {544, 118784},
- {528, 119808},
- {513, 120832},
+ {576, 116736},
+ {559, 117760},
+ {543, 118784},
+ {527, 119808},
+ {512, 120832},
{498, 121856},
{483, 122880},
{470, 123904},
- {457, 124928},
+ {456, 124928},
{444, 125952},
{431, 126976},
- {419, 128000}
+ {419, 128000},
+ {408, 129024},
+ {396, 130048}
};
static int32_t pm8xxx_adc_map_linear(const struct pm8xxx_adc_map_pt *pts,
@@ -716,6 +718,10 @@
struct pm8xxx_adc_chan_result *adc_chan_result)
{
int64_t xo_thm = 0;
+ uint32_t num1 = 0;
+ uint32_t num2 = 0;
+ uint32_t dnum = 0;
+ uint32_t rt_r25 = 0;
if (!chan_properties || !chan_properties->offset_gain_numerator ||
!chan_properties->offset_gain_denominator || !adc_properties
@@ -724,10 +730,21 @@
xo_thm = pm8xxx_adc_scale_ratiometric_calib(adc_code,
adc_properties, chan_properties);
- xo_thm <<= 4;
+ if (xo_thm < 0)
+ xo_thm = -xo_thm;
+
+ num1 = xo_thm << 14;
+ num2 = (adc_properties->adc_vdd_reference - xo_thm) >> 1;
+ dnum = (adc_properties->adc_vdd_reference - xo_thm);
+
+ if (dnum == 0)
+ rt_r25 = 0x7FFFFFFF ;
+ else
+ rt_r25 = (num1 + num2)/dnum ;
+
pm8xxx_adc_map_linear(adcmap_ntcg_104ef_104fb,
ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
- xo_thm, &adc_chan_result->physical);
+ rt_r25, &adc_chan_result->physical);
return 0;
}
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index 181a97e..1a163a4 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1075,7 +1075,7 @@
return 0;
}
-DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%lld\n");
#ifdef CONFIG_DEBUG_FS
static void create_debugfs_entries(void)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index bb505d8..2e807ac 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -233,14 +233,26 @@
#define MXT_BOOT_VALUE 0xa5
#define MXT_BACKUP_VALUE 0x55
#define MXT_BACKUP_TIME 25 /* msec */
-#define MXT224_RESET_TIME 65 /* msec */
-#define MXT224E_RESET_TIME 150 /* msec */
-#define MXT1386_RESET_TIME 250 /* msec */
+
+/* Software reset delay */
+#define MXT224_RESET_TIME 64 /* msec */
+#define MXT224E_RESET_TIME 21 /* msec */
#define MXT336S_RESET_TIME 25 /* msec */
-#define MXT1664S_RESET_TIME 65 /* msec */
+#define MXT1386_RESET_TIME 250 /* msec */
+#define MXT1386E_RESET_TIME 229 /* msec */
+#define MXT1664S_RESET_TIME 280 /* msec */
#define MXT_RESET_TIME 250 /* msec */
#define MXT_RESET_NOCHGREAD 400 /* msec */
+/* Power on delay */
+#define MXT224_POWER_ON_TIME 40 /* msec */
+#define MXT224E_POWER_ON_TIME 21 /* msec */
+#define MXT336S_POWER_ON_TIME 25 /* msec */
+#define MXT1386_POWER_ON_TIME 90 /* msec */
+#define MXT1386E_POWER_ON_TIME 81 /* msec */
+#define MXT1664S_POWER_ON_TIME 65 /* msec */
+#define MXT_POWER_ON_TIME 100 /* msec */
+
#define MXT_FWRESET_TIME 1000 /* msec */
#define MXT_WAKE_TIME 25
@@ -1291,6 +1303,42 @@
return 0;
}
+static void mxt_power_on_delay(struct mxt_data *data)
+{
+ const struct mxt_platform_data *pdata = data->pdata;
+ const struct mxt_config_info *cfg_info;
+ u32 delay = 0;
+ int i;
+
+ for (i = 0; i < pdata->config_array_size; i++) {
+ cfg_info = &pdata->config_array[i];
+
+ switch (cfg_info->family_id) {
+ case MXT224_ID:
+ delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
+ break;
+ case MXT224E_ID:
+ delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
+ break;
+ case MXT336S_ID:
+ delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
+ break;
+ case MXT1386_ID:
+ delay = max_t(u32, delay,
+ max_t(u32, MXT1386_POWER_ON_TIME,
+ MXT1386E_POWER_ON_TIME));
+ break;
+ case MXT1664S_ID:
+ delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
+ break;
+ default:
+ delay = max_t(u32, delay, MXT_POWER_ON_TIME);
+ }
+ }
+
+ msleep(delay);
+}
+
static void mxt_reset_delay(struct mxt_data *data)
{
struct mxt_info *info = &data->info;
@@ -1304,8 +1352,10 @@
break;
case MXT336S_ID:
msleep(MXT336S_RESET_TIME);
+ break;
case MXT1386_ID:
- msleep(MXT1386_RESET_TIME);
+ msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
+ break;
case MXT1664S_ID:
msleep(MXT1664S_RESET_TIME);
break;
@@ -2715,10 +2765,12 @@
}
}
- mxt_reset_delay(data);
+ mxt_power_on_delay(data);
+
error = mxt_initialize(data);
if (error)
goto err_reset_gpio_req;
+
error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
pdata->irqflags, client->dev.driver->name, data);
if (error) {
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
index 6eba5d1..6c4e6b7 100644
--- a/drivers/input/touchscreen/cyttsp-i2c-qc.c
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -2881,17 +2881,17 @@
cyttsp_debug("Wake Up\n");
- if (ts->is_suspended == false) {
- pr_err("%s: in wakeup state\n", __func__);
- return 0;
- }
-
if (device_may_wakeup(dev)) {
if (ts->client->irq)
disable_irq_wake(ts->client->irq);
return 0;
}
+ if (ts->is_suspended == false) {
+ pr_err("%s: in wakeup state\n", __func__);
+ return 0;
+ }
+
/* re-enable the interrupt prior to wake device */
if (ts->client->irq)
enable_irq(ts->client->irq);
@@ -2952,6 +2952,12 @@
cyttsp_debug("Enter Sleep\n");
+ if (device_may_wakeup(dev)) {
+ if (ts->client->irq)
+ enable_irq_wake(ts->client->irq);
+ return 0;
+ }
+
if (ts->is_suspended == true) {
pr_err("%s: in sleep state\n", __func__);
return 0;
@@ -2966,11 +2972,6 @@
}
mutex_unlock(&ts->mutex);
- if (device_may_wakeup(dev)) {
- if (ts->client->irq)
- enable_irq_wake(ts->client->irq);
- return 0;
- }
if (ts->client->irq == 0)
del_timer(&ts->timer);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 9b66b05..82b6aa0 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -4,7 +4,7 @@
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@@ -2255,6 +2255,7 @@
spin_lock_irq(&dmxdevfilter->dev->lock);
dvb_dmxdev_flush_output(&dmxdevfilter->buffer, &dmxdevfilter->events);
+ dvb_ringbuffer_reset(&dmxdevfilter->buffer);
spin_unlock_irq(&dmxdevfilter->dev->lock);
wake_up_all(&dmxdevfilter->buffer.queue);
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 642074f..5760fba 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -132,23 +132,25 @@
inline void vc_isr_error_checking(struct vcap_dev *dev,
struct v4l2_event v4l2_evt, uint32_t irq)
{
- if (irq & 0x8000200) {
- writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_PIX_ERR_EVENT;
- v4l2_event_queue(dev->vfd, &v4l2_evt);
- }
- if (irq & 0x40000200) {
- writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_LINE_ERR_EVENT;
- v4l2_event_queue(dev->vfd, &v4l2_evt);
- }
- if (irq & 0x20000200) {
- writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- VCAP_VC_VSYNC_ERR_EVENT;
- v4l2_event_queue(dev->vfd, &v4l2_evt);
+ if (irq & 0x200) {
+ if (irq & 0x80000000) {
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_PIX_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x40000000) {
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_LINE_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x20000000) {
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_VSYNC_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
}
if (irq & 0x00001000) {
writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index d4ff38b..563a013 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@
#include <linux/slab.h> /* kfree, kzalloc */
#include <linux/ioport.h> /* XXX_ mem_region */
#include <linux/dma-mapping.h> /* dma_XXX */
+#include <linux/dmapool.h> /* DMA pools */
#include <linux/delay.h> /* msleep */
#include <linux/platform_device.h>
#include <linux/clk.h>
@@ -65,6 +66,14 @@
#define TSPP_MAX_BUFFER_SIZE (32 * 1024 - 1)
/*
+ * Returns whether to use DMA pool for TSPP output buffers.
+ * For buffers smaller than page size, using DMA pool
+ * provides better memory utilization as dma_alloc_coherent
+ * allocates minimum of page size.
+ */
+#define TSPP_USE_DMA_POOL(buff_size) ((buff_size) < PAGE_SIZE)
+
+/*
* Max allowed TSPP buffers/descriptors.
* If SPS desc FIFO holds X descriptors, we can queue up to X-1 descriptors.
*/
@@ -398,6 +407,7 @@
void *notify_data; /* data to be passed with the notifier */
u32 expiration_period_ms; /* notification on partially filled buffers */
struct timer_list expiration_timer;
+ struct dma_pool *dma_pool;
tspp_memfree *memfree; /* user defined memory free function */
void *user_info; /* user cookie passed to memory alloc/free function */
};
@@ -898,7 +908,7 @@
}
static int tspp_alloc_buffer(u32 channel_id, struct tspp_data_descriptor *desc,
- u32 size, tspp_allocator *alloc, void *user)
+ u32 size, struct dma_pool *dma_pool, tspp_allocator *alloc, void *user)
{
if (size < TSPP_MIN_BUFFER_SIZE ||
size > TSPP_MAX_BUFFER_SIZE) {
@@ -911,10 +921,15 @@
desc->virt_base = alloc(channel_id, size,
&desc->phys_base, user);
} else {
- desc->virt_base = dma_alloc_coherent(NULL, size,
- &desc->phys_base, GFP_KERNEL);
+ if (!dma_pool)
+ desc->virt_base = dma_alloc_coherent(NULL, size,
+ &desc->phys_base, GFP_KERNEL);
+ else
+ desc->virt_base = dma_pool_alloc(dma_pool, GFP_KERNEL,
+ &desc->phys_base);
+
if (desc->virt_base == 0) {
- pr_err("tspp dma alloc coherent failed %i", size);
+ pr_err("tspp: dma buffer allocation failed %i\n", size);
return -ENOMEM;
}
}
@@ -1225,10 +1240,15 @@
pbuf->desc.phys_base,
channel->user_info);
} else {
- dma_free_coherent(NULL,
- pbuf->desc.size,
- pbuf->desc.virt_base,
- pbuf->desc.phys_base);
+ if (!channel->dma_pool)
+ dma_free_coherent(NULL,
+ pbuf->desc.size,
+ pbuf->desc.virt_base,
+ pbuf->desc.phys_base);
+ else
+ dma_pool_free(channel->dma_pool,
+ pbuf->desc.virt_base,
+ pbuf->desc.phys_base);
}
pbuf->desc.phys_base = 0;
}
@@ -1568,6 +1588,10 @@
config->desc.phys_base);
tspp_destroy_buffers(channel_id, channel);
+ if (channel->dma_pool) {
+ dma_pool_destroy(channel->dma_pool);
+ channel->dma_pool = NULL;
+ }
channel->src = TSPP_SOURCE_NONE;
channel->mode = TSPP_MODE_DISABLED;
@@ -1704,7 +1728,7 @@
*/
if (channel->buffer_count == 0) {
channel->buffer_size =
- tspp_align_buffer_size_by_mode(channel->buffer_size,
+ tspp_align_buffer_size_by_mode(channel->buffer_size,
channel->mode);
rc = tspp_allocate_buffers(dev, channel->id,
channel->max_buffers,
@@ -2072,6 +2096,7 @@
}
channel = &pdev->channels[channel_id];
+
/* allow buffer allocation only if there was no previous buffer
* allocation for this channel.
*/
@@ -2101,6 +2126,22 @@
channel->memfree = memfree;
channel->user_info = user;
+ /*
+ * For small buffers, create a DMA pool so that memory
+ * is not wasted through dma_alloc_coherent.
+ */
+ if (TSPP_USE_DMA_POOL(channel->buffer_size)) {
+ channel->dma_pool = dma_pool_create("tspp",
+ NULL, channel->buffer_size, 0, 0);
+ if (!channel->dma_pool) {
+ pr_err("%s: Can't allocate memory pool\n", __func__);
+ return -ENOMEM;
+ }
+ } else {
+ channel->dma_pool = NULL;
+ }
+
+
for (channel->buffer_count = 0;
channel->buffer_count < channel->max_buffers;
channel->buffer_count++) {
@@ -2117,7 +2158,8 @@
desc->desc.id = channel->buffer_count;
/* allocate the buffer */
if (tspp_alloc_buffer(channel_id, &desc->desc,
- channel->buffer_size, alloc, user) != 0) {
+ channel->buffer_size, channel->dma_pool,
+ alloc, user) != 0) {
kfree(desc);
pr_warn("%s: Can't allocate buffer %i",
__func__, channel->buffer_count);
@@ -2154,6 +2196,11 @@
*/
tspp_destroy_buffers(channel_id, channel);
channel->buffer_count = 0;
+
+ if (channel->dma_pool) {
+ dma_pool_destroy(channel->dma_pool);
+ channel->dma_pool = NULL;
+ }
return -ENOMEM;
}
@@ -2292,8 +2339,10 @@
*/
if (buffer->read_index == buffer->filled) {
buffer->state = TSPP_BUF_STATE_WAITING;
+
if (tspp_queue_buffer(channel, buffer))
pr_err("tspp: can't submit transfer");
+
channel->locked = channel->read;
channel->read = channel->read->next;
}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 0f4cc6d..0f9ee46d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -121,7 +121,8 @@
struct device_attribute force_ro;
struct device_attribute power_ro_lock;
struct device_attribute num_wr_reqs_to_start_packing;
- struct device_attribute min_sectors_to_check_bkops_status;
+ struct device_attribute bkops_check_threshold;
+ struct device_attribute no_pack_for_random;
int area_type;
};
@@ -331,6 +332,114 @@
return ret;
}
+static ssize_t
+bkops_check_threshold_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+ struct mmc_card *card = md->queue.card;
+ int ret;
+
+ if (!card)
+ ret = -EINVAL;
+ else
+ ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ card->bkops_info.size_percentage_to_queue_delayed_work);
+
+ mmc_blk_put(md);
+ return ret;
+}
+
+static ssize_t
+bkops_check_threshold_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+ struct mmc_card *card = md->queue.card;
+ unsigned int card_size;
+ int ret = count;
+
+ if (!card) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ sscanf(buf, "%d", &value);
+ if ((value <= 0) || (value >= 100)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ card_size = (unsigned int)get_capacity(md->disk);
+ if (card_size <= 0) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ card->bkops_info.size_percentage_to_queue_delayed_work = value;
+ card->bkops_info.min_sectors_to_queue_delayed_work =
+ (card_size * value) / 100;
+
+ pr_debug("%s: size_percentage = %d, min_sectors = %d",
+ mmc_hostname(card->host),
+ card->bkops_info.size_percentage_to_queue_delayed_work,
+ card->bkops_info.min_sectors_to_queue_delayed_work);
+
+exit:
+ mmc_blk_put(md);
+ return count;
+}
+
+static ssize_t
+no_pack_for_random_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", md->queue.no_pack_for_random);
+
+ mmc_blk_put(md);
+ return ret;
+}
+
+static ssize_t
+no_pack_for_random_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+ struct mmc_card *card = md->queue.card;
+ int ret = count;
+
+ if (!card) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ sscanf(buf, "%d", &value);
+
+ if (value < 0) {
+ pr_err("%s: value %d is not valid. old value remains = %d",
+ mmc_hostname(card->host), value,
+ md->queue.no_pack_for_random);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ md->queue.no_pack_for_random = (value > 0) ? true : false;
+
+ pr_debug("%s: no_pack_for_random: new value = %d",
+ mmc_hostname(card->host),
+ md->queue.no_pack_for_random);
+
+exit:
+ mmc_blk_put(md);
+ return ret;
+}
+
static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -958,6 +1067,9 @@
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
+ if (card->ext_csd.bkops_en)
+ card->bkops_info.sectors_changed += blk_rq_sectors(req);
+
if (mmc_can_discard(card))
arg = MMC_DISCARD_ARG;
else if (mmc_can_trim(card))
@@ -1657,8 +1769,21 @@
break;
}
- if (rq_data_dir(next) == WRITE)
+ if (mq->no_pack_for_random) {
+ if ((blk_rq_pos(cur) + blk_rq_sectors(cur)) !=
+ blk_rq_pos(next)) {
+ MMC_BLK_UPDATE_STOP_REASON(stats, RANDOM);
+ put_back = 1;
+ break;
+ }
+ }
+
+ if (rq_data_dir(next) == WRITE) {
mq->num_of_potential_packed_wr_reqs++;
+ if (card->ext_csd.bkops_en)
+ card->bkops_info.sectors_changed +=
+ blk_rq_sectors(next);
+ }
list_add_tail(&next->queuelist, &mq->mqrq_cur->packed_list);
cur = next;
reqs++;
@@ -1891,6 +2016,8 @@
return 0;
if (rqc) {
+ if ((card->ext_csd.bkops_en) && (rq_data_dir(rqc) == WRITE))
+ card->bkops_info.sectors_changed += blk_rq_sectors(rqc);
reqs = mmc_blk_prep_packed_list(mq, rqc);
}
@@ -1922,8 +2049,6 @@
mmc_queue_bounce_post(mq_rq);
switch (status) {
- case MMC_BLK_NEW_REQUEST:
- BUG(); /* should never get here */
case MMC_BLK_SUCCESS:
case MMC_BLK_PARTIAL:
/*
@@ -1996,6 +2121,11 @@
break;
case MMC_BLK_NOMEDIUM:
goto cmd_abort;
+ default:
+ pr_err("%s:%s: Unhandled return value (%d)",
+ req->rq_disk->disk_name,
+ __func__, status);
+ goto cmd_abort;
}
if (ret) {
@@ -2051,6 +2181,8 @@
int ret;
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
+ struct mmc_host *host = card->host;
+ unsigned long flags;
#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
if (mmc_bus_needs_resume(card->host)) {
@@ -2062,11 +2194,8 @@
if (req && !mq->mqrq_prev->req) {
/* claim host only for the first request */
mmc_claim_host(card->host);
- if (card->ext_csd.bkops_en &&
- card->bkops_info.started_delayed_bkops) {
- card->bkops_info.started_delayed_bkops = false;
+ if (card->ext_csd.bkops_en)
mmc_stop_bkops(card);
- }
}
ret = mmc_blk_part_switch(card, md);
@@ -2101,13 +2230,21 @@
mmc_blk_issue_rw_rq(mq, NULL);
ret = mmc_blk_issue_flush(mq, req);
} else {
+ if (!req && host->areq) {
+ spin_lock_irqsave(&host->context_info.lock, flags);
+ host->context_info.is_waiting_last_req = true;
+ spin_unlock_irqrestore(&host->context_info.lock, flags);
+ }
ret = mmc_blk_issue_rw_rq(mq, req);
}
out:
- if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST))
+ if (!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) {
+ if (mmc_card_need_bkops(card))
+ mmc_start_bkops(card, false);
/* release host only when there are no more requests */
mmc_release_host(card->host);
+ }
return ret;
}
@@ -2126,6 +2263,8 @@
{
struct mmc_blk_data *md;
int devidx, ret;
+ unsigned int percentage =
+ BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK;
devidx = find_first_zero_bit(dev_use, max_devices);
if (devidx >= max_devices)
@@ -2205,6 +2344,10 @@
blk_queue_logical_block_size(md->queue.queue, 512);
set_capacity(md->disk, size);
+ card->bkops_info.size_percentage_to_queue_delayed_work = percentage;
+ card->bkops_info.min_sectors_to_queue_delayed_work =
+ ((unsigned int)size * percentage) / 100;
+
if (mmc_host_cmd23(card->host)) {
if (mmc_card_mmc(card) ||
(mmc_card_sd(card) &&
@@ -2397,8 +2540,34 @@
if (ret)
goto num_wr_reqs_to_start_packing_fail;
+ md->bkops_check_threshold.show = bkops_check_threshold_show;
+ md->bkops_check_threshold.store = bkops_check_threshold_store;
+ sysfs_attr_init(&md->bkops_check_threshold.attr);
+ md->bkops_check_threshold.attr.name = "bkops_check_threshold";
+ md->bkops_check_threshold.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(disk_to_dev(md->disk),
+ &md->bkops_check_threshold);
+ if (ret)
+ goto bkops_check_threshold_fails;
+
+ md->no_pack_for_random.show = no_pack_for_random_show;
+ md->no_pack_for_random.store = no_pack_for_random_store;
+ sysfs_attr_init(&md->no_pack_for_random.attr);
+ md->no_pack_for_random.attr.name = "no_pack_for_random";
+ md->no_pack_for_random.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(disk_to_dev(md->disk),
+ &md->no_pack_for_random);
+ if (ret)
+ goto no_pack_for_random_fails;
+
return ret;
+no_pack_for_random_fails:
+ device_remove_file(disk_to_dev(md->disk),
+ &md->bkops_check_threshold);
+bkops_check_threshold_fails:
+ device_remove_file(disk_to_dev(md->disk),
+ &md->num_wr_reqs_to_start_packing);
num_wr_reqs_to_start_packing_fail:
device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock);
power_ro_lock_fail:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 5d571a5..4a21fd4 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -1893,6 +1893,8 @@
case BKOPS_DELAYED_WORK_LEVEL_1:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
+ card->bkops_info.sectors_changed =
+ card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
@@ -1909,6 +1911,8 @@
case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
+ card->bkops_info.sectors_changed =
+ card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
@@ -1937,6 +1941,8 @@
case BKOPS_CANCEL_DELAYED_WORK:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
+ card->bkops_info.sectors_changed =
+ card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dc27db6..9babeab 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -78,14 +78,6 @@
set_current_state(TASK_INTERRUPTIBLE);
req = blk_fetch_request(q);
mq->mqrq_cur->req = req;
- if (!req && mq->mqrq_prev->req &&
- !(mq->mqrq_prev->req->cmd_flags & REQ_SANITIZE) &&
- !(mq->mqrq_prev->req->cmd_flags & REQ_FLUSH) &&
- !(mq->mqrq_prev->req->cmd_flags & REQ_DISCARD)) {
- card->host->context_info.is_waiting_last_req = true;
- if (stats && stats->enabled)
- stats->null_fetched++;
- }
spin_unlock_irq(q->queue_lock);
if (req || mq->mqrq_prev->req) {
@@ -97,6 +89,16 @@
stats->fetch_due_to_new_req++;
continue; /* fetch again */
}
+
+ /*
+ * Current request becomes previous request
+ * and vice versa.
+ */
+ mq->mqrq_prev->brq.mrq.data = NULL;
+ mq->mqrq_prev->req = NULL;
+ tmp = mq->mqrq_prev;
+ mq->mqrq_prev = mq->mqrq_cur;
+ mq->mqrq_cur = tmp;
} else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
@@ -107,13 +109,6 @@
schedule();
down(&mq->thread_sem);
}
-
- /* Current request becomes previous request and vice versa. */
- mq->mqrq_prev->brq.mrq.data = NULL;
- mq->mqrq_prev->req = NULL;
- tmp = mq->mqrq_prev;
- mq->mqrq_prev = mq->mqrq_cur;
- mq->mqrq_cur = tmp;
} while (1);
up(&mq->thread_sem);
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 0a72372..119b0c7 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -51,6 +51,7 @@
bool wr_packing_enabled;
int num_of_potential_packed_wr_reqs;
int num_wr_reqs_to_start_packing;
+ bool no_pack_for_random;
int (*err_check_fn) (struct mmc_card *, struct mmc_async_req *);
void (*packed_test_fn) (struct request_queue *, struct mmc_queue_req *);
};
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f598e63..65f748f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -357,6 +357,10 @@
if (!card || !card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
return;
+ if (card->bkops_info.sectors_changed <
+ card->bkops_info.min_sectors_to_queue_delayed_work)
+ return;
+
pr_debug("%s: %s: queueing delayed_bkops_work\n",
mmc_hostname(card->host), __func__);
@@ -366,7 +370,6 @@
* it was removed from the queue work but not started yet
*/
card->bkops_info.cancel_delayed_work = false;
- card->bkops_info.started_delayed_bkops = true;
queue_delayed_work(system_nrt_wq, &card->bkops_info.dw,
msecs_to_jiffies(
card->bkops_info.delay_ms));
@@ -386,8 +389,6 @@
void mmc_start_bkops(struct mmc_card *card, bool from_exception)
{
int err;
- int timeout;
- bool use_busy_signal;
BUG_ON(!card);
if (!card->ext_csd.bkops_en)
@@ -408,43 +409,45 @@
goto out;
}
- err = mmc_read_bkops_status(card);
- if (err) {
- pr_err("%s: %s: Failed to read bkops status: %d\n",
- mmc_hostname(card->host), __func__, err);
+ if (from_exception && mmc_card_need_bkops(card))
goto out;
- }
-
- if (!card->ext_csd.raw_bkops_status)
- goto out;
-
- pr_info("%s: %s: card->ext_csd.raw_bkops_status = 0x%x\n",
- mmc_hostname(card->host), __func__,
- card->ext_csd.raw_bkops_status);
/*
- * If the function was called due to exception but there is no need
- * for urgent BKOPS, BKOPs will be performed by the delayed BKOPs
- * work, before going to suspend
+ * If the need BKOPS flag is set, there is no need to check if BKOPS
+ * is needed since we already know that it does
*/
- if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2 &&
- from_exception) {
- pr_debug("%s: %s: Level 1 from exception, exit",
- mmc_hostname(card->host), __func__);
+ if (!mmc_card_need_bkops(card)) {
+ err = mmc_read_bkops_status(card);
+ if (err) {
+ pr_err("%s: %s: Failed to read bkops status: %d\n",
+ mmc_hostname(card->host), __func__, err);
+ goto out;
+ }
+
+ if (!card->ext_csd.raw_bkops_status)
+ goto out;
+
+ pr_info("%s: %s: raw_bkops_status=0x%x, from_exception=%d\n",
+ mmc_hostname(card->host), __func__,
+ card->ext_csd.raw_bkops_status,
+ from_exception);
+ }
+
+ /*
+ * If the function was called due to exception, BKOPS will be performed
+ * after handling the last pending request
+ */
+ if (from_exception) {
+ pr_debug("%s: %s: Level %d from exception, exit",
+ mmc_hostname(card->host), __func__,
+ card->ext_csd.raw_bkops_status);
+ mmc_card_set_need_bkops(card);
goto out;
}
-
- if (card->ext_csd.raw_bkops_status >= EXT_CSD_BKOPS_LEVEL_2) {
- timeout = MMC_BKOPS_MAX_TIMEOUT;
- use_busy_signal = true;
- } else {
- timeout = 0;
- use_busy_signal = false;
- }
+ pr_info("%s: %s: Starting bkops\n", mmc_hostname(card->host), __func__);
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BKOPS_START, 1, timeout,
- use_busy_signal, use_busy_signal);
+ EXT_CSD_BKOPS_START, 1, 0, false, false);
if (err) {
pr_warn("%s: %s: Error %d when starting bkops\n",
mmc_hostname(card->host), __func__, err);
@@ -452,19 +455,13 @@
}
MMC_UPDATE_STATS_BKOPS_SEVERITY_LEVEL(card->bkops_info.bkops_stats,
card->ext_csd.raw_bkops_status);
+ mmc_card_clr_need_bkops(card);
- /*
- * For urgent bkops status (LEVEL_2 and more)
- * bkops executed synchronously, otherwise
- * the operation is in progress
- */
- if (!use_busy_signal) {
- mmc_card_set_doing_bkops(card);
- pr_debug("%s: %s: starting the polling thread\n",
- mmc_hostname(card->host), __func__);
- queue_work(system_nrt_wq,
- &card->bkops_info.poll_for_completion);
- }
+ mmc_card_set_doing_bkops(card);
+ pr_debug("%s: %s: starting the polling thread\n",
+ mmc_hostname(card->host), __func__);
+ queue_work(system_nrt_wq,
+ &card->bkops_info.poll_for_completion);
out:
mmc_release_host(card->host);
@@ -518,7 +515,7 @@
pr_debug("%s: %s: completed BKOPs, exit polling\n",
mmc_hostname(card->host), __func__);
mmc_card_clr_doing_bkops(card);
- card->bkops_info.started_delayed_bkops = false;
+ card->bkops_info.sectors_changed = 0;
goto out;
}
@@ -531,8 +528,12 @@
msleep(BKOPS_COMPLETION_POLLING_INTERVAL_MS);
} while (time_before(jiffies, timeout_jiffies));
- pr_err("%s: %s: exit polling due to timeout\n",
+ pr_err("%s: %s: exit polling due to timeout, stop bkops\n",
mmc_hostname(card->host), __func__);
+ err = mmc_stop_bkops(card);
+ if (err)
+ pr_err("%s: %s: mmc_stop_bkops failed, err=%d\n",
+ mmc_hostname(card->host), __func__, err);
return;
out:
@@ -622,7 +623,8 @@
* Returns enum mmc_blk_status after checking errors.
*/
static int mmc_wait_for_data_req_done(struct mmc_host *host,
- struct mmc_request *mrq)
+ struct mmc_request *mrq,
+ struct mmc_async_req *next_req)
{
struct mmc_command *cmd;
struct mmc_context_info *context_info = &host->context_info;
@@ -664,8 +666,10 @@
context_info->is_new_req = false;
if (stats->enabled)
stats->new_request_flag++;
- err = MMC_BLK_NEW_REQUEST;
- break; /* return err */
+ if (!next_req) {
+ err = MMC_BLK_NEW_REQUEST;
+ break; /* return err */
+ }
}
} /* while */
return err;
@@ -778,13 +782,9 @@
mmc_pre_req(host, areq->mrq, !host->areq);
if (host->areq) {
- err = mmc_wait_for_data_req_done(host, host->areq->mrq);
+ err = mmc_wait_for_data_req_done(host, host->areq->mrq,
+ areq);
if (err == MMC_BLK_NEW_REQUEST) {
- if (areq) {
- pr_err("%s: new request while areq = %p",
- mmc_hostname(host), areq);
- BUG_ON(1);
- }
if (error)
*error = err;
/*
@@ -936,7 +936,9 @@
* Send HPI command to stop ongoing background operations to
* allow rapid servicing of foreground operations, e.g. read/
* writes. Wait until the card comes out of the programming state
- * to avoid errors in servicing read/write requests.
+ * to avoid errors in servicing read/write requests.
+ *
+ * The function should be called with host claimed.
*/
int mmc_stop_bkops(struct mmc_card *card)
{
@@ -3061,6 +3063,7 @@
* Turn the cache ON/OFF.
* Turning the cache OFF shall trigger flushing of the data
* to the non-volatile storage.
+ * This function should be called with host claimed
*/
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
@@ -3072,9 +3075,6 @@
mmc_card_is_removable(host))
return err;
- if (!mmc_try_claim_host(host))
- return -EBUSY;
-
if (card && mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
@@ -3092,7 +3092,6 @@
card->ext_csd.cache_ctrl = enable;
}
}
- mmc_release_host(host);
return err;
}
@@ -3114,9 +3113,6 @@
if (cancel_delayed_work(&host->detect))
wake_unlock(&host->detect_wake_lock);
mmc_flush_scheduled_work();
- err = mmc_cache_ctrl(host, 0);
- if (err)
- goto out;
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
@@ -3174,7 +3170,6 @@
if (!err && !mmc_card_keep_power(host))
mmc_power_off(host);
-out:
return err;
stop_bkops_err:
if (!(host->card && mmc_card_sdio(host->card)))
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index ae8a619..d91bc31 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -484,6 +484,13 @@
pack_stats->pack_stop_reason[LARGE_SEC_ALIGN]);
strlcat(ubuf, temp_buf, cnt);
}
+ if (pack_stats->pack_stop_reason[RANDOM]) {
+ snprintf(temp_buf, TEMP_BUF_SIZE,
+ "%s: %d times: random request\n",
+ mmc_hostname(card->host),
+ pack_stats->pack_stop_reason[RANDOM]);
+ strlcat(ubuf, temp_buf, cnt);
+ }
spin_unlock(&pack_stats->lock);
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 751ba75..0cfddc4 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -33,6 +33,7 @@
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ kfree(host->wlock_name);
kfree(host);
}
@@ -337,8 +338,10 @@
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
+ host->wlock_name = kasprintf(GFP_KERNEL,
+ "%s_detect", mmc_hostname(host));
wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND,
- kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host)));
+ host->wlock_name);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
#ifdef CONFIG_PM
host->pm_notify.notifier_call = mmc_pm_notify;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index f3653b8..ec30cad 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1402,17 +1402,16 @@
/*
* Calculate the time to start the BKOPs checking.
- * The idle time of the host controller should be taken
- * into account in order to prevent a race condition
- * before starting BKOPs and going into suspend.
- * If the host controller didn't set its idle time,
+ * The host controller can set this time in order to
+ * prevent a race condition before starting BKOPs
+ * and going into suspend.
+ * If the host controller didn't set this time,
* a default value is used.
*/
card->bkops_info.delay_ms = MMC_IDLE_BKOPS_TIME_MS;
- if (card->bkops_info.host_suspend_tout_ms)
- card->bkops_info.delay_ms = min(
- card->bkops_info.delay_ms,
- card->bkops_info.host_suspend_tout_ms/2);
+ if (card->bkops_info.host_delay_ms)
+ card->bkops_info.delay_ms =
+ card->bkops_info.host_delay_ms;
}
}
@@ -1530,6 +1529,11 @@
mmc_disable_clk_scaling(host);
mmc_claim_host(host);
+
+ err = mmc_cache_ctrl(host, 0);
+ if (err)
+ goto out;
+
if (mmc_can_poweroff_notify(host->card))
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
else if (mmc_card_can_sleep(host))
@@ -1537,8 +1541,9 @@
else if (!mmc_host_is_spi(host))
mmc_deselect_cards(host);
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
- mmc_release_host(host);
+out:
+ mmc_release_host(host);
return err;
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index f1ba8ad..91720ee 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -236,14 +236,6 @@
{
int rc;
- /* Reset and init DML */
- rc = msmsdcc_dml_init(host);
- if (rc) {
- pr_err("%s: msmsdcc_dml_init error=%d\n",
- mmc_hostname(host->mmc), rc);
- goto out;
- }
-
/* Reset all SDCC BAM pipes */
rc = msmsdcc_sps_reset_ep(host, &host->sps.prod);
if (rc) {
@@ -276,13 +268,21 @@
}
rc = msmsdcc_sps_restore_ep(host, &host->sps.cons);
- if (rc)
+ if (rc) {
pr_err("%s: msmsdcc_sps_restore_ep(cons) error=%d\n",
mmc_hostname(host->mmc), rc);
- else
- host->sps.reset_bam = false;
+ goto out;
+ }
+
+ /* Reset and init DML */
+ rc = msmsdcc_dml_init(host);
+ if (rc)
+ pr_err("%s: msmsdcc_dml_init error=%d\n",
+ mmc_hostname(host->mmc), rc);
out:
+ if (!rc)
+ host->sps.reset_bam = false;
return rc;
}
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index bcb4cdb..2e858ec 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -644,7 +644,7 @@
int bam_init(void *base, u32 ee,
u16 summing_threshold,
u32 irq_mask, u32 *version,
- u32 *num_pipes, u32 p_rst)
+ u32 *num_pipes, u32 options)
{
u32 cfg_bits;
u32 ver = 0;
@@ -667,7 +667,7 @@
"use default 4.\n", (u32) base);
}
- if (p_rst)
+ if (options & SPS_BAM_NO_EXT_P_RST)
cfg_bits = 0xffffffff & ~(3 << 11);
else
cfg_bits = 0xffffffff & ~(1 << 11);
@@ -681,7 +681,10 @@
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
bam_write_reg_field(base, CTRL, CACHE_MISS_ERR_RESP_EN, 0);
- bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
+ if (options & SPS_BAM_NO_LOCAL_CLK_GATING)
+ bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 0);
+ else
+ bam_write_reg_field(base, CTRL, LOCAL_CLK_GATING, 1);
#endif
bam_write_reg(base, DESC_CNT_TRSHLD, summing_threshold);
@@ -842,21 +845,9 @@
static void bam_output_register_content(void *base)
{
u32 num_pipes;
- u32 test_bus_selection[] = {0x1, 0x2, 0x3, 0x4, 0xD, 0x10,
- 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
u32 i;
- u32 size = sizeof(test_bus_selection) / sizeof(u32);
- for (i = 0; i < size; i++) {
- bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL,
- test_bus_selection[i]);
-
- SPS_INFO("sps:bam 0x%x(va);BAM_TEST_BUS_REG is"
- "0x%x when BAM_TEST_BUS_SEL is 0x%x.",
- (u32) base, bam_read_reg(base, TEST_BUS_REG),
- bam_read_reg_field(base, TEST_BUS_SEL,
- BAM_TESTBUS_SEL));
- }
+ print_bam_test_bus_reg(base, 0);
print_bam_reg(base);
@@ -1359,7 +1350,7 @@
}
/* output descriptor FIFO of a pipe */
-void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index)
+void print_bam_pipe_desc_fifo(void *virt_addr, u32 pipe_index, u32 option)
{
void *base = virt_addr;
u32 pipe = pipe_index;
@@ -1393,33 +1384,93 @@
desc_fifo = (u32 *) phys_to_virt(desc_fifo_addr);
- SPS_INFO("-------------------- begin of FIFO --------------------\n");
+ if (option == 100) {
+ SPS_INFO("----- start of data blocks -----\n");
+ for (i = 0; i < desc_fifo_size; i += 8) {
+ u32 *data_block_vir;
+ u32 data_block_phy = desc_fifo[i / 4];
- for (i = 0; i < desc_fifo_size; i += 0x10)
- SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
- desc_fifo_addr + i,
- desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
- desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+ if (data_block_phy) {
+ data_block_vir =
+ (u32 *) phys_to_virt(data_block_phy);
- SPS_INFO("-------------------- end of FIFO --------------------\n");
+ SPS_INFO("desc addr:0x%x; data addr:0x%x:\n",
+ desc_fifo_addr + i, data_block_phy);
+ SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+ data_block_vir[0], data_block_vir[1],
+ data_block_vir[2], data_block_vir[3]);
+ SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+ data_block_vir[4], data_block_vir[5],
+ data_block_vir[6], data_block_vir[7]);
+ SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n",
+ data_block_vir[8], data_block_vir[9],
+ data_block_vir[10], data_block_vir[11]);
+ SPS_INFO("0x%x, 0x%x, 0x%x, 0x%x\n\n",
+ data_block_vir[12], data_block_vir[13],
+ data_block_vir[14], data_block_vir[15]);
+ }
+ }
+ SPS_INFO("----- end of data blocks -----\n");
+ } else if (option) {
+ u32 size = option * 128;
+ u32 current_desc = bam_pipe_get_desc_read_offset(base,
+ pipe_index);
+ u32 begin = 0;
+ u32 end = desc_fifo_size;
+
+ if (current_desc > size / 2)
+ begin = current_desc - size / 2;
+
+ if (desc_fifo_size > current_desc + size / 2)
+ end = current_desc + size / 2;
+
+ SPS_INFO("------------- begin of partial FIFO -------------\n");
+
+ for (i = begin; i < end; i += 0x10)
+ SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+ desc_fifo_addr + i,
+ desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
+ desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+
+ SPS_INFO("------------- end of partial FIFO -------------\n");
+ } else {
+ SPS_INFO("----------------- begin of FIFO -----------------\n");
+
+ for (i = 0; i < desc_fifo_size; i += 0x10)
+ SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+ desc_fifo_addr + i,
+ desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
+ desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+
+ SPS_INFO("----------------- end of FIFO -----------------\n");
+ }
}
/* output BAM_TEST_BUS_REG with specified TEST_BUS_SEL */
void print_bam_test_bus_reg(void *base, u32 tb_sel)
{
u32 i;
- u32 test_bus_selection[] = {0x1, 0x2, 0x3, 0x4, 0xD, 0x10,
+ u32 test_bus_selection[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x20, 0x21, 0x22, 0x23,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
u32 size = sizeof(test_bus_selection) / sizeof(u32);
- if ((base == NULL) || (tb_sel == 0))
+ if (base == NULL) {
+ SPS_ERR("sps:%s:BAM is NULL.\n", __func__);
return;
+ }
- SPS_INFO("\nsps:Specified TEST_BUS_SEL value: 0x%x\n", tb_sel);
- bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL, tb_sel);
- SPS_INFO("sps:BAM_TEST_BUS_REG: 0x%x when TEST_BUS_SEL: 0x%x\n\n",
- bam_read_reg(base, TEST_BUS_REG),
- bam_read_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL));
+ if (tb_sel) {
+ SPS_INFO("\nsps:Specified TEST_BUS_SEL value: 0x%x\n", tb_sel);
+ bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL,
+ tb_sel);
+ SPS_INFO("sps:BAM_TEST_BUS_REG:0x%x for TEST_BUS_SEL:0x%x\n\n",
+ bam_read_reg(base, TEST_BUS_REG),
+ bam_read_reg_field(base, TEST_BUS_SEL,
+ BAM_TESTBUS_SEL));
+ }
/* output other selections */
for (i = 0; i < size; i++) {
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index c183fcd..86808d9 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.h
@@ -102,7 +102,7 @@
*
* @num_pipes - return number of pipes
*
- * @p_rst - ignore external block pipe reset
+ * @options - BAM configuration options
*
* @return 0 on success, negative value on error
*
@@ -111,7 +111,7 @@
u32 ee,
u16 summing_threshold,
u32 irq_mask, u32 *version,
- u32 *num_pipes, u32 p_rst);
+ u32 *num_pipes, u32 options);
/**
* Initialize BAM device security execution environment
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index e9c3371..ae61f1b 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -91,7 +91,7 @@
u8 reg_dump_option;
u32 testbus_sel;
u32 bam_pipe_sel;
-
+u32 desc_option;
static char *debugfs_buf;
static u32 debugfs_buf_size;
@@ -106,6 +106,7 @@
struct dentry *dfile_reg_dump_option;
struct dentry *dfile_testbus_sel;
struct dentry *dfile_bam_pipe_sel;
+struct dentry *dfile_desc_option;
struct dentry *dfile_bam_addr;
static struct sps_bam *phy2bam(u32 phys_addr);
@@ -341,41 +342,187 @@
break;
case 7: /* output desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++)
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
break;
case 8: /* output desc FIFO of selected pipes */
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i))
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
break;
case 9: /* output desc FIFO of typical pipes */
- print_bam_pipe_desc_fifo(vir_addr, 4);
- print_bam_pipe_desc_fifo(vir_addr, 5);
+ print_bam_pipe_desc_fifo(vir_addr, 4, 0);
+ print_bam_pipe_desc_fifo(vir_addr, 5, 0);
break;
case 10: /* output selected registers and desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++) {
print_bam_pipe_selected_reg(vir_addr, i);
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
break;
case 11: /* output selected registers and desc FIFO of selected pipes */
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i)) {
print_bam_pipe_selected_reg(vir_addr, i);
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
break;
case 12: /* output selected registers and desc FIFO of typical pipes */
print_bam_pipe_selected_reg(vir_addr, 4);
- print_bam_pipe_desc_fifo(vir_addr, 4);
+ print_bam_pipe_desc_fifo(vir_addr, 4, 0);
print_bam_pipe_selected_reg(vir_addr, 5);
- print_bam_pipe_desc_fifo(vir_addr, 5);
+ print_bam_pipe_desc_fifo(vir_addr, 5, 0);
break;
case 13: /* output BAM_TEST_BUS_REG */
if (testbus_sel)
print_bam_test_bus_reg(vir_addr, testbus_sel);
- else
- pr_info("sps:TEST_BUS_SEL should NOT be zero.");
+ else {
+ pr_info("sps:output TEST_BUS_REG for all TEST_BUS_SEL");
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ }
+ break;
+ case 14: /* output partial desc FIFO of selected pipes */
+ if (desc_option == 0)
+ desc_option = 1;
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_option);
+ break;
+ case 15: /* output partial data blocks of descriptors */
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ break;
+ case 16: /* output all registers of selected pipes */
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ break;
+ case 91: /* output testbus register, BAM global regisers
+ and registers of all pipes */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_selected_reg(vir_addr, i);
+ break;
+ case 92: /* output testbus register, BAM global regisers
+ and registers of selected pipes */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ break;
+ case 93: /* output registers and partial desc FIFOs
+ of selected pipes: format 1 */
+ if (desc_option == 0)
+ desc_option = 1;
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_option);
+ break;
+ case 94: /* output registers and partial desc FIFOs
+ of selected pipes: format 2 */
+ if (desc_option == 0)
+ desc_option = 1;
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_option);
+ }
+ break;
+ case 95: /* output registers and desc FIFOs
+ of selected pipes: format 1 */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ break;
+ case 96: /* output registers and desc FIFOs
+ of selected pipes: format 2 */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ }
+ break;
+ case 97: /* output registers, desc FIFOs and partial data blocks
+ of selected pipes: format 1 */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ break;
+ case 98: /* output registers, desc FIFOs and partial data blocks
+ of selected pipes: format 2 */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ }
+ break;
+ case 99: /* output all registers, desc FIFOs and partial data blocks */
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
break;
default:
pr_info("sps:no dump option is chosen yet.");
@@ -397,6 +544,7 @@
reg_dump_option = 0;
testbus_sel = 0;
bam_pipe_sel = 0;
+ desc_option = 0;
debugfs_buf_size = 0;
debugfs_buf_used = 0;
wraparound = false;
@@ -460,6 +608,13 @@
goto bam_pipe_sel_err;
}
+ dfile_desc_option = debugfs_create_u32("desc_option", 0666,
+ dent, &desc_option);
+ if (!dfile_desc_option || IS_ERR(dfile_desc_option)) {
+ pr_err("sps:fail to create debug_fs file for desc_option.\n");
+ goto desc_option_err;
+ }
+
dfile_bam_addr = debugfs_create_file("bam_addr", 0666,
dent, 0, &sps_bam_addr_ops);
if (!dfile_bam_addr || IS_ERR(dfile_bam_addr)) {
@@ -471,6 +626,8 @@
return;
bam_addr_err:
+ debugfs_remove(dfile_desc_option);
+desc_option_err:
debugfs_remove(dfile_bam_pipe_sel);
bam_pipe_sel_err:
debugfs_remove(dfile_testbus_sel);
@@ -504,6 +661,8 @@
debugfs_remove(dfile_testbus_sel);
if (dfile_bam_pipe_sel)
debugfs_remove(dfile_bam_pipe_sel);
+ if (dfile_desc_option)
+ debugfs_remove(dfile_desc_option);
if (dfile_bam_addr)
debugfs_remove(dfile_bam_addr);
if (dent)
@@ -515,7 +674,7 @@
/* Get the debug info of BAM registers and descriptor FIFOs */
int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
- u32 tb_sel, u8 pre_level)
+ u32 tb_sel, u8 desc_sel)
{
int res = 0;
struct sps_bam *bam;
@@ -568,35 +727,35 @@
break;
case 7: /* output desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++)
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
break;
case 8: /* output desc FIFO of selected pipes */
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i))
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
break;
case 9: /* output desc FIFO of typical pipes */
- print_bam_pipe_desc_fifo(vir_addr, 4);
- print_bam_pipe_desc_fifo(vir_addr, 5);
+ print_bam_pipe_desc_fifo(vir_addr, 4, 0);
+ print_bam_pipe_desc_fifo(vir_addr, 5, 0);
break;
case 10: /* output selected registers and desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++) {
print_bam_pipe_selected_reg(vir_addr, i);
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
break;
case 11: /* output selected registers and desc FIFO of selected pipes */
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i)) {
print_bam_pipe_selected_reg(vir_addr, i);
- print_bam_pipe_desc_fifo(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
break;
case 12: /* output selected registers and desc FIFO of typical pipes */
print_bam_pipe_selected_reg(vir_addr, 4);
- print_bam_pipe_desc_fifo(vir_addr, 4);
+ print_bam_pipe_desc_fifo(vir_addr, 4, 0);
print_bam_pipe_selected_reg(vir_addr, 5);
- print_bam_pipe_desc_fifo(vir_addr, 5);
+ print_bam_pipe_desc_fifo(vir_addr, 5, 0);
break;
case 13: /* output BAM_TEST_BUS_REG */
if (tb_sel)
@@ -604,6 +763,150 @@
else
pr_info("sps:TEST_BUS_SEL should NOT be zero.");
break;
+ case 14: /* output partial desc FIFO of selected pipes */
+ if (desc_sel == 0)
+ desc_sel = 1;
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_sel);
+ break;
+ case 15: /* output partial data blocks of descriptors */
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ break;
+ case 16: /* output all registers of selected pipes */
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ break;
+ case 91: /* output testbus register, BAM global regisers
+ and registers of all pipes */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_selected_reg(vir_addr, i);
+ break;
+ case 92: /* output testbus register, BAM global regisers
+ and registers of selected pipes */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ break;
+ case 93: /* output registers and partial desc FIFOs
+ of selected pipes: format 1 */
+ if (desc_sel == 0)
+ desc_sel = 1;
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_sel);
+ break;
+ case 94: /* output registers and partial desc FIFOs
+ of selected pipes: format 2 */
+ if (desc_sel == 0)
+ desc_sel = 1;
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i,
+ desc_sel);
+ }
+ break;
+ case 95: /* output registers and desc FIFOs
+ of selected pipes: format 1 */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ break;
+ case 96: /* output registers and desc FIFOs
+ of selected pipes: format 2 */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ }
+ break;
+ case 97: /* output registers, desc FIFOs and partial data blocks
+ of selected pipes: format 1 */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ break;
+ case 98: /* output registers, desc FIFOs and partial data blocks
+ of selected pipes: format 2 */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ if (para & (1UL << i)) {
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ }
+ break;
+ case 99: /* output all registers, desc FIFOs and partial data blocks */
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ print_bam_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_reg(vir_addr, i);
+ print_bam_selected_reg(vir_addr);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_selected_reg(vir_addr, i);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_desc_fifo(vir_addr, i, 0);
+ for (i = 0; i < num_pipes; i++)
+ print_bam_pipe_desc_fifo(vir_addr, i, 100);
+ break;
default:
pr_info("sps:no option is chosen yet.");
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index af421ac..a1ff7cb 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -255,7 +255,7 @@
(u16) dev->props.summing_threshold,
irq_mask,
&dev->version, &num_pipes,
- dev->props.options & SPS_BAM_NO_EXT_P_RST);
+ dev->props.options);
else
/* No, so just verify that it is enabled */
rc = bam_check(dev->base, &dev->version, &num_pipes);
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 8a5deff..eba9b7d 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -198,7 +198,7 @@
void print_bam_pipe_selected_reg(void *, u32);
/* output descriptor FIFO of a pipe */
-void print_bam_pipe_desc_fifo(void *, u32);
+void print_bam_pipe_desc_fifo(void *, u32, u32);
/* output BAM_TEST_BUS_REG */
void print_bam_test_bus_reg(void *, u32);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 52bdae1..a808e0b 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -387,6 +387,9 @@
int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
{
struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+ struct msm_usb_bam_platform_data *pdata =
+ usb_bam_pdev->dev.platform_data;
+ int usb_active_bam = pdata->usb_active_bam;
int ret;
if (!usb_bam_pdev) {
@@ -409,6 +412,10 @@
connection->dst_pipe = dst_pipe_idx;
connection->idx = idx;
+ /* Check if BAM requires RESET before connect */
+ if (pdata->reset_on_connect[usb_active_bam] == true)
+ sps_device_reset(h_bam);
+
if (src_pipe_idx) {
/* open USB -> Peripheral pipe */
ret = connect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL,
@@ -899,6 +906,7 @@
u32 pipe_entry = 0;
char *key = NULL;
enum usb_pipe_mem_type mem_type;
+ bool reset_bam;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -985,6 +993,10 @@
pr_err("Cannot read string\n");
goto err;
}
+ reset_bam = of_property_read_bool(node,
+ "qcom,reset-bam-on-connect");
+ if (reset_bam)
+ pdata->reset_on_connect[bam] = true;
if (strnstr(str, "usb-to", 30))
dir = USB_TO_PEER_PERIPHERAL;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index f6591c3d..ed57f2c 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.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
@@ -160,6 +160,8 @@
int soc_calc_period;
int normal_voltage_calc_ms;
int low_voltage_calc_ms;
+ int imax_ua;
+ struct wake_lock soc_wake_lock;
};
/*
@@ -728,8 +730,9 @@
* CC_RESOLUTION_N, CC_RESOLUTION_D, CC_READING_TICKS
* and rsense
*/
-#define CC_RAW_5MAH 0x00110000
-#define MIN_OCV_UV 2000000
+#define CC_RAW_5MAH 0x00110000
+#define MIN_OCV_UV 2000000
+#define OCV_RAW_UNINITIALIZED 0xFFFF
static int read_soc_params_raw(struct pm8921_bms_chip *chip,
struct pm8921_soc_params *raw,
int batt_temp_decidegc)
@@ -749,7 +752,7 @@
usb_chg = usb_chg_plugged_in(chip);
- if (chip->prev_last_good_ocv_raw == 0) {
+ if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
convert_vbatt_raw_to_uv(chip, usb_chg,
@@ -801,7 +804,7 @@
/* fake a high OCV if we are just done charging */
if (chip->ocv_reading_at_100 != raw->last_good_ocv_raw) {
- chip->ocv_reading_at_100 = 0;
+ chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
chip->cc_reading_at_100 = 0;
} else {
/*
@@ -1025,28 +1028,34 @@
return uuc;
}
+#define TIME_PER_PERCENT_UUC 60
static int adjust_uuc(struct pm8921_bms_chip *chip, int fcc_uah,
int new_pc_unusable,
int new_uuc,
int batt_temp,
int rbatt,
- int *iavg_ma)
+ int *iavg_ma,
+ int delta_time_s)
{
int new_unusable_mv;
int batt_temp_degc = batt_temp / 10;
+ int max_percent_change;
+
+ max_percent_change = max(delta_time_s / TIME_PER_PERCENT_UUC, 1);
if (chip->prev_pc_unusable == -EINVAL
- || abs(chip->prev_pc_unusable - new_pc_unusable) <= 1) {
+ || abs(chip->prev_pc_unusable - new_pc_unusable)
+ <= max_percent_change) {
chip->prev_pc_unusable = new_pc_unusable;
return new_uuc;
}
/* the uuc is trying to change more than 1% restrict it */
if (new_pc_unusable > chip->prev_pc_unusable)
- chip->prev_pc_unusable++;
+ chip->prev_pc_unusable += max_percent_change;
else
- chip->prev_pc_unusable--;
-
+ chip->prev_pc_unusable -= max_percent_change;
+ chip->prev_pc_unusable = clamp(chip->prev_pc_unusable, 0, 100);
new_uuc = (fcc_uah * chip->prev_pc_unusable) / 100;
/* also find update the iavg_ma accordingly */
@@ -1096,57 +1105,58 @@
return 0;
}
-static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
- int *iavg_ua, int *delta_time_s)
+static int calculate_delta_time(struct pm8921_bms_chip *chip, int *delta_time_s)
{
- int delta_cc_uah;
unsigned long now_tm_sec = 0;
- int rc = 0;
+
+ /* default to delta time = 0 if anything fails */
+ *delta_time_s = 0;
+
+ get_current_time(&now_tm_sec);
+
+ *delta_time_s = (now_tm_sec - chip->tm_sec);
+ pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d\n",
+ chip->tm_sec, now_tm_sec, *delta_time_s);
+
+ /* remember this time */
+ chip->tm_sec = now_tm_sec;
+ return 0;
+}
+
+static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
+ int *iavg_ua, int delta_time_s)
+{
+ int delta_cc_uah = 0;
/* if anything fails report the previous iavg_ua */
*iavg_ua = chip->prev_iavg_ua;
- rc = get_current_time(&now_tm_sec);
- if (rc) {
- pr_err("Could not get current time: %d\n", rc);
- goto out;
- }
-
- if (chip->tm_sec == 0) {
- *delta_time_s = 0;
+ if (chip->last_cc_uah == INT_MIN) {
pm8921_bms_get_battery_current(iavg_ua);
goto out;
}
- *delta_time_s = (now_tm_sec - chip->tm_sec);
-
/* use the previous iavg if called within 15 seconds */
- if (*delta_time_s < 15) {
+ if (delta_time_s < 15) {
*iavg_ua = chip->prev_iavg_ua;
goto out;
}
delta_cc_uah = cc_uah - chip->last_cc_uah;
- *iavg_ua = div_s64((s64)delta_cc_uah * 3600, *delta_time_s);
-
- pr_debug("tm_sec = %ld, now_tm_sec = %ld delta_s = %d delta_cc = %d iavg_ua = %d\n",
- chip->tm_sec, now_tm_sec,
- *delta_time_s, delta_cc_uah, (int)*iavg_ua);
+ *iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
out:
+ pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
/* remember the iavg */
chip->prev_iavg_ua = *iavg_ua;
/* remember cc_uah */
chip->last_cc_uah = cc_uah;
-
- /* remember this time */
- chip->tm_sec = now_tm_sec;
}
#define IAVG_SAMPLES 16
-#define CHARGING_IAVG_MA 250
+#define MIN_IAVG_MA 250
#define MIN_SECONDS_FOR_VALID_SAMPLE 20
static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
int rbatt, int fcc_uah, int cc_uah,
@@ -1180,8 +1190,8 @@
* if we are charging use a nominal avg current so that we keep
* a reasonable UUC while charging
*/
- if (iavg_ma < 0)
- iavg_ma = CHARGING_IAVG_MA;
+ if (iavg_ma < MIN_IAVG_MA)
+ iavg_ma = MIN_IAVG_MA;
iavg_samples[iavg_index] = iavg_ma;
iavg_index = (iavg_index + 1) % IAVG_SAMPLES;
iavg_num_samples++;
@@ -1205,9 +1215,9 @@
&pc_unusable);
pr_debug("iavg = %d uuc_iavg = %d\n", iavg_ma, uuc_uah_iavg);
- /* restrict the uuc such that it can increase only by one percent */
+ /* restrict the uuc change to one percent per 60 seconds */
uuc_uah_iavg = adjust_uuc(chip, fcc_uah, pc_unusable, uuc_uah_iavg,
- batt_temp, rbatt, &iavg_ma);
+ batt_temp, rbatt, &iavg_ma, delta_time_s);
/* find out what the avg current should be for this uuc */
chip->prev_uuc_iavg_ma = iavg_ma;
@@ -1239,11 +1249,17 @@
int *remaining_charge_uah,
int *cc_uah,
int *rbatt,
- int *iavg_ua,
- int *delta_time_s)
+ int *iavg_ua)
{
int soc_rbatt;
+ int delta_time_s;
+ int rc;
+ rc = calculate_delta_time(chip, &delta_time_s);
+ if (rc) {
+ pr_err("Failed to get delta time from RTC: %d\n", rc);
+ delta_time_s = 0;
+ }
*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
*fcc_uah, batt_temp, chargecycles);
@@ -1271,7 +1287,7 @@
*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
*fcc_uah, *cc_uah, soc_rbatt,
batt_temp, chargecycles, *iavg_ua,
- *delta_time_s);
+ delta_time_s);
pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
}
@@ -1286,7 +1302,6 @@
int real_fcc_uah;
int rbatt;
int iavg_ua;
- int delta_time_s;
calculate_soc_params(chip, raw, batt_temp, chargecycles,
&fcc_uah,
@@ -1294,8 +1309,7 @@
&remaining_charge_uah,
&cc_uah,
&rbatt,
- &iavg_ua,
- &delta_time_s);
+ &iavg_ua);
real_fcc_uah = remaining_charge_uah - cc_uah;
*ret_fcc_uah = fcc_uah;
@@ -1406,6 +1420,13 @@
*ret_rc = rc_uah;
*ret_uuc = uuc_uah;
}
+
+static void calc_current_max(struct pm8921_bms_chip *chip, int ocv_uv,
+ int rbatt_mohm)
+{
+ chip->imax_ua = 1000 * (ocv_uv - chip->v_cutoff * 1000) / rbatt_mohm;
+}
+
static int bound_soc(int soc)
{
soc = max(0, soc);
@@ -1533,6 +1554,7 @@
delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
+ calc_current_max(chip, ocv_est_uv, rbatt);
pc_est = calculate_pc(chip, ocv_est_uv, batt_temp, last_chargecycles);
soc_est = div_s64((s64)fcc_uah * pc_est - uuc_uah*100,
(s64)fcc_uah - uuc_uah);
@@ -1903,7 +1925,6 @@
int cc_uah;
int rbatt;
int iavg_ua;
- int delta_time_s;
int new_ocv;
int new_rc_uah;
int new_ucc_uah;
@@ -1919,8 +1940,7 @@
&remaining_charge_uah,
&cc_uah,
&rbatt,
- &iavg_ua,
- &delta_time_s);
+ &iavg_ua);
/* calculate remaining usable charge */
remaining_usable_charge_uah = remaining_charge_uah
@@ -2047,6 +2067,7 @@
struct pm8921_soc_params raw;
int soc;
+ wake_lock(&the_chip->soc_wake_lock);
get_batt_temp(chip, &batt_temp);
mutex_lock(&chip->last_ocv_uv_mutex);
@@ -2055,6 +2076,7 @@
soc = calculate_state_of_charge(chip, &raw,
batt_temp, last_chargecycles);
mutex_unlock(&chip->last_ocv_uv_mutex);
+ wake_unlock(&the_chip->soc_wake_lock);
return soc;
}
@@ -2241,42 +2263,15 @@
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
-int pm8921_bms_get_rbatt(void)
+int pm8921_bms_get_current_max(void)
{
- int batt_temp;
- struct pm8921_soc_params raw;
- int fcc_uah;
- int unusable_charge_uah;
- int remaining_charge_uah;
- int cc_uah;
- int rbatt;
- int iavg_ua;
- int delta_time_s;
-
if (!the_chip) {
pr_err("called before initialization\n");
return -EINVAL;
}
-
- get_batt_temp(the_chip, &batt_temp);
-
- mutex_lock(&the_chip->last_ocv_uv_mutex);
-
- read_soc_params_raw(the_chip, &raw, batt_temp);
-
- calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
- &fcc_uah,
- &unusable_charge_uah,
- &remaining_charge_uah,
- &cc_uah,
- &rbatt,
- &iavg_ua,
- &delta_time_s);
- mutex_unlock(&the_chip->last_ocv_uv_mutex);
-
- return rbatt;
+ return the_chip->imax_ua;
}
-EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
+EXPORT_SYMBOL_GPL(pm8921_bms_get_current_max);
int pm8921_bms_get_fcc(void)
{
@@ -3018,6 +3013,9 @@
chip->rconn_mohm = pdata->rconn_mohm;
chip->start_percent = -EINVAL;
chip->end_percent = -EINVAL;
+ chip->last_cc_uah = INT_MIN;
+ chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
+ chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
chip->shutdown_soc_valid_limit = pdata->shutdown_soc_valid_limit;
chip->adjust_soc_low_threshold = pdata->adjust_soc_low_threshold;
@@ -3031,6 +3029,7 @@
chip->prev_pc_unusable = -EINVAL;
chip->soc_at_cv = -EINVAL;
+ chip->imax_ua = -EINVAL;
chip->ignore_shutdown_soc = pdata->ignore_shutdown_soc;
rc = set_battery_data(chip);
@@ -3063,10 +3062,12 @@
INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
calculate_soc_work);
+ wake_lock_init(&chip->soc_wake_lock,
+ WAKE_LOCK_SUSPEND, "pm8921_soc_lock");
rc = request_irqs(chip, pdev);
if (rc) {
pr_err("couldn't register interrupts rc = %d\n", rc);
- goto free_chip;
+ goto destroy_soc_wl;
}
wake_lock_init(&chip->low_voltage_wake_lock,
@@ -3108,7 +3109,10 @@
return 0;
free_irqs:
+ wake_lock_destroy(&chip->low_voltage_wake_lock);
free_irqs(chip);
+destroy_soc_wl:
+ wake_lock_destroy(&chip->soc_wake_lock);
free_chip:
kfree(chip);
return rc;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index c86ba9e..a09e5ee 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.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
@@ -1663,32 +1663,7 @@
static int get_prop_batt_current_max(struct pm8921_chg_chip *chip)
{
- int rbatt, ibatt_ua, vbatt_uv, ocv_uv;
- int imax_ma;
- int rc;
-
- rbatt = pm8921_bms_get_rbatt();
-
- if (rbatt < 0) {
- rc = -ENXIO;
- return rc;
- }
-
- rc = pm8921_bms_get_simultaneous_battery_voltage_and_current
- (&ibatt_ua, &vbatt_uv);
-
- if (rc)
- return rc;
-
- ocv_uv = vbatt_uv + ibatt_ua*rbatt/1000;
-
- imax_ma = (ocv_uv - chip->min_voltage_mv*1000)/rbatt;
-
- if (imax_ma < 0)
- imax_ma = 0;
-
- return imax_ma*1000;
-
+ return pm8921_bms_get_current_max();
}
static int get_prop_batt_current(struct pm8921_chg_chip *chip)
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4ffe0d8..2d73af6 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3,7 +3,7 @@
* MSM 7k High speed uart driver
*
* Copyright (c) 2008 Google Inc.
- * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved.
* Modified: Nick Pelly <npelly@google.com>
*
* All source code in this file is licensed under the following license
@@ -754,7 +754,7 @@
uport->ignore_status_mask = termios->c_iflag & INPCK;
uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
- uport->ignore_status_mask = termios->c_iflag & IGNBRK;
+ uport->ignore_status_mask |= termios->c_iflag & IGNBRK;
uport->read_status_mask = (termios->c_cflag & CREAD);
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 8debc36..20d6781 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -1,6 +1,6 @@
/* drivers/serial/msm_serial_hs_hwreg.h
*
- * Copyright (c) 2007-2009, 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2009, 2012-2013,The Linux Foundation. All rights reserved.
*
* All source code in this file is licensed under the following license
* except where indicated.
@@ -59,8 +59,16 @@
#define UARTDM_MR1_ADDR 0x0
#define UARTDM_MR2_ADDR 0x4
+/* Backward Compatability Register for UARTDM Core v1.4 */
+#define UARTDM_BCR_ADDR 0xc8
+
+/*
+ * UARTDM Core v1.4 STALE_IRQ_EMPTY bit defination
+ * Stale interrupt will fire if bit is set when RX-FIFO is empty
+ */
+#define UARTDM_BCR_STALE_IRQ_EMPTY 0x2
+
/* write only register */
-#define UARTDM_CSR_ADDR 0x8
#define UARTDM_CSR_115200 0xFF
#define UARTDM_CSR_57600 0xEE
#define UARTDM_CSR_38400 0xDD
@@ -79,22 +87,11 @@
#define UARTDM_CSR_75 0x00
/* write only register */
-#define UARTDM_TF_ADDR 0x70
-#define UARTDM_TF2_ADDR 0x74
-#define UARTDM_TF3_ADDR 0x78
-#define UARTDM_TF4_ADDR 0x7C
-
-/* write only register */
-#define UARTDM_CR_ADDR 0x10
-/* write only register */
-#define UARTDM_IMR_ADDR 0x14
-
#define UARTDM_IPR_ADDR 0x18
#define UARTDM_TFWR_ADDR 0x1c
#define UARTDM_RFWR_ADDR 0x20
#define UARTDM_HCR_ADDR 0x24
#define UARTDM_DMRX_ADDR 0x34
-#define UARTDM_IRDA_ADDR 0x38
#define UARTDM_DMEN_ADDR 0x3c
/* UART_DM_NO_CHARS_FOR_TX */
@@ -105,21 +102,6 @@
#define UARTDM_SIM_CFG_ADDR 0x80
/* Read Only register */
-#define UARTDM_SR_ADDR 0x8
-
-/* Read Only register */
-#define UARTDM_RF_ADDR 0x70
-#define UARTDM_RF2_ADDR 0x74
-#define UARTDM_RF3_ADDR 0x78
-#define UARTDM_RF4_ADDR 0x7C
-
-/* Read Only register */
-#define UARTDM_MISR_ADDR 0x10
-
-/* Read Only register */
-#define UARTDM_ISR_ADDR 0x14
-#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
-
#define UARTDM_TXFS_ADDR 0x4C
#define UARTDM_RXFS_ADDR 0x50
@@ -155,11 +137,25 @@
#define RESET_TX_ERROR 0x800
#define RESET_TX_DONE 0x810
+/*
+ * UARTDM_CR BAM IFC comman bit value
+ * for UARTDM Core v1.4
+ */
+#define START_RX_BAM_IFC 0x850
+#define START_TX_BAM_IFC 0x860
+
#define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
#define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
#define UARTDM_MR1_CTS_CTL_BMSK 0x40
#define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80
+/*
+ * UARTDM Core v1.4 MR2_RFR_CTS_LOOP bitmask
+ * Enables internal loopback between RFR_N of
+ * RX channel and CTS_N of TX channel.
+ */
+#define UARTDM_MR2_RFR_CTS_LOOP_MODE_BMSK 0x400
+
#define UARTDM_MR2_LOOP_MODE_BMSK 0x80
#define UARTDM_MR2_ERROR_MODE_BMSK 0x40
#define UARTDM_MR2_BITS_PER_CHAR_BMSK 0x30
@@ -204,4 +200,110 @@
#define UARTDM_TX_DM_EN_BMSK 0x1
#define UARTDM_RX_DM_EN_BMSK 0x2
+/*
+ * UARTDM Core v1.4 bitmask
+ * Bitmasks for enabling Rx and Tx BAM Interface
+ */
+#define UARTDM_TX_BAM_ENABLE_BMSK 0x4
+#define UARTDM_RX_BAM_ENABLE_BMSK 0x8
+
+/*
+ * Some of the BLSP Based UART Core(v14) existing register offsets
+ * are different compare to GSBI based UART Core(v13)
+ * Hence add the changed register offsets for UART Core v14
+ */
+#ifdef CONFIG_MSM_UARTDM_Core_v14
+
+/* write only register */
+#define UARTDM_CSR_ADDR 0x0a
+
+/* write only register */
+#define UARTDM_TF_ADDR 0x100
+#define UARTDM_TF2_ADDR 0x104
+#define UARTDM_TF3_ADDR 0x108
+#define UARTDM_TF4_ADDR 0x10c
+#define UARTDM_TF5_ADDR 0x110
+#define UARTDM_TF6_ADDR 0x114
+#define UARTDM_TF7_ADDR 0x118
+#define UARTDM_TF8_ADDR 0x11c
+#define UARTDM_TF9_ADDR 0x120
+#define UARTDM_TF10_ADDR 0x124
+#define UARTDM_TF11_ADDR 0x128
+#define UARTDM_TF12_ADDR 0x12c
+#define UARTDM_TF13_ADDR 0x130
+#define UARTDM_TF14_ADDR 0x134
+#define UARTDM_TF15_ADDR 0x138
+#define UARTDM_TF16_ADDR 0x13c
+
+/* write only register */
+#define UARTDM_CR_ADDR 0xa8
+/* write only register */
+#define UARTDM_IMR_ADDR 0xb0
+#define UARTDM_IRDA_ADDR 0xb8
+
+/* Read Only register */
+#define UARTDM_SR_ADDR 0xa4
+
+/* Read Only register */
+#define UARTDM_RF_ADDR 0x140
+#define UARTDM_RF2_ADDR 0x144
+#define UARTDM_RF3_ADDR 0x148
+#define UARTDM_RF4_ADDR 0x14c
+#define UARTDM_RF5_ADDR 0x150
+#define UARTDM_RF6_ADDR 0x154
+#define UARTDM_RF7_ADDR 0x158
+#define UARTDM_RF8_ADDR 0x15c
+#define UARTDM_RF9_ADDR 0x160
+#define UARTDM_RF10_ADDR 0x164
+#define UARTDM_RF11_ADDR 0x168
+#define UARTDM_RF12_ADDR 0x16c
+#define UARTDM_RF13_ADDR 0x170
+#define UARTDM_RF14_ADDR 0x174
+#define UARTDM_RF15_ADDR 0x178
+#define UARTDM_RF16_ADDR 0x17c
+
+/* Read Only register */
+#define UARTDM_MISR_ADDR 0xac
+
+/* Read Only register */
+#define UARTDM_ISR_ADDR 0xb4
+#define UARTDM_RX_TOTAL_SNAP_ADDR 0xbc
+
+#else
+
+/* Register offsets for UART Core v13 */
+
+/* write only register */
+#define UARTDM_CSR_ADDR 0x8
+
+/* write only register */
+#define UARTDM_TF_ADDR 0x70
+#define UARTDM_TF2_ADDR 0x74
+#define UARTDM_TF3_ADDR 0x78
+#define UARTDM_TF4_ADDR 0x7c
+
+/* write only register */
+#define UARTDM_CR_ADDR 0x10
+/* write only register */
+#define UARTDM_IMR_ADDR 0x14
+#define UARTDM_IRDA_ADDR 0x38
+
+/* Read Only register */
+#define UARTDM_SR_ADDR 0x8
+
+/* Read Only register */
+#define UARTDM_RF_ADDR 0x70
+#define UARTDM_RF2_ADDR 0x74
+#define UARTDM_RF3_ADDR 0x78
+#define UARTDM_RF4_ADDR 0x7c
+
+/* Read Only register */
+#define UARTDM_MISR_ADDR 0x10
+
+/* Read Only register */
+#define UARTDM_ISR_ADDR 0x14
+#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
+
+#endif
+
#endif /* MSM_SERIAL_HS_HWREG_H */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index ccb9aa3..1ee0828 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -189,6 +189,7 @@
u32 bus_perf_client;
struct msm_bus_scale_pdata *bus_scale_table;
struct power_supply usb_psy;
+ struct power_supply *ext_vbus_psy;
unsigned int online;
unsigned int host_mode;
unsigned int current_max;
@@ -197,6 +198,7 @@
unsigned int vdd_high_vol_level;
bool vbus_active;
bool ext_inuse;
+ enum dwc3_id_state id_state;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -1441,6 +1443,7 @@
struct dwc3_msm *mdwc = context;
if (start == false) {
+ dev_dbg(mdwc->dev, "canceling charging detection work\n");
cancel_delayed_work_sync(&mdwc->chg_work);
mdwc->chg_state = USB_CHG_STATE_UNDEFINED;
charger->chg_type = DWC3_INVALID_CHARGER;
@@ -1797,8 +1800,8 @@
/* Process PMIC notification in PRESENT prop */
case POWER_SUPPLY_PROP_PRESENT:
dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__);
- if (mdwc->otg_xceiv && (mdwc->ext_xceiv.otg_capability ||
- !init)) {
+ if (mdwc->otg_xceiv && !mdwc->ext_inuse &&
+ (mdwc->ext_xceiv.otg_capability || !init)) {
mdwc->ext_xceiv.bsv = val->intval;
if (atomic_read(&mdwc->in_lpm)) {
dev_dbg(mdwc->dev,
@@ -1810,9 +1813,10 @@
mdwc->otg_xceiv->otg,
DWC3_EVENT_XCEIV_STATE);
}
+
+ if (!init)
+ init = true;
}
- if (!init)
- init = true;
mdwc->vbus_active = val->intval;
break;
case POWER_SUPPLY_PROP_ONLINE:
@@ -1829,6 +1833,33 @@
return 0;
}
+static void dwc3_msm_external_power_changed(struct power_supply *psy)
+{
+ struct dwc3_msm *mdwc = container_of(psy, struct dwc3_msm, usb_psy);
+ union power_supply_propval ret = {0,};
+
+ if (!mdwc->ext_vbus_psy)
+ mdwc->ext_vbus_psy = power_supply_get_by_name("ext-vbus");
+
+ if (!mdwc->ext_vbus_psy) {
+ pr_err("%s: Unable to get ext_vbus power_supply\n", __func__);
+ return;
+ }
+
+ mdwc->ext_vbus_psy->get_property(mdwc->ext_vbus_psy,
+ POWER_SUPPLY_PROP_ONLINE, &ret);
+ if (ret.intval) {
+ dwc3_start_chg_det(&mdwc->charger, false);
+ mdwc->ext_vbus_psy->get_property(mdwc->ext_vbus_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
+ power_supply_set_current_limit(&mdwc->usb_psy, ret.intval);
+ }
+
+ power_supply_set_online(&mdwc->usb_psy, ret.intval);
+ power_supply_changed(&mdwc->usb_psy);
+}
+
+
static char *dwc3_msm_pm_power_supplied_to[] = {
"battery",
};
@@ -1845,6 +1876,7 @@
static void dwc3_ext_notify_online(int on)
{
struct dwc3_msm *mdwc = context;
+ bool notify_otg = false;
if (!mdwc) {
pr_err("%s: DWC3 driver already removed\n", __func__);
@@ -1853,11 +1885,31 @@
dev_dbg(mdwc->dev, "notify %s%s\n", on ? "" : "dis", "connected");
- if (!on) {
- /* external client offline; revert back to USB */
- mdwc->ext_inuse = false;
- queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+ if (!mdwc->ext_vbus_psy)
+ mdwc->ext_vbus_psy = power_supply_get_by_name("ext-vbus");
+
+ mdwc->ext_inuse = on;
+ if (on) {
+ /* force OTG to exit B-peripheral state */
+ mdwc->ext_xceiv.bsv = false;
+ notify_otg = true;
+ dwc3_start_chg_det(&mdwc->charger, false);
+ } else {
+ /* external client offline; tell OTG about cached ID/BSV */
+ if (mdwc->ext_xceiv.id != mdwc->id_state) {
+ mdwc->ext_xceiv.id = mdwc->id_state;
+ notify_otg = true;
+ }
+
+ mdwc->ext_xceiv.bsv = mdwc->vbus_active;
+ notify_otg |= mdwc->vbus_active;
}
+
+ if (mdwc->ext_vbus_psy)
+ power_supply_set_present(mdwc->ext_vbus_psy, on);
+
+ if (notify_otg)
+ queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
}
static bool dwc3_ext_trigger_handled(struct dwc3_msm *mdwc,
@@ -1887,21 +1939,26 @@
dev_dbg(mdwc->dev, "%s: state = %s\n", __func__,
state == ADC_TM_HIGH_STATE ? "high" : "low");
+ /* Give external client a chance to handle */
+ if (!mdwc->ext_inuse)
+ dwc3_ext_trigger_handled(mdwc, (state == ADC_TM_HIGH_STATE));
+
+ /* save ID state, but don't necessarily notify OTG */
if (state == ADC_TM_HIGH_STATE) {
- mdwc->ext_xceiv.id = DWC3_ID_FLOAT;
+ mdwc->id_state = DWC3_ID_FLOAT;
mdwc->adc_param.state_request = ADC_TM_LOW_THR_ENABLE;
} else {
- mdwc->ext_xceiv.id = DWC3_ID_GROUND;
+ mdwc->id_state = DWC3_ID_GROUND;
mdwc->adc_param.state_request = ADC_TM_HIGH_THR_ENABLE;
}
- /* Give external client a chance to handle, otherwise notify OTG */
- if (!mdwc->ext_inuse &&
- !dwc3_ext_trigger_handled(mdwc, mdwc->ext_xceiv.id))
- queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
-
/* re-arm ADC interrupt */
qpnp_adc_tm_usbid_configure(&mdwc->adc_param);
+
+ if (!mdwc->ext_inuse) { /* notify OTG */
+ mdwc->ext_xceiv.id = mdwc->id_state;
+ queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0);
+ }
}
static void dwc3_init_adc_work(struct work_struct *w)
@@ -2234,6 +2291,8 @@
msm->usb_psy.num_properties = ARRAY_SIZE(dwc3_msm_pm_power_props_usb);
msm->usb_psy.get_property = dwc3_msm_power_get_property_usb;
msm->usb_psy.set_property = dwc3_msm_power_set_property_usb;
+ msm->usb_psy.external_power_changed =
+ dwc3_msm_external_power_changed;
ret = power_supply_register(&pdev->dev, &msm->usb_psy);
if (ret < 0) {
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 0a9f500..6df0c96 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2043,6 +2043,7 @@
struct android_usb_function_holder *f_holder;
struct android_configuration *conf;
int enabled = 0;
+ bool audio_enabled = false;
if (!cdev)
return -ENODEV;
@@ -2061,12 +2062,22 @@
cdev->desc.bDeviceClass = device_desc.bDeviceClass;
cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
+
+ /* Audio dock accessory is unable to enumerate device if
+ * pull-up is enabled immediately. The enumeration is
+ * reliable with 100 msec delay.
+ */
list_for_each_entry(conf, &dev->configs, list_item)
list_for_each_entry(f_holder, &conf->enabled_functions,
enabled_list) {
if (f_holder->f->enable)
f_holder->f->enable(f_holder->f);
+ if (!strncmp(f_holder->f->name,
+ "audio_source", 12))
+ audio_enabled = true;
}
+ if (audio_enabled)
+ msleep(100);
android_enable(dev);
dev->enabled = true;
} else if (!enabled && dev->enabled) {
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index aca2af3..a95bf24 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -2,7 +2,7 @@
* Diag Function Device - Route ARM9 and ARM11 DIAG messages
* between HOST and DEVICE.
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2013, Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -334,22 +334,10 @@
}
EXPORT_SYMBOL(usb_diag_close);
-/**
- * usb_diag_free_req() - Free USB requests
- * @ch: Channel handler
- *
- * This function free read and write USB requests for the interface
- * associated with this channel.
- *
- */
-void usb_diag_free_req(struct usb_diag_ch *ch)
+static void free_reqs(struct diag_context *ctxt)
{
- struct diag_context *ctxt = ch->priv_usb;
- struct usb_request *req;
struct list_head *act, *tmp;
-
- if (!ctxt)
- return;
+ struct usb_request *req;
list_for_each_safe(act, tmp, &ctxt->write_pool) {
req = list_entry(act, struct usb_request, list);
@@ -363,6 +351,27 @@
usb_ep_free_request(ctxt->out, req);
}
}
+
+/**
+ * usb_diag_free_req() - Free USB requests
+ * @ch: Channel handler
+ *
+ * This function free read and write USB requests for the interface
+ * associated with this channel.
+ *
+ */
+void usb_diag_free_req(struct usb_diag_ch *ch)
+{
+ struct diag_context *ctxt = ch->priv_usb;
+ unsigned long flags;
+
+ if (ctxt) {
+ spin_lock_irqsave(&ctxt->lock, flags);
+ free_reqs(ctxt);
+ spin_unlock_irqrestore(&ctxt->lock, flags);
+ }
+
+}
EXPORT_SYMBOL(usb_diag_free_req);
/**
@@ -381,10 +390,14 @@
struct diag_context *ctxt = ch->priv_usb;
struct usb_request *req;
int i;
+ unsigned long flags;
if (!ctxt)
return -ENODEV;
+ spin_lock_irqsave(&ctxt->lock, flags);
+ /* Free previous session's stale requests */
+ free_reqs(ctxt);
for (i = 0; i < n_write; i++) {
req = usb_ep_alloc_request(ctxt->in, GFP_ATOMIC);
if (!req)
@@ -400,11 +413,11 @@
req->complete = diag_read_complete;
list_add_tail(&req->list, &ctxt->read_pool);
}
-
+ spin_unlock_irqrestore(&ctxt->lock, flags);
return 0;
-
fail:
- usb_diag_free_req(ch);
+ free_reqs(ctxt);
+ spin_unlock_irqrestore(&ctxt->lock, flags);
return -ENOMEM;
}
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 4947f15..00744fb 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -220,7 +220,7 @@
ret = usb_ep_queue(ep, req, GFP_ATOMIC);
spin_lock(&port->port_lock_dl);
if (ret) {
- pr_err("%s: usb epIn failed\n", __func__);
+ pr_err("%s: usb epIn failed with %d\n", __func__, ret);
list_add(&req->list, &d->tx_idle);
dev_kfree_skb_any(skb);
break;
@@ -517,7 +517,8 @@
dev_kfree_skb_any(skb);
if (printk_ratelimit())
- pr_err("%s: rx queue failed\n", __func__);
+ pr_err("%s: rx queue failed %d\n",
+ __func__, ret);
if (port->port_usb)
list_add(&req->list, &d->rx_idle);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 3ad05b06..a4bb7b2 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2013, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2167,8 +2167,8 @@
}
}
-#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
-#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
+#define MSM_CHG_DCD_TIMEOUT (750 * HZ/1000) /* 750 msec */
+#define MSM_CHG_DCD_POLL_TIME (50 * HZ/1000) /* 50 msec */
#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
#define MSM_CHG_SECONDARY_DET_TIME (50 * HZ/1000) /* TVDMSRC_ON */
static void msm_chg_detect_work(struct work_struct *w)
@@ -2192,7 +2192,7 @@
msm_chg_enable_dcd(motg);
msm_chg_enable_aca_det(motg);
motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
- motg->dcd_retries = 0;
+ motg->dcd_time = 0;
delay = MSM_CHG_DCD_POLL_TIME;
break;
case USB_CHG_STATE_WAIT_FOR_DCD:
@@ -2217,7 +2217,8 @@
}
}
is_dcd = msm_chg_check_dcd(motg);
- tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
+ motg->dcd_time += MSM_CHG_DCD_POLL_TIME;
+ tmout = motg->dcd_time >= MSM_CHG_DCD_TIMEOUT;
if (is_dcd || tmout) {
msm_chg_disable_dcd(motg);
msm_chg_enable_primary_det(motg);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 7396013..20b20bc 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -73,6 +73,7 @@
#define MDPOP_SHARPENING BIT(11) /* enable sharpening */
#define MDPOP_BLUR BIT(12) /* enable blur */
#define MDPOP_FG_PM_ALPHA BIT(13)
+#define MDPOP_LAYER_IS_FG BIT(14)
#define MDP_ALLOC(x) kmalloc(x, GFP_KERNEL)
struct mdp_buf_type {
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 8631d6d..c8367c3 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1401,6 +1401,9 @@
iBuf.mdpImg.mdpOp = MDPOP_NOP;
+ if (req->flags & MDP_IS_FG)
+ iBuf.mdpImg.mdpOp |= MDPOP_LAYER_IS_FG;
+
/* blending check */
if (req->transp_mask != MDP_TRANSP_NOP) {
iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index 418528e..5da6b4f5 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2467,7 +2467,8 @@
bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
PPP_BLEND_BG_ALPHA_REVERSE;
- if (perPixelAlpha) {
+ if ((perPixelAlpha) && !(iBuf->mdpImg.mdpOp &
+ MDPOP_LAYER_IS_FG)) {
bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
} else {
bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
@@ -2478,7 +2479,12 @@
if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
} else if (perPixelAlpha) {
- *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ if (iBuf->mdpImg.mdpOp & MDPOP_LAYER_IS_FG)
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA;
+ else
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
PPP_OP_BLEND_ON |
PPP_OP_BLEND_SRCPIXEL_ALPHA;
outpdw(MDP_BASE + 0x70010, 0);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 0227e70..f3be983 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -30,6 +30,7 @@
#define MHL_DRIVER_NAME "sii8334"
#define COMPATIBLE_NAME "qcom,mhl-sii8334"
+#define MAX_CURRENT 700000
#define pr_debug_intr(...) pr_debug("\n")
@@ -63,6 +64,9 @@
void (*notify_usb_online)(int online);
struct usb_ext_notification *mhl_info;
bool disc_enabled;
+ struct power_supply mhl_psy;
+ bool vbus_active;
+ int current_val;
};
@@ -267,6 +271,65 @@
return rc;
}
+static int mhl_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct mhl_tx_ctrl *mhl_ctrl =
+ container_of(psy, struct mhl_tx_ctrl, mhl_psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = mhl_ctrl->current_val;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = mhl_ctrl->vbus_active;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mhl_ctrl->vbus_active && mhl_ctrl->mhl_mode;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int mhl_power_set_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ const union power_supply_propval *val)
+{
+ struct mhl_tx_ctrl *mhl_ctrl =
+ container_of(psy, struct mhl_tx_ctrl, mhl_psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ mhl_ctrl->vbus_active = val->intval;
+ if (mhl_ctrl->vbus_active)
+ mhl_ctrl->current_val = MAX_CURRENT;
+ else
+ mhl_ctrl->current_val = 0;
+ power_supply_changed(psy);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static char *mhl_pm_power_supplied_to[] = {
+ "usb",
+};
+
+static enum power_supply_property mhl_pm_power_props[] = {
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
static void cbus_reset(struct i2c_client *client)
{
uint8_t i;
@@ -620,6 +683,7 @@
if (0x02 == rgnd_imp) {
pr_debug("%s: mhl sink\n", __func__);
mhl_ctrl->mhl_mode = 1;
+ power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online(1);
} else {
@@ -718,9 +782,9 @@
/* Short RGND */
MHL_SII_REG_NAME_MOD(REG_DISC_STAT2, BIT0 | BIT1, 0x00);
mhl_msm_disconnection(mhl_ctrl);
+ power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online(0);
-
}
if (status & BIT5) {
@@ -730,6 +794,7 @@
reg = MHL_SII_REG_NAME_RD(REG_INTR4);
MHL_SII_REG_NAME_WR(REG_INTR4, reg);
mhl_msm_disconnection(mhl_ctrl);
+ power_supply_changed(&mhl_ctrl->mhl_psy);
if (mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online(0);
}
@@ -1255,6 +1320,24 @@
} else {
pr_debug("request_threaded_irq succeeded\n");
}
+
+ mhl_ctrl->mhl_psy.name = "ext-vbus";
+ mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
+ mhl_ctrl->mhl_psy.supplied_to = mhl_pm_power_supplied_to;
+ mhl_ctrl->mhl_psy.num_supplicants = ARRAY_SIZE(
+ mhl_pm_power_supplied_to);
+ mhl_ctrl->mhl_psy.properties = mhl_pm_power_props;
+ mhl_ctrl->mhl_psy.num_properties = ARRAY_SIZE(mhl_pm_power_props);
+ mhl_ctrl->mhl_psy.get_property = mhl_power_get_property;
+ mhl_ctrl->mhl_psy.set_property = mhl_power_set_property;
+
+ rc = power_supply_register(&client->dev, &mhl_ctrl->mhl_psy);
+ if (rc < 0) {
+ dev_err(&client->dev, "%s:power_supply_register ext_vbus_psy failed\n",
+ __func__);
+ goto failed_probe;
+ }
+
pr_debug("%s: i2c client addr is [%x]\n", __func__, client->addr);
mhl_info = devm_kzalloc(&client->dev, sizeof(*mhl_info), GFP_KERNEL);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 9fe5d8f..e4e93eb 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -726,36 +726,11 @@
},
};
-#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_FB_MSM_MDP303)
-static void memset32_io(u32 __iomem *_ptr, u32 val, size_t count)
-{
- count >>= 2;
- while (count--)
- writel(val, _ptr++);
-}
-#endif
-
#ifdef CONFIG_HAS_EARLYSUSPEND
static void msmfb_early_suspend(struct early_suspend *h)
{
struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
early_suspend);
-#if defined(CONFIG_FB_MSM_MDP303)
- /*
- * For MDP with overlay, set framebuffer with black pixels
- * to show black screen on HDMI.
- */
- struct fb_info *fbi = mfd->fbi;
- switch (mfd->fbi->var.bits_per_pixel) {
- case 32:
- memset32_io((void *)fbi->screen_base, 0xFF000000,
- fbi->fix.smem_len);
- break;
- default:
- memset32_io((void *)fbi->screen_base, 0x00, fbi->fix.smem_len);
- break;
- }
-#endif
msm_fb_suspend_sub(mfd);
}
@@ -3144,6 +3119,7 @@
#endif
DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
+DEFINE_SEMAPHORE(msm_fb_ioctl_vsync_sem);
DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
/* Set color conversion matrix from user space */
@@ -3384,12 +3360,12 @@
#endif
case MSMFB_VSYNC_CTRL:
case MSMFB_OVERLAY_VSYNC_CTRL:
- down(&msm_fb_ioctl_ppp_sem);
+ down(&msm_fb_ioctl_vsync_sem);
if (mdp_rev >= MDP_REV_40)
ret = msmfb_overlay_vsync_ctrl(info, argp);
else
ret = msmfb_vsync_ctrl(info, argp);
- up(&msm_fb_ioctl_ppp_sem);
+ up(&msm_fb_ioctl_vsync_sem);
break;
case MSMFB_BLIT:
down(&msm_fb_ioctl_ppp_sem);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 95f4bf0..5cf2f9c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1115,14 +1115,21 @@
encoder->client_output_buf_req.sz/num_slices;
encoder->client_output_buf_req.sz =
DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+ if (encoder->client_output_buf_req. \
+ actual_count < encoder-> \
+ client_output_buf_req.min_count) {
+ encoder->client_output_buf_req. \
+ actual_count = encoder-> \
+ client_output_buf_req.min_count;
+ }
encoder->output_buf_req =
encoder->client_output_buf_req;
- DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
- "output_buf_count = %u "
- "output_buf_size = %u aligned size = %u\n",
+ DDL_MSG_HIGH("%s num_mb = %u num_slices = %u" \
+ " min_count = %u act_count = %u" \
+ " aligned size = %u\n",
__func__, num_mb, num_slices,
encoder->client_output_buf_req.min_count,
- output_buf_size,
+ encoder->client_output_buf_req.actual_count,
encoder->client_output_buf_req.sz);
vcd_status = VCD_S_SUCCESS;
}
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 983923b..884050b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1750,7 +1750,7 @@
vcd_get_buffer_requirements_cmn,
NULL,
NULL,
- NULL,
+ vcd_free_buffer_cmn,
vcd_fill_output_buffer_cmn,
vcd_clnt_cb_in_flushing,
},
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 46ae59f..9a7081d 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -439,6 +439,7 @@
header-y += msm_audio_sbc.h
header-y += msm_ipc.h
header-y += msm_charm.h
+header-y += msm_rmnet.h
header-y += qseecom.h
header-y += qcedev.h
header-y += idle_stats_device.h
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 6db6204..8ab3ac2 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -123,9 +123,11 @@
int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
int *vbat_uv);
/**
- * pm8921_bms_get_rbatt - function to get the battery resistance in mOhm.
+ * pm8921_bms_get_current_max
+ * - function to get the max current that can be drawn from
+ * the battery before it dips below the min allowed voltage
*/
-int pm8921_bms_get_rbatt(void);
+int pm8921_bms_get_current_max(void);
/**
* pm8921_bms_invalidate_shutdown_soc - function to notify the bms driver that
* the battery was replaced between reboot
@@ -184,6 +186,10 @@
{
return -ENXIO;
}
+static inline int pm8921_bms_get_current_max(void)
+{
+ return -ENXIO;
+}
#endif
#endif
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 3e5c8cb..4d004c2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -198,6 +198,7 @@
REL_WRITE,
THRESHOLD,
LARGE_SEC_ALIGN,
+ RANDOM,
MAX_REASONS,
};
@@ -261,32 +262,48 @@
/**
* struct mmc_bkops_info - BKOPS data
* @dw: Idle time bkops delayed work
- * @host_suspend_tout_ms: The host controller idle time,
- * before getting into suspend
+ * @host_delay_ms: The host controller time to start bkops
* @delay_ms: The time to start the BKOPS
* delayed work once MMC thread is idle
+ * @min_sectors_to_queue_delayed_work: the changed
+ * number of sectors that should issue check for BKOPS
+ * need
+ * @size_percentage_to_queue_delayed_work: the changed
+ * percentage of sectors that should issue check for
+ * BKOPS need
+ * @bkops_stats: BKOPS statistics
* @poll_for_completion: Poll on BKOPS completion
* @cancel_delayed_work: A flag to indicate if the delayed work
* should be cancelled
- * @started_delayed_bkops: A flag to indicate if the delayed
- * work was scheduled
+ * @sectors_changed: number of sectors written or
+ * discard since the last idle BKOPS were scheduled
*/
struct mmc_bkops_info {
struct delayed_work dw;
- unsigned int host_suspend_tout_ms;
+ unsigned int host_delay_ms;
unsigned int delay_ms;
- struct mmc_bkops_stats bkops_stats; /* BKOPS statistics */
+ unsigned int min_sectors_to_queue_delayed_work;
+ unsigned int size_percentage_to_queue_delayed_work;
+ struct mmc_bkops_stats bkops_stats;
/*
* A default time for checking the need for non urgent BKOPS once mmcqd
* is idle.
*/
-#define MMC_IDLE_BKOPS_TIME_MS 2000
+#define MMC_IDLE_BKOPS_TIME_MS 200
struct work_struct poll_for_completion;
/* Polling timeout and interval for waiting on non-blocking BKOPs completion */
-#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS 10000 /* in ms */
+#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS (4 * 60 * 1000) /* in ms */
#define BKOPS_COMPLETION_POLLING_INTERVAL_MS 1000 /* in ms */
bool cancel_delayed_work;
- bool started_delayed_bkops;
+ unsigned int sectors_changed;
+/*
+ * Since canceling the delayed work might have significant effect on the
+ * performance of small requests we won't queue the delayed work every time
+ * mmcqd thread is idle.
+ * The delayed work for idle BKOPS will be scheduled only after a significant
+ * amount of write or discard data.
+ */
+#define BKOPS_SIZE_PERCENTAGE_TO_QUEUE_DELAYED_WORK 1 /* 1% */
};
/**
@@ -337,6 +354,7 @@
#define MMC_CARD_REMOVED (1<<7) /* card has been removed */
#define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */
#define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */
+#define MMC_STATE_NEED_BKOPS (1<<11) /* card needs to do BKOPS */
unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
@@ -511,6 +529,7 @@
#define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
+#define mmc_card_need_bkops(c) ((c)->state & MMC_STATE_NEED_BKOPS)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -524,7 +543,8 @@
#define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
#define mmc_card_set_doing_bkops(c) ((c)->state |= MMC_STATE_DOING_BKOPS)
#define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS)
-
+#define mmc_card_set_need_bkops(c) ((c)->state |= MMC_STATE_NEED_BKOPS)
+#define mmc_card_clr_need_bkops(c) ((c)->state &= ~MMC_STATE_NEED_BKOPS)
/*
* Quirk add/remove for MMC products.
*/
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 6982c45..f9e0627 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -315,6 +315,7 @@
struct delayed_work detect;
struct wake_lock detect_wake_lock;
+ const char *wlock_name;
int detect_change; /* card detect flag */
struct mmc_hotplug hotplug;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index aa2d948..7e67db0 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -145,6 +145,7 @@
#define MDP_DITHER 0x8
#define MDP_BLUR 0x10
#define MDP_BLEND_FG_PREMULT 0x20000
+#define MDP_IS_FG 0x40000
#define MDP_DEINTERLACE 0x80000000
#define MDP_SHARPENING 0x40000000
#define MDP_NO_DMA_BARRIER_START 0x20000000
diff --git a/include/linux/msm_rmnet.h b/include/linux/msm_rmnet.h
index 063a8f1..d41b55c 100644
--- a/include/linux/msm_rmnet.h
+++ b/include/linux/msm_rmnet.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
#ifndef _MSM_RMNET_H_
#define _MSM_RMNET_H_
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 279b72f..9240277 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2012, Code Aurora Forum. 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
@@ -340,7 +340,7 @@
struct delayed_work suspend_work;
enum usb_chg_state chg_state;
enum usb_chg_type chg_type;
- u8 dcd_retries;
+ unsigned dcd_time;
struct wake_lock wlock;
struct notifier_block usbdev_nb;
unsigned mA_port;
@@ -456,6 +456,13 @@
u32 desc_fifo_size;
};
+enum usb_bam {
+ SSUSB_BAM = 0,
+ HSUSB_BAM,
+ HSIC_BAM,
+ MAX_BAMS,
+};
+
/**
* struct msm_usb_bam_platform_data: pipe connection information
* between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
@@ -474,13 +481,7 @@
u32 total_bam_num;
u32 usb_base_address;
bool ignore_core_reset_ack;
-};
-
-enum usb_bam {
- SSUSB_BAM = 0,
- HSUSB_BAM,
- HSIC_BAM,
- MAX_BAMS,
+ bool reset_on_connect[MAX_BAMS];
};
/**
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 444b432..3da152c 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -73,6 +73,8 @@
IDX_RT_PROXY_PORT_001_TX = 31,
IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX = 32,
IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX = 33,
+ IDX_AFE_PORT_ID_SECONDARY_MI2S_RX = 34,
+ IDX_AFE_PORT_ID_SECONDARY_MI2S_TX = 35,
AFE_MAX_PORTS
};
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 1967297..f2aa5de 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -106,24 +106,28 @@
static void __spin_lock_debug(raw_spinlock_t *lock)
{
u64 i;
- u64 loops = loops_per_jiffy * HZ;
- int print_once = 1;
+ u64 loops = (loops_per_jiffy * HZ) >> 4;
- for (;;) {
- for (i = 0; i < loops; i++) {
- if (arch_spin_trylock(&lock->raw_lock))
- return;
- __delay(1);
- }
- /* lockup suspected: */
- if (print_once) {
- print_once = 0;
- spin_dump(lock, "lockup");
-#ifdef CONFIG_SMP
- trigger_all_cpu_backtrace();
-#endif
- }
+ for (i = 0; i < loops; i++) {
+ if (arch_spin_trylock(&lock->raw_lock))
+ return;
+ __delay(1);
}
+ /* lockup suspected: */
+ spin_dump(lock, "lockup");
+#ifdef CONFIG_SMP
+ trigger_all_cpu_backtrace();
+#endif
+
+ /*
+ * The trylock above was causing a livelock. Give the lower level arch
+ * specific lock code a chance to acquire the lock. We have already
+ * printed a warning/backtrace at this point. The non-debug arch
+ * specific code might actually succeed in acquiring the lock. If it is
+ * not successful, the end-result is the same - there is no forward
+ * progress.
+ */
+ arch_spin_lock(&lock->raw_lock);
}
void do_raw_spin_lock(raw_spinlock_t *lock)
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 0704394..fb85c02 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1409,8 +1409,24 @@
hci_dev_lock_bh(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
- if (conn)
+ if (conn) {
conn->auth_type = req.type;
+ switch (conn->auth_type) {
+ case HCI_AT_NO_BONDING:
+ conn->pending_sec_level = BT_SECURITY_LOW;
+ break;
+ case HCI_AT_DEDICATED_BONDING:
+ case HCI_AT_GENERAL_BONDING:
+ conn->pending_sec_level = BT_SECURITY_MEDIUM;
+ break;
+ case HCI_AT_DEDICATED_BONDING_MITM:
+ case HCI_AT_GENERAL_BONDING_MITM:
+ conn->pending_sec_level = BT_SECURITY_HIGH;
+ break;
+ default:
+ break;
+ }
+ }
hci_dev_unlock_bh(hdev);
if (!conn)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8568dae7..1cd09f9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1758,7 +1758,7 @@
return;
}
- if (status)
+ if (status || conn->pending_sec_level < BT_SECURITY_MEDIUM)
pairing_complete(cmd, status);
hci_conn_put(conn);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 56b2cfa..517779f 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -446,6 +446,8 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
&reason);
del_timer(&hcon->smp_timer);
+ if (hcon->disconn_cfm_cb)
+ hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
hci_conn_put(hcon);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 73a39d5..1546b9e 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -198,6 +198,8 @@
static const u32 vport_i2s_check_table[NUM_CODEC_DAIS] = {
0, /* AIF1_PB */
0, /* AIF1_CAP */
+ 0, /* AIF2_PB */
+ 0, /* AIF2_CAP */
};
struct taiko_priv {
@@ -1694,7 +1696,7 @@
mutex_lock(&codec->mutex);
if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
- if (widget->value > 1) {
+ if (widget->value > 2) {
dev_err(codec->dev, "%s: invalid AIF for I2C mode\n",
__func__);
goto err;
@@ -3743,6 +3745,34 @@
},
.ops = &taiko_dai_ops,
},
+ {
+ .name = "taiko_i2s_rx2",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_i2s_tx2",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
};
static int taiko_codec_enable_slim_chmask(struct wcd9xxx_codec_dai_data *dai,
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index 4c7b69d..eadb365 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.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
@@ -27,13 +27,6 @@
#include <qdsp6v2/msm-pcm-routing-v2.h>
#include "../codecs/wcd9320.h"
-/* MI2S GPIO SECTION */
-
-#define GPIO_MI2S_WS 12
-#define GPIO_MI2S_SCLK 15
-#define GPIO_MI2S_DOUT 14
-#define GPIO_MI2S_DIN 13
-#define GPIO_MI2S_MCLK 71
/* Spk control */
#define MDM9625_SPK_ON 1
@@ -45,59 +38,61 @@
#define MDM_MCLK_CLK_12P288MHZ 12288000
#define MDM_MCLK_CLK_9P6HZ 9600000
#define MDM_IBIT_CLK_DIV_1P56MHZ 7
+#define MDM_MI2S_PRIM_INTF 0
+#define MDM_MI2S_SEC_INTF 1
+
/* Machine driver Name*/
#define MDM9625_MACHINE_DRV_NAME "mdm9625-asoc-taiko"
-struct mdm9625_machine_data {
- u32 mclk_freq;
+/* I2S GPIO */
+struct msm_i2s_gpio {
+ unsigned gpio_no;
+ const char *gpio_name;
+};
+
+struct msm_i2s_ctrl {
+ struct msm_i2s_gpio *pin_data;
+ struct clk *cdc_bit_clk;
+ u32 cnt;
};
/* MI2S clock */
struct mdm_mi2s_clk {
struct clk *cdc_cr_clk;
struct clk *cdc_osr_clk;
- struct clk *cdc_bit_clk;
- bool clk_enable;
+ u32 clk_usrs;
+};
+
+struct mdm9625_machine_data {
+ u32 mclk_freq;
+ struct msm_i2s_gpio *mclk_pin;
+ struct msm_i2s_ctrl *pri_ctrl;
};
-static struct mdm_mi2s_clk prim_clk;
-/* I2S GPIO */
-struct request_gpio {
- unsigned gpio_no;
- char *gpio_name;
+#define GPIO_NAME_INDEX 0
+#define DT_PARSE_INDEX 1
+
+
+static char *mdm_i2s_gpio_name[][2] = {
+ {"PRIM_MI2S_WS", "prim-i2s-gpio-ws"},
+ {"PRIM_MI2S_DIN", "prim-i2s-gpio-din"},
+ {"PRIM_MI2S_DOUT", "prim-i2s-gpio-dout"},
+ {"PRIM_MI2S_SCLK", "prim-i2s-gpio-sclk"},
};
+
+static char *mdm_mclk_gpio[][2] = {
+ {"MI2S_MCLK", "prim-i2s-gpio-mclk"},
+};
+
+static struct mdm_mi2s_clk clk_ctl;
static struct mutex cdc_mclk_mutex;
static int mdm9625_mi2s_rx_ch = 1;
static int mdm9625_mi2s_tx_ch = 1;
static int msm_spk_control;
static atomic_t mi2s_ref_count;
-/* MI2S GPIO CONFIG */
-static struct request_gpio mi2s_gpio[] = {
- {
- .gpio_no = GPIO_MI2S_WS,
- .gpio_name = "MI2S_WS",
- },
- {
- .gpio_no = GPIO_MI2S_SCLK,
- .gpio_name = "MI2S_SCLK",
- },
- {
- .gpio_no = GPIO_MI2S_DOUT,
- .gpio_name = "MI2S_DOUT",
- },
- {
- .gpio_no = GPIO_MI2S_DIN,
- .gpio_name = "MI2S_DIN",
- },
- {
- .gpio_no = GPIO_MI2S_MCLK,
- .gpio_name = "MI2S_MCLK",
- },
-};
-
static int mdm9625_enable_codec_ext_clk(struct snd_soc_codec *codec,
int enable, bool dapm);
@@ -120,53 +115,104 @@
#define WCD9XXX_MBHC_DEF_BUTTONS 8
#define WCD9XXX_MBHC_DEF_RLOADS 5
-
-static bool gpio_enable;
-
-static int mdm9625_set_mi2s_gpio(void)
+static int mdm9625_set_mi2s_gpio(struct snd_pcm_substream *substream, u32 intf)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_i2s_ctrl *i2s_ctrl = NULL;
+ struct msm_i2s_gpio *pin_data = NULL;
int rtn = 0;
int i;
int j;
- if (gpio_enable == false) {
- for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++) {
- rtn = gpio_request(mi2s_gpio[i].gpio_no,
- mi2s_gpio[i].gpio_name);
- pr_debug("%s: gpio = %d, gpio name = %s\n"
- "rtn = %d\n", __func__,
- mi2s_gpio[i].gpio_no,
- mi2s_gpio[i].gpio_name,
- rtn);
- if (rtn) {
- pr_err("%s: Failed to request gpio %d\n",
- __func__, mi2s_gpio[i].gpio_no);
- /* Release all the GPIO on failure */
- for (j = i; j >= 0; j--)
- gpio_free(mi2s_gpio[j].gpio_no);
- goto err;
- }
+ if (pdata == NULL) {
+ pr_err("%s: pdata is NULL\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+
+ if (intf == MDM_MI2S_PRIM_INTF)
+ i2s_ctrl = pdata->pri_ctrl;
+ else {
+ pr_err("%s: Wrong I2S Interface\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+ if (i2s_ctrl == NULL || i2s_ctrl->pin_data == NULL) {
+ pr_err("%s: Intf ptr NULL\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+ pin_data = i2s_ctrl->pin_data;
+ for (i = 0; i < i2s_ctrl->cnt; i++, pin_data++) {
+ rtn = gpio_request(pin_data->gpio_no,
+ pin_data->gpio_name);
+ pr_debug("%s: gpio = %d, gpio name = %s\n"
+ "rtn = %d\n", __func__,
+ pin_data->gpio_no,
+ pin_data->gpio_name,
+ rtn);
+ if (rtn) {
+ pr_err("%s: Failed to request gpio %d\n",
+ __func__, pin_data->gpio_no);
+ /* Release all the GPIO on failure */
+ for (j = i; j >= 0; j--)
+ gpio_free(pin_data->gpio_no);
+ goto err;
}
- gpio_enable = true;
}
err:
return rtn;
+
}
-static int mdm9625_mi2s_free_gpios(void)
+static int mdm9625_mi2s_free_gpios(struct snd_pcm_substream *substream,
+ u32 intf)
{
int i;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_i2s_ctrl *i2s_ctrl = NULL;
+ struct msm_i2s_gpio *pin_data = NULL;
+ int rtn = 0;
+
pr_debug("%s:", __func__);
- for (i = 0; i < ARRAY_SIZE(mi2s_gpio); i++)
- gpio_free(mi2s_gpio[i].gpio_no);
- gpio_enable = false;
- return 0;
+ if (pdata == NULL) {
+ pr_err("%s: pdata is NULL\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+ if (intf == MDM_MI2S_PRIM_INTF)
+ i2s_ctrl = pdata->pri_ctrl;
+ else {
+ pr_debug("%s: Wrong Interface\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+ if (i2s_ctrl == NULL || i2s_ctrl->pin_data == NULL) {
+ pr_err("%s: Intf ptr NULL\n", __func__);
+ rtn = -EINVAL;
+ goto err;
+ }
+ pin_data = i2s_ctrl->pin_data;
+ for (i = 0; i < i2s_ctrl->cnt; i++, pin_data++) {
+ gpio_free(pin_data->gpio_no);
+ pr_debug("%s: gpio = %d, gpio name = %s\n",
+ __func__, pin_data->gpio_no,
+ pin_data->gpio_name);
+ }
+err:
+ return rtn;
+
}
static int mdm9625_mi2s_clk_ctl(struct snd_soc_pcm_runtime *rtd, bool enable)
{
- struct mdm_mi2s_clk *clk = &prim_clk;
+ struct mdm_mi2s_clk *clk = &clk_ctl;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_card *card = rtd->card;
+ struct clk *bclk = NULL;
struct mdm9625_machine_data *pdata = snd_soc_card_get_drvdata(card);
int ret = 0;
@@ -174,78 +220,52 @@
pr_err("%s:platform data is null\n", __func__);
return -ENODEV;
}
+ bclk = pdata->pri_ctrl->cdc_bit_clk;
if (enable) {
- if (clk->clk_enable == true) {
- pr_info("%s:Device clock already enabled\n", __func__);
- return 0;
+ if (clk->clk_usrs == 0) {
+ /* Set rate core and ibit clock */
+ clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
+ /* Enable clocks. core clock need not be enabled.
+ * Enabling branch clocks indirectly enables
+ * core clock.
+ */
+ ret = clk_prepare_enable(clk->cdc_osr_clk);
+ if (ret != 0) {
+ pr_err("Fail to enable cdc_osr_clk\n");
+ goto exit_osrclk_err;
+ }
}
- /* Set up core clock. */
- clk->cdc_cr_clk = clk_get(cpu_dai->dev, "core_clk");
- if (IS_ERR(clk->cdc_cr_clk)) {
- pr_err("%s: Failed to Core clk %ld\n"
- "CPU dai name %s\n", __func__,
- PTR_ERR(clk->cdc_cr_clk),
- cpu_dai->dev->driver->name);
- return -ENODEV ;
- }
- /* osr clock */
- clk->cdc_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
- if (IS_ERR(clk->cdc_osr_clk)) {
- pr_err("%s: Failed to request OSR %ld\n"
- "CPU dai name %s\n", __func__,
- PTR_ERR(clk->cdc_osr_clk),
- cpu_dai->dev->driver->name);
- clk_put(clk->cdc_cr_clk);
- return -ENODEV ;
- }
+ clk->clk_usrs++;
/* ibit clock */
- clk->cdc_bit_clk = clk_get(cpu_dai->dev, "ibit_clk");
- if (IS_ERR(clk->cdc_bit_clk)) {
+ bclk = clk_get(cpu_dai->dev, "ibit_clk");
+ if (IS_ERR(bclk)) {
pr_err("%s: Failed to request Bit %ld\n"
"CPU dai name %s\n", __func__,
- PTR_ERR(clk->cdc_bit_clk),
+ PTR_ERR(bclk),
cpu_dai->dev->driver->name);
- clk_put(clk->cdc_cr_clk);
- clk_put(clk->cdc_osr_clk);
return -ENODEV ;
}
- /* Set rate core and ibit clock */
- clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
- clk_set_rate(clk->cdc_bit_clk, MDM_IBIT_CLK_DIV_1P56MHZ);
-
- /* Enable clocks. core clock need not be enabled.
- * Enabling branch clocks indirectly enables
- * core clock.
- */
- ret = clk_prepare_enable(clk->cdc_osr_clk);
- if (ret != 0) {
- pr_err("Fail to enable cdc_osr_clk\n");
- goto exit_osrclk_err;
- }
- ret = clk_prepare_enable(clk->cdc_bit_clk);
+ clk_set_rate(bclk, MDM_IBIT_CLK_DIV_1P56MHZ);
+ ret = clk_prepare_enable(bclk);
if (ret != 0) {
pr_err("Fail to enable cdc_bit_clk\n");
goto exit_bclk_err;
}
- clk->clk_enable = true;
return ret;
} else {
- clk->clk_enable = false;
+ if (clk->clk_usrs > 0)
+ clk->clk_usrs--;
ret = 0;
goto exit_bclk_err;
}
exit_bclk_err:
- clk_disable_unprepare(clk->cdc_bit_clk);
- clk_put(clk->cdc_bit_clk);
+ clk_disable_unprepare(bclk);
+ clk_put(bclk);
exit_osrclk_err:
- clk_disable_unprepare(clk->cdc_osr_clk);
- clk_put(clk->cdc_osr_clk);
- clk_put(clk->cdc_cr_clk);
- clk->cdc_cr_clk = NULL;
- clk->cdc_bit_clk = NULL;
- clk->cdc_osr_clk = NULL;
- clk->clk_enable = false;
+ if (clk->clk_usrs == 0)
+ clk_disable_unprepare(clk->cdc_osr_clk);
+ bclk = NULL;
return ret;
}
@@ -254,7 +274,7 @@
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int ret;
if (atomic_dec_return(&mi2s_ref_count) == 0) {
- mdm9625_mi2s_free_gpios();
+ mdm9625_mi2s_free_gpios(substream, MDM_MI2S_PRIM_INTF);
ret = mdm9625_mi2s_clk_ctl(rtd, false);
if (ret < 0)
pr_err("%s:clock disable failed\n", __func__);
@@ -269,7 +289,7 @@
int ret = 0;
if (atomic_inc_return(&mi2s_ref_count) == 1) {
- mdm9625_set_mi2s_gpio();
+ mdm9625_set_mi2s_gpio(substream, MDM_MI2S_PRIM_INTF);
ret = mdm9625_mi2s_clk_ctl(rtd, true);
if (ret < 0) {
pr_err("set format for codec dai failed\n");
@@ -397,13 +417,36 @@
int enable, bool dapm)
{
int ret = 0;
+ struct mdm9625_machine_data *pdata =
+ snd_soc_card_get_drvdata(codec->card);
+ struct mdm_mi2s_clk *clk = &clk_ctl;
+
pr_debug("%s: enable = %d codec name %s\n", __func__,
- enable, codec->name);
+ enable, codec->name);
mutex_lock(&cdc_mclk_mutex);
- if (enable)
+
+ if (enable) {
+ if (clk->clk_usrs == 0) {
+ /* Set rate core and ibit clock */
+ clk_set_rate(clk->cdc_cr_clk, pdata->mclk_freq);
+ /* Enable clocks. core clock need not be enabled.
+ * Enabling branch clocks indirectly enables
+ * core clock.
+ */
+ ret = clk_prepare_enable(clk->cdc_osr_clk);
+ if (ret != 0)
+ pr_err("Fail to enable cdc_osr_clk\n");
+ }
+ clk->clk_usrs++;
taiko_mclk_enable(codec, 1, dapm);
- else
+
+ } else {
+ if (clk->clk_usrs > 0)
+ clk->clk_usrs--;
+ if (clk->clk_usrs == 0)
+ clk_disable_unprepare(clk->cdc_osr_clk);
taiko_mclk_enable(codec, 0, dapm);
+ }
mutex_unlock(&cdc_mclk_mutex);
return ret;
}
@@ -464,13 +507,45 @@
mdm9625_mi2s_tx_ch_put),
};
+static int msm9625_set_codec_mclk(struct snd_soc_pcm_runtime *rtd, bool enable)
+{
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct mdm_mi2s_clk *clk = &clk_ctl;
+ int ret = 0;
+
+ if (clk->clk_usrs == 0) {
+ clk->cdc_cr_clk = clk_get(cpu_dai->dev, "core_clk");
+ if (IS_ERR(clk->cdc_cr_clk)) {
+ pr_err("%s: Failed to Core clk %ld\n"
+ "CPU dai name %s\n", __func__,
+ PTR_ERR(clk->cdc_cr_clk),
+ cpu_dai->dev->driver->name);
+ return -ENODEV ;
+ }
+ /* osr clock */
+ clk->cdc_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
+ if (IS_ERR(clk->cdc_osr_clk)) {
+ pr_err("%s: Failed to request OSR %ld\n"
+ "CPU dai name %s\n", __func__,
+ PTR_ERR(clk->cdc_osr_clk),
+ cpu_dai->dev->driver->name);
+ clk_put(clk->cdc_cr_clk);
+ return -ENODEV ;
+ }
+ } else {
+ pr_err("%s: Failed to get MCLK\n", __func__);
+ ret = -ENODEV ;
+ }
+ return ret;
+}
+
static int mdm9625_mi2s_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- pr_info("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+ pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
rtd->pmdown_time = 0;
err = snd_soc_add_codec_controls(codec, mdm_snd_controls,
@@ -491,8 +566,9 @@
snd_soc_dapm_sync(dapm);
/* start mbhc */
- mdm9625_set_mi2s_gpio();
- mdm9625_mi2s_clk_ctl(rtd, true);
+ err = msm9625_set_codec_mclk(rtd, true);
+ if (err < 0)
+ return err;
mbhc_cfg.calibration = def_taiko_mbhc_cal();
if (mbhc_cfg.calibration)
err = taiko_hs_detect(codec, &mbhc_cfg);
@@ -683,14 +759,103 @@
.num_links = ARRAY_SIZE(mdm9625_dai),
};
+static int mdm9625_dtparse_mi2s(struct platform_device *pdev,
+ struct mdm9625_machine_data **pdata)
+{
+ int ret = 0, i = 0;
+ struct msm_i2s_gpio *pin_data = NULL;
+ struct msm_i2s_ctrl *ctrl;
+ struct msm_i2s_gpio *mclk_pin = NULL;
+ unsigned int gpio_no[4];
+ unsigned int dt_mclk = 0;
+ enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
+ int prim_cnt = 0;
+ pin_data = devm_kzalloc(&pdev->dev, (4 *
+ sizeof(struct msm_i2s_gpio)),
+ GFP_KERNEL);
+ mclk_pin = devm_kzalloc(&pdev->dev,
+ sizeof(struct msm_i2s_gpio),
+ GFP_KERNEL);
+
+ if (!pin_data || !mclk_pin) {
+ dev_err(&pdev->dev, "No memory for gpio\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ for (i = 0; i < ARRAY_SIZE(gpio_no); i++) {
+ gpio_no[i] = of_get_named_gpio_flags(pdev->dev.of_node,
+ mdm_i2s_gpio_name[i][DT_PARSE_INDEX],
+ 0, &flags);
+ if (gpio_no[i] > 0) {
+ pin_data[i].gpio_name =
+ mdm_i2s_gpio_name[prim_cnt][GPIO_NAME_INDEX];
+ pin_data[i].gpio_no = gpio_no[i];
+ dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
+ "0x%x\n", __func__,
+ pin_data[i].gpio_name,
+ pin_data[i].gpio_no);
+ prim_cnt++;
+ } else {
+ dev_err(&pdev->dev, "%s:Invalid I2S GPIO[%s] = %x\n",
+ __func__,
+ mdm_i2s_gpio_name[i][GPIO_NAME_INDEX],
+ gpio_no[i]);
+ ret = -ENODEV;
+ goto err;
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE(mdm_mclk_gpio); i++) {
+ dt_mclk = of_get_named_gpio_flags(pdev->dev.of_node,
+ mdm_mclk_gpio[i][DT_PARSE_INDEX], 0,
+ &flags);
+ if (dt_mclk > 0) {
+ mclk_pin->gpio_name =
+ mdm_mclk_gpio[i][GPIO_NAME_INDEX];
+ mclk_pin->gpio_no = dt_mclk;
+ ret = gpio_request(mclk_pin->gpio_no,
+ mclk_pin->gpio_name);
+ dev_dbg(&pdev->dev, "%s:Request MCLK Gpio\n"
+ "gpio[%s] = 0x%x\n", __func__,
+ mclk_pin->gpio_name,
+ dt_mclk);
+ } else {
+ dev_err(&pdev->dev, "%s:MCLK gpio is incorrect\n",
+ __func__);
+ ret = -ENODEV;
+ goto err;
+ }
+ }
+
+ ctrl = devm_kzalloc(&pdev->dev,
+ sizeof(struct msm_i2s_ctrl), GFP_KERNEL);
+ if (!ctrl) {
+ dev_err(&pdev->dev, "No memory for gpio\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ ctrl->pin_data = pin_data;
+ ctrl->cnt = prim_cnt;
+ (*pdata)->pri_ctrl = ctrl;
+ (*pdata)->mclk_pin = mclk_pin;
+ return ret;
+
+err:
+ if (mclk_pin)
+ devm_kfree(&pdev->dev, mclk_pin);
+ if (pin_data)
+ devm_kfree(&pdev->dev, pin_data);
+ return ret;
+}
+
static __devinit int mdm9625_asoc_machine_probe(struct platform_device *pdev)
{
int ret;
struct snd_soc_card *card = &snd_soc_card_mdm9625;
+ struct mdm_mi2s_clk *clk = &clk_ctl;
struct mdm9625_machine_data *pdata;
mutex_init(&cdc_mclk_mutex);
- gpio_enable = false;
+ clk->clk_usrs = 0;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform supplied from device tree\n");
return -EINVAL;
@@ -698,19 +863,17 @@
pdata = devm_kzalloc(&pdev->dev, sizeof(struct mdm9625_machine_data),
GFP_KERNEL);
if (!pdata) {
- dev_err(&pdev->dev, "Can't allocate msm8974_asoc_mach_data\n");
+ dev_err(&pdev->dev, "Can't allocate mdm9625_asoc_mach_data\n");
ret = -ENOMEM;
goto err;
}
- card->dev = &pdev->dev;
- platform_set_drvdata(pdev, card);
- snd_soc_card_set_drvdata(card, pdata);
- ret = snd_soc_of_parse_card_name(card, "qcom,model");
- if (ret)
+ ret = mdm9625_dtparse_mi2s(pdev, &pdata);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: mi2s Pin data parse failed",
+ __func__);
goto err;
- ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
- if (ret)
- goto err;
+ }
ret = of_property_read_u32(pdev->dev.of_node,
"qcom,taiko-mclk-clk-freq",
&pdata->mclk_freq);
@@ -728,6 +891,15 @@
ret = -EINVAL;
goto err;
}
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, pdata);
+ ret = snd_soc_of_parse_card_name(card, "qcom,model");
+ if (ret)
+ goto err;
+ ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+ if (ret)
+ goto err;
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index cef8659..784d516 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-2013, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1441,7 +1441,7 @@
.name = "MSM8960 Media3",
.stream_name = "MultiMedia3",
.cpu_dai_name = "MultiMedia3",
- .platform_name = "msm-pcm-dsp",
+ .platform_name = "msm-multi-ch-pcm-dsp",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index b7b4d51..f871f52 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -322,8 +322,8 @@
(app_cb)q6asm_event_handler, prtd);
if (!prtd->audio_client) {
pr_debug("%s: Could not allocate memory\n", __func__);
- kfree(prtd);
mutex_unlock(&prtd->lock);
+ kfree(prtd);
return -ENOMEM;
}
hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 841d313..8237d81 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.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
@@ -71,6 +71,10 @@
static const DECLARE_TLV_DB_LINEAR(multimedia5_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
+static int msm_route_multimedia3_vol_control;
+static const DECLARE_TLV_DB_LINEAR(multimedia3_rx_vol_gain, 0,
+ INT_RX_VOL_MAX_STEPS);
+
static int msm_route_compressed_vol_control;
static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
@@ -78,6 +82,10 @@
static int msm_route_compressed2_vol_control;
static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
+
+static int msm_route_compressed3_vol_control;
+static const DECLARE_TLV_DB_LINEAR(compressed3_rx_vol_gain, 0,
+ INT_RX_VOL_MAX_STEPS);
static int msm_route_ec_ref_rx;
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
@@ -982,6 +990,23 @@
return 0;
}
+static int msm_routing_get_multimedia3_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = msm_route_multimedia3_vol_control;
+ return 0;
+}
+
+static int msm_routing_set_multimedia3_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (!multi_ch_pcm_set_volume(ucontrol->value.integer.value[0]))
+ msm_route_multimedia3_vol_control =
+ ucontrol->value.integer.value[0];
+
+ return 0;
+}
+
static int msm_routing_get_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1016,6 +1041,22 @@
return 0;
}
+static int msm_routing_get_compressed3_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = msm_route_compressed3_vol_control;
+ return 0;
+}
+
+static int msm_routing_set_compressed3_vol_mixer(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ if (!compressed_set_volume(ucontrol->value.integer.value[0]))
+ msm_route_compressed3_vol_control =
+ ucontrol->value.integer.value[0];
+ return 0;
+}
+
static int msm_routing_get_srs_trumedia_control(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2124,6 +2165,12 @@
msm_routing_set_multimedia5_vol_mixer, multimedia5_rx_vol_gain),
};
+static const struct snd_kcontrol_new multimedia3_vol_mixer_controls[] = {
+ SOC_SINGLE_EXT_TLV("HIFI4 RX Volume", SND_SOC_NOPM, 0,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_multimedia3_vol_mixer,
+ msm_routing_set_multimedia3_vol_mixer, multimedia3_rx_vol_gain),
+};
+
static const struct snd_kcontrol_new compressed_vol_mixer_controls[] = {
SOC_SINGLE_EXT_TLV("COMPRESSED RX Volume", SND_SOC_NOPM, 0,
INT_RX_VOL_GAIN, 0, msm_routing_get_compressed_vol_mixer,
@@ -2136,6 +2183,12 @@
msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
};
+static const struct snd_kcontrol_new compressed3_vol_mixer_controls[] = {
+ SOC_SINGLE_EXT_TLV("COMPRESSED3 RX Volume", SND_SOC_NOPM, 0,
+ INT_RX_VOL_GAIN, 0, msm_routing_get_compressed3_vol_mixer,
+ msm_routing_set_compressed3_vol_mixer, compressed3_rx_vol_gain),
+};
+
static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "SRS TruMedia",
@@ -3188,13 +3241,22 @@
ARRAY_SIZE(multimedia5_vol_mixer_controls));
snd_soc_add_platform_controls(platform,
+ multimedia3_vol_mixer_controls,
+ ARRAY_SIZE(multimedia3_vol_mixer_controls));
+
+ snd_soc_add_platform_controls(platform,
compressed_vol_mixer_controls,
ARRAY_SIZE(compressed_vol_mixer_controls));
+
snd_soc_add_platform_controls(platform,
compressed2_vol_mixer_controls,
ARRAY_SIZE(compressed2_vol_mixer_controls));
snd_soc_add_platform_controls(platform,
+ compressed3_vol_mixer_controls,
+ ARRAY_SIZE(compressed3_vol_mixer_controls));
+
+ snd_soc_add_platform_controls(platform,
lpa_SRS_trumedia_controls,
ARRAY_SIZE(lpa_SRS_trumedia_controls));
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index bb9f2be..d674b8b 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -170,8 +170,12 @@
}
} else {
- if (machine_is_msm8930_mtp()
- || machine_is_msm8930_fluid()) {
+ /*
+ * 8930 CDP does not have a 5V speaker boost,
+ * hence the GPIO enable for speaker boost is
+ * only required for platforms other than CDP
+ */
+ if (!machine_is_msm8930_cdp()) {
ret = msm8930_cfg_spkr_gpio(
SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
if (ret) {
@@ -208,8 +212,7 @@
return;
}
- if (machine_is_msm8930_mtp()
- || machine_is_msm8930_fluid()) {
+ if (!machine_is_msm8930_cdp()) {
pr_debug("%s: Free speaker boost gpio %u\n",
__func__, SPKR_BOOST_GPIO);
gpio_direction_output(SPKR_BOOST_GPIO, 0);
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 2f4c256..a7a80a6 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -1259,6 +1259,12 @@
SOC_ENUM_EXT("PRI MI2S TX Format", mi2s_config_enum[0],
msm_dai_q6_mi2s_format_get,
msm_dai_q6_mi2s_format_put),
+ SOC_ENUM_EXT("SEC MI2S RX Format", mi2s_config_enum[0],
+ msm_dai_q6_mi2s_format_get,
+ msm_dai_q6_mi2s_format_put),
+ SOC_ENUM_EXT("SEC MI2S TX Format", mi2s_config_enum[0],
+ msm_dai_q6_mi2s_format_get,
+ msm_dai_q6_mi2s_format_put),
};
static int msm_dai_q6_dai_mi2s_probe(struct snd_soc_dai *dai)
@@ -1267,26 +1273,37 @@
dev_get_drvdata(dai->dev);
struct snd_kcontrol *kcontrol = NULL;
int rc = 0;
+ const struct snd_kcontrol_new *ctrl = NULL;
if (mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.i2s.channel_mode) {
- kcontrol = snd_ctl_new1(&mi2s_config_controls[0],
+ if (!strncmp(dai->name, "msm-dai-q6-mi2s.0", 17))
+ ctrl = &mi2s_config_controls[0];
+ if (!strncmp(dai->name, "msm-dai-q6-mi2s.1", 17))
+ ctrl = &mi2s_config_controls[3];
+ kcontrol = snd_ctl_new1(ctrl,
&mi2s_dai_data->rx_dai.mi2s_dai_data);
rc = snd_ctl_add(dai->card->snd_card, kcontrol);
if (IS_ERR_VALUE(rc)) {
- dev_err(dai->dev, "%s: err add RX fmt ctl\n", __func__);
+ dev_err(dai->dev, "%s: err add RX fmt ctl DAI = %s\n",
+ __func__, dai->name);
goto rtn;
}
}
if (mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.i2s.channel_mode) {
+ if (!strncmp(dai->name, "msm-dai-q6-mi2s.0", 17))
+ ctrl = &mi2s_config_controls[2];
+ if (!strncmp(dai->name, "msm-dai-q6-mi2s.1", 17))
+ ctrl = &mi2s_config_controls[4];
rc = snd_ctl_add(dai->card->snd_card,
- snd_ctl_new1(&mi2s_config_controls[2],
+ snd_ctl_new1(ctrl,
&mi2s_dai_data->tx_dai.mi2s_dai_data));
if (IS_ERR_VALUE(rc)) {
if (kcontrol)
snd_ctl_remove(dai->card->snd_card, kcontrol);
- dev_err(dai->dev, "%s: err add TX fmt ctl\n", __func__);
+ dev_err(dai->dev, "%s: err add TX fmt ctl DAI = %s\n",
+ __func__, dai->name);
}
}
rtn:
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 58300c4..26f634b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -188,6 +188,8 @@
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
{ AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, 0, 0, 0},
{ AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, 0, 0, 0},
};
@@ -1106,6 +1108,21 @@
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX ,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1209,6 +1226,9 @@
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -1852,11 +1872,14 @@
SND_SOC_DAPM_AIF_OUT("MI2S_RX", "MI2S Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback",
0, 0, 0, 0),
-
+ SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MI2S_TX", "MI2S Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
0, 0, 0 , 0),
@@ -1919,6 +1942,9 @@
SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
quaternary_mi2s_rx_mixer_controls,
ARRAY_SIZE(quaternary_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ secondary_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
@@ -2068,6 +2094,13 @@
{"QUAT_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Audio Mixer"},
+
+ {"SEC_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"SEC_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"SEC_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"SEC_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Audio Mixer"},
+
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
{"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"},
{"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"},
@@ -2075,6 +2108,7 @@
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
@@ -2249,10 +2283,11 @@
{"BE_OUT", NULL, "HDMI"},
{"BE_OUT", NULL, "MI2S_RX"},
{"BE_OUT", NULL, "QUAT_MI2S_RX"},
-
+ {"BE_OUT", NULL, "SEC_MI2S_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"MI2S_TX", NULL, "BE_IN"},
{"QUAT_MI2S_TX", NULL, "BE_IN"},
+ {"SEC_MI2S_TX", NULL, "BE_IN"},
{"SLIMBUS_0_TX", NULL, "BE_IN" },
{"SLIMBUS_1_TX", NULL, "BE_IN" },
{"SLIMBUS_3_TX", NULL, "BE_IN" },
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index be646ed..69b3fe3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -35,6 +35,8 @@
#define LPASS_BE_MI2S_TX "MI2S_TX"
#define LPASS_BE_QUAT_MI2S_RX "QUAT_MI2S_RX"
#define LPASS_BE_QUAT_MI2S_TX "QUAT_MI2S_TX"
+#define LPASS_BE_SEC_MI2S_RX "SEC_MI2S_RX"
+#define LPASS_BE_SEC_MI2S_TX "SEC_MI2S_TX"
#define LPASS_BE_STUB_RX "STUB_RX"
#define LPASS_BE_STUB_TX "STUB_TX"
#define LPASS_BE_SLIMBUS_1_RX "SLIMBUS_1_RX"
@@ -99,6 +101,8 @@
MSM_BACKEND_DAI_EXTPROC_EC_TX,
MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+ MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
MSM_BACKEND_DAI_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9387d21..d836610 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -174,6 +174,7 @@
case VOICE_PLAYBACK_TX:
case RT_PROXY_PORT_001_RX:
case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+ case AFE_PORT_ID_SECONDARY_MI2S_RX:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -193,6 +194,7 @@
case INT_BT_SCO_TX:
case RT_PROXY_PORT_001_TX:
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+ case AFE_PORT_ID_SECONDARY_MI2S_TX:
ret = MSM_AFE_PORT_TYPE_TX;
break;
@@ -564,6 +566,11 @@
return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ case AFE_PORT_ID_SECONDARY_MI2S_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
+ case AFE_PORT_ID_SECONDARY_MI2S_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
+
default: return -EINVAL;
}
}
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 033cb8e..5e2e618 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -52,6 +52,11 @@
return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX;
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ case AFE_PORT_ID_SECONDARY_MI2S_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX;
+ case AFE_PORT_ID_SECONDARY_MI2S_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX;
+
default: return -EINVAL;
}
}
@@ -89,6 +94,10 @@
return AFE_PORT_ID_QUATERNARY_MI2S_RX;
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
return AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ case AFE_PORT_ID_SECONDARY_MI2S_RX:
+ return AFE_PORT_ID_SECONDARY_MI2S_RX;
+ case AFE_PORT_ID_SECONDARY_MI2S_TX:
+ return AFE_PORT_ID_SECONDARY_MI2S_TX;
default: return -EINVAL;
}
@@ -147,6 +156,8 @@
case RT_PROXY_PORT_001_TX:
case AFE_PORT_ID_QUATERNARY_MI2S_RX:
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+ case AFE_PORT_ID_SECONDARY_MI2S_RX:
+ case AFE_PORT_ID_SECONDARY_MI2S_TX:
{
ret = 0;
break;