Merge "Bluetooth: Handle error command status for AUTH_REQUESTED command" into msm-3.0
diff --git a/Documentation/devicetree/bindings/spmi/msm-spmi.txt b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
index fa91514..8fe415b 100644
--- a/Documentation/devicetree/bindings/spmi/msm-spmi.txt
+++ b/Documentation/devicetree/bindings/spmi/msm-spmi.txt
@@ -25,8 +25,8 @@
Second level
Required properties :
- - spmi-dev-container: Used by the parser to understand that this is the second
- level of the tree.
+ - spmi-slave-container: Used by the parser to understand that this is the
+ second level of the tree.
- reg: <a b> where a is < 65536 and b is a size. Each device supports an
arbitrary number of address ranges.
- compatible : "qcom," prefixed string to match against the driver.
@@ -50,7 +50,7 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <0xd>;
- spmi-dev-container;
+ spmi-slave-container;
coincell@2800 {
compatible = "qcom,qpnp-coincell";
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0a7fe5f..b46d7f1 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -140,7 +140,7 @@
Enable ticket locks, which help preserve fairness among
contended locks and prevent livelock in multicore systems.
Say 'y' if system stability is important.
- default y if ARCH_MSM_SCORPIONMP
+ default y if ARCH_MSM_SCORPIONMP || ARCH_MSM_KRAITMP
depends on SMP
config RWSEM_GENERIC_SPINLOCK
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 3d4b37d..c671d32 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -114,7 +114,6 @@
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index ebff2d2..80252d8 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -112,7 +112,6 @@
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 58aece2..0b89d45 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -37,6 +37,10 @@
CONFIG_CPU_HAS_L2_PMU=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_NO_HZ=y
@@ -102,6 +106,8 @@
# CONFIG_MFD_SUPPORT is not set
CONFIG_ION=y
CONFIG_ION_MSM=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_CI13XXX_MSM=y
@@ -168,13 +174,3 @@
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_MSM_SMD=y
-CONFIG_MSM_SMD_PKG4=y
-CONFIG_MSM_SMD_PKT=y
-CONFIG_MSM_SMD_DEBUG=y
-CONFIG_MSM_SMD_TTY=y
-CONFIG_MSM_N_WAY_SMD=y
-CONFIG_MSM_N_WAY_SMSM=y
-CONFIG_MSM_SMD_LOGGING=y
-CONFIG_MSM_IPC_ROUTER=y
-CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 642d843..f4646dc 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -45,7 +45,6 @@
# CONFIG_MSM_HW3D is not set
CONFIG_MSM7X27A_AUDIO=y
CONFIG_MSM_DMA_TEST=y
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_MSM_SLEEP_STATS_DEVICE=y
CONFIG_BT_MSM_PINTEST=y
CONFIG_MSM_RPC_VIBRATOR=y
@@ -235,6 +234,7 @@
# CONFIG_MT9T013 is not set
# CONFIG_MT9D112 is not set
CONFIG_OV5640=y
+CONFIG_OV5647=y
CONFIG_WEBCAM_OV7692_QRD=y
CONFIG_WEBCAM_OV9726=y
# CONFIG_MT9P012 is not set
@@ -330,9 +330,9 @@
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_SHIRQ=y
-# CONFIG_SCHED_DEBUG is not set
CONFIG_LOCKUP_DETECTOR=y
CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_SLAB_LEAK=y
@@ -342,7 +342,6 @@
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_LIST=y
-CONFIG_LATENCYTOP=y
CONFIG_DEBUG_PAGEALLOC=y
# CONFIG_FTRACE is not set
CONFIG_DYNAMIC_DEBUG=y
@@ -352,4 +351,3 @@
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRC_CCITT=y
-CONFIG_OV5647=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index e319f0d..5466498 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -40,7 +40,6 @@
CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -223,7 +222,6 @@
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_MSM=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index b4babeb..1a70816 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -40,7 +40,6 @@
CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
@@ -224,7 +223,6 @@
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_MSM=y
@@ -371,7 +369,6 @@
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
CONFIG_LOCKUP_DETECTOR=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_SCHED_DEBUG is not set
@@ -380,7 +377,6 @@
CONFIG_DEBUG_SLAB=y
CONFIG_DEBUG_SLAB_LEAK=y
# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_SPINLOCK=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_STACK_USAGE=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index b3a45d2..1365641 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -70,7 +70,6 @@
CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_MSM_WATCHDOG=y
CONFIG_MSM_DLOAD_MODE=y
-# CONFIG_MSM_JTAG_V7 is not set
CONFIG_MSM_ETM=y
CONFIG_MSM_SLEEP_STATS=y
CONFIG_MSM_GSBI9_UART=y
@@ -272,7 +271,6 @@
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -299,7 +297,6 @@
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_SX150X=y
-# CONFIG_MPP_PMIC8901 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
CONFIG_BATTERY_MSM8X60=y
@@ -324,9 +321,9 @@
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_USB_VIDEO_CLASS=y
+CONFIG_IMX074=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
-CONFIG_IMX074=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 1f511bb..fa4ba4e 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -271,7 +271,6 @@
CONFIG_KEYBOARD_GPIO=y
CONFIG_KEYBOARD_MATRIX=y
CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_KEYBOARD_PMIC8058 is not set
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
@@ -299,7 +298,6 @@
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_SX150X=y
-# CONFIG_MPP_PMIC8901 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_BATTERY_MSM is not set
CONFIG_BATTERY_MSM8X60=y
@@ -324,9 +322,9 @@
CONFIG_VIDEO_DEV=y
# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
CONFIG_USB_VIDEO_CLASS=y
+CONFIG_IMX074=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
-CONFIG_IMX074=y
CONFIG_MSM_GEMINI=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index f54573d..e4456dc 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -227,7 +227,7 @@
CONFIG_BLK_DEV_RAM=y
CONFIG_HAPTIC_ISA1200=y
CONFIG_PMIC8XXX_VIBRATOR=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -301,6 +301,7 @@
CONFIG_MFD_PM8821_CORE=y
CONFIG_MFD_PM8038_CORE=y
CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_WCD9304_CODEC=y
CONFIG_WCD9310_CODEC=y
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_GPIO=y
@@ -310,15 +311,15 @@
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_IMX074=y
CONFIG_MT9M114=y
+CONFIG_IMX074_ACT=y
CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV2720=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX074=y
-CONFIG_IMX074_ACT=y
-CONFIG_OV2720=y
-CONFIG_S5K3L1YX=y
CONFIG_MSM_GEMINI=y
+CONFIG_S5K3L1YX=y
CONFIG_RADIO_IRIS=y
CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
@@ -335,9 +336,9 @@
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
+CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
-CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
@@ -351,7 +352,6 @@
CONFIG_HID_APPLE=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
-CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 2b56a11..406992a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -229,7 +229,7 @@
CONFIG_BLK_DEV_RAM=y
CONFIG_HAPTIC_ISA1200=y
CONFIG_PMIC8XXX_VIBRATOR=y
-CONFIG_TZCOM=y
+CONFIG_QSEECOM=y
CONFIG_SCSI=y
CONFIG_SCSI_TGT=y
CONFIG_BLK_DEV_SD=y
@@ -297,12 +297,11 @@
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8960=y
-CONFIG_THERMAL_PM8XXX=y
-CONFIG_THERMAL_MONITOR=y
CONFIG_MFD_PM8921_CORE=y
CONFIG_MFD_PM8821_CORE=y
CONFIG_MFD_PM8038_CORE=y
CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_WCD9304_CODEC=y
CONFIG_WCD9310_CODEC=y
CONFIG_REGULATOR_PM8XXX=y
CONFIG_REGULATOR_GPIO=y
@@ -312,15 +311,15 @@
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_USB_VIDEO_CLASS=y
CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_IMX074=y
CONFIG_MT9M114=y
+CONFIG_IMX074_ACT=y
CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV2720=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX074=y
-CONFIG_IMX074_ACT=y
-CONFIG_OV2720=y
-CONFIG_S5K3L1YX=y
CONFIG_MSM_GEMINI=y
+CONFIG_S5K3L1YX=y
CONFIG_RADIO_IRIS=y
CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
@@ -353,7 +352,6 @@
CONFIG_HID_APPLE=y
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
-CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_SUSPEND=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 7ba17e6..d4552f8 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -70,6 +70,7 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 65c3f24..4e25f18 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -137,6 +137,11 @@
disable_irq
.endm
+ .macro save_and_disable_irqs_notrace, oldcpsr
+ mrs \oldcpsr, cpsr
+ disable_irq_notrace
+ .endm
+
/*
* Restore interrupt state previously stored in a register. We don't
* guarantee that this will preserve the flags.
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 0083033..de314ea 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -763,6 +763,7 @@
break;
case 0x0490: /* 8960 sim */
case 0x04D0: /* 8960 */
+ case 0x06F0: /* 8064 */
armpmu = armv7_krait_pmu_init();
krait_l2_pmu_init();
break;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 18fbcf6..a2c8827 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -477,6 +477,22 @@
help
Support for the Qualcomm MSM8625 RUMI3 Emulation Platform.
+config MACH_MSM8625_SURF
+ depends on ARCH_MSM8625
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8625 SURF"
+ help
+ Support for the Qualcomm MSM8625 SURF.
+
+config MACH_MSM8625_EVB
+ depends on ARCH_MSM8625
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8625 EVB"
+ help
+ Support for the Qualcomm MSM8625 Reference Design.
+
config MACH_MSM7X30_SURF
depends on ARCH_MSM7X30
depends on !MSM_STACKED_MEMORY
@@ -2082,6 +2098,7 @@
config MSM_RTB_SEPARATE_CPUS
bool "Separate entries for each cpu"
depends on MSM_RTB
+ depends on SMP
help
Under some circumstances, it may be beneficial to give dedicated space
for each cpu to log accesses. Selecting this option will log each cpu
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8347a25..1f3945e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,7 +23,7 @@
obj-y += acpuclock.o
obj-$(CONFIG_ARCH_MSM7X01A) += acpuclock-7201.o
obj-$(CONFIG_ARCH_MSM7X25) += acpuclock-7201.o
-obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7201.o
+obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7201.o clock-pll.o
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o
obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
@@ -221,14 +221,18 @@
obj-$(CONFIG_MACH_MSM7X27_SURF) += board-msm7x27.o devices-msm7x27.o
obj-$(CONFIG_MACH_MSM7X27_FFA) += board-msm7x27.o devices-msm7x27.o
obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o devices-msm7x27a.o
-obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
-obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o board-msm7627a-display.o board-msm7627a-wlan.o
+board-7627a-all-objs += board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
+board-7627a-all-objs += board-msm7627a-display.o board-msm7627a-wlan.o
+obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_QRD1) += board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_QRD3) += board-qrd7627a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM7627A_EVB) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_ARCH_MSM8625) += devices-msm7x27a.o clock-pcom-lookup.o
obj-$(CONFIG_MACH_MSM8625_RUMI3) += board-msm7x27a.o
+obj-$(CONFIG_MACH_MSM8625_SURF) += board-msm7x27a.o board-7627a-all.o
+obj-$(CONFIG_MACH_MSM8625_EVB) += board-qrd7627a.o board-7627a-all.o
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o
obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 5a21407..781d896 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -27,7 +27,6 @@
#include <linux/mutex.h>
#include <linux/io.h>
#include <linux/sort.h>
-#include <linux/remote_spinlock.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include <asm/mach-types.h>
@@ -39,17 +38,16 @@
#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
-#define PLLn_MODE(n) (MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
-#define PLLn_L_VAL(n) (MSM_CLK_CTL_BASE + 0x304 + 28 * (n))
-#define PLL4_MODE (MSM_CLK_CTL_BASE + 0x374)
-#define PLL4_L_VAL (MSM_CLK_CTL_BASE + 0x378)
#define POWER_COLLAPSE_KHZ 19200
/* Max CPU frequency allowed by hardware while in standby waiting for an irq. */
#define MAX_WAIT_FOR_IRQ_KHZ 128000
+/**
+ * enum - For acpuclock PLL IDs
+ */
enum {
ACPU_PLL_TCXO = -1,
ACPU_PLL_0 = 0,
@@ -60,15 +58,16 @@
ACPU_PLL_END,
};
-static const struct pll {
- void __iomem *mod_reg;
- const uint32_t l_val_mask;
-} soc_pll[ACPU_PLL_END] = {
- [ACPU_PLL_0] = {PLLn_MODE(ACPU_PLL_0), 0x3f},
- [ACPU_PLL_1] = {PLLn_MODE(ACPU_PLL_1), 0x3f},
- [ACPU_PLL_2] = {PLLn_MODE(ACPU_PLL_2), 0x3f},
- [ACPU_PLL_3] = {PLLn_MODE(ACPU_PLL_3), 0x3f},
- [ACPU_PLL_4] = {PLL4_MODE, 0x3ff},
+struct acpu_clk_src {
+ struct clk *clk;
+ const char *name;
+};
+
+static struct acpu_clk_src pll_clk[ACPU_PLL_END] = {
+ [ACPU_PLL_0] = { .name = "pll0_clk" },
+ [ACPU_PLL_1] = { .name = "pll1_clk" },
+ [ACPU_PLL_2] = { .name = "pll2_clk" },
+ [ACPU_PLL_4] = { .name = "pll4_clk" },
};
struct clock_state {
@@ -78,24 +77,6 @@
struct clk *ebi1_clk;
};
-#define PLL_BASE 7
-
-struct shared_pll_control {
- uint32_t version;
- struct {
- /* Denotes if the PLL is ON. Technically, this can be read
- * directly from the PLL registers, but this feild is here,
- * so let's use it.
- */
- uint32_t on;
- /* One bit for each processor core. The application processor
- * is allocated bit position 1. All other bits should be
- * considered as votes from other processors.
- */
- uint32_t votes;
- } pll[PLL_BASE + ACPU_PLL_END];
-};
-
struct clkctl_acpu_speed {
unsigned int use_for_scaling;
unsigned int a11clk_khz;
@@ -106,14 +87,11 @@
unsigned int ahbclk_div;
int vdd;
unsigned int axiclk_khz;
- unsigned long lpj; /* loops_per_jiffy */
/* Pointers in acpu_freq_tbl[] for max up/down steppings. */
struct clkctl_acpu_speed *down[ACPU_PLL_END];
struct clkctl_acpu_speed *up[ACPU_PLL_END];
};
-static remote_spinlock_t pll_lock;
-static struct shared_pll_control *pll_control;
static struct clock_state drv_state = { 0 };
static struct clkctl_acpu_speed *acpu_freq_tbl;
@@ -136,7 +114,7 @@
{ 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 160000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627 with CDMA capable modem */
@@ -150,7 +128,7 @@
{ 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 160000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627 with GSM capable modem - PLL2 @ 800 */
@@ -164,7 +142,7 @@
{ 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 160000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
{ 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627 with CDMA capable modem - PLL2 @ 800 */
@@ -178,7 +156,7 @@
{ 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 160000 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 160000 },
{ 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627a PLL2 @ 1200MHz with GSM capable modem */
@@ -193,7 +171,7 @@
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627a PLL2 @ 1200MHz with CDMA capable modem */
@@ -208,7 +186,7 @@
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627aa PLL4 @ 1008MHz with GSM capable modem */
@@ -223,7 +201,7 @@
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
@@ -238,7 +216,7 @@
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7625a PLL2 @ 1200MHz with GSM capable modem */
@@ -252,7 +230,7 @@
{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627a PLL2 @ 1200MHz with GSM capable modem */
@@ -267,7 +245,7 @@
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627a PLL2 @ 1200MHz with CDMA capable modem */
@@ -282,7 +260,7 @@
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 120000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 800000, ACPU_PLL_4, 6, 0, 100000, 3, 7, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627aa PLL4 @ 1008MHz with GSM capable modem */
@@ -297,7 +275,7 @@
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7627aa PLL4 @ 1008MHz with CDMA capable modem */
@@ -312,7 +290,7 @@
{ 0, 504000, ACPU_PLL_4, 6, 1, 63000, 3, 6, 200000 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
{ 1, 1008000, ACPU_PLL_4, 6, 0, 126000, 3, 7, 200000},
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
/* 7625a PLL2 @ 1200MHz with GSM capable modem */
@@ -326,29 +304,19 @@
{ 0, 400000, ACPU_PLL_2, 2, 2, 50000, 3, 4, 122880 },
{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
{ 1, 600000, ACPU_PLL_2, 2, 1, 75000, 3, 6, 200000 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
};
-#define PLL_0_MHZ 0
-#define PLL_196_MHZ 10
-#define PLL_245_MHZ 12
-#define PLL_589_MHZ 30
-#define PLL_737_MHZ 38
-#define PLL_800_MHZ 41
-#define PLL_960_MHZ 50
-#define PLL_1008_MHZ 52
-#define PLL_1200_MHZ 62
-
#define PLL_CONFIG(m0, m1, m2, m4) { \
- PLL_##m0##_MHZ, PLL_##m1##_MHZ, PLL_##m2##_MHZ, PLL_##m4##_MHZ, \
+ m0, m1, m2, m4, \
pll0_##m0##_pll1_##m1##_pll2_##m2##_pll4_##m4 \
}
struct pll_freq_tbl_map {
- unsigned int pll0_l;
- unsigned int pll1_l;
- unsigned int pll2_l;
- unsigned int pll4_l;
+ unsigned int pll0_rate;
+ unsigned int pll1_rate;
+ unsigned int pll2_rate;
+ unsigned int pll4_rate;
struct clkctl_acpu_speed *tbl;
};
@@ -405,59 +373,6 @@
}
#endif
-static void pll_enable(void __iomem *addr, unsigned on)
-{
- if (on) {
- writel_relaxed(2, addr);
- mb();
- udelay(5);
- writel_relaxed(6, addr);
- mb();
- udelay(50);
- writel_relaxed(7, addr);
- } else {
- writel_relaxed(0, addr);
- }
-}
-
-static int pc_pll_request(unsigned id, unsigned on)
-{
- int res = 0;
- on = !!on;
-
- if (on)
- pr_debug("Enabling PLL %d\n", id);
- else
- pr_debug("Disabling PLL %d\n", id);
-
- if (id >= ACPU_PLL_END)
- return -EINVAL;
-
- remote_spin_lock(&pll_lock);
- if (on) {
- pll_control->pll[PLL_BASE + id].votes |= 2;
- if (!pll_control->pll[PLL_BASE + id].on) {
- pll_enable(soc_pll[id].mod_reg, 1);
- pll_control->pll[PLL_BASE + id].on = 1;
- }
- } else {
- pll_control->pll[PLL_BASE + id].votes &= ~2;
- if (pll_control->pll[PLL_BASE + id].on
- && !pll_control->pll[PLL_BASE + id].votes) {
- pll_enable(soc_pll[id].mod_reg, 0);
- pll_control->pll[PLL_BASE + id].on = 0;
- }
- }
- remote_spin_unlock(&pll_lock);
-
- if (on)
- pr_debug("PLL enabled\n");
- else
- pr_debug("PLL disabled\n");
-
- return res;
-}
-
static int acpuclk_set_vdd_level(int vdd)
{
uint32_t current_vdd;
@@ -576,7 +491,7 @@
if (reason == SETRATE_CPUFREQ) {
if (strt_s->pll != tgt_s->pll && tgt_s->pll != ACPU_PLL_TCXO) {
- rc = pc_pll_request(tgt_s->pll, 1);
+ rc = clk_prepare_enable(pll_clk[tgt_s->pll].clk);
if (rc < 0) {
pr_err("PLL%d enable failed (%d)\n",
tgt_s->pll, rc);
@@ -651,7 +566,7 @@
if (cur_s->pll != ACPU_PLL_TCXO
&& !(plls_enabled & (1 << cur_s->pll))) {
- rc = pc_pll_request(cur_s->pll, 1);
+ rc = clk_prepare_enable(pll_clk[cur_s->pll].clk);
if (rc < 0) {
pr_err("PLL%d enable failed (%d)\n",
cur_s->pll, rc);
@@ -662,8 +577,6 @@
acpuclk_set_div(cur_s);
drv_state.current_speed = cur_s;
- /* Re-adjust lpj for the new clock speed. */
- loops_per_jiffy = cur_s->lpj;
mb();
udelay(50);
}
@@ -684,12 +597,8 @@
if (tgt_s->pll != ACPU_PLL_TCXO)
plls_enabled &= ~(1 << tgt_s->pll);
for (pll = ACPU_PLL_0; pll < ACPU_PLL_END; pll++)
- if (plls_enabled & (1 << pll)) {
- res = pc_pll_request(pll, 0);
- if (res < 0)
- pr_warning("PLL%d disable failed (%d)\n",
- pll, res);
- }
+ if (plls_enabled & (1 << pll))
+ clk_disable_unprepare(pll_clk[pll].clk);
/* Nothing else to do for power collapse. */
if (reason == SETRATE_PC)
@@ -742,9 +651,10 @@
}
drv_state.current_speed = speed;
- if (speed->pll != ACPU_PLL_TCXO)
- if (pc_pll_request(speed->pll, 1))
+ if (speed->pll != ACPU_PLL_TCXO) {
+ if (clk_prepare_enable(pll_clk[speed->pll].clk))
pr_warning("Failed to vote for boot PLL\n");
+ }
/* Fix div2 to 2 for 7x27/5a(aa) targets */
if (!cpu_is_msm7x27()) {
@@ -777,64 +687,52 @@
/*----------------------------------------------------------------------------
* Clock driver initialization
*---------------------------------------------------------------------------*/
-
-static void __init acpu_freq_tbl_fixup(void)
+#define MHZ 1000000
+static void __init select_freq_plan(void)
{
- unsigned long pll0_l, pll1_l, pll2_l, pll4_l;
- struct pll_freq_tbl_map *lst;
+ unsigned long pll_mhz[ACPU_PLL_END];
+ struct pll_freq_tbl_map *t;
+ int i;
- /* Wait for the PLLs to be initialized and then read their frequency.
- */
- do {
- pll0_l = readl_relaxed(PLLn_L_VAL(0)) &
- soc_pll[ACPU_PLL_0].l_val_mask;
- cpu_relax();
- udelay(50);
- } while (pll0_l == 0);
- do {
- pll1_l = readl_relaxed(PLLn_L_VAL(1)) &
- soc_pll[ACPU_PLL_1].l_val_mask;
- cpu_relax();
- udelay(50);
- } while (pll1_l == 0);
- do {
- pll2_l = readl_relaxed(PLLn_L_VAL(2)) &
- soc_pll[ACPU_PLL_2].l_val_mask;
- cpu_relax();
- udelay(50);
- } while (pll2_l == 0);
-
- pr_info("L val: PLL0: %d, PLL1: %d, PLL2: %d\n",
- (int)pll0_l, (int)pll1_l, (int)pll2_l);
-
- if (!cpu_is_msm7x27() && !cpu_is_msm7x25a()) {
- do {
- pll4_l = readl_relaxed(PLL4_L_VAL) &
- soc_pll[ACPU_PLL_4].l_val_mask;
- cpu_relax();
- udelay(50);
- } while (pll4_l == 0);
- pr_info("L val: PLL4: %d\n", (int)pll4_l);
- } else {
- pll4_l = 0;
+ /* Get PLL clocks */
+ for (i = 0; i < ACPU_PLL_END; i++) {
+ if (pll_clk[i].name) {
+ pll_clk[i].clk = clk_get_sys("acpu", pll_clk[i].name);
+ if (IS_ERR(pll_clk[i].clk)) {
+ pll_mhz[i] = 0;
+ continue;
+ }
+ /* Get PLL's Rate */
+ pll_mhz[i] = clk_get_rate(pll_clk[i].clk)/MHZ;
+ }
}
- /* Fix the tables for 7x25a variant to not conflict with 7x27 ones */
+ /*
+ * For the pll configuration used in acpuclock table e.g.
+ * pll0_960_pll1_245_pll2_1200" is same for 7627 and
+ * 7625a (as pll0,pll1,pll2) having same rates, but frequency
+ * table is different for both targets.
+ *
+ * Hence below for loop will not be able to select correct
+ * table based on PLL rates as rates are same. Hence we need
+ * to add this cpu check for selecting the correct acpuclock table.
+ */
if (cpu_is_msm7x25a()) {
- if (pll1_l == PLL_245_MHZ) {
+ if (pll_mhz[ACPU_PLL_1] == 245) {
acpu_freq_tbl =
pll0_960_pll1_245_pll2_1200_25a;
- } else if (pll1_l == PLL_737_MHZ) {
+ } else if (pll_mhz[ACPU_PLL_1] == 737) {
acpu_freq_tbl =
pll0_960_pll1_737_pll2_1200_25a;
}
} else {
/* Select the right table to use. */
- for (lst = acpu_freq_tbl_list; lst->tbl != 0; lst++) {
- if (lst->pll0_l == pll0_l && lst->pll1_l == pll1_l
- && lst->pll2_l == pll2_l
- && lst->pll4_l == pll4_l) {
- acpu_freq_tbl = lst->tbl;
+ for (t = acpu_freq_tbl_list; t->tbl != 0; t++) {
+ if (t->pll0_rate == pll_mhz[ACPU_PLL_0]
+ && t->pll1_rate == pll_mhz[ACPU_PLL_1]
+ && t->pll2_rate == pll_mhz[ACPU_PLL_2]
+ && t->pll4_rate == pll_mhz[ACPU_PLL_4]) {
+ acpu_freq_tbl = t->tbl;
break;
}
}
@@ -862,18 +760,6 @@
return found_khz;
}
-/* Initalize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
-{
- int i;
- const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
- for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
- acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
- base_clk->a11clk_khz,
- acpu_freq_tbl[i].a11clk_khz);
- }
-}
-
static void __init precompute_stepping(void)
{
int i, step_idx;
@@ -945,33 +831,6 @@
}
}
-static void shared_pll_control_init(void)
-{
-#define PLL_REMOTE_SPINLOCK_ID "S:7"
- unsigned smem_size;
-
- remote_spin_lock_init(&pll_lock, PLL_REMOTE_SPINLOCK_ID);
- pll_control = smem_get_entry(SMEM_CLKREGIM_SOURCES, &smem_size);
-
- if (!pll_control) {
- pr_err("Can't find shared PLL control data structure!\n");
- BUG();
- /* There might be more PLLs than what the application processor knows
- * about. But the index used for each PLL is guaranteed to remain the
- * same. */
- } else if (smem_size < sizeof(struct shared_pll_control)) {
- pr_err("Shared PLL control data"
- "structure too small!\n");
- BUG();
- } else if (pll_control->version != 0xCCEE0001) {
- pr_err("Shared PLL control version mismatch!\n");
- BUG();
- } else {
- pr_info("Shared PLL control available.\n");
- return;
- }
-
-}
static struct acpuclk_data acpuclk_7627_data = {
.set_rate = acpuclk_7627_set_rate,
@@ -988,13 +847,11 @@
BUG_ON(IS_ERR(drv_state.ebi1_clk));
mutex_init(&drv_state.lock);
- shared_pll_control_init();
drv_state.max_speed_delta_khz = soc_data->max_speed_delta_khz;
- acpu_freq_tbl_fixup();
+ select_freq_plan();
acpuclk_7627_data.wait_for_irq_khz = find_wait_for_irq_khz();
precompute_stepping();
acpuclk_hw_init();
- lpj_init();
print_acpu_freq_tbl();
acpuclk_register(&acpuclk_7627_data);
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 99c3d78..8d35148 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -194,7 +194,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x200,
.aux_clk_sel = MSM_ACC0_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait0", 1150000 },
+ .vreg[VREG_CORE] = { "krait0", 1300000 },
.vreg[VREG_MEM] = { "krait0_mem", 1150000,
RPM_VREG_VOTER1,
RPM_VREG_ID_PM8921_L24 },
@@ -209,7 +209,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x240,
.aux_clk_sel = MSM_ACC1_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait1", 1150000 },
+ .vreg[VREG_CORE] = { "krait1", 1300000 },
.vreg[VREG_MEM] = { "krait1_mem", 1150000,
RPM_VREG_VOTER2,
RPM_VREG_ID_PM8921_L24 },
@@ -224,7 +224,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x280,
.aux_clk_sel = MSM_ACC2_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait2", 1150000 },
+ .vreg[VREG_CORE] = { "krait2", 1300000 },
.vreg[VREG_MEM] = { "krait2_mem", 1150000,
RPM_VREG_VOTER4,
RPM_VREG_ID_PM8921_L24 },
@@ -239,7 +239,7 @@
.hfpll_base = MSM_HFPLL_BASE + 0x2C0,
.aux_clk_sel = MSM_ACC3_BASE + 0x014,
.l2cpmr_iaddr = L2CPUCPMR_IADDR,
- .vreg[VREG_CORE] = { "krait3", 1150000 },
+ .vreg[VREG_CORE] = { "krait3", 1300000 },
.vreg[VREG_MEM] = { "krait3_mem", 1150000,
RPM_VREG_VOTER5,
RPM_VREG_ID_PM8921_L24 },
@@ -375,6 +375,7 @@
[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
+ [7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
};
static struct msm_bus_scale_pdata bus_client_pdata = {
@@ -546,47 +547,48 @@
#define L2(x) (&l2_freq_tbl_8064[(x)])
static struct l2_level l2_freq_tbl_8064[] = {
[0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
- [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 0 },
- [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
- [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
- [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
[5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
- [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
- [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
- [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 3 },
- [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
- [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
- [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
- [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 3 },
- [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 3 },
- [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
- [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
- [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
- [17] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 4 },
- [18] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 4 },
- [19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 4 },
- [20] = { { 1404000, HFPLL, 1, 0, 0x34 }, 1150000, 1150000, 4 },
- [21] = { { 1458000, HFPLL, 1, 0, 0x36 }, 1150000, 1150000, 5 },
- [22] = { { 1512000, HFPLL, 1, 0, 0x38 }, 1150000, 1150000, 5 },
- [23] = { { 1566000, HFPLL, 1, 0, 0x3A }, 1150000, 1150000, 5 },
- [24] = { { 1620000, HFPLL, 1, 0, 0x3C }, 1150000, 1150000, 5 },
- [25] = { { 1674000, HFPLL, 1, 0, 0x3E }, 1150000, 1150000, 5 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 7 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 7 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 7 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 7 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 7 },
};
/* TODO: Update core voltages when data is available. */
static struct acpu_level acpu_freq_tbl_8064[] = {
- { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 1050000 },
- { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 1050000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(2), 1050000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(3), 1050000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(4), 1050000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(5), 1050000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1050000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1050000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(8), 1150000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(9), 1150000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(10), 1150000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1150000 },
+ { 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
{ 0, { 0 } }
};
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 5bef079..97f8722 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -556,8 +556,7 @@
if (!a2_pc_disabled) {
a2_pc_disabled = 1;
- schedule_delayed_work(&ul_timeout_work,
- msecs_to_jiffies(UL_TIMEOUT_DELAY));
+ ul_wakeup();
}
handle_bam_mux_cmd_open(rx_hdr);
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 486ebd3..f23bf2a 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -102,6 +102,13 @@
static struct msm_gpiomux_config apq8064_cam_common_configs[] = {
{
+ .gpio = 1,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
+ [GPIOMUX_SUSPENDED] = &cam_settings[0],
+ },
+ },
+ {
.gpio = 2,
.settings = {
[GPIOMUX_ACTIVE] = &cam_settings[12],
@@ -111,7 +118,7 @@
{
.gpio = 3,
.settings = {
- [GPIOMUX_ACTIVE] = &cam_settings[1],
+ [GPIOMUX_ACTIVE] = &cam_settings[2],
[GPIOMUX_SUSPENDED] = &cam_settings[0],
},
},
@@ -173,6 +180,16 @@
},
};
+
+#define VFE_CAMIF_TIMER1_GPIO 3
+#define VFE_CAMIF_TIMER2_GPIO 1
+
+static struct msm_camera_sensor_flash_src msm_flash_src = {
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_EXT,
+ ._fsrc.ext_driver_src.led_en = VFE_CAMIF_TIMER1_GPIO,
+ ._fsrc.ext_driver_src.led_flash_en = VFE_CAMIF_TIMER2_GPIO,
+};
+
static struct msm_gpiomux_config apq8064_cam_2d_configs[] = {
};
@@ -419,7 +436,8 @@
};
static struct msm_camera_sensor_flash_data flash_imx074 = {
- .flash_type = MSM_CAMERA_FLASH_NONE,
+ .flash_type = MSM_CAMERA_FLASH_LED,
+ .flash_src = &msm_flash_src
};
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
@@ -518,6 +536,9 @@
I2C_BOARD_INFO("ov2720", 0x6C),
.platform_data = &msm_camera_sensor_ov2720_data,
},
+ {
+ I2C_BOARD_INFO("sc628a", 0x6E),
+ },
};
struct msm_camera_board_info apq8064_camera_board_info = {
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 213215e..9fbb1c7 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -150,24 +150,23 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 192000000,
- .bus_freq = 2,
- .io_fraction = 100,
+ .gpu_freq = 400000000,
+ .bus_freq = 3,
+ .io_fraction = 0,
},
{
- .gpu_freq = 192000000,
+ .gpu_freq = 320000000,
.bus_freq = 2,
- .io_fraction = 100,
+ .io_fraction = 33,
},
{
.gpu_freq = 1920000000,
- .bus_freq = 2,
+ .bus_freq = 1,
.io_fraction = 100,
},
{
- .gpu_freq = 192000000,
- .bus_freq = 2,
- .io_fraction = 100,
+ .gpu_freq = 27000000,
+ .bus_freq = 0,
},
},
.init_level = 0,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index bd5f703..05002a2 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -310,8 +310,8 @@
static struct pm8xxx_irq_platform_data
apq8064_pm8921_irq_pdata __devinitdata = {
.irq_base = PM8921_IRQ_BASE,
- .devirq = PM8921_USR_IRQ_N,
- .irq_trigger_flag = IRQF_TRIGGER_HIGH,
+ .devirq = MSM_GPIO_TO_INT(74),
+ .irq_trigger_flag = IRQF_TRIGGER_LOW,
.dev_id = 0,
};
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 247b230..5a1957b 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -469,15 +469,15 @@
/* SAW regulator constraints */
struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 =
/* ID vreg_name min_uV max_uV */
- SAW_VREG_INIT(S5, "8921_s5", 950000, 1150000);
+ SAW_VREG_INIT(S5, "8921_s5", 950000, 1300000);
struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 =
- SAW_VREG_INIT(S6, "8921_s6", 950000, 1150000);
+ SAW_VREG_INIT(S6, "8921_s6", 950000, 1300000);
struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0 =
/* ID vreg_name min_uV max_uV */
- SAW_VREG_INIT(8821_S0, "8821_s0", 950000, 1150000);
+ SAW_VREG_INIT(8821_S0, "8821_s0", 950000, 1300000);
struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 =
- SAW_VREG_INIT(8821_S1, "8821_s1", 950000, 1150000);
+ SAW_VREG_INIT(8821_S1, "8821_s1", 950000, 1300000);
/* PM8921 regulator constraints */
struct pm8xxx_regulator_platform_data
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 2f94a2e..9d4f0aa 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -16,8 +16,8 @@
#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
#include <linux/mfd/pm8xxx/misc.h>
#include <linux/msm_ssbi.h>
#include <linux/spi/spi.h>
@@ -54,10 +54,12 @@
#include <linux/bootmem.h>
#include <asm/setup.h>
#include <mach/dma.h>
+#include <mach/msm_dsps.h>
#include <mach/msm_bus_board.h>
#include <mach/cpuidle.h>
#include <mach/mdm2.h>
#include <linux/msm_tsens.h>
+#include <mach/msm_xo.h>
#include "msm_watchdog.h"
#include "board-8064.h"
@@ -499,14 +501,14 @@
* does not need to be as high as 2.85V. It is choosen for
* microphone sensitivity purpose.
*/
-static struct tabla_pdata apq8064_tabla_platform_data = {
+static struct wcd9xxx_pdata apq8064_tabla_platform_data = {
.slimbus_slave_device = {
.name = "tabla-slave",
.e_addr = {0, 0, 0x10, 0, 0x17, 2},
},
.irq = MSM_GPIO_TO_INT(42),
.irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
+ .num_irqs = NR_WCD9XXX_IRQS,
.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
@@ -517,7 +519,45 @@
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
.bias3_cfilt_sel = TABLA_CFILT3_SEL,
.bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "VDDD_CDC_D",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_A_1P2V",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
+ },
};
static struct slim_device apq8064_slim_tabla = {
@@ -528,14 +568,14 @@
},
};
-static struct tabla_pdata apq8064_tabla20_platform_data = {
+static struct wcd9xxx_pdata apq8064_tabla20_platform_data = {
.slimbus_slave_device = {
.name = "tabla-slave",
.e_addr = {0, 0, 0x60, 0, 0x17, 2},
},
.irq = MSM_GPIO_TO_INT(42),
.irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
+ .num_irqs = NR_WCD9XXX_IRQS,
.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
@@ -546,7 +586,45 @@
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
.bias3_cfilt_sel = TABLA_CFILT3_SEL,
.bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "VDDD_CDC_D",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_A_1P2V",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
+ },
};
static struct slim_device apq8064_slim_tabla20 = {
@@ -1770,6 +1848,18 @@
},
};
+/* Sensors DSPS platform data */
+#define DSPS_PIL_GENERIC_NAME "dsps"
+static void __init apq8064_init_dsps(void)
+{
+ struct msm_dsps_platform_data *pdata =
+ msm_dsps_device_8064.dev.platform_data;
+ pdata->pil_name = DSPS_PIL_GENERIC_NAME;
+ pdata->gpios = NULL;
+ pdata->gpios_num = 0;
+
+ platform_device_register(&msm_dsps_device_8064);
+}
static void __init apq8064_clock_init(void)
{
@@ -1863,6 +1953,8 @@
BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
regulator_suppress_info_printing();
platform_device_register(&apq8064_device_rpm_regulator);
+ if (msm_xo_init())
+ pr_err("Failed to initialize XO votes\n");
apq8064_clock_init();
apq8064_init_gpiomux();
apq8064_i2c_init();
@@ -1891,6 +1983,7 @@
platform_device_register(&apq8064_slim_ctrl);
slim_register_board_info(apq8064_slim_devices,
ARRAY_SIZE(apq8064_slim_devices));
+ apq8064_init_dsps();
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
acpuclk_init(&acpuclk_8064_soc_data);
msm_spm_l2_init(msm_spm_l2_data);
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index dee1e98..e89bed4 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -122,8 +122,8 @@
static struct msm_mmc_pad_pull sdc1_pad_pull_off_cfg[] = {
{TLMM_PULL_SDC1_CLK, GPIO_CFG_NO_PULL},
- {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_DOWN},
- {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_DOWN}
+ {TLMM_PULL_SDC1_CMD, GPIO_CFG_PULL_UP},
+ {TLMM_PULL_SDC1_DATA, GPIO_CFG_PULL_UP}
};
/* SDC3 pad data */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ad71007..278c08c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -42,6 +42,10 @@
#include <linux/gpio_keys.h>
#include <linux/memory.h>
+#include <linux/slimbus/slimbus.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
@@ -68,12 +72,6 @@
#include <mach/msm_xo.h>
#include <mach/restart.h>
-#ifdef CONFIG_WCD9310_CODEC
-#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
-#endif
-
#include <linux/ion.h>
#include <mach/ion.h>
#include <mach/mdm2.h>
@@ -518,9 +516,9 @@
msm8930_allocate_fb_region();
}
-#ifdef CONFIG_WCD9310_CODEC
+#ifdef CONFIG_WCD9304_CODEC
-#define TABLA_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
+#define SITAR_INTERRUPT_BASE (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS)
/* Micbias setting is based on 8660 CDP/MTP/FLUID requirement
* 4 micbiases are used to power various analog and digital
@@ -531,82 +529,77 @@
* does not need to be as high as 2.85V. It is choosen for
* microphone sensitivity purpose.
*/
-static struct tabla_pdata tabla_platform_data = {
- .slimbus_slave_device = {
- .name = "tabla-slave",
- .e_addr = {0, 0, 0x10, 0, 0x17, 2},
+static struct wcd9xxx_pdata sitar_platform_data = {
+ .slimbus_slave_device = {
+ .name = "sitar-slave",
+ .e_addr = {0, 0, 0x00, 0, 0x17, 2},
},
.irq = MSM_GPIO_TO_INT(62),
- .irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
-
-/*TODO: Replace this with right PM8038 gpio */
-#ifndef MSM8930_PHASE_2
- .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
-#endif
+ .irq_base = SITAR_INTERRUPT_BASE,
+ .num_irqs = NR_WCD9XXX_IRQS,
+ .reset_gpio = 42,
.micbias = {
- .ldoh_v = TABLA_LDOH_2P85_V,
+ .ldoh_v = SITAR_LDOH_2P85_V,
.cfilt1_mv = 1800,
.cfilt2_mv = 1800,
- .cfilt3_mv = 1800,
- .bias1_cfilt_sel = TABLA_CFILT1_SEL,
- .bias2_cfilt_sel = TABLA_CFILT2_SEL,
- .bias3_cfilt_sel = TABLA_CFILT3_SEL,
- .bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
-};
-
-static struct slim_device msm_slim_tabla = {
- .name = "tabla-slim",
- .e_addr = {0, 1, 0x10, 0, 0x17, 2},
- .dev = {
- .platform_data = &tabla_platform_data,
+ .bias1_cfilt_sel = SITAR_CFILT1_SEL,
+ .bias2_cfilt_sel = SITAR_CFILT2_SEL,
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 2200000,
+ .max_uV = 2200000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "VDDD_CDC_D",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_A_1P2V",
+ .min_uV = 1200000,
+ .max_uV = 1200000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
},
};
-static struct tabla_pdata tabla20_platform_data = {
- .slimbus_slave_device = {
- .name = "tabla-slave",
- .e_addr = {0, 0, 0x60, 0, 0x17, 2},
- },
- .irq = MSM_GPIO_TO_INT(62),
- .irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
-
-/*TODO: Replace this with right PM8038 gpio */
-#ifndef MSM8930_PHASE_2
- .reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
-#endif
- .micbias = {
- .ldoh_v = TABLA_LDOH_2P85_V,
- .cfilt1_mv = 1800,
- .cfilt2_mv = 1800,
- .cfilt3_mv = 1800,
- .bias1_cfilt_sel = TABLA_CFILT1_SEL,
- .bias2_cfilt_sel = TABLA_CFILT2_SEL,
- .bias3_cfilt_sel = TABLA_CFILT3_SEL,
- .bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
-};
-
-static struct slim_device msm_slim_tabla20 = {
- .name = "tabla2x-slim",
- .e_addr = {0, 1, 0x60, 0, 0x17, 2},
+static struct slim_device msm_slim_sitar = {
+ .name = "sitar-slim",
+ .e_addr = {0, 1, 0x00, 0, 0x17, 2},
.dev = {
- .platform_data = &tabla20_platform_data,
+ .platform_data = &sitar_platform_data,
},
};
#endif
+
static struct slim_boardinfo msm_slim_devices[] = {
-#ifdef CONFIG_WCD9310_CODEC
+#ifdef CONFIG_WCD9304_CODEC
{
.bus_num = 1,
- .slim_slave = &msm_slim_tabla,
- },
- {
- .bus_num = 1,
- .slim_slave = &msm_slim_tabla20,
+ .slim_slave = &msm_slim_sitar,
},
#endif
/* add more slimbus slaves as needed */
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 37a988a..4dba1be 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -670,6 +670,12 @@
mdp_ui_vectors[0].ab = 2000000000;
mdp_ui_vectors[0].ib = 2000000000;
+ mdp_vga_vectors[0].ab = 2000000000;
+ mdp_vga_vectors[0].ib = 2000000000;
+ mdp_720p_vectors[0].ab = 2000000000;
+ mdp_720p_vectors[0].ib = 2000000000;
+ mdp_1080p_vectors[0].ab = 2000000000;
+ mdp_1080p_vectors[0].ib = 2000000000;
mdp_pdata.mdp_core_clk_rate = 200000000;
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index e3646ed..4e18f89 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -564,6 +564,17 @@
.r_sense = 10,
};
+/**
+ * PM8XXX_PWM_DTEST_CHANNEL_NONE shall be used when no LPG
+ * channel should be in DTEST mode.
+ */
+
+#define PM8XXX_PWM_DTEST_CHANNEL_NONE (-1)
+
+static struct pm8xxx_pwm_platform_data pm8xxx_pwm_pdata = {
+ .dtest_channel = PM8XXX_PWM_DTEST_CHANNEL_NONE,
+};
+
static struct pm8921_platform_data pm8921_platform_data __devinitdata = {
.irq_pdata = &pm8xxx_irq_pdata,
.gpio_pdata = &pm8xxx_gpio_pdata,
@@ -578,6 +589,7 @@
.adc_pdata = &pm8xxx_adc_pdata,
.leds_pdata = &pm8xxx_leds_pdata,
.ccadc_pdata = &pm8xxx_ccadc_pdata,
+ .pwm_pdata = &pm8xxx_pwm_pdata,
};
static struct msm_ssbi_platform_data msm8960_ssbi_pm8921_pdata __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index d98ae56..9c1a439 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -221,7 +221,6 @@
};
VREG_CONSUMERS(USB_OTG) = {
REGULATOR_SUPPLY("8921_usb_otg", NULL),
- REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
};
VREG_CONSUMERS(HDMI_MVS) = {
REGULATOR_SUPPLY("8921_hdmi_mvs", NULL),
@@ -245,12 +244,12 @@
};
VREG_CONSUMERS(EXT_OTG_SW) = {
REGULATOR_SUPPLY("ext_otg_sw", NULL),
+ REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
_apply_uV, _pull_down, _always_on, _supply_regulator, \
- _system_uA, _enable_time, _reg_id, _ocp_enable, \
- _ocp_enable_time) \
+ _system_uA, _enable_time, _reg_id) \
{ \
.init_data = { \
.constraints = { \
@@ -272,8 +271,6 @@
.pull_down_enable = _pull_down, \
.system_uA = _system_uA, \
.enable_time = _enable_time, \
- .ocp_enable = _ocp_enable, \
- .ocp_enable_time = _ocp_enable_time, \
}
#define PM8XXX_LDO(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
@@ -282,7 +279,7 @@
| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
- _supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+ _supply_regulator, _system_uA, _enable_time, _reg_id)
#define PM8XXX_NLDO1200(_id, _name, _always_on, _pull_down, _min_uV, \
_max_uV, _enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -290,7 +287,7 @@
| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
- _supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+ _supply_regulator, _system_uA, _enable_time, _reg_id)
#define PM8XXX_SMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
_enable_time, _supply_regulator, _system_uA, _reg_id) \
@@ -298,32 +295,32 @@
| REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
REGULATOR_CHANGE_DRMS, 0, _pull_down, _always_on, \
- _supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+ _supply_regulator, _system_uA, _enable_time, _reg_id)
#define PM8XXX_FTSMPS(_id, _name, _always_on, _pull_down, _min_uV, _max_uV, \
_enable_time, _supply_regulator, _system_uA, _reg_id) \
PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS \
| REGULATOR_CHANGE_MODE, 0, _pull_down, _always_on, \
- _supply_regulator, _system_uA, _enable_time, _reg_id, 0, 0)
+ _supply_regulator, _system_uA, _enable_time, _reg_id)
#define PM8XXX_VS(_id, _name, _always_on, _pull_down, _enable_time, \
- _ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
+ _supply_regulator, _reg_id) \
PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
- _reg_id, _ocp_enable, _ocp_enable_time)
+ _reg_id)
#define PM8XXX_VS300(_id, _name, _always_on, _pull_down, _enable_time, \
- _ocp_enable, _ocp_enable_time, _supply_regulator, _reg_id) \
+ _supply_regulator, _reg_id) \
PM8XXX_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, \
_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
- _reg_id, _ocp_enable, _ocp_enable_time)
+ _reg_id)
#define PM8XXX_NCP(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
_supply_regulator, _reg_id) \
PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, 0, \
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
- _always_on, _supply_regulator, 0, _enable_time, _reg_id, 0, 0)
+ _always_on, _supply_regulator, 0, _enable_time, _reg_id)
/* Pin control initialization */
#define PM8XXX_PC(_id, _name, _always_on, _pin_fn, _pin_ctrl, \
@@ -472,7 +469,7 @@
GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
PM8921_GPIO_PM_TO_SYS(17), NULL),
GPIO_VREG(EXT_OTG_SW, "ext_otg_sw", "ext_otg_sw_en",
- PM8921_GPIO_PM_TO_SYS(42), "ext_5v"),
+ PM8921_GPIO_PM_TO_SYS(42), "8921_usb_otg"),
};
/* SAW regulator constraints */
@@ -498,13 +495,9 @@
PM8XXX_LDO(L29, "8921_l29", 0, 1, 2050000, 2100000, 200, "8921_s8",
0, 4),
- /*
- * ID name always_on pd en_t ocp ocp_t supply
- * reg_ID
- */
- PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, 1, 500, "ext_otg_sw",
- 5),
- PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, 0, 0, "ext_5v", 6),
+ /* ID name always_on pd en_t supply reg_ID */
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 1, 0, "ext_5v", 5),
+ PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 6),
};
static struct rpm_regulator_init_data
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index cb6674c..9a8b843 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -70,9 +70,8 @@
#include <mach/restart.h>
#ifdef CONFIG_WCD9310_CODEC
-#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
#endif
#include <linux/ion.h>
@@ -664,14 +663,14 @@
* does not need to be as high as 2.85V. It is choosen for
* microphone sensitivity purpose.
*/
-static struct tabla_pdata tabla_platform_data = {
+static struct wcd9xxx_pdata tabla_platform_data = {
.slimbus_slave_device = {
.name = "tabla-slave",
.e_addr = {0, 0, 0x10, 0, 0x17, 2},
},
.irq = MSM_GPIO_TO_INT(62),
.irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
+ .num_irqs = NR_WCD9XXX_IRQS,
.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
@@ -682,7 +681,45 @@
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
.bias3_cfilt_sel = TABLA_CFILT3_SEL,
.bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "VDDD_CDC_D",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_A_1P2V",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
+ },
};
static struct slim_device msm_slim_tabla = {
@@ -693,14 +730,14 @@
},
};
-static struct tabla_pdata tabla20_platform_data = {
+static struct wcd9xxx_pdata tabla20_platform_data = {
.slimbus_slave_device = {
.name = "tabla-slave",
.e_addr = {0, 0, 0x60, 0, 0x17, 2},
},
.irq = MSM_GPIO_TO_INT(62),
.irq_base = TABLA_INTERRUPT_BASE,
- .num_irqs = NR_TABLA_IRQS,
+ .num_irqs = NR_WCD9XXX_IRQS,
.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
@@ -711,7 +748,45 @@
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
.bias3_cfilt_sel = TABLA_CFILT3_SEL,
.bias4_cfilt_sel = TABLA_CFILT3_SEL,
- }
+ },
+ .regulator = {
+ {
+ .name = "CDC_VDD_CP",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_RX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_RX_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_TX",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_CDC_VDDA_TX_CUR_MAX,
+ },
+ {
+ .name = "VDDIO_CDC",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .optimum_uA = WCD9XXX_VDDIO_CDC_CUR_MAX,
+ },
+ {
+ .name = "VDDD_CDC_D",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
+ },
+ {
+ .name = "CDC_VDDA_A_1P2V",
+ .min_uV = 1225000,
+ .max_uV = 1225000,
+ .optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
+ },
+ },
};
static struct slim_device msm_slim_tabla20 = {
@@ -1817,6 +1892,7 @@
.variant_id = 0x2,
.version = 0x10,
.build = 0xAA,
+ .fw_name = "atmel_8960_liquid_v2_1_AA.hex",
},
{
.config = mxt1386e_config_data_v2_1,
@@ -2005,8 +2081,8 @@
&msm_device_saw_core0,
&msm_device_saw_core1,
&msm8960_device_ext_5v_vreg,
- &msm8960_device_ext_otg_sw_vreg,
&msm8960_device_ssbi_pmic,
+ &msm8960_device_ext_otg_sw_vreg,
&msm8960_device_qup_spi_gsbi1,
&msm8960_device_qup_i2c_gsbi3,
&msm8960_device_qup_i2c_gsbi4,
@@ -2044,6 +2120,14 @@
&msm_device_bam_dmux,
&msm_fm_platform_init,
+#if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE)
+#ifdef CONFIG_MSM_USE_TSIF1
+ &msm_device_tsif[1],
+#else
+ &msm_device_tsif[0],
+#endif
+#endif
+
#ifdef CONFIG_HW_RANDOM_MSM
&msm_device_rng,
#endif
@@ -2266,62 +2350,62 @@
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
true,
- 100, 8000, 100000, 1,
+ 100, 650, 801, 200,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
true,
- 2000, 6000, 60100000, 3000,
+ 2000, 200, 576000, 2000,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(ON, GDHS, MAX, ACTIVE),
false,
- 4200, 5000, 60350000, 3500,
+ 8500, 51, 1122000, 8500,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(ON, HSFS_OPEN, MAX, ACTIVE),
false,
- 6300, 4500, 65350000, 4800,
+ 9000, 51, 1130300, 9000,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(ON, HSFS_OPEN, ACTIVE, RET_HIGH),
false,
- 7000, 3500, 66600000, 5150,
+ 10000, 51, 1130300, 10000,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(OFF, GDHS, MAX, ACTIVE),
false,
- 11700, 2500, 67850000, 5500,
+ 12000, 14, 2205900, 12000,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, MAX, ACTIVE),
false,
- 13800, 2000, 71850000, 6800,
+ 18000, 12, 2364250, 18000,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, ACTIVE, RET_HIGH),
false,
- 29700, 500, 75850000, 8800,
+ 23500, 10, 2667000, 23500,
},
{
MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
MSM_RPMRS_LIMITS(OFF, HSFS_OPEN, RET_HIGH, RET_LOW),
false,
- 29700, 0, 76350000, 9800,
+ 29700, 5, 2867000, 30000,
},
};
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index dc26d72..c30be16 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -37,6 +37,7 @@
#endif
#include <mach/msm_memtypes.h>
#include <mach/msm_smd.h>
+#include <mach/qpnp-int.h>
#include "clock.h"
#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
@@ -361,6 +362,7 @@
static struct of_device_id irq_match[] __initdata = {
{ .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
{ .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+ { .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
{}
};
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index c70b30e..644c0855 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -32,7 +32,7 @@
{"bt", 21, 2900000, 3300000, 1, NULL}
};
-struct platform_device msm_bt_power_device = {
+static struct platform_device msm_bt_power_device = {
.name = "bt_power",
};
@@ -100,7 +100,7 @@
{
if (machine_is_msm7627a_qrd1())
gpio_bt_sys_rest_en = 114;
- if (machine_is_msm7627a_evb())
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
gpio_bt_sys_rest_en = 16;
}
@@ -324,7 +324,8 @@
int pin, rc = 0;
if (mode == FM_I2S_ON) {
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+ || machine_is_msm8625_surf())
config_pcm_i2s_mode(0);
pr_err("%s mode = FM_I2S_ON", __func__);
@@ -367,7 +368,8 @@
int pin, rc = 0;
if (mode == BT_PCM_ON) {
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+ || machine_is_msm8625_surf())
config_pcm_i2s_mode(1);
pr_err("%s mode =BT_PCM_ON", __func__);
rc = switch_pcm_i2s_reg_mode(1);
@@ -940,9 +942,20 @@
gpio_bt_config();
- i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
- bahama_devices,
- ARRAY_SIZE(bahama_devices));
+ rc = i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
+ bahama_devices,
+ ARRAY_SIZE(bahama_devices));
+ if (rc < 0) {
+ pr_err("%s: I2C Register failed\n", __func__);
+ return;
+ }
+
+ rc = platform_device_register(&msm_bt_power_device);
+ if (rc < 0) {
+ pr_err("%s: device register failed\n", __func__);
+ return;
+ }
+
dev = &msm_bt_power_device.dev;
for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
@@ -964,6 +977,6 @@
regulator_put(bt_vregs[i].reg);
bt_vregs[i].reg = NULL;
}
- return;
+ platform_device_unregister(&msm_bt_power_device);
}
#endif
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 06fbb7b..7b075cd 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -1041,7 +1041,7 @@
pr_debug("msm7627a_camera_init Entered\n");
/* LCD and camera power (VREG & LDO) init */
- if (machine_is_msm7627a_evb())
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
lcd_camera_power_init();
#ifndef CONFIG_MSM_CAMERA_V4L2
@@ -1049,7 +1049,7 @@
qrd1_camera_gpio_cfg();
platform_add_devices(camera_devices_qrd,
ARRAY_SIZE(camera_devices_qrd));
- } else if (machine_is_msm7627a_evb()) {
+ } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
evb_camera_gpio_cfg();
platform_add_devices(camera_devices_evb,
ARRAY_SIZE(camera_devices_evb));
@@ -1059,7 +1059,8 @@
platform_add_devices(camera_devices_msm,
ARRAY_SIZE(camera_devices_msm));
#endif
- if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb())
+ if (!machine_is_msm7627a_qrd1() || !machine_is_msm7627a_evb()
+ || !machine_is_msm8625_evb())
register_i2c_devices();
rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
@@ -1083,7 +1084,7 @@
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices_qrd,
ARRAY_SIZE(i2c_camera_devices_qrd));
- } else if (machine_is_msm7627a_evb()) {
+ } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
pr_debug("machine_is_msm7627a_evb i2c_register_board_info\n");
i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID,
i2c_camera_devices_evb,
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 4e856b1..45bfaed 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -216,7 +216,8 @@
{
int ret = -ENODEV;
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+ machine_is_msm8625_surf()) {
if (!strncmp(name, "lcdc_toshiba_fwvga_pt", 21) ||
!strncmp(name, "mipi_cmd_renesas_fwvga", 22))
ret = 0;
@@ -226,7 +227,7 @@
} else if (machine_is_msm7627a_qrd1()) {
if (!strncmp(name, "mipi_video_truly_wvga", 21))
ret = 0;
- } else if (machine_is_msm7627a_evb()) {
+ } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
ret = 0;
}
@@ -235,7 +236,8 @@
!defined(CONFIG_FB_MSM_MIPI_PANEL_AUTO_DETECT) && \
!defined(CONFIG_FB_MSM_LCDC_MIPI_PANEL_AUTO_DETECT)
if (machine_is_msm7x27a_surf() ||
- machine_is_msm7625a_surf()) {
+ machine_is_msm7625a_surf() ||
+ machine_is_msm8625_surf()) {
if (!strncmp(name, LCDC_TOSHIBA_FWVGA_PANEL_NAME,
strnlen(LCDC_TOSHIBA_FWVGA_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
@@ -427,7 +429,8 @@
gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
if (!rc) {
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+ || machine_is_msm8625_surf()) {
lcdc_reset_ptr = ioremap_nocache(LCDC_RESET_PHYS,
sizeof(uint32_t));
@@ -555,7 +558,7 @@
if (machine_is_msm7627a_qrd1())
rc = msm_fb_dsi_client_qrd1_reset();
- else if (machine_is_msm7627a_evb())
+ else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
rc = msm_fb_dsi_client_qrd3_reset();
else
rc = msm_fb_dsi_client_msm_reset();
@@ -586,7 +589,8 @@
return rc;
}
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
+ || machine_is_msm8625_surf()) {
rc = gpio_direction_output(GPIO_DISPLAY_PWR_EN, 1);
if (rc < 0) {
pr_err("failed to enable display pwr\n");
@@ -625,7 +629,8 @@
dsi_gpio_initialized = 1;
}
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()) {
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+ machine_is_msm8625_surf()) {
gpio_set_value_cansleep(GPIO_DISPLAY_PWR_EN, on);
gpio_set_value_cansleep(GPIO_BACKLIGHT_EN, on);
} else if (machine_is_msm7x27a_ffa() ||
@@ -649,7 +654,8 @@
gpio_set_value_cansleep(GPIO_LCDC_BRDG_PD, 0);
if (machine_is_msm7x27a_surf() ||
- machine_is_msm7625a_surf()) {
+ machine_is_msm7625a_surf() ||
+ machine_is_msm8625_surf()) {
lcdc_reset_cfg = readl_relaxed(lcdc_reset_ptr);
rmb();
lcdc_reset_cfg &= ~1;
@@ -817,7 +823,7 @@
if (machine_is_msm7627a_qrd1())
rc = mipi_dsi_panel_qrd1_power(on);
- else if (machine_is_msm7627a_evb())
+ else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
rc = mipi_dsi_panel_qrd3_power(on);
else
rc = mipi_dsi_panel_msm_power(on);
@@ -840,7 +846,7 @@
if (machine_is_msm7627a_qrd1())
platform_add_devices(qrd_fb_devices,
ARRAY_SIZE(qrd_fb_devices));
- else if (machine_is_msm7627a_evb())
+ else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
platform_add_devices(evb_fb_devices,
ARRAY_SIZE(evb_fb_devices));
else if (machine_is_msm7627a_qrd3())
@@ -850,7 +856,8 @@
ARRAY_SIZE(msm_fb_devices));
msm_fb_register_device("mdp", &mdp_pdata);
- if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf())
+ if (machine_is_msm7625a_surf() || machine_is_msm7x27a_surf() ||
+ machine_is_msm8625_surf())
msm_fb_register_device("lcdc", &lcdc_pdata);
#ifdef CONFIG_FB_MSM_MDP303
msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index 88a519d..e4ee52e 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -19,6 +19,7 @@
#include <mach/board.h>
#include "devices.h"
+#include "pm.h"
#include "board-msm7627a.h"
#if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\
@@ -149,7 +150,8 @@
static int gpio_sdc1_hw_det = 85;
static void gpio_sdc1_config(void)
{
- if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
+ if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+ || machine_is_msm8625_evb())
gpio_sdc1_hw_det = 42;
}
@@ -250,7 +252,8 @@
status = gpio_direction_input(gpio_sdc1_hw_det);
if (!status) {
if (machine_is_msm7627a_qrd1() ||
- machine_is_msm7627a_evb())
+ machine_is_msm7627a_evb() ||
+ machine_is_msm8625_evb())
status = !gpio_get_value(gpio_sdc1_hw_det);
else
status = gpio_get_value(gpio_sdc1_hw_det);
@@ -366,6 +369,8 @@
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
if (mmc_regulator_init(3, "emmc", 3000000))
return;
+ sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+ MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_add_sdcc(3, &sdc3_plat_data);
#endif
/* Micro-SD slot */
@@ -374,6 +379,8 @@
if (mmc_regulator_init(1, "mmc", 2850000))
return;
sdc1_plat_data.status_irq = MSM_GPIO_TO_INT(gpio_sdc1_hw_det);
+ sdc1_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+ MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
msm_add_sdcc(1, &sdc1_plat_data);
#endif
/* SDIO WLAN slot */
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 6df7626..53d3c56 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -48,7 +48,8 @@
int gpio_wlan_sys_rest_en = 134;
static void gpio_wlan_config(void)
{
- if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb())
+ if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+ || machine_is_msm8625_evb())
gpio_wlan_sys_rest_en = 124;
}
@@ -229,7 +230,8 @@
* gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
* EVB1.0 and QRD8625,so the below step is required for those devices.
*/
- if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+ if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+ || machine_is_msm8625_evb()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -302,7 +304,8 @@
* gpio_wlan_sys_rest_en is not from the GPIO expander for QRD7627a,
* EVB1.0 and QRD8625,so the below step is required for those devices.
*/
- if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()) {
+ if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
+ || machine_is_msm8625_evb()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index b0481a0..bde9b61 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -13,6 +13,7 @@
#ifndef __ARCH_ARM_MACH_MSM_BOARD_7627A__
#define __ARCH_ARM_MACH_MSM_BOARD_7627A__
+#include "pm.h"
void __init msm7627a_init_mmc(void);
void __init msm_msm7627a_allocate_memory_regions(void);
@@ -65,6 +66,7 @@
QRD_GPIO_CAM_GP_CAMIF_RESET,
};
+#define ADSP_RPC_PROG 0x3000000a
#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
#define FPGA_MSM_CNTRL_REG2 0x90008010
@@ -97,11 +99,9 @@
struct regulator *reg;
};
-extern struct platform_device msm_bt_power_device;
-
void __init msm7627a_bt_power_init(void);
#endif
void __init msm7627a_camera_init(void);
-
+u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
#endif
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index d5d8edc..34ae4c8 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -92,6 +92,7 @@
#define PMEM_KERNEL_EBI1_SIZE 0x1C000
#endif
+#define ADSP_RPC_PROG 0x3000000a
static struct resource smc91x_resources[] = {
[0] = {
@@ -1731,6 +1732,25 @@
}
}
+static void msm_adsp_add_pdev(void)
+{
+ int rc = 0;
+ struct rpc_board_dev *rpc_adsp_pdev;
+
+ rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+ if (rpc_adsp_pdev == NULL) {
+ pr_err("%s: Memory Allocation failure\n", __func__);
+ return;
+ }
+ rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+ rpc_adsp_pdev->pdev = msm_adsp_device;
+ rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+ if (rc < 0) {
+ pr_err("%s: return val: %d\n", __func__, rc);
+ kfree(rpc_adsp_pdev);
+ }
+}
+
static void __init msm7x2x_init(void)
{
@@ -1797,6 +1817,7 @@
#ifdef CONFIG_MSM_CAMERA
config_camera_off_gpios(); /* might not be necessary */
#endif
+ msm_adsp_add_pdev();
msm_device_i2c_init();
i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index a6b29dc..3ad4773 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -14,6 +14,7 @@
#include <linux/gpio_event.h>
#include <linux/memblock.h>
#include <asm/mach-types.h>
+#include <linux/memblock.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
#include <mach/board.h>
@@ -93,7 +94,8 @@
static void __init register_i2c_devices(void)
{
- if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf())
+ if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf() ||
+ machine_is_msm8625_surf())
sx150x_data[SX150X_CORE].io_open_drain_ena = 0xe0f0;
core_exp_i2c_info[0].platform_data =
@@ -153,10 +155,6 @@
.msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
};
-static struct msm_i2c_platform_data msm8625_gsbi0_qup_i2c_pdata = {
- .clk_freq = 100000,
-};
-
#ifdef CONFIG_ARCH_MSM7X27A
#define MSM_PMEM_MDP_SIZE 0x2300000
#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1500000
@@ -361,11 +359,97 @@
},
};
+u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode mode)
+{
+ switch (mode) {
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+ return msm7x27a_pm_data
+ [MSM_PM_SLEEP_MODE_POWER_COLLAPSE].latency;
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN:
+ return msm7x27a_pm_data
+ [MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN].latency;
+ case MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT:
+ return msm7x27a_pm_data
+ [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+ case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+ return msm7x27a_pm_data
+ [MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT].latency;
+ default:
+ return 0;
+ }
+}
+
static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
.mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS,
.p_addr = 0,
};
+/* 8625 PM platform data */
+static struct msm_pm_platform_data msm8625_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
+ /* CORE0 entries */
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 16000,
+ .residency = 20000,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 12000,
+ .residency = 20000,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+ /* picked latency & redisdency values from 7x30 */
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 0,
+ .suspend_enabled = 0,
+ .latency = 500,
+ .residency = 6000,
+ },
+
+ [MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+ .idle_supported = 1,
+ .suspend_supported = 1,
+ .idle_enabled = 1,
+ .suspend_enabled = 1,
+ .latency = 2,
+ .residency = 10,
+ },
+
+};
+
+static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = {
+ .mode = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
+ .v_addr = MSM_CFG_CTL_BASE,
+};
+
static struct android_pmem_platform_data android_pmem_adsp_pdata = {
.name = "pmem_adsp",
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -697,37 +781,50 @@
static struct platform_device *msm8625_rumi3_devices[] __initdata = {
&msm8625_device_dmov,
+ &msm8625_device_smd,
&msm8625_device_uart1,
- &msm8625_device_qup_i2c_gsbi0,
+ &msm8625_gsbi0_qup_i2c_device,
};
-static struct platform_device *surf_ffa_devices[] __initdata = {
+static struct platform_device *msm7627a_surf_ffa_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
&msm_device_uart1,
&msm_device_uart_dm1,
&msm_device_uart_dm2,
- &msm_device_nand,
&msm_gsbi0_qup_i2c_device,
&msm_gsbi1_qup_i2c_device,
&msm_device_otg,
&msm_device_gadget_peripheral,
- &fmem_device,
+ &smsc911x_device,
+ &msm_kgsl_3d0,
+};
+
+static struct platform_device *common_devices[] __initdata = {
&android_usb_device,
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_audio_device,
+ &fmem_device,
+ &msm_device_nand,
&msm_device_snd,
&msm_device_adspdec,
- &msm_batt_device,
- &smsc911x_device,
- &msm_kgsl_3d0,
-#ifdef CONFIG_BT
- &msm_bt_power_device,
-#endif
&asoc_msm_pcm,
&asoc_msm_dai0,
&asoc_msm_dai1,
+ &msm_batt_device,
+};
+
+static struct platform_device *msm8625_surf_devices[] __initdata = {
+ &msm8625_device_dmov,
+ &msm8625_device_uart1,
+ &msm8625_device_uart_dm1,
+ &msm8625_device_uart_dm2,
+ &msm8625_gsbi0_qup_i2c_device,
+ &msm8625_gsbi1_qup_i2c_device,
+ &msm8625_device_smd,
+ &msm8625_device_otg,
+ &msm8625_device_gadget_peripheral,
};
static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
@@ -849,21 +946,25 @@
static void __init msm8625_reserve(void)
{
+ msm7x27a_reserve();
memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
}
-static void __init msm_device_i2c_init(void)
+static void __init msm7x27a_device_i2c_init(void)
{
- if (machine_is_msm8625_rumi3()) {
- msm8625_device_qup_i2c_gsbi0.dev.platform_data =
- &msm8625_gsbi0_qup_i2c_pdata;
- return;
- }
-
msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
msm_gsbi1_qup_i2c_device.dev.platform_data = &msm_gsbi1_qup_i2c_pdata;
}
+static void __init msm8625_device_i2c_init(void)
+{
+ msm8625_gsbi0_qup_i2c_device.dev.platform_data =
+ &msm_gsbi0_qup_i2c_pdata;
+ msm8625_gsbi1_qup_i2c_device.dev.platform_data =
+ &msm_gsbi1_qup_i2c_pdata;
+}
+
#define MSM_EBI2_PHYS 0xa0d00000
#define MSM_EBI2_XMEM_CS2_CFG1 0xa0d10030
@@ -878,7 +979,7 @@
ebi2_cfg = readl(ebi2_cfg_ptr);
if (machine_is_msm7x27a_rumi3() || machine_is_msm7x27a_surf() ||
- machine_is_msm7625a_surf())
+ machine_is_msm7625a_surf() || machine_is_msm8625_surf())
ebi2_cfg |= (1 << 4); /* CS2 */
writel(ebi2_cfg, ebi2_cfg_ptr);
@@ -1115,6 +1216,29 @@
}
};
+static void msm_adsp_add_pdev(void)
+{
+ int rc = 0;
+ struct rpc_board_dev *rpc_adsp_pdev;
+
+ rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+ if (rpc_adsp_pdev == NULL) {
+ pr_err("%s: Memory Allocation failure\n", __func__);
+ return;
+ }
+ rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+ if (cpu_is_msm8625())
+ rpc_adsp_pdev->pdev = msm8625_device_adsp;
+ else
+ rpc_adsp_pdev->pdev = msm_adsp_device;
+ rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+ if (rc < 0) {
+ pr_err("%s: return val: %d\n", __func__, rc);
+ kfree(rpc_adsp_pdev);
+ }
+}
+
static void __init msm7627a_rumi3_init(void)
{
msm7x27a_init_ebi2();
@@ -1125,9 +1249,15 @@
static void __init msm8625_rumi3_init(void)
{
msm7x2x_misc_init();
- msm_device_i2c_init();
+ msm_adsp_add_pdev();
+ msm8625_device_i2c_init();
platform_add_devices(msm8625_rumi3_devices,
ARRAY_SIZE(msm8625_rumi3_devices));
+
+ msm_pm_set_platform_data(msm8625_pm_data,
+ ARRAY_SIZE(msm8625_pm_data));
+ BUG_ON(msm_pm_boot_init(&msm_pm_8625_boot_pdata));
+ msm8x25_spm_device_init();
}
#define LED_GPIO_PDM 96
@@ -1151,55 +1281,56 @@
__func__, rc);
}
-static void __init msm7x2x_init(void)
+static void __init msm7x27a_add_footswitch_devices(void)
{
- msm7x2x_misc_init();
-
- /* Initialize regulators first so that other devices can use them */
- msm7x27a_init_regulators();
-
- /* Common functions for SURF/FFA/RUMI3 */
- msm_device_i2c_init();
- msm7x27a_init_ebi2();
- msm7x27a_cfg_uart2dm_serial();
-#ifdef CONFIG_SERIAL_MSM_HS
- msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
- msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
-#endif
-
-#ifdef CONFIG_USB_MSM_OTG_72K
- msm_otg_pdata.swfi_latency =
- msm7x27a_pm_data
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
- msm_device_otg.dev.platform_data = &msm_otg_pdata;
-#endif
- msm_device_gadget_peripheral.dev.platform_data =
- &msm_gadget_pdata;
- msm7x27a_cfg_smsc911x();
platform_add_devices(msm_footswitch_devices,
msm_num_footswitch_devices);
- platform_add_devices(surf_ffa_devices,
- ARRAY_SIZE(surf_ffa_devices));
- /* Ensure ar6000pm device is registered before MMC/SDC */
- msm7x27a_init_ar6000pm();
-#ifdef CONFIG_MMC_MSM
- msm7627a_init_mmc();
-#endif
- msm_fb_add_devices();
-#ifdef CONFIG_USB_EHCI_MSM_72K
- msm7x2x_init_host();
-#endif
+}
- msm_pm_set_platform_data(msm7x27a_pm_data,
- ARRAY_SIZE(msm7x27a_pm_data));
- BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+static void __init msm7x27a_add_platform_devices(void)
+{
+ if (machine_is_msm8625_surf()) {
+ platform_add_devices(msm8625_surf_devices,
+ ARRAY_SIZE(msm8625_surf_devices));
+ } else {
+ platform_add_devices(msm7627a_surf_ffa_devices,
+ ARRAY_SIZE(msm7627a_surf_ffa_devices));
+ }
-#if defined(CONFIG_I2C) && defined(CONFIG_GPIO_SX150X)
- register_i2c_devices();
-#endif
-#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
- msm7627a_bt_power_init();
-#endif
+ platform_add_devices(common_devices,
+ ARRAY_SIZE(common_devices));
+}
+
+static void __init msm7x27a_uartdm_config(void)
+{
+ msm7x27a_cfg_uart2dm_serial();
+ msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
+ if (cpu_is_msm8625())
+ msm8625_device_uart_dm1.dev.platform_data =
+ &msm_uart_dm1_pdata;
+ else
+ msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
+}
+
+static void __init msm7x27a_otg_gadget(void)
+{
+ msm_otg_pdata.swfi_latency =
+ msm7x27a_pm_data[
+ MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+ if (cpu_is_msm8625()) {
+ msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm8625_device_gadget_peripheral.dev.platform_data =
+ &msm_gadget_pdata;
+ } else {
+ msm_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm_device_gadget_peripheral.dev.platform_data =
+ &msm_gadget_pdata;
+ }
+}
+
+static void __init msm7x27a_add_io_devices(void)
+{
+ /* touchscreen */
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
atmel_ts_pdata.min_x = 0;
atmel_ts_pdata.max_x = 480;
@@ -1208,16 +1339,15 @@
}
i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
- atmel_ts_i2c_info,
- ARRAY_SIZE(atmel_ts_i2c_info));
-
-#if defined(CONFIG_MSM_CAMERA)
- msm7627a_camera_init();
-#endif
+ atmel_ts_i2c_info,
+ ARRAY_SIZE(atmel_ts_i2c_info));
+ /* keypad */
platform_device_register(&kp_pdev);
+
+ /* headset */
platform_device_register(&hs_pdev);
- /* configure it as a pdm function*/
+ /* LED: configure it as a pdm function */
if (gpio_tlmm_config(GPIO_CFG(LED_GPIO_PDM, 3,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_8MA), GPIO_CFG_ENABLE))
@@ -1226,10 +1356,50 @@
else
platform_device_register(&led_pdev);
-#ifdef CONFIG_MSM_RPC_VIBRATOR
+ /* Vibrator */
if (machine_is_msm7x27a_ffa() || machine_is_msm7625a_ffa())
msm_init_pmic_vibrator();
-#endif
+}
+
+static void __init msm7x27a_pm_init(void)
+{
+ if (machine_is_msm8625_surf())
+ return;
+
+ msm_pm_set_platform_data(msm7x27a_pm_data,
+ ARRAY_SIZE(msm7x27a_pm_data));
+ BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+}
+
+static void __init msm7x2x_init(void)
+{
+ msm7x2x_misc_init();
+
+ /* Initialize regulators first so that other devices can use them */
+ msm7x27a_init_regulators();
+ msm_adsp_add_pdev();
+ if (cpu_is_msm8625())
+ msm8625_device_i2c_init();
+ else
+ msm7x27a_device_i2c_init();
+ msm7x27a_init_ebi2();
+ msm7x27a_uartdm_config();
+
+ msm7x27a_otg_gadget();
+ msm7x27a_cfg_smsc911x();
+
+ msm7x27a_add_footswitch_devices();
+ msm7x27a_add_platform_devices();
+ /* Ensure ar6000pm device is registered before MMC/SDC */
+ msm7x27a_init_ar6000pm();
+ msm7627a_init_mmc();
+ msm_fb_add_devices();
+ msm7x2x_init_host();
+ msm7x27a_pm_init();
+ register_i2c_devices();
+ msm7627a_bt_power_init();
+ msm7627a_camera_init();
+ msm7x27a_add_io_devices();
/*7x25a kgsl initializations*/
msm7x25a_kgsl_3d0_init();
}
@@ -1298,3 +1468,13 @@
.timer = &msm_timer,
.handle_irq = gic_handle_irq,
MACHINE_END
+MACHINE_START(MSM8625_SURF, "QCT MSM8625 SURF")
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = msm8625_map_io,
+ .reserve = msm8625_reserve,
+ .init_irq = msm8625_init_irq,
+ .init_machine = msm7x2x_init,
+ .timer = &msm_timer,
+ .init_early = msm7x2x_init_early,
+ .handle_irq = gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 260c880..9f7104f 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -5236,7 +5236,8 @@
&msm_batt_device,
&msm_adc_device,
&msm_ebi0_thermal,
- &msm_ebi1_thermal
+ &msm_ebi1_thermal,
+ &msm_adsp_device
};
static struct msm_gpio msm_i2c_gpios_hw[] = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 0427632..61443c3 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -28,9 +28,11 @@
#include <linux/input/rmi_i2c.h>
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/regulator/consumer.h>
+#include <linux/memblock.h>
#include <asm/mach/mmc.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
#include <mach/msm_hsusb.h>
@@ -659,7 +661,20 @@
.dev.platform_data = &msm_psy_batt_data,
};
-static struct platform_device *qrd_common_devices[] __initdata = {
+static struct platform_device *common_devices[] __initdata = {
+ &android_usb_device,
+ &android_pmem_device,
+ &android_pmem_adsp_device,
+ &android_pmem_audio_device,
+ &msm_batt_device,
+ &msm_device_adspdec,
+ &msm_device_snd,
+ &asoc_msm_pcm,
+ &asoc_msm_dai0,
+ &asoc_msm_dai1,
+};
+
+static struct platform_device *qrd7627a_devices[] __initdata = {
&msm_device_dmov,
&msm_device_smd,
&msm_device_uart1,
@@ -668,26 +683,23 @@
&msm_gsbi1_qup_i2c_device,
&msm_device_otg,
&msm_device_gadget_peripheral,
- &android_usb_device,
- &android_pmem_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
- &msm_device_snd,
- &msm_device_adspdec,
- &msm_batt_device,
&msm_kgsl_3d0,
-#ifdef CONFIG_BT
- &msm_bt_power_device,
-#endif
- &asoc_msm_pcm,
- &asoc_msm_dai0,
- &asoc_msm_dai1,
};
static struct platform_device *qrd3_devices[] __initdata = {
&msm_device_nand,
};
+static struct platform_device *msm8625_evb_devices[] __initdata = {
+ &msm8625_device_dmov,
+ &msm8625_device_smd,
+ &msm8625_gsbi0_qup_i2c_device,
+ &msm8625_gsbi1_qup_i2c_device,
+ &msm8625_device_uart1,
+ &msm8625_device_otg,
+ &msm8625_device_gadget_peripheral,
+};
+
static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
static int __init pmem_kernel_ebi1_size_setup(char *p)
{
@@ -762,12 +774,49 @@
msm_reserve();
}
-static void __init msm_device_i2c_init(void)
+static void __init msm8625_reserve(void)
+{
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ msm7627a_reserve();
+}
+
+static void msmqrd_adsp_add_pdev(void)
+{
+ int rc = 0;
+ struct rpc_board_dev *rpc_adsp_pdev;
+
+ rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+ if (rpc_adsp_pdev == NULL) {
+ pr_err("%s: Memory Allocation failure\n", __func__);
+ return;
+ }
+ rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+ if (cpu_is_msm8625())
+ rpc_adsp_pdev->pdev = msm8625_device_adsp;
+ else
+ rpc_adsp_pdev->pdev = msm_adsp_device;
+ rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+ if (rc < 0) {
+ pr_err("%s: return val: %d\n", __func__, rc);
+ kfree(rpc_adsp_pdev);
+ }
+}
+
+static void __init msm7627a_device_i2c_init(void)
{
msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
msm_gsbi1_qup_i2c_device.dev.platform_data = &msm_gsbi1_qup_i2c_pdata;
}
+static void __init msm8625_device_i2c_init(void)
+{
+ msm8625_gsbi0_qup_i2c_device.dev.platform_data
+ = &msm_gsbi0_qup_i2c_pdata;
+ msm8625_gsbi1_qup_i2c_device.dev.platform_data
+ = &msm_gsbi1_qup_i2c_pdata;
+}
+
static struct msm_handset_platform_data hs_platform_data = {
.hs_name = "7k_handset",
.pwr_key_delay_ms = 500, /* 0 will disable end key */
@@ -958,7 +1007,7 @@
i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
synaptic_i2c_clearpad3k,
ARRAY_SIZE(synaptic_i2c_clearpad3k));
- } else if (machine_is_msm7627a_evb()) {
+ } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
GPIO_CFG_8MA), GPIO_CFG_ENABLE);
@@ -989,11 +1038,11 @@
#endif
/* keypad */
- if (machine_is_msm7627a_evb())
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
platform_device_register(&kp_pdev_8625);
/* leds */
- if (machine_is_msm7627a_evb()) {
+ if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
rc = gpio_tlmm_config(GPIO_CFG(LED_RED_GPIO_8625, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP,
GPIO_CFG_16MA), GPIO_CFG_ENABLE);
@@ -1022,32 +1071,63 @@
static void add_platform_devices(void)
{
- platform_add_devices(qrd_common_devices,
- ARRAY_SIZE(qrd_common_devices));
-
- if (machine_is_msm7627a_qrd3())
- platform_add_devices(qrd3_devices,
- ARRAY_SIZE(qrd3_devices));
+ if (machine_is_msm8625_evb())
+ platform_add_devices(msm8625_evb_devices,
+ ARRAY_SIZE(msm8625_evb_devices));
+ else {
+ platform_add_devices(qrd7627a_devices,
+ ARRAY_SIZE(qrd7627a_devices));
+ if (machine_is_msm7627a_qrd3())
+ platform_add_devices(qrd3_devices,
+ ARRAY_SIZE(qrd3_devices));
+ }
+ platform_add_devices(common_devices,
+ ARRAY_SIZE(common_devices));
}
#define UART1DM_RX_GPIO 45
+static void __init qrd7627a_uart1dm_config(void)
+{
+ msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
+ if (cpu_is_msm8625())
+ msm8625_device_uart_dm1.dev.platform_data =
+ &msm_uart_dm1_pdata;
+ else
+ msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
+}
+
+static void __init qrd7627a_otg_gadget(void)
+{
+ msm_otg_pdata.swfi_latency = msm7627a_pm_data
+ [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
+
+ if (cpu_is_msm8625()) {
+ msm8625_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm8625_device_gadget_peripheral.dev.platform_data =
+ &msm_gadget_pdata;
+
+ } else {
+ msm_device_otg.dev.platform_data = &msm_otg_pdata;
+ msm_device_gadget_peripheral.dev.platform_data =
+ &msm_gadget_pdata;
+ }
+}
+
static void __init msm_qrd_init(void)
{
msm7x2x_misc_init();
msm7627a_init_regulators();
- msm_device_i2c_init();
-#ifdef CONFIG_SERIAL_MSM_HS
- msm_uart_dm1_pdata.wakeup_irq = gpio_to_irq(UART1DM_RX_GPIO);
- msm_device_uart_dm1.dev.platform_data = &msm_uart_dm1_pdata;
-#endif
+ msmqrd_adsp_add_pdev();
-#ifdef CONFIG_USB_MSM_OTG_72K
- msm_otg_pdata.swfi_latency = msm7627a_pm_data
- [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency;
- msm_device_otg.dev.platform_data = &msm_otg_pdata;
-#endif
- msm_device_gadget_peripheral.dev.platform_data =
- &msm_gadget_pdata;
+ if (cpu_is_msm8625())
+ msm8625_device_i2c_init();
+ else
+ msm7627a_device_i2c_init();
+
+ /* uart1dm*/
+ qrd7627a_uart1dm_config();
+ /*OTG gadget*/
+ qrd7627a_otg_gadget();
add_platform_devices();
@@ -1058,9 +1138,11 @@
#ifdef CONFIG_USB_EHCI_MSM_72K
msm7627a_init_host();
#endif
- msm_pm_set_platform_data(msm7627a_pm_data,
+ if (!machine_is_msm8625_evb()) {
+ msm_pm_set_platform_data(msm7627a_pm_data,
ARRAY_SIZE(msm7627a_pm_data));
- BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+ BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
+ }
msm_fb_add_devices();
@@ -1069,7 +1151,6 @@
#endif
msm7627a_camera_init();
-
msm7627a_add_io_devices();
}
@@ -1108,3 +1189,13 @@
.init_early = qrd7627a_init_early,
.handle_irq = vic_handle_irq,
MACHINE_END
+MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = msm8625_map_io,
+ .reserve = msm8625_reserve,
+ .init_irq = msm8625_init_irq,
+ .init_machine = msm_qrd_init,
+ .timer = &msm_timer,
+ .init_early = qrd7627a_init_early,
+ .handle_irq = gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 5996388..0a3632e 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5045,7 +5045,7 @@
CLK_LOOKUP("tv_clk", mdp_tv_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("hdmi_clk", hdmi_tv_clk.c, ""),
CLK_LOOKUP("core_clk", hdmi_app_clk.c, ""),
- CLK_LOOKUP("vpe_clk", vpe_clk.c, ""),
+ CLK_LOOKUP("vpe_clk", vpe_clk.c, "msm_vpe.0"),
CLK_LOOKUP("core_clk", vpe_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("vfe_clk", vfe_clk.c, "msm_vfe.0"),
CLK_LOOKUP("core_clk", vfe_clk.c, "footswitch-8x60.8"),
@@ -5082,7 +5082,7 @@
CLK_LOOKUP("iface_clk", vcodec_p_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("vfe_pclk", vfe_p_clk.c, "msm_vfe.0"),
CLK_LOOKUP("iface_clk", vfe_p_clk.c, "footswitch-8x60.8"),
- CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, ""),
+ CLK_LOOKUP("vpe_pclk", vpe_p_clk.c, "msm_vpe.0"),
CLK_LOOKUP("iface_clk", vpe_p_clk.c, "footswitch-8x60.9"),
CLK_LOOKUP("bit_clk", mi2s_bit_clk.c, "msm-dai-q6.6"),
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index 200cbfe..c20b7e4 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -11,9 +11,16 @@
*/
#include "clock.h"
+#include "clock-pll.h"
#include "clock-pcom.h"
#include "clock-voter.h"
+#include <mach/msm_iomap.h>
+#include <mach/socinfo.h>
+
+#define PLLn_MODE(n) (MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
+#define PLL4_MODE (MSM_CLK_CTL_BASE + 0x374)
+
static DEFINE_CLK_PCOM(adm_clk, ADM_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(adsp_clk, ADSP_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(ahb_m_clk, AHB_M_CLK, CLKFLAG_SKIP_AUTO_OFF);
@@ -28,6 +35,46 @@
static DEFINE_CLK_PCOM(csi1_p_clk, CSI1_P_CLK, CLKFLAG_SKIP_AUTO_OFF);
static DEFINE_CLK_PCOM(csi1_vfe_clk, CSI1_VFE_CLK, CLKFLAG_SKIP_AUTO_OFF);
+static struct pll_shared_clk pll0_clk = {
+ .id = PLL_0,
+ .mode_reg = PLLn_MODE(0),
+ .c = {
+ .ops = &clk_pll_ops,
+ .dbg_name = "pll0_clk",
+ CLK_INIT(pll0_clk.c),
+ },
+};
+
+static struct pll_shared_clk pll1_clk = {
+ .id = PLL_1,
+ .mode_reg = PLLn_MODE(1),
+ .c = {
+ .ops = &clk_pll_ops,
+ .dbg_name = "pll1_clk",
+ CLK_INIT(pll1_clk.c),
+ },
+};
+
+static struct pll_shared_clk pll2_clk = {
+ .id = PLL_2,
+ .mode_reg = PLLn_MODE(2),
+ .c = {
+ .ops = &clk_pll_ops,
+ .dbg_name = "pll2_clk",
+ CLK_INIT(pll2_clk.c),
+ },
+};
+
+static struct pll_shared_clk pll4_clk = {
+ .id = PLL_4,
+ .mode_reg = PLL4_MODE,
+ .c = {
+ .ops = &clk_pll_ops,
+ .dbg_name = "pll4_clk",
+ CLK_INIT(pll4_clk.c),
+ },
+};
+
static struct pcom_clk dsi_byte_clk = {
.id = P_DSI_BYTE_CLK,
.c = {
@@ -251,14 +298,20 @@
CLK_LOOKUP("core_clk", ebi_usb_clk.c, "msm_otg"),
CLK_LOOKUP("ebi1_vfe_clk", ebi_vfe_clk.c, NULL),
CLK_LOOKUP("mem_clk", ebi_adm_clk.c, "msm_dmov"),
+
+ CLK_LOOKUP("pll0_clk", pll0_clk.c, "acpu"),
+ CLK_LOOKUP("pll1_clk", pll1_clk.c, "acpu"),
+ CLK_LOOKUP("pll2_clk", pll2_clk.c, "acpu"),
};
struct clock_init_data msm7x27_clock_init_data __initdata = {
.table = msm_clocks_7x27,
.size = ARRAY_SIZE(msm_clocks_7x27),
+ .init = msm_shared_pll_control_init,
};
-static struct clk_lookup msm_clocks_7x27a[] = {
+/* Clock table for common clocks between 7627a and 7625a */
+static struct clk_lookup msm_cmn_clk_7625a_7627a[] __initdata = {
CLK_LOOKUP("core_clk", adm_clk.c, "msm_dmov"),
CLK_LOOKUP("adsp_clk", adsp_clk.c, NULL),
CLK_LOOKUP("ahb_m_clk", ahb_m_clk.c, NULL),
@@ -340,11 +393,41 @@
CLK_LOOKUP("ebi1_mddi_clk", ebi_mddi_clk.c, NULL),
CLK_LOOKUP("ebi1_vfe_clk", ebi_vfe_clk.c, NULL),
CLK_LOOKUP("mem_clk", ebi_adm_clk.c, "msm_dmov"),
+
+ CLK_LOOKUP("pll0_clk", pll0_clk.c, "acpu"),
+ CLK_LOOKUP("pll1_clk", pll1_clk.c, "acpu"),
+ CLK_LOOKUP("pll2_clk", pll2_clk.c, "acpu"),
+
};
+/* PLL 4 clock is available for 7627a target. */
+static struct clk_lookup msm_clk_7627a[] __initdata = {
+ CLK_LOOKUP("pll4_clk", pll4_clk.c, "acpu"),
+};
+
+static struct clk_lookup msm_clk_7627a_7625a[ARRAY_SIZE(msm_cmn_clk_7625a_7627a)
+ + ARRAY_SIZE(msm_clk_7627a)];
+
+static void __init msm7627a_clock_init(void)
+{
+ int size = ARRAY_SIZE(msm_cmn_clk_7625a_7627a);
+
+ /* Intialize shared PLL control structure */
+ msm_shared_pll_control_init();
+
+ memcpy(&msm_clk_7627a_7625a, &msm_cmn_clk_7625a_7627a,
+ sizeof(msm_cmn_clk_7625a_7627a));
+ if (!cpu_is_msm7x25a()) {
+ memcpy(&msm_clk_7627a_7625a[size],
+ &msm_clk_7627a, sizeof(msm_clk_7627a));
+ size += ARRAY_SIZE(msm_clk_7627a);
+ }
+ msm7x27a_clock_init_data.size = size;
+}
+
struct clock_init_data msm7x27a_clock_init_data __initdata = {
- .table = msm_clocks_7x27a,
- .size = ARRAY_SIZE(msm_clocks_7x27a),
+ .table = msm_clk_7627a_7625a,
+ .init = msm7627a_clock_init,
};
static struct clk_lookup msm_clocks_8x50[] = {
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
new file mode 100644
index 0000000..f6b2b45
--- /dev/null
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/remote_spinlock.h>
+
+#include <mach/socinfo.h>
+#include <mach/msm_iomap.h>
+
+#include "clock.h"
+#include "clock-pll.h"
+#include "smd_private.h"
+
+struct pll_rate {
+ unsigned int lvalue;
+ unsigned long rate;
+};
+
+static struct pll_rate pll_l_rate[] = {
+ {10, 196000000},
+ {12, 245760000},
+ {30, 589820000},
+ {38, 737280000},
+ {41, 800000000},
+ {50, 960000000},
+ {52, 1008000000},
+ {62, 1200000000},
+ {0, 0},
+};
+
+#define PLL_BASE 7
+
+struct shared_pll_control {
+ uint32_t version;
+ struct {
+ /*
+ * Denotes if the PLL is ON. Technically, this can be read
+ * directly from the PLL registers, but this feild is here,
+ * so let's use it.
+ */
+ uint32_t on;
+ /*
+ * One bit for each processor core. The application processor
+ * is allocated bit position 1. All other bits should be
+ * considered as votes from other processors.
+ */
+ uint32_t votes;
+ } pll[PLL_BASE + PLL_END];
+};
+
+static remote_spinlock_t pll_lock;
+static struct shared_pll_control *pll_control;
+
+void __init msm_shared_pll_control_init(void)
+{
+#define PLL_REMOTE_SPINLOCK_ID "S:7"
+ unsigned smem_size;
+
+ remote_spin_lock_init(&pll_lock, PLL_REMOTE_SPINLOCK_ID);
+
+ pll_control = smem_get_entry(SMEM_CLKREGIM_SOURCES, &smem_size);
+ if (!pll_control) {
+ pr_err("Can't find shared PLL control data structure!\n");
+ BUG();
+ /*
+ * There might be more PLLs than what the application processor knows
+ * about. But the index used for each PLL is guaranteed to remain the
+ * same.
+ */
+ } else if (smem_size < sizeof(struct shared_pll_control)) {
+ pr_err("Shared PLL control data"
+ "structure too small!\n");
+ BUG();
+ } else if (pll_control->version != 0xCCEE0001) {
+ pr_err("Shared PLL control version mismatch!\n");
+ BUG();
+ } else {
+ pr_info("Shared PLL control available.\n");
+ return;
+ }
+
+}
+
+static void pll_enable(void __iomem *addr, unsigned on)
+{
+ if (on) {
+ writel_relaxed(2, addr);
+ mb();
+ udelay(5);
+ writel_relaxed(6, addr);
+ mb();
+ udelay(50);
+ writel_relaxed(7, addr);
+ } else {
+ writel_relaxed(0, addr);
+ }
+}
+
+static int pll_clk_enable(struct clk *clk)
+{
+ struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ unsigned int pll_id = pll->id;
+
+ remote_spin_lock(&pll_lock);
+
+ pll_control->pll[PLL_BASE + pll_id].votes |= BIT(1);
+ if (!pll_control->pll[PLL_BASE + pll_id].on) {
+ pll_enable(pll->mode_reg, 1);
+ pll_control->pll[PLL_BASE + pll_id].on = 1;
+ }
+
+ remote_spin_unlock(&pll_lock);
+ return 0;
+}
+
+static void pll_clk_disable(struct clk *clk)
+{
+ struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ unsigned int pll_id = pll->id;
+
+ remote_spin_lock(&pll_lock);
+
+ pll_control->pll[PLL_BASE + pll_id].votes &= ~BIT(1);
+ if (pll_control->pll[PLL_BASE + pll_id].on
+ && !pll_control->pll[PLL_BASE + pll_id].votes) {
+ pll_enable(pll->mode_reg, 0);
+ pll_control->pll[PLL_BASE + pll_id].on = 0;
+ }
+
+ remote_spin_unlock(&pll_lock);
+}
+
+static int pll_clk_is_enabled(struct clk *clk)
+{
+ struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+
+ return readl_relaxed(pll->mode_reg) & BIT(0);
+}
+
+static bool pll_clk_is_local(struct clk *clk)
+{
+ return true;
+}
+
+static int pll_clk_handoff(struct clk *clk)
+{
+ struct pll_shared_clk *pll = to_pll_shared_clk(clk);
+ unsigned int pll_lval;
+ struct pll_rate *l;
+
+ /*
+ * Wait for the PLLs to be initialized and then read their frequency.
+ */
+ do {
+ pll_lval = readl_relaxed(pll->mode_reg + 4) & 0x3ff;
+ cpu_relax();
+ udelay(50);
+ } while (pll_lval == 0);
+
+ /* Convert PLL L values to PLL Output rate */
+ for (l = pll_l_rate; l->rate != 0; l++) {
+ if (l->lvalue == pll_lval) {
+ clk->rate = l->rate;
+ break;
+ }
+ }
+
+ if (!clk->rate) {
+ pr_crit("Unknown PLL's L value!\n");
+ BUG();
+ }
+
+ return 0;
+}
+
+struct clk_ops clk_pll_ops = {
+ .enable = pll_clk_enable,
+ .disable = pll_clk_disable,
+ .handoff = pll_clk_handoff,
+ .is_local = pll_clk_is_local,
+ .is_enabled = pll_clk_is_enabled,
+};
diff --git a/arch/arm/mach-msm/clock-pll.h b/arch/arm/mach-msm/clock-pll.h
new file mode 100644
index 0000000..ae0ca17
--- /dev/null
+++ b/arch/arm/mach-msm/clock-pll.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/**
+ * enum - For PLL IDs
+ */
+enum {
+ PLL_TCXO = -1,
+ PLL_0 = 0,
+ PLL_1,
+ PLL_2,
+ PLL_3,
+ PLL_4,
+ PLL_END,
+};
+
+/**
+ * struct pll_shared_clk - PLL shared with other processors without
+ * any HW voting
+ * @id: PLL ID
+ * @mode_reg: enable register
+ * @parent: clock source
+ * @c: clk
+ */
+struct pll_shared_clk {
+ unsigned int id;
+ void __iomem *const mode_reg;
+ struct clk c;
+};
+
+extern struct clk_ops clk_pll_ops;
+
+static inline struct pll_shared_clk *to_pll_shared_clk(struct clk *clk)
+{
+ return container_of(clk, struct pll_shared_clk, c);
+}
+
+/**
+ * msm_shared_pll_control_init() - Initialize shared pll control structure
+ */
+void msm_shared_pll_control_init(void);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index ca85a0a..630c128 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -23,11 +23,13 @@
#include <mach/usbdiag.h>
#include <mach/msm_sps.h>
#include <mach/dma.h>
+#include <mach/msm_dsps.h>
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
#include <mach/msm_bus_board.h>
#include <mach/rpm.h>
#include <mach/mdm2.h>
+#include <mach/msm_smd.h>
#include <linux/ion.h>
#include "clock.h"
#include "devices.h"
@@ -1217,9 +1219,157 @@
.dev.platform_data = &msm_sps_pdata,
};
+static struct resource smd_resource[] = {
+ {
+ .name = "a9_m2a_0",
+ .start = INT_A9_M2A_0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "a9_m2a_5",
+ .start = INT_A9_M2A_5,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_a11",
+ .start = INT_ADSP_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_a11_smsm",
+ .start = INT_ADSP_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "dsps_a11",
+ .start = INT_DSPS_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "dsps_a11_smsm",
+ .start = INT_DSPS_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_a11",
+ .start = INT_WCNSS_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_a11_smsm",
+ .start = INT_WCNSS_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+ {
+ .irq_config_id = SMD_MODEM,
+ .subsys_name = "gss",
+ .edge = SMD_APPS_MODEM,
+
+ .smd_int.irq_name = "a9_m2a_0",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 3,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "a9_m2a_5",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 4,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_Q6,
+ .subsys_name = "q6",
+ .edge = SMD_APPS_QDSP,
+
+ .smd_int.irq_name = "adsp_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 15,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "adsp_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 14,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_DSPS,
+ .subsys_name = "dsps",
+ .edge = SMD_APPS_DSPS,
+
+ .smd_int.irq_name = "dsps_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1,
+ .smd_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+ .smd_int.out_offset = 0x4080,
+
+ .smsm_int.irq_name = "dsps_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1,
+ .smsm_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+ .smsm_int.out_offset = 0x4094,
+ },
+ {
+ .irq_config_id = SMD_WCNSS,
+ .subsys_name = "wcnss",
+ .edge = SMD_APPS_WCNSS,
+
+ .smd_int.irq_name = "wcnss_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 25,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "wcnss_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 23,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+};
+
+static struct smd_platform smd_platform_data = {
+ .num_ss_configs = ARRAY_SIZE(smd_config_list),
+ .smd_ss_configs = smd_config_list,
+};
+
struct platform_device msm_device_smd_apq8064 = {
.name = "msm_smd",
.id = -1,
+ .resource = smd_resource,
+ .num_resources = ARRAY_SIZE(smd_resource),
+ .dev = {
+ .platform_data = &smd_platform_data,
+ },
};
#ifdef CONFIG_HW_RANDOM_MSM
@@ -1752,6 +1902,53 @@
},
};
+/* Sensors DSPS platform data */
+
+#define PPSS_REG_PHYS_BASE 0x12080000
+
+static struct dsps_clk_info dsps_clks[] = {};
+static struct dsps_regulator_info dsps_regs[] = {};
+
+/*
+ * Note: GPIOs field is intialized in run-time at the function
+ * apq8064_init_dsps().
+ */
+
+struct msm_dsps_platform_data msm_dsps_pdata_8064 = {
+ .clks = dsps_clks,
+ .clks_num = ARRAY_SIZE(dsps_clks),
+ .gpios = NULL,
+ .gpios_num = 0,
+ .regs = dsps_regs,
+ .regs_num = ARRAY_SIZE(dsps_regs),
+ .dsps_pwr_ctl_en = 1,
+ .signature = DSPS_SIGNATURE,
+};
+
+static struct resource msm_dsps_resources[] = {
+ {
+ .start = PPSS_REG_PHYS_BASE,
+ .end = PPSS_REG_PHYS_BASE + SZ_8K - 1,
+ .name = "ppss_reg",
+ .flags = IORESOURCE_MEM,
+ },
+
+ {
+ .start = PPSS_WDOG_TIMER_IRQ,
+ .end = PPSS_WDOG_TIMER_IRQ,
+ .name = "ppss_wdog",
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_dsps_device_8064 = {
+ .name = "msm_dsps",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_dsps_resources),
+ .resource = msm_dsps_resources,
+ .dev.platform_data = &msm_dsps_pdata_8064,
+};
+
#ifdef CONFIG_MSM_MPM
static uint16_t msm_mpm_irqs_m2a[MSM_MPM_NR_MPM_IRQS] __initdata = {
[1] = MSM_GPIO_TO_INT(26),
@@ -1891,4 +2088,3 @@
.num_resources = ARRAY_SIZE(mdm_resources),
.resource = mdm_resources,
};
-
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 19a8db7..718cfb1 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -30,8 +30,10 @@
#include <mach/rpm.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
+#include <mach/msm_tsif.h>
#include "clock.h"
#include "devices.h"
#include "devices-msm8x60.h"
@@ -950,9 +952,158 @@
.id = -1,
};
+static struct resource smd_resource[] = {
+ {
+ .name = "a9_m2a_0",
+ .start = INT_A9_M2A_0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "a9_m2a_5",
+ .start = INT_A9_M2A_5,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_a11",
+ .start = INT_ADSP_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "adsp_a11_smsm",
+ .start = INT_ADSP_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "dsps_a11",
+ .start = INT_DSPS_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "dsps_a11_smsm",
+ .start = INT_DSPS_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_a11",
+ .start = INT_WCNSS_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "wcnss_a11_smsm",
+ .start = INT_WCNSS_A11_SMSM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smd_subsystem_config smd_config_list[] = {
+ {
+ .irq_config_id = SMD_MODEM,
+ .subsys_name = "modem",
+ .edge = SMD_APPS_MODEM,
+
+ .smd_int.irq_name = "a9_m2a_0",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 3,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "a9_m2a_5",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 4,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_Q6,
+ .subsys_name = "q6",
+ .edge = SMD_APPS_QDSP,
+
+ .smd_int.irq_name = "adsp_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 15,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "adsp_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 14,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+ {
+ .irq_config_id = SMD_DSPS,
+ .subsys_name = "dsps",
+ .edge = SMD_APPS_DSPS,
+
+ .smd_int.irq_name = "dsps_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1,
+ .smd_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+ .smd_int.out_offset = 0x4080,
+
+ .smsm_int.irq_name = "dsps_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1,
+ .smsm_int.out_base = (void __iomem *)MSM_SIC_NON_SECURE_BASE,
+ .smsm_int.out_offset = 0x4094,
+ },
+ {
+ .irq_config_id = SMD_WCNSS,
+ .subsys_name = "wcnss",
+ .edge = SMD_APPS_WCNSS,
+
+ .smd_int.irq_name = "wcnss_a11",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+ .smd_int.out_bit_pos = 1 << 25,
+ .smd_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smd_int.out_offset = 0x8,
+
+ .smsm_int.irq_name = "wcnss_a11_smsm",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smd_smsm",
+ .smsm_int.dev_id = 0,
+ .smsm_int.out_bit_pos = 1 << 23,
+ .smsm_int.out_base = (void __iomem *)MSM_APCS_GCC_BASE,
+ .smsm_int.out_offset = 0x8,
+ },
+};
+
+static struct smd_platform smd_platform_data = {
+ .num_ss_configs = ARRAY_SIZE(smd_config_list),
+ .smd_ss_configs = smd_config_list,
+};
+
+
struct platform_device msm_device_smd = {
.name = "msm_smd",
.id = -1,
+ .resource = smd_resource,
+ .num_resources = ARRAY_SIZE(smd_resource),
+ .dev = {
+ .platform_data = &smd_platform_data,
+ },
};
struct platform_device msm_device_bam_dmux = {
@@ -1355,6 +1506,111 @@
};
#endif
+#define MSM_TSIF0_PHYS (0x18200000)
+#define MSM_TSIF1_PHYS (0x18201000)
+#define MSM_TSIF_SIZE (0x200)
+
+#define TSIF_0_CLK GPIO_CFG(75, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_EN GPIO_CFG(76, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_DATA GPIO_CFG(77, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_0_SYNC GPIO_CFG(82, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_CLK GPIO_CFG(79, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_EN GPIO_CFG(80, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_DATA GPIO_CFG(81, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+#define TSIF_1_SYNC GPIO_CFG(78, 1, GPIO_CFG_INPUT, \
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA)
+
+static const struct msm_gpio tsif0_gpios[] = {
+ { .gpio_cfg = TSIF_0_CLK, .label = "tsif_clk", },
+ { .gpio_cfg = TSIF_0_EN, .label = "tsif_en", },
+ { .gpio_cfg = TSIF_0_DATA, .label = "tsif_data", },
+ { .gpio_cfg = TSIF_0_SYNC, .label = "tsif_sync", },
+};
+
+static const struct msm_gpio tsif1_gpios[] = {
+ { .gpio_cfg = TSIF_1_CLK, .label = "tsif_clk", },
+ { .gpio_cfg = TSIF_1_EN, .label = "tsif_en", },
+ { .gpio_cfg = TSIF_1_DATA, .label = "tsif_data", },
+ { .gpio_cfg = TSIF_1_SYNC, .label = "tsif_sync", },
+};
+
+struct msm_tsif_platform_data tsif1_platform_data = {
+ .num_gpios = ARRAY_SIZE(tsif1_gpios),
+ .gpios = tsif1_gpios,
+ .tsif_pclk = "tsif_pclk",
+ .tsif_ref_clk = "tsif_ref_clk",
+};
+
+struct resource tsif1_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = TSIF2_IRQ,
+ .end = TSIF2_IRQ,
+ },
+ [1] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSIF1_PHYS,
+ .end = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
+ },
+ [2] = {
+ .flags = IORESOURCE_DMA,
+ .start = DMOV_TSIF_CHAN,
+ .end = DMOV_TSIF_CRCI,
+ },
+};
+
+struct msm_tsif_platform_data tsif0_platform_data = {
+ .num_gpios = ARRAY_SIZE(tsif0_gpios),
+ .gpios = tsif0_gpios,
+ .tsif_pclk = "tsif_pclk",
+ .tsif_ref_clk = "tsif_ref_clk",
+};
+struct resource tsif0_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = TSIF1_IRQ,
+ .end = TSIF1_IRQ,
+ },
+ [1] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSIF0_PHYS,
+ .end = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
+ },
+ [2] = {
+ .flags = IORESOURCE_DMA,
+ .start = DMOV_TSIF_CHAN,
+ .end = DMOV_TSIF_CRCI,
+ },
+};
+
+struct platform_device msm_device_tsif[2] = {
+ {
+ .name = "msm_tsif",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tsif0_resources),
+ .resource = tsif0_resources,
+ .dev = {
+ .platform_data = &tsif0_platform_data
+ },
+ },
+ {
+ .name = "msm_tsif",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(tsif1_resources),
+ .resource = tsif1_resources,
+ .dev = {
+ .platform_data = &tsif1_platform_data
+ },
+ }
+};
+
static struct resource resources_ssbi_pmic[] = {
{
.start = MSM_PMIC1_SSBI_CMD_PHYS,
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index b895870..26f246d 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -76,6 +76,21 @@
.resource = resources_uart2,
};
+static struct resource resources_adsp[] = {
+ {
+ .start = INT_ADSP_A9_A11,
+ .end = INT_ADSP_A9_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_adsp_device = {
+ .name = "msm_adsp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_adsp),
+ .resource = resources_adsp,
+};
+
#define MSM_UART1DM_PHYS 0xA0200000
#define MSM_UART2DM_PHYS 0xA0300000
static struct resource msm_uart1_dm_resources[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index c18b6b2..9a4696f 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -33,6 +33,7 @@
#include "devices-msm7x2xa.h"
#include "footswitch.h"
#include "acpuclock.h"
+#include "spm.h"
/* Address of GSBI blocks */
#define MSM_GSBI0_PHYS 0xA1200000
@@ -210,6 +211,78 @@
.id = -1,
};
+static struct resource smd_8625_resource[] = {
+ {
+ .name = "a9_m2a_0",
+ .start = MSM8625_INT_A9_M2A_0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "a9_m2a_5",
+ .start = MSM8625_INT_A9_M2A_5,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct smd_subsystem_config smd_8625_config_list[] = {
+ {
+ .irq_config_id = SMD_MODEM,
+ .subsys_name = "modem",
+ .edge = SMD_APPS_MODEM,
+
+ .smd_int.irq_name = "a9_m2a_0",
+ .smd_int.flags = IRQF_TRIGGER_RISING,
+ .smd_int.irq_id = -1,
+ .smd_int.device_name = "smd_dev",
+ .smd_int.dev_id = 0,
+
+ .smd_int.out_bit_pos = 1,
+ .smd_int.out_base = (void __iomem *)MSM_CSR_BASE,
+ .smd_int.out_offset = 0x400 + (0) * 4,
+
+ .smsm_int.irq_name = "a9_m2a_5",
+ .smsm_int.flags = IRQF_TRIGGER_RISING,
+ .smsm_int.irq_id = -1,
+ .smsm_int.device_name = "smsm_dev",
+ .smsm_int.dev_id = 0,
+
+ .smsm_int.out_bit_pos = 1,
+ .smsm_int.out_base = (void __iomem *)MSM_CSR_BASE,
+ .smsm_int.out_offset = 0x400 + (5) * 4,
+
+ }
+};
+
+static struct smd_platform smd_8625_platform_data = {
+ .num_ss_configs = ARRAY_SIZE(smd_8625_config_list),
+ .smd_ss_configs = smd_8625_config_list,
+};
+
+struct platform_device msm8625_device_smd = {
+ .name = "msm_smd",
+ .id = -1,
+ .resource = smd_8625_resource,
+ .num_resources = ARRAY_SIZE(smd_8625_resource),
+ .dev = {
+ .platform_data = &smd_8625_platform_data,
+ }
+};
+
+static struct resource resources_adsp[] = {
+ {
+ .start = INT_ADSP_A9_A11,
+ .end = INT_ADSP_A9_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm_adsp_device = {
+ .name = "msm_adsp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_adsp),
+ .resource = resources_adsp,
+};
+
static struct resource resources_uart1[] = {
{
.start = INT_UART1,
@@ -569,6 +642,55 @@
#endif
+/* Command sequence for simple WFI */
+static uint8_t spm_wfi_cmd_sequence[] __initdata = {
+ 0x00, 0x40, 0x40, 0x03,
+ 0x00, 0x40, 0x40, 0x0f,
+};
+
+/* Command sequence for GDFS, this won't send any interrupt to the modem */
+static uint8_t spm_pc_without_modem[] __initdata = {
+ 0x20, 0x00, 0x30, 0x10,
+ 0x40, 0x40, 0x03, 0x10,
+ 0x00, 0x30, 0x2E, 0x40,
+ 0x40, 0x0f,
+};
+
+static struct msm_spm_seq_entry msm_spm_seq_list[] __initdata = {
+ [0] = {
+ .mode = MSM_SPM_MODE_CLOCK_GATING,
+ .notify_rpm = false,
+ .cmd = spm_wfi_cmd_sequence,
+ },
+ [1] = {
+ .mode = MSM_SPM_MODE_POWER_COLLAPSE,
+ .notify_rpm = false,
+ .cmd = spm_pc_without_modem,
+ },
+};
+
+static struct msm_spm_platform_data msm_spm_data[] __initdata = {
+ [0] = {
+ .reg_base_addr = MSM_SAW0_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x0,
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+ [1] = {
+ .reg_base_addr = MSM_SAW1_BASE,
+ .reg_init_values[MSM_SPM_REG_SAW2_CFG] = 0x0,
+ .reg_init_values[MSM_SPM_REG_SAW2_SPM_CTL] = 0x01,
+ .num_modes = ARRAY_SIZE(msm_spm_seq_list),
+ .modes = msm_spm_seq_list,
+ },
+};
+
+void __init msm8x25_spm_device_init(void)
+{
+ msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
+}
+
#define MDP_BASE 0xAA200000
#define MIPI_DSI_HW_BASE 0xA1100000
@@ -843,6 +965,21 @@
.resource = msm8625_uart2dm_resources,
};
+static struct resource msm8625_resources_adsp[] = {
+ {
+ .start = MSM8625_INT_ADSP_A9_A11,
+ .end = MSM8625_INT_ADSP_A9_A11,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device msm8625_device_adsp = {
+ .name = "msm_adsp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm8625_resources_adsp),
+ .resource = msm8625_resources_adsp,
+};
+
static struct resource msm8625_dmov_resource[] = {
{
.start = MSM8625_INT_ADM_AARM,
@@ -887,7 +1024,7 @@
};
/* Use GSBI0 QUP for /dev/i2c-0 */
-struct platform_device msm8625_device_qup_i2c_gsbi0 = {
+struct platform_device msm8625_gsbi0_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI0_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi0_msm8625_qup_resources),
@@ -916,7 +1053,7 @@
};
/* Use GSBI1 QUP for /dev/i2c-1 */
-struct platform_device msm8625_device_qup_i2c_gsbi1 = {
+struct platform_device msm8625_gsbi1_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI1_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi1_qup_i2c_resources),
@@ -1401,7 +1538,7 @@
}
msm_clock_init(&msm7x27a_clock_init_data);
- if (cpu_is_msm7x27aa())
+ if (cpu_is_msm7x27aa() || cpu_is_msm8625())
acpuclk_init(&acpuclk_7x27aa_soc_data);
else
acpuclk_init(&acpuclk_7x27a_soc_data);
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index c2383c6..3c81ccf 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -30,4 +30,5 @@
void __init msm8625_init_irq(void);
void __init msm8625_map_io(void);
int ar600x_wlan_power(bool on);
+void __init msm8x25_spm_device_init(void);
#endif
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index e9b94f6..89c8aaf 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -74,6 +74,20 @@
.resource = msm_ebi1_thermal_resources
};
+static struct resource resources_adsp[] = {
+{
+ .start = INT_ADSP_A9_A11,
+ .end = INT_ADSP_A9_A11,
+ .flags = IORESOURCE_IRQ,
+},
+};
+
+struct platform_device msm_adsp_device = {
+ .name = "msm_adsp",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_adsp),
+ .resource = resources_adsp,
+};
static struct resource resources_uart1[] = {
{
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 6da7b8f..7f2855d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -38,6 +38,7 @@
extern struct platform_device msm_ebi0_thermal;
extern struct platform_device msm_ebi1_thermal;
+extern struct platform_device msm_adsp_device;
extern struct platform_device msm_device_uart1;
extern struct platform_device msm_device_uart2;
extern struct platform_device msm_device_uart3;
@@ -127,8 +128,8 @@
extern struct platform_device msm_gsbi9_qup_i2c_device;
extern struct platform_device msm_gsbi12_qup_i2c_device;
-extern struct platform_device msm8625_device_qup_i2c_gsbi0;
-extern struct platform_device msm8625_device_qup_i2c_gsbi1;
+extern struct platform_device msm8625_gsbi0_qup_i2c_device;
+extern struct platform_device msm8625_gsbi1_qup_i2c_device;
extern struct platform_device msm8625_device_uart_dm1;
extern struct platform_device msm8625_device_uart_dm2;
extern struct platform_device msm8625_device_sdc1;
@@ -139,6 +140,7 @@
extern struct platform_device msm8625_device_hsusb_host;
extern struct platform_device msm8625_device_otg;
extern struct platform_device msm8625_kgsl_3d0;
+extern struct platform_device msm8625_device_adsp;
extern struct platform_device msm_slim_ctrl;
extern struct platform_device msm_device_sps;
@@ -147,6 +149,7 @@
extern struct platform_device msm_device_bam_dmux;
extern struct platform_device msm_device_smd;
extern struct platform_device msm_device_smd_apq8064;
+extern struct platform_device msm8625_device_smd;
extern struct platform_device msm_device_dmov;
extern struct platform_device msm8960_device_dmov;
extern struct platform_device apq8064_device_dmov;
@@ -320,3 +323,5 @@
extern struct platform_device msm_bus_8064_cpss_fpb;
extern struct platform_device mdm_8064_device;
+
+extern struct platform_device msm_dsps_device_8064;
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index 830e36b..6311b3c 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2009,2011 Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2007-2009,2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,15 @@
{
/* empty */
}
+static inline void msm_pm_boot_entry(void)
+{
+ /* empty */
+}
+static inline void msm_pm_write_boot_vector(unsigned int cpu,
+ unsigned long address)
+{
+ /* empty */
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/diag_bridge.h b/arch/arm/mach-msm/include/mach/diag_bridge.h
index a39ed25..b06f020 100644
--- a/arch/arm/mach-msm/include/mach/diag_bridge.h
+++ b/arch/arm/mach-msm/include/mach/diag_bridge.h
@@ -19,6 +19,8 @@
int buf_size, int actual);
void (*write_complete_cb)(void *ctxt, char *buf,
int buf_size, int actual);
+ int (*suspend)(void *ctxt);
+ void (*resume)(void *ctxt);
};
#if defined(CONFIG_USB_QCOM_DIAG_BRIDGE) \
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 3cb79b7..d170f5f 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -177,6 +177,9 @@
#define DMOV_CE_OUT_CHAN 1
#define DMOV_CE_OUT_CRCI 3
+#define DMOV_TSIF_CHAN 2
+#define DMOV_TSIF_CRCI 11
+
#define DMOV_HSUART_GSBI6_TX_CHAN 7
#define DMOV_HSUART_GSBI6_TX_CRCI 6
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 821eaeb..c961804 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.h
@@ -36,7 +36,8 @@
#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
#define NR_GPIO_IRQS 156
-#define NR_BOARD_IRQS 100
+#define NR_QPNP_IRQS 32768 /* SPARSE_IRQ is required to support this */
+#define NR_BOARD_IRQS NR_QPNP_IRQS
#define NR_TLMM_MSM_DIR_CONN_IRQ 8
#define NR_MSM_GPIOS NR_GPIO_IRQS
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 954b673..1ae7454 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -42,10 +42,11 @@
#define NR_GPIO_IRQS 152
#define NR_PM8921_IRQS 256
#define NR_PM8821_IRQS 64
-#define NR_TABLA_IRQS 49
+#define NR_WCD9XXX_IRQS 49
+#define NR_TABLA_IRQS NR_WCD9XXX_IRQS
#define NR_GPIO_EXPANDER_IRQS 8
#define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
- NR_TABLA_IRQS + NR_GPIO_EXPANDER_IRQS)
+ NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS)
#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
#define NR_MSM_GPIOS NR_GPIO_IRQS
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 4be6d9ea..8d3e640 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -236,6 +236,22 @@
*/
int smd_write_end(smd_channel_t *ch);
+/*
+ * Returns a pointer to the subsystem name or NULL if no
+ * subsystem name is available.
+ *
+ * @type - Edge definition
+ */
+const char *smd_edge_to_subsystem(uint32_t type);
+
+/*
+ * Returns a pointer to the subsystem name given the
+ * remote processor ID.
+ *
+ * @pid Remote processor ID
+ * @returns Pointer to subsystem name or NULL if not found
+ */
+const char *smd_pid_to_subsystem(uint32_t pid);
#else
static inline int smd_open(const char *name, smd_channel_t **ch, void *priv,
@@ -337,6 +353,16 @@
{
return -ENODEV;
}
+
+static inline const char *smd_edge_to_subsystem(uint32_t type)
+{
+ return NULL;
+}
+
+static inline const char *smd_pid_to_subsystem(uint32_t pid)
+{
+ return NULL;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
index 71f2bd9..20c6fc4 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_dev_ctl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -96,6 +96,8 @@
int msm_reset_all_device(void);
+int reset_device(void);
+
int msm_clear_all_session(void);
struct msm_snddev_info *audio_dev_ctrl_find_dev(u32 dev_id);
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 6aa944f..af4691a 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,7 @@
#define SCM_SVC_FUSE 0x8
#define SCM_SVC_PWR 0x9
#define SCM_SVC_CP 0xC
+#define SCM_SVC_DCVS 0xD
#define SCM_SVC_TZSCHEDULER 0xFC
#ifdef CONFIG_MSM_SCM
@@ -30,6 +31,8 @@
extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1);
extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2);
+extern s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3,
+ u32 arg4, u32 *ret1, u32 *ret2);
#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
@@ -54,6 +57,12 @@
return 0;
}
+static inline s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+ u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
+{
+ return 0;
+}
+
static inline u32 scm_get_version(void)
{
return 0;
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 8e74238..a643c68 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -419,6 +419,8 @@
MSM_CHIP_DEVICE(CLK_CTL, MSM8625),
MSM_CHIP_DEVICE(SAW0, MSM8625),
MSM_CHIP_DEVICE(SAW1, MSM8625),
+ MSM_CHIP_DEVICE(AD5, MSM7XXX),
+ MSM_CHIP_DEVICE(MDC, MSM7XXX),
#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
defined(CONFIG_DEBUG_MSM_UART3)
MSM_CHIP_DEVICE(DEBUG_UART, MSM7XXX),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index 463d6c9..853888a 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,7 +56,7 @@
static int msm_iommu_tex_class[4];
-DEFINE_SPINLOCK(msm_iommu_lock);
+DEFINE_MUTEX(msm_iommu_lock);
struct msm_priv {
unsigned long *pgtable;
@@ -68,14 +68,14 @@
{
int ret;
- ret = clk_enable(drvdata->pclk);
+ ret = clk_prepare_enable(drvdata->pclk);
if (ret)
goto fail;
if (drvdata->clk) {
- ret = clk_enable(drvdata->clk);
+ ret = clk_prepare_enable(drvdata->clk);
if (ret)
- clk_disable(drvdata->pclk);
+ clk_disable_unprepare(drvdata->pclk);
}
fail:
return ret;
@@ -84,8 +84,8 @@
static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
{
if (drvdata->clk)
- clk_disable(drvdata->clk);
- clk_disable(drvdata->pclk);
+ clk_disable_unprepare(drvdata->clk);
+ clk_disable_unprepare(drvdata->pclk);
}
static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
@@ -299,11 +299,10 @@
static void msm_iommu_domain_destroy(struct iommu_domain *domain)
{
struct msm_priv *priv;
- unsigned long flags;
unsigned long *fl_table;
int i;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
domain->priv = NULL;
@@ -320,7 +319,7 @@
}
kfree(priv);
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
}
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -331,9 +330,8 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
int ret = 0;
- unsigned long flags;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
@@ -373,7 +371,7 @@
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -384,10 +382,9 @@
struct msm_iommu_ctx_dev *ctx_dev;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
if (!priv || !dev)
@@ -412,7 +409,7 @@
list_del_init(&ctx_drvdata->attached_elm);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
}
static int __get_pgprot(int prot, int len)
@@ -447,7 +444,6 @@
phys_addr_t pa, int order, int prot)
{
struct msm_priv *priv;
- unsigned long flags;
unsigned long *fl_table;
unsigned long *fl_pte;
unsigned long fl_offset;
@@ -458,7 +454,7 @@
size_t len = 0x1000UL << order;
int ret = 0;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
if (!priv) {
@@ -525,7 +521,7 @@
if (*fl_pte == 0) {
unsigned long *sl;
- sl = (unsigned long *) __get_free_pages(GFP_ATOMIC,
+ sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
get_order(SZ_4K));
if (!sl) {
@@ -583,7 +579,7 @@
ret = __flush_iotlb_va(domain, va);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -591,7 +587,6 @@
int order)
{
struct msm_priv *priv;
- unsigned long flags;
unsigned long *fl_table;
unsigned long *fl_pte;
unsigned long fl_offset;
@@ -601,7 +596,7 @@
size_t len = 0x1000UL << order;
int i, ret = 0;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
@@ -686,7 +681,7 @@
ret = __flush_iotlb_va(domain, va);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -702,13 +697,12 @@
unsigned long fl_offset;
unsigned long *sl_table;
unsigned long sl_offset, sl_start;
- unsigned long flags;
unsigned int chunk_offset = 0;
unsigned int chunk_pa;
int ret = 0;
struct msm_priv *priv;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
BUG_ON(len & (SZ_4K - 1));
@@ -734,7 +728,7 @@
/* Set up a 2nd level page table if one doesn't exist */
if (*fl_pte == 0) {
sl_table = (unsigned long *)
- __get_free_pages(GFP_ATOMIC, get_order(SZ_4K));
+ __get_free_pages(GFP_KERNEL, get_order(SZ_4K));
if (!sl_table) {
pr_debug("Could not allocate second level table\n");
@@ -782,7 +776,7 @@
}
__flush_iotlb(domain);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -796,11 +790,10 @@
unsigned long fl_offset;
unsigned long *sl_table;
unsigned long sl_start, sl_end;
- unsigned long flags;
int used, i;
struct msm_priv *priv;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
BUG_ON(len & (SZ_4K - 1));
@@ -854,7 +847,7 @@
}
__flush_iotlb(domain);
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return 0;
}
@@ -865,12 +858,11 @@
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
unsigned int par;
- unsigned long flags;
void __iomem *base;
phys_addr_t ret = 0;
int ctx;
- spin_lock_irqsave(&msm_iommu_lock, flags);
+ mutex_lock(&msm_iommu_lock);
priv = domain->priv;
if (list_empty(&priv->list_attached))
@@ -903,7 +895,7 @@
__disable_clocks(iommu_drvdata);
fail:
- spin_unlock_irqrestore(&msm_iommu_lock, flags);
+ mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -947,7 +939,7 @@
unsigned int fsr;
int i, ret;
- spin_lock(&msm_iommu_lock);
+ mutex_lock(&msm_iommu_lock);
if (!drvdata) {
pr_err("Invalid device ID in context interrupt handler\n");
@@ -975,7 +967,7 @@
}
__disable_clocks(drvdata);
fail:
- spin_unlock(&msm_iommu_lock);
+ mutex_unlock(&msm_iommu_lock);
return 0;
}
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 1982082..70e96b0 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -156,7 +156,7 @@
goto fail;
}
- ret = clk_enable(iommu_pclk);
+ ret = clk_prepare_enable(iommu_pclk);
if (ret)
goto fail_enable;
@@ -168,7 +168,7 @@
clk_set_rate(iommu_clk, ret);
}
- ret = clk_enable(iommu_clk);
+ ret = clk_prepare_enable(iommu_clk);
if (ret) {
clk_put(iommu_clk);
goto fail_pclk;
@@ -226,8 +226,8 @@
goto fail_io;
}
- ret = request_irq(irq, msm_iommu_fault_handler, 0,
- "msm_iommu_secure_irpt_handler", drvdata);
+ ret = request_threaded_irq(irq, NULL, msm_iommu_fault_handler,
+ IRQF_ONESHOT, "msm_iommu_secure_irpt_handler", drvdata);
if (ret) {
pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
goto fail_io;
@@ -247,9 +247,9 @@
platform_set_drvdata(pdev, drvdata);
if (iommu_clk)
- clk_disable(iommu_clk);
+ clk_disable_unprepare(iommu_clk);
- clk_disable(iommu_pclk);
+ clk_disable_unprepare(iommu_pclk);
return 0;
fail_io:
@@ -258,11 +258,11 @@
release_mem_region(r->start, len);
fail_clk:
if (iommu_clk) {
- clk_disable(iommu_clk);
+ clk_disable_unprepare(iommu_clk);
clk_put(iommu_clk);
}
fail_pclk:
- clk_disable(iommu_pclk);
+ clk_disable_unprepare(iommu_pclk);
fail_enable:
clk_put(iommu_pclk);
fail:
@@ -315,14 +315,14 @@
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
platform_set_drvdata(pdev, ctx_drvdata);
- ret = clk_enable(drvdata->pclk);
+ ret = clk_prepare_enable(drvdata->pclk);
if (ret)
goto fail;
if (drvdata->clk) {
- ret = clk_enable(drvdata->clk);
+ ret = clk_prepare_enable(drvdata->clk);
if (ret) {
- clk_disable(drvdata->pclk);
+ clk_disable_unprepare(drvdata->pclk);
goto fail;
}
}
@@ -357,8 +357,8 @@
mb();
if (drvdata->clk)
- clk_disable(drvdata->clk);
- clk_disable(drvdata->pclk);
+ clk_disable_unprepare(drvdata->clk);
+ clk_disable_unprepare(drvdata->pclk);
dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
return 0;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index feabe04..56aba3e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_config.c b/arch/arm/mach-msm/msm_bus/msm_bus_config.c
index 7d9d18f..28f3073 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_config.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_config.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.c b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
index 9fe05b7..4d73b03 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -9,6 +9,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 50afa81..e35130e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,22 +20,14 @@
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
-#if defined DEBUG
-
#define MSM_BUS_DBG(msg, ...) \
- printk(KERN_DEBUG "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
-
-#else
-#define MSM_BUS_DBG(msg, ...) no_printk("AXI")
-#endif
-
+ pr_debug(msg, ## __VA_ARGS__)
#define MSM_BUS_ERR(msg, ...) \
- printk(KERN_ERR "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
+ pr_err(msg, ## __VA_ARGS__)
#define MSM_BUS_WARN(msg, ...) \
- printk(KERN_WARNING "AXI: %s(): " msg, __func__, ## __VA_ARGS__)
+ pr_warn(msg, ## __VA_ARGS__)
#define MSM_FAB_ERR(msg, ...) \
- dev_err(&fabric->fabdev.dev, "AXI: %s(): " msg, __func__, ## \
- __VA_ARGS__)
+ dev_err(&fabric->fabdev.dev, msg, ## __VA_ARGS__)
enum msm_bus_dbg_op_type {
MSM_BUS_DBG_UNREGISTER = -2,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
index abd986b..e63df1b 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -10,6 +10,9 @@
* GNU General Public License for more details.
*
*/
+
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 3b178b5..2c69914 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -10,6 +10,8 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
index a8dc7c8..b13037e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_rpm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,8 @@
*
*/
+#define pr_fmt(fmt) "AXI: %s(): " fmt, __func__
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
@@ -342,7 +344,7 @@
fab_pdata->nmasters) + 1);
ret = memcmp(cd1->arb, cd2->arb, n);
if (ret) {
- MSM_BUS_DBG("Commit Data arb[%d] not equal\n", i);
+ MSM_BUS_DBG("Commit Data arb[%d] not equal\n", n);
return ret;
}
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 6e79dfe..3f56d1a 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -54,6 +54,7 @@
int nentries;
int size;
int enabled;
+ int initialized;
uint32_t filter;
int step_size;
};
@@ -66,6 +67,7 @@
struct msm_rtb_state msm_rtb = {
.filter = 1 << LOGK_LOGBUF,
+ .enabled = 1,
};
module_param_named(filter, msm_rtb.filter, uint, 0644);
@@ -73,7 +75,7 @@
int msm_rtb_event_should_log(enum logk_event_type log_type)
{
- return msm_rtb.enabled &&
+ return msm_rtb.initialized && msm_rtb.enabled &&
((1 << log_type) & msm_rtb.filter);
}
EXPORT_SYMBOL(msm_rtb_event_should_log);
@@ -217,7 +219,7 @@
#endif
- msm_rtb.enabled = 1;
+ msm_rtb.initialized = 1;
return 0;
}
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 74c64c1..f7d2bcb 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -237,13 +237,6 @@
unsigned long flags;
struct msm_xo_voter *xo_voter;
- /*
- * TODO: Remove early return for 8064 once RPM XO voting support
- * is available.
- */
- if (cpu_is_apq8064())
- return NULL;
-
if (xo_id >= NUM_MSM_XO_IDS) {
ret = -EINVAL;
goto err;
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 534fc0e..3c46d0f 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -28,6 +28,8 @@
#include "pm.h"
#define MSM_CORE1_RESET 0xA8600590
+#define MSM_CORE1_STATUS_MSK 0x02800000
+
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
@@ -60,6 +62,10 @@
void __cpuinit platform_secondary_init(unsigned int cpu)
{
+ pr_debug("CPU%u: Booted secondary processor\n", cpu);
+
+ WARN_ON(msm_platform_secondary_init(cpu));
+
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
@@ -80,20 +86,53 @@
spin_unlock(&boot_lock);
}
+static int __cpuinit msm8625_release_secondary(void)
+{
+ void __iomem *base_ptr;
+ int value = 0;
+ unsigned long timeout;
+
+ /*
+ * loop to ensure that the GHS_STATUS_CORE1 bit in the
+ * MPA5_STATUS_REG(0x3c) is set. The timeout for the while
+ * loop can be set as 20us as of now
+ */
+ timeout = jiffies + usecs_to_jiffies(20);
+ while (time_before(jiffies, timeout)) {
+ value = __raw_readl(MSM_CFG_CTL_BASE + 0x3c);
+ if ((value & MSM_CORE1_STATUS_MSK) ==
+ MSM_CORE1_STATUS_MSK)
+ break;
+ udelay(1);
+ }
+
+ if (!value) {
+ pr_err("Core 1 cannot be brought out of Reset!!!\n");
+ return -ENODEV;
+ }
+
+ base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+ if (!base_ptr)
+ return -ENODEV;
+ /* Reset core 1 out of reset */
+ __raw_writel(0x0, base_ptr);
+ mb();
+
+ iounmap(base_ptr);
+
+ return 0;
+}
+
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
- void __iomem *base_ptr;
if (cold_boot_done == false) {
- base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
- if (!base_ptr)
+ if (msm8625_release_secondary()) {
+ pr_err("Failed to release secondary core\n");
return -ENODEV;
- /* Reset core 1 out of reset */
- __raw_writel(0x0, base_ptr);
- mb();
+ }
cold_boot_done = true;
- iounmap(base_ptr);
}
/*
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index ce09f9f..f4536f7 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -101,6 +101,7 @@
int __init msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
{
int ret = 0;
+ unsigned long entry;
switch (pdata->mode) {
case MSM_PM_BOOT_CONFIG_TZ:
@@ -130,15 +131,44 @@
if (!pdata->p_addr || !pdata->v_addr)
return -ENODEV;
- __raw_writel((pdata->p_addr | BOOT_REMAP_ENABLE),
- pdata->v_addr);
-
ret = msm_pm_boot_reset_vector_init(__va(pdata->p_addr));
- msm_pm_boot_before_pc
- = msm_pm_config_rst_vector_before_pc;
- msm_pm_boot_after_pc
- = msm_pm_config_rst_vector_after_pc;
+ if (!cpu_is_msm8625()) {
+ __raw_writel((pdata->p_addr | BOOT_REMAP_ENABLE),
+ pdata->v_addr);
+
+ msm_pm_boot_before_pc
+ = msm_pm_config_rst_vector_before_pc;
+ msm_pm_boot_after_pc
+ = msm_pm_config_rst_vector_after_pc;
+ } else {
+ entry = virt_to_phys(msm_pm_boot_entry);
+
+ msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
+ msm_pm_reset_vector[1] = entry;
+
+ /* Here upper 16bits[16:31] used by CORE1
+ * lower 16bits[0:15] used by CORE0
+ */
+ entry = (pdata->p_addr) |
+ ((pdata->p_addr & 0xFFFF0000) >> 16);
+
+ /* write 'entry' to boot remapper register */
+ __raw_writel(entry, (pdata->v_addr +
+ MPA5_BOOT_REMAP_ADDR));
+
+ /* Enable boot remapper for C0 [bit:25th] */
+ __raw_writel(readl_relaxed(pdata->v_addr +
+ MPA5_CFG_CTL_REG) | BIT(25),
+ pdata->v_addr + MPA5_CFG_CTL_REG);
+
+ /* Enable boot remapper for C1 [bit:26th] */
+ __raw_writel(readl_relaxed(pdata->v_addr +
+ MPA5_CFG_CTL_REG) | BIT(26),
+ pdata->v_addr + MPA5_CFG_CTL_REG);
+
+ msm_pm_boot_before_pc = msm_pm_write_boot_vector;
+ }
break;
default:
__WARN();
diff --git a/arch/arm/mach-msm/pm-boot.h b/arch/arm/mach-msm/pm-boot.h
index 185d542..30b67c21 100644
--- a/arch/arm/mach-msm/pm-boot.h
+++ b/arch/arm/mach-msm/pm-boot.h
@@ -13,6 +13,11 @@
#ifndef _ARCH_ARM_MACH_MSM_PM_BOOT_H
#define _ARCH_ARM_MACH_MSM_PM_BOOT_H
+/* 8x25 specific macros */
+#define MPA5_CFG_CTL_REG 0x30
+#define MPA5_BOOT_REMAP_ADDR 0x34
+/* end */
+
enum {
MSM_PM_BOOT_CONFIG_TZ = 0,
MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS = 1,
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 7977d22..1396463 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -48,6 +48,7 @@
#ifdef CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN
#include <mach/msm_migrate_pages.h>
#endif
+#include <mach/socinfo.h>
#include "smd_private.h"
#include "smd_rpcrouter.h"
@@ -68,13 +69,14 @@
*****************************************************************************/
enum {
- MSM_PM_DEBUG_SUSPEND = 1U << 0,
- MSM_PM_DEBUG_POWER_COLLAPSE = 1U << 1,
- MSM_PM_DEBUG_STATE = 1U << 2,
- MSM_PM_DEBUG_CLOCK = 1U << 3,
- MSM_PM_DEBUG_RESET_VECTOR = 1U << 4,
- MSM_PM_DEBUG_SMSM_STATE = 1U << 5,
- MSM_PM_DEBUG_IDLE = 1U << 6,
+ MSM_PM_DEBUG_SUSPEND = BIT(0),
+ MSM_PM_DEBUG_POWER_COLLAPSE = BIT(1),
+ MSM_PM_DEBUG_STATE = BIT(2),
+ MSM_PM_DEBUG_CLOCK = BIT(3),
+ MSM_PM_DEBUG_RESET_VECTOR = BIT(4),
+ MSM_PM_DEBUG_SMSM_STATE = BIT(5),
+ MSM_PM_DEBUG_IDLE = BIT(6),
+ MSM_PM_DEBUG_HOTPLUG = BIT(7),
};
static int msm_pm_debug_mask;
@@ -142,7 +144,6 @@
static char *msm_pm_sleep_mode_labels[MSM_PM_SLEEP_MODE_NR] = {
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND] = " ",
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = "power_collapse",
- [MSM_PM_SLEEP_MODE_APPS_SLEEP] = "apps_sleep",
[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
"ramp_down_and_wfi",
[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = "wfi",
@@ -682,8 +683,6 @@
MSM_PM_STAT_IDLE_WFI,
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE,
- MSM_PM_STAT_IDLE_SLEEP,
- MSM_PM_STAT_IDLE_FAILED_SLEEP,
MSM_PM_STAT_IDLE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
MSM_PM_STAT_SUSPEND,
@@ -1008,6 +1007,13 @@
memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data));
+ if (cpu_is_msm8625()) {
+ /* Program the SPM */
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE,
+ false);
+ WARN_ON(ret);
+ }
+
msm_irq_enter_sleep1(true, from_idle, &msm_pm_smem_data->irq_mask);
msm_sirc_enter_sleep();
msm_gpio_enter_sleep(from_idle);
@@ -1210,6 +1216,13 @@
MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");
smd_sleep_exit();
+
+ if (cpu_is_msm8625()) {
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+ false);
+ WARN_ON(ret);
+ }
+
return 0;
power_collapse_early_exit:
@@ -1263,6 +1276,12 @@
smd_sleep_exit();
power_collapse_bail:
+ if (cpu_is_msm8625()) {
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+ false);
+ WARN_ON(ret);
+ }
+
return ret;
}
@@ -1272,10 +1291,11 @@
* Return value:
* 0: success
*/
-static int msm_pm_power_collapse_standalone(void)
+static int msm_pm_power_collapse_standalone(bool from_idle)
{
int collapsed = 0;
int ret;
+ void *entry;
MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
KERN_INFO, "%s()\n", __func__);
@@ -1283,21 +1303,26 @@
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE, false);
WARN_ON(ret);
+ entry = (!smp_processor_id() || from_idle) ?
+ msm_pm_collapse_exit : msm_secondary_startup;
+
msm_pm_boot_config_before_pc(smp_processor_id(),
- virt_to_phys(msm_pm_collapse_exit));
+ virt_to_phys(entry));
#ifdef CONFIG_VFP
vfp_flush_context();
#endif
#ifdef CONFIG_CACHE_L2X0
- l2x0_suspend();
+ if (!cpu_is_msm8625())
+ l2x0_suspend();
#endif
collapsed = msm_pm_collapse();
#ifdef CONFIG_CACHE_L2X0
- l2x0_resume(collapsed);
+ if (!cpu_is_msm8625())
+ l2x0_resume(collapsed);
#endif
msm_pm_boot_config_after_pc(smp_processor_id());
@@ -1321,18 +1346,6 @@
}
/*
- * Apps-sleep the Apps processor. This function execute the handshake
- * protocol with Modem.
- *
- * Return value:
- * -ENOSYS: function not implemented yet
- */
-static int msm_pm_apps_sleep(uint32_t sleep_delay, uint32_t sleep_limit)
-{
- return -ENOSYS;
-}
-
-/*
* Bring the Apps processor to SWFI.
*
* Return value:
@@ -1353,7 +1366,9 @@
return -EIO;
}
- msm_pm_config_hw_before_swfi();
+ if (!cpu_is_msm8625())
+ msm_pm_config_hw_before_swfi();
+
msm_arch_idle();
if (ramp_acpu) {
@@ -1395,7 +1410,7 @@
int64_t t1;
static int64_t t2;
int exit_stat;
- #endif /* CONFIG_MSM_IDLE_STATS */
+ #endif
if (!atomic_read(&msm_pm_init_done))
return;
@@ -1412,19 +1427,19 @@
exit_stat = MSM_PM_STAT_IDLE_SPIN;
low_power = 0;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
for (i = 0; i < ARRAY_SIZE(allow); i++)
allow[i] = true;
- if ((timer_expiration < msm_pm_idle_sleep_min_time) ||
+ if (num_online_cpus() > 1 ||
+ (timer_expiration < msm_pm_idle_sleep_min_time) ||
#ifdef CONFIG_HAS_WAKELOCK
has_wake_lock(WAKE_LOCK_IDLE) ||
#endif
!msm_irq_idle_sleep_allowed()) {
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
- allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
}
for (i = 0; i < ARRAY_SIZE(allow); i++) {
@@ -1493,32 +1508,15 @@
exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
msm_pm_sleep_limit = sleep_limit;
}
-#endif /* CONFIG_MSM_IDLE_STATS */
- } else if (allow[MSM_PM_SLEEP_MODE_APPS_SLEEP]) {
- uint32_t sleep_delay;
-
- sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
- timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
- if (sleep_delay == 0) /* 0 would mean infinite time */
- sleep_delay = 1;
-
- ret = msm_pm_apps_sleep(sleep_delay, sleep_limit);
- low_power = 0;
-
-#ifdef CONFIG_MSM_IDLE_STATS
- if (ret)
- exit_stat = MSM_PM_STAT_IDLE_FAILED_SLEEP;
- else
- exit_stat = MSM_PM_STAT_IDLE_SLEEP;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- ret = msm_pm_power_collapse_standalone();
+ ret = msm_pm_power_collapse_standalone(true);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = ret ?
MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE :
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
ret = msm_pm_swfi(true);
if (ret)
@@ -1527,20 +1525,20 @@
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = ret ? MSM_PM_STAT_IDLE_SPIN : MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
msm_pm_swfi(false);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else {
while (!msm_irq_pending())
udelay(1);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = MSM_PM_STAT_IDLE_SPIN;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
}
msm_timer_exit_idle(low_power);
@@ -1548,13 +1546,14 @@
#ifdef CONFIG_MSM_IDLE_STATS
t2 = ktime_to_ns(ktime_get());
msm_pm_add_stat(exit_stat, t2 - t1);
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
}
/*
* Suspend the Apps processor.
*
* Return value:
+ * -EPERM: Suspend happened by a not permitted core
* -EAGAIN: modem reset occurred or early exit from suspend
* -EBUSY: modem not ready for our suspend
* -EINVAL: invalid sleep mode
@@ -1566,13 +1565,20 @@
{
bool allow[MSM_PM_SLEEP_MODE_NR];
uint32_t sleep_limit = SLEEP_LIMIT_NONE;
- int ret;
+ int ret = -EPERM;
int i;
-
#ifdef CONFIG_MSM_IDLE_STATS
int64_t period = 0;
int64_t time = 0;
+#endif
+ /* Must executed by CORE0 */
+ if (smp_processor_id()) {
+ __WARN();
+ goto suspend_exit;
+ }
+
+#ifdef CONFIG_MSM_IDLE_STATS
time = msm_timer_get_sclk_time(&period);
#endif
@@ -1589,8 +1595,6 @@
allow[i] = false;
}
- ret = 0;
-
if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] ||
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) {
#ifdef CONFIG_MSM_IDLE_STATS
@@ -1647,7 +1651,7 @@
msm_pm_add_stat(id, time);
#endif
} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- ret = msm_pm_power_collapse_standalone();
+ ret = msm_pm_power_collapse_standalone(false);
} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
ret = msm_pm_swfi(true);
if (ret)
@@ -1657,6 +1661,7 @@
msm_pm_swfi(false);
}
+suspend_exit:
MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND, KERN_INFO,
"%s(): return %d\n", __func__, ret);
@@ -1673,7 +1678,27 @@
*/
void msm_pm_cpu_enter_lowpower(unsigned int cpu)
{
- return;
+ bool allow[MSM_PM_SLEEP_MODE_NR];
+ int i;
+
+ for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
+ struct msm_pm_platform_data *mode;
+
+ mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+ allow[i] = mode->suspend_supported && mode->suspend_enabled;
+ }
+
+ MSM_PM_DPRINTK(MSM_PM_DEBUG_HOTPLUG, KERN_INFO,
+ "CPU%u: %s: shutting down cpu\n", cpu, __func__);
+
+ if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
+ msm_pm_power_collapse_standalone(false);
+ } else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
+ msm_pm_swfi(false);
+ } else {
+ MSM_PM_DPRINTK(MSM_PM_DEBUG_HOTPLUG, KERN_INFO,
+ "CPU%u: %s: shutting down failed!!!\n", cpu, __func__);
+ }
}
/******************************************************************************
@@ -1725,10 +1750,6 @@
};
-/******************************************************************************
- *
- *****************************************************************************/
-
/*
* Initialize the power management subsystem.
*
@@ -1837,15 +1858,6 @@
first_bucket_time =
CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
- stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
- stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
- stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
- "idle-failed-sleep";
- stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
"idle-power-collapse";
stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 1bf2a55..31a54b7 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -58,8 +58,6 @@
#include <mach/msm_adsp.h>
#include "adsp.h"
-#define INT_ADSP INT_ADSP_A9_A11
-
static struct adsp_info adsp_info;
static struct msm_rpc_endpoint *rpc_cb_server_client;
static struct msm_adsp_module *adsp_modules;
@@ -1090,7 +1088,7 @@
mutex_lock(&adsp_open_lock);
if (adsp_open_count++ == 0) {
- enable_irq(INT_ADSP);
+ enable_irq(adsp_info.int_adsp);
prevent_suspend();
}
mutex_unlock(&adsp_open_lock);
@@ -1148,7 +1146,7 @@
clk_disable(module->clk);
mutex_lock(&adsp_open_lock);
if (--adsp_open_count == 0) {
- disable_irq(INT_ADSP);
+ disable_irq(adsp_info.int_adsp);
allow_suspend();
MM_DBG("disable interrupt\n");
}
@@ -1177,8 +1175,11 @@
unsigned count;
int rc, i;
- if (pdev->id != (rpc_adsp_rtos_atom_vers & RPC_VERSION_MAJOR_MASK))
- return -EINVAL;
+ adsp_info.int_adsp = platform_get_irq(pdev, 0);
+ if (adsp_info.int_adsp < 0) {
+ MM_ERR("no irq resource?\n");
+ return -ENODEV;
+ }
wake_lock_init(&adsp_wake_lock, WAKE_LOCK_SUSPEND, "adsp");
adsp_info.init_info_ptr = kzalloc(
@@ -1206,11 +1207,11 @@
spin_lock_init(&adsp_write_lock);
mutex_init(&adsp_info.lock);
- rc = request_irq(INT_ADSP, adsp_irq_handler, IRQF_TRIGGER_RISING,
- "adsp", 0);
+ rc = request_irq(adsp_info.int_adsp, adsp_irq_handler,
+ IRQF_TRIGGER_RISING, "adsp", 0);
if (rc < 0)
goto fail_request_irq;
- disable_irq(INT_ADSP);
+ disable_irq(adsp_info.int_adsp);
rpc_cb_server_client = msm_rpc_open();
if (IS_ERR(rpc_cb_server_client)) {
@@ -1262,8 +1263,8 @@
msm_rpc_close(rpc_cb_server_client);
rpc_cb_server_client = NULL;
fail_rpc_open:
- enable_irq(INT_ADSP);
- free_irq(INT_ADSP, 0);
+ enable_irq(adsp_info.int_adsp);
+ free_irq(adsp_info.int_adsp, 0);
fail_request_irq:
kfree(adsp_modules);
kfree(adsp_info.init_info_ptr);
@@ -1392,7 +1393,7 @@
},
};
-static char msm_adsp_driver_name[] = "rs00000000";
+static const char msm_adsp_driver_name[] = "msm_adsp";
#ifdef CONFIG_DEBUG_FS
static const struct file_operations adsp_debug_fops = {
@@ -1431,9 +1432,6 @@
rpc_adsp_rtos_mtoa_vers_comp = 0x00030001;
#endif
- snprintf(msm_adsp_driver_name, sizeof(msm_adsp_driver_name),
- "rs%08x",
- rpc_adsp_rtos_atom_prog);
msm_adsp_driver.driver.name = msm_adsp_driver_name;
rc = platform_driver_register(&msm_adsp_driver);
MM_INFO("%s -- %d\n", msm_adsp_driver_name, rc);
diff --git a/arch/arm/mach-msm/qdsp5/adsp.h b/arch/arm/mach-msm/qdsp5/adsp.h
index 8e5a4f3..0f16111 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.h
+++ b/arch/arm/mach-msm/qdsp5/adsp.h
@@ -118,6 +118,9 @@
wait_queue_head_t init_info_wait;
unsigned init_info_state;
struct mutex lock;
+
+ /* Interrupt value */
+ int int_adsp;
};
#define RPC_ADSP_RTOS_ATOM_NULL_PROC 0
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index 7a962b2..2011c42 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -836,6 +836,7 @@
file->private_data = audio;
audio->opened = 1;
+ audio->stopped = 0;
rc = 0;
done:
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.c b/arch/arm/mach-msm/qdsp5v2/adsp.c
index b7b56c8..acd9c4c 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.c
@@ -2,7 +2,7 @@
* Register/Interrupt access for userspace aDSP library.
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2009,2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009,2011-2012 Code Aurora Forum. All rights reserved.
* Author: Iliyan Malchev <ibm@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -46,8 +46,6 @@
static int wdump, rdump;
#endif /* CONFIG_DEBUG_FS */
-#define INT_ADSP INT_ADSP_A9_A11
-
static struct adsp_info adsp_info;
static struct msm_adsp_module *adsp_modules;
static int adsp_open_count;
@@ -889,7 +887,7 @@
mutex_lock(&adsp_open_lock);
if (adsp_open_count++ == 0)
- enable_irq(INT_ADSP);
+ enable_irq(adsp_info.int_adsp);
mutex_unlock(&adsp_open_lock);
break;
case ADSP_STATE_ENABLING:
@@ -944,7 +942,7 @@
mutex_unlock(&module->lock);
mutex_lock(&adsp_open_lock);
if (--adsp_open_count == 0) {
- disable_irq(INT_ADSP);
+ disable_irq(adsp_info.int_adsp);
MM_INFO("disable interrupt\n");
}
mutex_unlock(&adsp_open_lock);
@@ -959,6 +957,12 @@
unsigned count;
int rc, i;
+ adsp_info.int_adsp = platform_get_irq(pdev, 0);
+ if (adsp_info.int_adsp < 0) {
+ MM_ERR("no irq resource?\n");
+ return -ENODEV;
+ }
+
adsp_info.init_info_ptr = kzalloc(
(sizeof(struct adsp_rtos_mp_mtoa_init_info_type)), GFP_KERNEL);
if (!adsp_info.init_info_ptr)
@@ -996,11 +1000,11 @@
spin_lock_init(&adsp_cmd_lock);
spin_lock_init(&adsp_write_lock);
- rc = request_irq(INT_ADSP, adsp_irq_handler,
+ rc = request_irq(adsp_info.int_adsp, adsp_irq_handler,
IRQF_TRIGGER_RISING, "adsp", 0);
if (rc < 0)
goto fail_request_irq;
- disable_irq(INT_ADSP);
+ disable_irq(adsp_info.int_adsp);
for (i = 0; i < count; i++) {
struct msm_adsp_module *mod = adsp_modules + i;
@@ -1056,8 +1060,8 @@
daldevice_detach(adsp_info.handle);
adsp_info.handle = NULL;
fail_dal_attach:
- enable_irq(INT_ADSP);
- free_irq(INT_ADSP, 0);
+ enable_irq(adsp_info.int_adsp);
+ free_irq(adsp_info.int_adsp, 0);
fail_request_irq:
kfree(adsp_modules);
kfree(adsp_info.init_info_ptr);
@@ -1187,11 +1191,6 @@
},
};
-struct platform_device msm_adsp_device = {
- .name = "msm_adsp",
- .id = -1,
-};
-
static char msm_adsp_driver_name[] = "msm_adsp";
#ifdef CONFIG_DEBUG_FS
@@ -1218,7 +1217,6 @@
#endif /* CONFIG_DEBUG_FS */
msm_adsp_driver.driver.name = msm_adsp_driver_name;
- rc = platform_device_register(&msm_adsp_device);
rc = platform_driver_register(&msm_adsp_driver);
MM_INFO("%s -- %d\n", msm_adsp_driver_name, rc);
return rc;
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp.h b/arch/arm/mach-msm/qdsp5v2/adsp.h
index 18f4046..5aceff9 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp.h
+++ b/arch/arm/mach-msm/qdsp5v2/adsp.h
@@ -229,6 +229,9 @@
void *handle;
void *cb_handle;
+
+ /* Interrupt value */
+ int int_adsp;
};
#define ADSP_STATE_DISABLED 0
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index ce5d084..9b03985 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -15,7 +15,7 @@
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+#include <linux/ion.h>
#include <linux/mm.h>
#include <mach/qdsp6v2/audio_acdb.h>
@@ -62,13 +62,13 @@
/* Sidetone Cal */
struct sidetone_atomic_cal sidetone_cal;
- /* PMEM information */
- atomic_t pmem_fd;
+ /* Allocation information */
+ struct ion_client *ion_client;
+ struct ion_handle *ion_handle;
+ atomic_t map_handle;
atomic64_t paddr;
atomic64_t kvaddr;
- atomic64_t pmem_len;
- struct file *file;
-
+ atomic64_t mem_len;
};
static struct acdb_data acdb_data;
@@ -200,10 +200,10 @@
{
pr_debug("%s,\n", __func__);
- if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_block->cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
goto done;
}
@@ -221,10 +221,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_block->cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
goto done;
}
if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
@@ -271,10 +271,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_block->cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -321,10 +321,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_block->cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -371,10 +371,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_block->cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -432,10 +432,10 @@
atomic_set(&acdb_data.vocproc_total_cal_size, 0);
for (i = 0; i < len; i++) {
if (cal_blocks[i].cal_offset >
- atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
} else {
atomic_add(cal_blocks[i].cal_size,
@@ -484,10 +484,10 @@
atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
for (i = 0; i < len; i++) {
if (cal_blocks[i].cal_offset >
- atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
} else {
atomic_add(cal_blocks[i].cal_size,
@@ -536,10 +536,10 @@
atomic_set(&acdb_data.vocvol_total_cal_size, 0);
for (i = 0; i < len; i++) {
if (cal_blocks[i].cal_offset >
- atomic64_read(&acdb_data.pmem_len)) {
- pr_err("%s: offset %d is > pmem_len %ld\n",
+ atomic64_read(&acdb_data.mem_len)) {
+ pr_err("%s: offset %d is > mem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
} else {
atomic_add(cal_blocks[i].cal_size,
@@ -603,8 +603,9 @@
s32 result = 0;
pr_debug("%s\n", __func__);
- if (atomic_read(&acdb_data.pmem_fd)) {
- pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
+ if (atomic64_read(&acdb_data.mem_len)) {
+ pr_debug("%s: ACDB opened but memory allocated, "
+ "using existing allocation!\n",
__func__);
}
@@ -612,46 +613,74 @@
return result;
}
-static int deregister_pmem(void)
+static int deregister_memory(void)
{
- if (atomic_read(&acdb_data.pmem_fd)) {
+ if (atomic64_read(&acdb_data.mem_len)) {
mutex_lock(&acdb_data.acdb_mutex);
- put_pmem_file(acdb_data.file);
+ ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
+ ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+ ion_client_destroy(acdb_data.ion_client);
mutex_unlock(&acdb_data.acdb_mutex);
- atomic_set(&acdb_data.pmem_fd, 0);
+ atomic64_set(&acdb_data.mem_len, 0);
}
return 0;
}
-static int register_pmem(void)
+static int register_memory(void)
{
- int result;
- unsigned long paddr;
- unsigned long kvaddr;
- unsigned long pmem_len;
+ int result;
+ unsigned long paddr;
+ unsigned long kvaddr;
+ unsigned long mem_len;
mutex_lock(&acdb_data.acdb_mutex);
- result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
- &paddr, &kvaddr, &pmem_len,
- &acdb_data.file);
- mutex_unlock(&acdb_data.acdb_mutex);
- if (result != 0) {
- atomic_set(&acdb_data.pmem_fd, 0);
- atomic64_set(&acdb_data.pmem_len, 0);
- pr_err("%s: Could not register PMEM!!!\n", __func__);
- goto done;
+ acdb_data.ion_client =
+ msm_ion_client_create(UINT_MAX, "audio_acdb_client");
+ if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
+ pr_err("%s: Could not register ION client!!!\n", __func__);
+ goto err;
}
+ acdb_data.ion_handle = ion_import_fd(acdb_data.ion_client,
+ atomic_read(&acdb_data.map_handle));
+ if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
+ pr_err("%s: Could not import map handle!!!\n", __func__);
+ goto err_ion_client;
+ }
+
+ result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
+ &paddr, (size_t *)&mem_len);
+ if (result != 0) {
+ pr_err("%s: Could not get phys addr!!!\n", __func__);
+ goto err_ion_handle;
+ }
+
+ kvaddr = (unsigned long)ion_map_kernel(acdb_data.ion_client,
+ acdb_data.ion_handle, 0);
+ if (IS_ERR_OR_NULL(&kvaddr)) {
+ pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
+ goto err_ion_handle;
+ }
+ mutex_unlock(&acdb_data.acdb_mutex);
+
atomic64_set(&acdb_data.paddr, paddr);
atomic64_set(&acdb_data.kvaddr, kvaddr);
- atomic64_set(&acdb_data.pmem_len, pmem_len);
- pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
+ atomic64_set(&acdb_data.mem_len, mem_len);
+ pr_debug("%s done! paddr = 0x%lx, "
"kvaddr = 0x%lx, len = x%lx\n",
+ __func__,
(long)atomic64_read(&acdb_data.paddr),
(long)atomic64_read(&acdb_data.kvaddr),
- (long)atomic64_read(&acdb_data.pmem_len));
+ (long)atomic64_read(&acdb_data.mem_len));
-done:
+ return result;
+err_ion_handle:
+ ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+err_ion_client:
+ ion_client_destroy(acdb_data.ion_client);
+err:
+ atomic64_set(&acdb_data.mem_len, 0);
+ mutex_unlock(&acdb_data.acdb_mutex);
return result;
}
static long acdb_ioctl(struct file *f,
@@ -659,7 +688,7 @@
{
int32_t result = 0;
int32_t size;
- int32_t pmem_fd;
+ int32_t map_fd;
uint32_t topology;
struct cal_block data[MAX_NETWORKS];
pr_debug("%s\n", __func__);
@@ -667,23 +696,23 @@
switch (cmd) {
case AUDIO_REGISTER_PMEM:
pr_debug("AUDIO_REGISTER_PMEM\n");
- if (atomic_read(&acdb_data.pmem_fd)) {
- deregister_pmem();
- pr_debug("Remove the existing PMEM\n");
+ if (atomic_read(&acdb_data.mem_len)) {
+ deregister_memory();
+ pr_debug("Remove the existing memory\n");
}
- if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
- pr_err("%s: fail to copy pmem handle!\n", __func__);
+ if (copy_from_user(&map_fd, (void *)arg, sizeof(map_fd))) {
+ pr_err("%s: fail to copy memory handle!\n", __func__);
result = -EFAULT;
} else {
- atomic_set(&acdb_data.pmem_fd, pmem_fd);
- result = register_pmem();
+ atomic_set(&acdb_data.map_handle, map_fd);
+ result = register_memory();
}
goto done;
case AUDIO_DEREGISTER_PMEM:
pr_debug("AUDIO_DEREGISTER_PMEM\n");
- deregister_pmem();
+ deregister_memory();
goto done;
case AUDIO_SET_VOICE_RX_TOPOLOGY:
if (copy_from_user(&topology, (void *)arg,
@@ -835,8 +864,8 @@
pr_debug("%s\n", __func__);
- if (atomic_read(&acdb_data.pmem_fd)) {
- if (size <= atomic64_read(&acdb_data.pmem_len)) {
+ if (atomic64_read(&acdb_data.mem_len)) {
+ if (size <= atomic64_read(&acdb_data.mem_len)) {
vma->vm_page_prot = pgprot_noncached(
vma->vm_page_prot);
result = remap_pfn_range(vma,
@@ -845,11 +874,11 @@
size,
vma->vm_page_prot);
} else {
- pr_err("%s: Not enough PMEM memory!\n", __func__);
+ pr_err("%s: Not enough memory!\n", __func__);
result = -ENOMEM;
}
} else {
- pr_err("%s: PMEM is not allocated, yet!\n", __func__);
+ pr_err("%s: memory is not allocated, yet!\n", __func__);
result = -ENODEV;
}
@@ -869,7 +898,7 @@
if (atomic_read(&usage_count) >= 1)
result = -EBUSY;
else
- result = deregister_pmem();
+ result = deregister_memory();
return result;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c b/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
index 0a5acce..aaae776 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_dev_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/sched.h>
+#include <linux/workqueue.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <mach/qdsp6v2/audio_dev_ctl.h>
@@ -31,6 +32,9 @@
static DEFINE_MUTEX(session_lock);
+static struct workqueue_struct *msm_reset_device_work_queue;
+static void reset_device_work(struct work_struct *work);
+static DECLARE_WORK(msm_reset_device_work, reset_device_work);
struct audio_dev_ctrl_state {
struct msm_snddev_info *devs[AUDIO_DEV_CTL_MAX_DEV];
@@ -119,6 +123,18 @@
}
EXPORT_SYMBOL(msm_reset_all_device);
+static void reset_device_work(struct work_struct *work)
+{
+ msm_reset_all_device();
+}
+
+int reset_device(void)
+{
+ queue_work(msm_reset_device_work_queue, &msm_reset_device_work);
+ return 0;
+}
+EXPORT_SYMBOL(reset_device);
+
int msm_set_copp_id(int session_id, int copp_id)
{
int rc = 0;
@@ -1686,7 +1702,9 @@
init_waitqueue_head(&audio_dev_ctrl.wait);
event.cb = NULL;
-
+ msm_reset_device_work_queue = create_workqueue("reset_device");
+ if (msm_reset_device_work_queue == NULL)
+ return -ENOMEM;
atomic_set(&audio_dev_ctrl.opened, 0);
audio_dev_ctrl.num_dev = 0;
audio_dev_ctrl.voice_tx_dev = NULL;
@@ -1704,6 +1722,7 @@
static void __exit audio_dev_ctrl_exit(void)
{
+ destroy_workqueue(msm_reset_device_work_queue);
}
module_init(audio_dev_ctrl_init);
module_exit(audio_dev_ctrl_exit);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
index 3225d61..41a7387 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -28,8 +28,8 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/earlysuspend.h>
+#include <linux/ion.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
@@ -45,7 +45,7 @@
#include <mach/debug_mm.h>
#include <linux/fs.h>
-#define MAX_BUF 3
+#define MAX_BUF 4
#define BUFSZ (524288)
#define AUDDEC_DEC_PCM 0
@@ -88,10 +88,10 @@
int event_type;
union msm_audio_event_payload payload;
};
-
-struct audlpa_pmem_region {
+struct audlpa_ion_region {
struct list_head list;
- struct file *file;
+ struct ion_handle *handle;
+ struct ion_client *client;
int fd;
void *vaddr;
unsigned long paddr;
@@ -115,12 +115,13 @@
static void audlpa_post_event(struct audio *audio, int type,
union msm_audio_event_payload payload);
-static unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
+
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
unsigned long len, int ref_up);
+static void audlpa_unmap_ion_region(struct audio *audio);
static void audlpa_async_send_data(struct audio *audio, unsigned needed,
uint32_t token);
static int audlpa_pause(struct audio *audio);
-static void audlpa_unmap_pmem_region(struct audio *audio);
static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static int audlpa_set_pcm_params(void *data);
@@ -422,7 +423,7 @@
drv_evt->event_type == AUDIO_EVENT_READ_DONE)) {
pr_debug("%s: AUDIO_EVENT_WRITE_DONE completing\n", __func__);
mutex_lock(&audio->lock);
- audlpa_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+ audlpa_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
drv_evt->payload.aio_buf.buf_len, 0);
mutex_unlock(&audio->lock);
}
@@ -432,38 +433,41 @@
return rc;
}
-static int audlpa_pmem_check(struct audio *audio,
- void *vaddr, unsigned long len)
+static int audlpa_ion_check(struct audio *audio,
+ void *vaddr, unsigned long len)
{
- struct audlpa_pmem_region *region_elt;
- struct audlpa_pmem_region t = { .vaddr = vaddr, .len = len };
+ struct audlpa_ion_region *region_elt;
+ struct audlpa_ion_region t = {.vaddr = vaddr, .len = len };
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
OVERLAPS(region_elt, &t)) {
- pr_err("%s: region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- __func__, vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
+ pr_err("%s[%p]:region (vaddr %p len %ld)"
+ " clashes with registered region"
+ " (vaddr %p paddr %p len %ld)\n",
+ __func__, audio, vaddr, len,
+ region_elt->vaddr,
+ (void *)region_elt->paddr, region_elt->len);
return -EINVAL;
}
}
return 0;
}
-
-static int audlpa_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
+static int audlpa_ion_add(struct audio *audio,
+ struct msm_audio_ion_info *info)
{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audlpa_pmem_region *region;
+ ion_phys_addr_t paddr;
+ size_t len;
+ unsigned long kvaddr;
+ struct audlpa_ion_region *region;
int rc = -EINVAL;
+ struct ion_handle *handle;
+ struct ion_client *client;
+ unsigned long ionflag;
+ void *temp_ptr;
- pr_debug("%s:\n", __func__);
+ pr_debug("%s[%p]:\n", __func__, audio);
region = kmalloc(sizeof(*region), GFP_KERNEL);
if (!region) {
@@ -471,61 +475,105 @@
goto end;
}
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
+ client = msm_ion_client_create(UINT_MAX, "Audio_LPA_Client");
+ if (IS_ERR_OR_NULL(client)) {
+ pr_err("Unable to create ION client\n");
+ goto client_error;
}
- rc = audlpa_pmem_check(audio, info->vaddr, len);
+ handle = ion_import_fd(client, info->fd);
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: could not get handle of the given fd\n", __func__);
+ goto import_error;
+ }
+
+ rc = ion_handle_get_flags(client, handle, &ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n", __func__);
+ goto flag_error;
+ }
+
+ temp_ptr = ion_map_kernel(client, handle, ionflag);
+ if (IS_ERR_OR_NULL(temp_ptr)) {
+ pr_err("%s: could not get virtual address\n", __func__);
+ goto map_error;
+ }
+ kvaddr = (unsigned long) temp_ptr;
+
+ rc = ion_phys(client, handle, &paddr, &len);
+ if (rc) {
+ pr_err("%s: could not get physical address\n", __func__);
+ goto ion_error;
+ }
+
+ rc = audlpa_ion_check(audio, info->vaddr, len);
if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
+ pr_err("%s: audlpa_ion_check failed\n", __func__);
+ goto ion_error;
}
+ region->client = client;
+ region->handle = handle;
region->vaddr = info->vaddr;
region->fd = info->fd;
region->paddr = paddr;
region->kvaddr = kvaddr;
region->len = len;
- region->file = file;
region->ref_cnt = 0;
- pr_debug("%s: add region paddr %lx vaddr %p, len %lu\n", __func__,
- region->paddr, region->vaddr,
- region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
+ pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
+ __func__, audio,
+ region->paddr, region->vaddr, region->len, region->kvaddr);
+ list_add_tail(®ion->list, &audio->ion_region_queue);
+
rc = q6asm_memory_map(audio->ac, (uint32_t)paddr, IN, (uint32_t)len, 1);
- if (rc < 0)
- pr_err("%s: memory map failed\n", __func__);
+ if (rc < 0) {
+ pr_err("%s[%p]: memory map failed\n", __func__, audio);
+ goto ion_error;
+ } else {
+ goto end;
+ }
+
+ion_error:
+ ion_unmap_kernel(client, handle);
+map_error:
+ ion_free(client, handle);
+flag_error:
+import_error:
+ ion_client_destroy(client);
+client_error:
+ kfree(region);
end:
return rc;
}
-static int audlpa_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
+static int audlpa_ion_remove(struct audio *audio,
+ struct msm_audio_ion_info *info)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
struct list_head *ptr, *next;
int rc = -EINVAL;
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audlpa_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audlpa_ion_region, list);
- if ((region != NULL) && (region->fd == info->fd) &&
- (region->vaddr == info->vaddr)) {
+ if (region != NULL && (region->fd == info->fd) &&
+ (region->vaddr == info->vaddr)) {
if (region->ref_cnt) {
- pr_debug("%s: region %p in use ref_cnt %d\n",
- __func__, region, region->ref_cnt);
+ pr_debug("%s[%p]:region %p in use ref_cnt %d\n",
+ __func__, audio, region,
+ region->ref_cnt);
break;
}
rc = q6asm_memory_unmap(audio->ac,
- (uint32_t)region->paddr,
- IN);
+ (uint32_t) region->paddr, IN);
if (rc < 0)
- pr_err("%s: memory unmap failed\n", __func__);
+ pr_err("%s[%p]: memory unmap failed\n",
+ __func__, audio);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(region->client, region->handle);
+ ion_free(region->client, region->handle);
+ ion_client_destroy(region->client);
kfree(region);
rc = 0;
break;
@@ -535,24 +583,21 @@
return rc;
}
-static int audlpa_pmem_lookup_vaddr(struct audio *audio, void *addr,
- unsigned long len, struct audlpa_pmem_region **region)
+static int audlpa_ion_lookup_vaddr(struct audio *audio, void *addr,
+ unsigned long len, struct audlpa_ion_region **region)
{
- struct audlpa_pmem_region *region_elt;
-
+ struct audlpa_ion_region *region_elt;
int match_count = 0;
-
*region = NULL;
/* returns physical address or zero */
- list_for_each_entry(region_elt, &audio->pmem_region_queue,
- list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (addr >= region_elt->vaddr &&
- addr < region_elt->vaddr + region_elt->len &&
- addr + len <= region_elt->vaddr + region_elt->len) {
+ addr < region_elt->vaddr + region_elt->len &&
+ addr + len <= region_elt->vaddr + region_elt->len) {
/* offset since we could pass vaddr inside a registerd
- * pmem buffer
- */
+ * ion buffer
+ */
match_count++;
if (!*region)
@@ -561,32 +606,33 @@
}
if (match_count > 1) {
- pr_err("%s: multiple hits for vaddr %p, len %ld\n", __func__,
- addr, len);
- list_for_each_entry(region_elt,
- &audio->pmem_region_queue, list) {
- if (addr >= region_elt->vaddr &&
- addr < region_elt->vaddr + region_elt->len &&
- addr + len <= region_elt->vaddr + region_elt->len)
- pr_err("%s: \t%p, %ld --> %p\n", __func__,
- region_elt->vaddr, region_elt->len,
- (void *)region_elt->paddr);
+ pr_err("%s[%p]:multiple hits for vaddr %p, len %ld\n",
+ __func__, audio, addr, len);
+ list_for_each_entry(region_elt, &audio->ion_region_queue,
+ list) {
+ if (addr >= region_elt->vaddr &&
+ addr < region_elt->vaddr + region_elt->len &&
+ addr + len <= region_elt->vaddr + region_elt->len)
+ pr_err("\t%s[%p]:%p, %ld --> %p\n",
+ __func__, audio,
+ region_elt->vaddr,
+ region_elt->len,
+ (void *)region_elt->paddr);
}
}
-
return *region ? 0 : -1;
}
-
-unsigned long audlpa_pmem_fixup(struct audio *audio, void *addr,
- unsigned long len, int ref_up)
+static unsigned long audlpa_ion_fixup(struct audio *audio, void *addr,
+ unsigned long len, int ref_up)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
unsigned long paddr;
int ret;
- ret = audlpa_pmem_lookup_vaddr(audio, addr, len, ®ion);
+ ret = audlpa_ion_lookup_vaddr(audio, addr, len, ®ion);
if (ret) {
- pr_err("%s: lookup (%p, %ld) failed\n", __func__, addr, len);
+ pr_err("%s[%p]:lookup (%p, %ld) failed\n",
+ __func__, audio, addr, len);
return 0;
}
if (ref_up)
@@ -613,7 +659,7 @@
return -EFAULT;
}
- buf_node->paddr = audlpa_pmem_fixup(
+ buf_node->paddr = audlpa_ion_fixup(
audio, buf_node->buf.buf_addr,
buf_node->buf.buf_len, 1);
if (dir) {
@@ -669,6 +715,9 @@
break;
case ASM_SESSION_CMDRSP_GET_SESSION_TIME:
break;
+ case RESET_EVENTS:
+ reset_device();
+ break;
default:
break;
}
@@ -918,25 +967,26 @@
}
break;
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- pr_debug("%s: AUDIO_REGISTER_PMEM\n", __func__);
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audlpa_pmem_add(audio, &info);
- break;
- }
+ case AUDIO_REGISTER_ION: {
+ struct msm_audio_ion_info info;
+ pr_debug("%s: AUDIO_REGISTER_ION\n", __func__);
+ if (copy_from_user(&info, (void *)arg, sizeof(info)))
+ rc = -EFAULT;
+ else
+ rc = audlpa_ion_add(audio, &info);
+ break;
+ }
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- pr_debug("%s: AUDIO_DEREGISTER_PMEM\n", __func__);
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audlpa_pmem_remove(audio, &info);
- break;
- }
+ case AUDIO_DEREGISTER_ION: {
+ struct msm_audio_ion_info info;
+ pr_debug("%s: AUDIO_DEREGISTER_ION\n", __func__);
+ if (copy_from_user(&info, (void *)arg, sizeof(info)))
+ rc = -EFAULT;
+ else
+ rc = audlpa_ion_remove(audio, &info);
+ break;
+ }
+
case AUDIO_ASYNC_WRITE:
pr_debug("%s: AUDIO_ASYNC_WRITE\n", __func__);
if (audio->drv_status & ADRV_STATUS_FSYNC)
@@ -1035,34 +1085,37 @@
return audlpa_async_fsync(audio);
}
-static void audlpa_reset_pmem_region(struct audio *audio)
+void audlpa_reset_ion_region(struct audio *audio)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
struct list_head *ptr, *next;
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audlpa_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audlpa_ion_region, list);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(region->client, region->handle);
+ ion_free(region->client, region->handle);
+ ion_client_destroy(region->client);
kfree(region);
}
return;
}
-static void audlpa_unmap_pmem_region(struct audio *audio)
+static void audlpa_unmap_ion_region(struct audio *audio)
{
- struct audlpa_pmem_region *region;
+ struct audlpa_ion_region *region;
struct list_head *ptr, *next;
int rc = -EINVAL;
- pr_debug("%s:\n", __func__);
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audlpa_pmem_region, list);
- pr_debug("%s: phy_address = 0x%lx\n", __func__, region->paddr);
+ pr_debug("%s[%p]:\n", __func__, audio);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audlpa_ion_region, list);
+ pr_debug("%s[%p]: phy_address = 0x%lx\n",
+ __func__, audio, region->paddr);
if (region != NULL) {
rc = q6asm_memory_unmap(audio->ac,
- (uint32_t)region->paddr, IN);
+ (uint32_t)region->paddr, IN);
if (rc < 0)
pr_err("%s: memory unmap failed\n", __func__);
}
@@ -1081,12 +1134,12 @@
if (audio->out_enabled)
audlpa_async_flush(audio);
audio->wflush = 0;
- audlpa_unmap_pmem_region(audio);
+ audlpa_unmap_ion_region(audio);
audio_disable(audio);
msm_clear_session_id(audio->ac->session);
auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->ac->session);
q6asm_audio_client_free(audio->ac);
- audlpa_reset_pmem_region(audio);
+ audlpa_reset_ion_region(audio);
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&audio->suspend_ctl.node);
#endif
@@ -1096,7 +1149,6 @@
audio->event_abort = 1;
wake_up(&audio->event_wait);
audlpa_reset_event_queue(audio);
- pmem_kfree(audio->phys);
if (audio->stopped == 0)
audlpa_allow_sleep(audio);
wake_lock_destroy(&audio->wakelock);
@@ -1274,7 +1326,7 @@
spin_lock_init(&audio->dsp_lock);
init_waitqueue_head(&audio->write_wait);
INIT_LIST_HEAD(&audio->out_queue);
- INIT_LIST_HEAD(&audio->pmem_region_queue);
+ INIT_LIST_HEAD(&audio->ion_region_queue);
INIT_LIST_HEAD(&audio->free_event_queue);
INIT_LIST_HEAD(&audio->event_queue);
init_waitqueue_head(&audio->wait);
@@ -1339,7 +1391,6 @@
return rc;
err:
q6asm_audio_client_free(audio->ac);
- pmem_kfree(audio->phys);
kfree(audio);
return rc;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_lpa.h b/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
index ffc27ad..34b53f2 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_lpa.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -88,7 +88,7 @@
uint32_t device_events;
- struct list_head pmem_region_queue; /* protected by lock */
+ struct list_head ion_region_queue; /* protected by lock */
int eq_enable;
int eq_needs_commit;
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index c1b5e8b..d2557ca 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1,6 +1,6 @@
/* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -129,23 +129,23 @@
}
}
-static int audio_aio_pmem_lookup_vaddr(struct q6audio_aio *audio, void *addr,
+static int audio_aio_ion_lookup_vaddr(struct q6audio_aio *audio, void *addr,
unsigned long len,
- struct audio_aio_pmem_region **region)
+ struct audio_aio_ion_region **region)
{
- struct audio_aio_pmem_region *region_elt;
+ struct audio_aio_ion_region *region_elt;
int match_count = 0;
*region = NULL;
/* returns physical address or zero */
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (addr >= region_elt->vaddr &&
addr < region_elt->vaddr + region_elt->len &&
addr + len <= region_elt->vaddr + region_elt->len) {
/* offset since we could pass vaddr inside a registerd
- * pmem buffer
+ * ion buffer
*/
match_count++;
@@ -157,7 +157,7 @@
if (match_count > 1) {
pr_err("%s[%p]:multiple hits for vaddr %p, len %ld\n",
__func__, audio, addr, len);
- list_for_each_entry(region_elt, &audio->pmem_region_queue,
+ list_for_each_entry(region_elt, &audio->ion_region_queue,
list) {
if (addr >= region_elt->vaddr &&
addr < region_elt->vaddr + region_elt->len &&
@@ -173,14 +173,14 @@
return *region ? 0 : -1;
}
-static unsigned long audio_aio_pmem_fixup(struct q6audio_aio *audio, void *addr,
+static unsigned long audio_aio_ion_fixup(struct q6audio_aio *audio, void *addr,
unsigned long len, int ref_up, void **kvaddr)
{
- struct audio_aio_pmem_region *region;
+ struct audio_aio_ion_region *region;
unsigned long paddr;
int ret;
- ret = audio_aio_pmem_lookup_vaddr(audio, addr, len, ®ion);
+ ret = audio_aio_ion_lookup_vaddr(audio, addr, len, ®ion);
if (ret) {
pr_err("%s[%p]:lookup (%p, %ld) failed\n",
__func__, audio, addr, len);
@@ -519,15 +519,17 @@
return rc;
}
-void audio_aio_reset_pmem_region(struct q6audio_aio *audio)
+void audio_aio_reset_ion_region(struct q6audio_aio *audio)
{
- struct audio_aio_pmem_region *region;
+ struct audio_aio_ion_region *region;
struct list_head *ptr, *next;
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audio_aio_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audio_aio_ion_region, list);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(region->client, region->handle);
+ ion_free(region->client, region->handle);
+ ion_client_destroy(region->client);
kfree(region);
}
@@ -558,15 +560,15 @@
return;
}
-static void audio_aio_unmap_pmem_region(struct q6audio_aio *audio)
+static void audio_aio_unmap_ion_region(struct q6audio_aio *audio)
{
- struct audio_aio_pmem_region *region;
+ struct audio_aio_ion_region *region;
struct list_head *ptr, *next;
int rc = -EINVAL;
pr_debug("%s[%p]:\n", __func__, audio);
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audio_aio_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audio_aio_ion_region, list);
pr_debug("%s[%p]: phy_address = 0x%lx\n",
__func__, audio, region->paddr);
if (region != NULL) {
@@ -590,9 +592,9 @@
audio->wflush = 0;
audio->drv_ops.out_flush(audio);
audio->drv_ops.in_flush(audio);
- audio_aio_unmap_pmem_region(audio);
+ audio_aio_unmap_ion_region(audio);
audio_aio_disable(audio);
- audio_aio_reset_pmem_region(audio);
+ audio_aio_reset_ion_region(audio);
audio->event_abort = 1;
wake_up(&audio->event_wait);
audio_aio_reset_event_queue(audio);
@@ -746,14 +748,14 @@
pr_debug("%s[%p]:posted AUDIO_EVENT_WRITE_DONE to user\n",
__func__, audio);
mutex_lock(&audio->write_lock);
- audio_aio_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+ audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
drv_evt->payload.aio_buf.buf_len, 0, 0);
mutex_unlock(&audio->write_lock);
} else if (drv_evt->event_type == AUDIO_EVENT_READ_DONE) {
pr_debug("%s[%p]:posted AUDIO_EVENT_READ_DONE to user\n",
__func__, audio);
mutex_lock(&audio->read_lock);
- audio_aio_pmem_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
+ audio_aio_ion_fixup(audio, drv_evt->payload.aio_buf.buf_addr,
drv_evt->payload.aio_buf.buf_len, 0, 0);
mutex_unlock(&audio->read_lock);
}
@@ -773,13 +775,13 @@
return rc;
}
-static int audio_aio_pmem_check(struct q6audio_aio *audio,
+static int audio_aio_ion_check(struct q6audio_aio *audio,
void *vaddr, unsigned long len)
{
- struct audio_aio_pmem_region *region_elt;
- struct audio_aio_pmem_region t = {.vaddr = vaddr, .len = len };
+ struct audio_aio_ion_region *region_elt;
+ struct audio_aio_ion_region t = {.vaddr = vaddr, .len = len };
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
+ list_for_each_entry(region_elt, &audio->ion_region_queue, list) {
if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
OVERLAPS(region_elt, &t)) {
pr_err("%s[%p]:region (vaddr %p len %ld)"
@@ -795,13 +797,18 @@
return 0;
}
-static int audio_aio_pmem_add(struct q6audio_aio *audio,
- struct msm_audio_pmem_info *info)
+static int audio_aio_ion_add(struct q6audio_aio *audio,
+ struct msm_audio_ion_info *info)
{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audio_aio_pmem_region *region;
+ ion_phys_addr_t paddr;
+ size_t len;
+ unsigned long kvaddr;
+ struct audio_aio_ion_region *region;
int rc = -EINVAL;
+ struct ion_handle *handle;
+ struct ion_client *client;
+ unsigned long ionflag;
+ void *temp_ptr;
pr_debug("%s[%p]:\n", __func__, audio);
region = kmalloc(sizeof(*region), GFP_KERNEL);
@@ -811,50 +818,89 @@
goto end;
}
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
+ client = msm_ion_client_create(UINT_MAX, "Audio_Dec_Client");
+ if (IS_ERR_OR_NULL(client)) {
+ pr_err("Unable to create ION client\n");
+ goto client_error;
}
- rc = audio_aio_pmem_check(audio, info->vaddr, len);
+ handle = ion_import_fd(client, info->fd);
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: could not get handle of the given fd\n", __func__);
+ goto import_error;
+ }
+
+ rc = ion_handle_get_flags(client, handle, &ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n", __func__);
+ goto flag_error;
+ }
+
+ temp_ptr = ion_map_kernel(client, handle, ionflag);
+ if (IS_ERR_OR_NULL(temp_ptr)) {
+ pr_err("%s: could not get virtual address\n", __func__);
+ goto map_error;
+ }
+ kvaddr = (unsigned long)temp_ptr;
+
+ rc = ion_phys(client, handle, &paddr, &len);
+ if (rc) {
+ pr_err("%s: could not get physical address\n", __func__);
+ goto ion_error;
+ }
+
+ rc = audio_aio_ion_check(audio, info->vaddr, len);
if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
+ pr_err("%s: audio_aio_ion_check failed\n", __func__);
+ goto ion_error;
}
+ region->client = client;
+ region->handle = handle;
region->vaddr = info->vaddr;
region->fd = info->fd;
region->paddr = paddr;
region->kvaddr = kvaddr;
region->len = len;
- region->file = file;
region->ref_cnt = 0;
pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
__func__, audio,
region->paddr, region->vaddr, region->len, region->kvaddr);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
-
+ list_add_tail(®ion->list, &audio->ion_region_queue);
rc = q6asm_memory_map(audio->ac, (uint32_t) paddr, IN, (uint32_t) len,
1);
- if (rc < 0)
+ if (rc < 0) {
pr_err("%s[%p]: memory map failed\n", __func__, audio);
+ goto ion_error;
+ } else {
+ goto end;
+ }
+
+ion_error:
+ ion_unmap_kernel(client, handle);
+map_error:
+ ion_free(client, handle);
+flag_error:
+import_error:
+ ion_client_destroy(client);
+client_error:
+ kfree(region);
end:
return rc;
}
-static int audio_aio_pmem_remove(struct q6audio_aio *audio,
- struct msm_audio_pmem_info *info)
+static int audio_aio_ion_remove(struct q6audio_aio *audio,
+ struct msm_audio_ion_info *info)
{
- struct audio_aio_pmem_region *region;
+ struct audio_aio_ion_region *region;
struct list_head *ptr, *next;
int rc = -EINVAL;
pr_debug("%s[%p]:info fd %d vaddr %p\n",
__func__, audio, info->fd, info->vaddr);
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audio_aio_pmem_region, list);
+ list_for_each_safe(ptr, next, &audio->ion_region_queue) {
+ region = list_entry(ptr, struct audio_aio_ion_region, list);
if ((region->fd == info->fd) &&
(region->vaddr == info->vaddr)) {
@@ -873,7 +919,9 @@
__func__, audio);
list_del(®ion->list);
- put_pmem_file(region->file);
+ ion_unmap_kernel(region->client, region->handle);
+ ion_free(region->client, region->handle);
+ ion_client_destroy(region->client);
kfree(region);
rc = 0;
break;
@@ -989,8 +1037,7 @@
pr_debug("%s[%p]:node %p dir %x buf_addr %p buf_len %d data_len \
%d\n", __func__, audio, buf_node, dir, buf_node->buf.buf_addr,
buf_node->buf.buf_len, buf_node->buf.data_len);
-
- buf_node->paddr = audio_aio_pmem_fixup(audio, buf_node->buf.buf_addr,
+ buf_node->paddr = audio_aio_ion_fixup(audio, buf_node->buf.buf_addr,
buf_node->buf.buf_len, 1,
&buf_node->kvaddr);
if (dir) {
@@ -1125,7 +1172,7 @@
init_waitqueue_head(&audio->event_wait);
INIT_LIST_HEAD(&audio->out_queue);
INIT_LIST_HEAD(&audio->in_queue);
- INIT_LIST_HEAD(&audio->pmem_region_queue);
+ INIT_LIST_HEAD(&audio->ion_region_queue);
INIT_LIST_HEAD(&audio->free_event_queue);
INIT_LIST_HEAD(&audio->event_queue);
@@ -1281,25 +1328,25 @@
mutex_unlock(&audio->lock);
break;
}
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- pr_debug("%s[%p]:AUDIO_REGISTER_PMEM\n", __func__, audio);
+ case AUDIO_REGISTER_ION: {
+ struct msm_audio_ion_info info;
+ pr_debug("%s[%p]:AUDIO_REGISTER_ION\n", __func__, audio);
mutex_lock(&audio->lock);
if (copy_from_user(&info, (void *)arg, sizeof(info)))
rc = -EFAULT;
else
- rc = audio_aio_pmem_add(audio, &info);
+ rc = audio_aio_ion_add(audio, &info);
mutex_unlock(&audio->lock);
break;
}
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
+ case AUDIO_DEREGISTER_ION: {
+ struct msm_audio_ion_info info;
mutex_lock(&audio->lock);
- pr_debug("%s[%p]:AUDIO_DEREGISTER_PMEM\n", __func__, audio);
+ pr_debug("%s[%p]:AUDIO_DEREGISTER_ION\n", __func__, audio);
if (copy_from_user(&info, (void *)arg, sizeof(info)))
rc = -EFAULT;
else
- rc = audio_aio_pmem_remove(audio, &info);
+ rc = audio_aio_ion_remove(audio, &info);
mutex_unlock(&audio->lock);
break;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
index ebf3668..a25ca4d 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.h
@@ -1,6 +1,6 @@
/* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -23,15 +23,13 @@
#include <linux/msm_audio.h>
#include <linux/debugfs.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
+#include <linux/ion.h>
#include <asm/ioctls.h>
#include <asm/atomic.h>
#include <sound/q6asm.h>
#include <sound/apr_audio.h>
-
-
#define TUNNEL_MODE 0x0000
#define NON_TUNNEL_MODE 0x0001
@@ -114,9 +112,10 @@
#define FRAME_NUM (2)
#define FRAME_SIZE ((4*1536) + sizeof(struct dec_meta_in))
-struct audio_aio_pmem_region {
+struct audio_aio_ion_region {
struct list_head list;
- struct file *file;
+ struct ion_handle *handle;
+ struct ion_client *client;
int fd;
void *vaddr;
unsigned long paddr;
@@ -174,7 +173,7 @@
struct list_head in_queue; /* queue to retain input buffers */
struct list_head free_event_queue;
struct list_head event_queue;
- struct list_head pmem_region_queue; /* protected by lock */
+ struct list_head ion_region_queue; /* protected by lock */
struct audio_aio_drv_operations drv_ops;
union msm_audio_event_payload eos_write_payload;
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_in.c b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
index 1f20aa7..667628c 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_in.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2009 HTC Corporation
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -72,6 +72,9 @@
case ASM_DATA_EVENT_READ_DONE:
pcm_in_get_dsp_buffers(pcm, token, payload);
break;
+ case RESET_EVENTS:
+ reset_device();
+ break;
default:
break;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/pcm_out.c b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
index a4a6b72..733d5e3 100644
--- a/arch/arm/mach-msm/qdsp6v2/pcm_out.c
+++ b/arch/arm/mach-msm/qdsp6v2/pcm_out.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009 Google, Inc.
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -66,6 +66,9 @@
atomic_inc(&pcm->out_count);
wake_up(&pcm->write_wait);
break;
+ case RESET_EVENTS:
+ reset_device();
+ break;
default:
break;
}
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 6794a88..cdb0cbe 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -333,6 +333,38 @@
}
EXPORT_SYMBOL(scm_call_atomic2);
+s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+ u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
+{
+ int ret;
+ int context_id;
+ register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4);
+ register u32 r1 asm("r1") = (u32)&context_id;
+ register u32 r2 asm("r2") = arg1;
+ register u32 r3 asm("r3") = arg2;
+ register u32 r4 asm("r4") = arg3;
+ register u32 r5 asm("r5") = arg4;
+
+ asm volatile(
+ __asmeq("%0", "r0")
+ __asmeq("%1", "r1")
+ __asmeq("%2", "r2")
+ __asmeq("%3", "r0")
+ __asmeq("%4", "r1")
+ __asmeq("%5", "r2")
+ __asmeq("%6", "r3")
+ "smc #0 @ switch to secure world\n"
+ : "=r" (r0), "=r" (r1), "=r" (r2)
+ : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5));
+ ret = r0;
+ if (ret1)
+ *ret1 = r1;
+ if (ret2)
+ *ret2 = r2;
+ return r0;
+}
+EXPORT_SYMBOL(scm_call_atomic4_3);
+
u32 scm_get_version(void)
{
int context_id;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index bca1e0c..9321b40 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -72,6 +72,7 @@
MSM_SMSM_DEBUG = 1U << 1,
MSM_SMD_INFO = 1U << 2,
MSM_SMSM_INFO = 1U << 3,
+ MSM_SMx_POWER_INFO = 1U << 4,
};
struct smsm_shared_info {
@@ -117,29 +118,34 @@
};
static irqreturn_t smd_modem_irq_handler(int irq, void *data);
+static irqreturn_t smsm_modem_irq_handler(int irq, void *data);
static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+static irqreturn_t smsm_dsp_irq_handler(int irq, void *data);
static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+static irqreturn_t smsm_dsps_irq_handler(int irq, void *data);
static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data);
static irqreturn_t smsm_irq_handler(int irq, void *data);
static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
[SMD_MODEM] = {
.smd.irq_handler = smd_modem_irq_handler,
- .smsm.irq_handler = smsm_irq_handler,
+ .smsm.irq_handler = smsm_modem_irq_handler,
},
[SMD_Q6] = {
.smd.irq_handler = smd_dsp_irq_handler,
- .smsm.irq_handler = smsm_irq_handler,
+ .smsm.irq_handler = smsm_dsp_irq_handler,
},
[SMD_DSPS] = {
.smd.irq_handler = smd_dsps_irq_handler,
- .smsm.irq_handler = smsm_irq_handler,
+ .smsm.irq_handler = smsm_dsps_irq_handler,
},
[SMD_WCNSS] = {
.smd.irq_handler = smd_wcnss_irq_handler,
- .smsm.irq_handler = smsm_irq_handler,
+ .smsm.irq_handler = smsm_wcnss_irq_handler,
},
};
+struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
#define SMSM_STATE_ADDR(entry) (smsm_info.state + entry)
#define SMSM_INTR_MASK_ADDR(entry, host) (smsm_info.intr_mask + \
@@ -175,11 +181,16 @@
if (msm_smd_debug_mask & MSM_SMSM_INFO) \
printk(KERN_INFO x); \
} while (0)
+#define SMx_POWER_INFO(x...) do { \
+ if (msm_smd_debug_mask & MSM_SMx_POWER_INFO) \
+ printk(KERN_INFO x); \
+ } while (0)
#else
#define SMD_DBG(x...) do { } while (0)
#define SMSM_DBG(x...) do { } while (0)
#define SMD_INFO(x...) do { } while (0)
#define SMSM_INFO(x...) do { } while (0)
+#define SMx_POWER_INFO(x...) do { } while (0)
#endif
static unsigned last_heap_free = 0xffffffff;
@@ -214,24 +225,6 @@
#define MSM_TRIG_A2DSPS_SMSM_INT
#define MSM_TRIG_A2WCNSS_SMD_INT
#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_MSM8930) || \
- defined(CONFIG_ARCH_APQ8064)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1 << 3, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1 << 15, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1 << 4, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1 << 14, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT \
- (smd_write_intr(1, MSM_SIC_NON_SECURE_BASE + 0x4080))
-#define MSM_TRIG_A2DSPS_SMSM_INT \
- (smd_write_intr(1, MSM_SIC_NON_SECURE_BASE + 0x4094))
-#define MSM_TRIG_A2WCNSS_SMD_INT \
- (smd_write_intr(1 << 25, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2WCNSS_SMSM_INT \
- (smd_write_intr(1 << 23, MSM_APCS_GCC_BASE + 0x8))
#elif defined(CONFIG_ARCH_MSM9615)
#define MSM_TRIG_A2M_SMD_INT \
(smd_write_intr(1 << 3, MSM_APCS_GCC_BASE + 0x8))
@@ -258,15 +251,33 @@
#define MSM_TRIG_A2DSPS_SMSM_INT
#define MSM_TRIG_A2WCNSS_SMD_INT
#define MSM_TRIG_A2WCNSS_SMSM_INT
-#else
+#elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7x25)
#define MSM_TRIG_A2M_SMD_INT \
(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (8) * 4))
+#define MSM_TRIG_A2Q6_SMD_INT
#define MSM_TRIG_A2M_SMSM_INT \
(smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (8) * 4))
+#define MSM_TRIG_A2Q6_SMSM_INT
+#define MSM_TRIG_A2DSPS_SMD_INT
+#define MSM_TRIG_A2DSPS_SMSM_INT
+#define MSM_TRIG_A2WCNSS_SMD_INT
+#define MSM_TRIG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM7X27A)
+#define MSM_TRIG_A2M_SMD_INT \
+ (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
+#define MSM_TRIG_A2Q6_SMD_INT
+#define MSM_TRIG_A2M_SMSM_INT \
+ (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
+#define MSM_TRIG_A2Q6_SMSM_INT
+#define MSM_TRIG_A2DSPS_SMD_INT
+#define MSM_TRIG_A2DSPS_SMSM_INT
+#define MSM_TRIG_A2WCNSS_SMD_INT
+#define MSM_TRIG_A2WCNSS_SMSM_INT
+#else /* use platform device / device tree configuration */
+#define MSM_TRIG_A2M_SMD_INT
+#define MSM_TRIG_A2Q6_SMD_INT
+#define MSM_TRIG_A2M_SMSM_INT
+#define MSM_TRIG_A2Q6_SMSM_INT
#define MSM_TRIG_A2DSPS_SMD_INT
#define MSM_TRIG_A2DSPS_SMSM_INT
#define MSM_TRIG_A2WCNSS_SMD_INT
@@ -349,33 +360,42 @@
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_MODEM].smd;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_MODEM].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_MODEM].smd_out_hardcode_count;
MSM_TRIG_A2M_SMD_INT;
+ }
}
static inline void notify_dsp_smd(void)
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_Q6].smd;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_Q6].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_Q6].smd_out_hardcode_count;
MSM_TRIG_A2Q6_SMD_INT;
+ }
}
static inline void notify_dsps_smd(void)
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_DSPS].smd;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_DSPS].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_DSPS].smd_out_hardcode_count;
MSM_TRIG_A2DSPS_SMD_INT;
+ }
}
static inline void notify_wcnss_smd(void)
@@ -384,44 +404,56 @@
= &private_intr_config[SMD_WCNSS].smd;
wakeup_v1_riva();
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_WCNSS].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_WCNSS].smd_out_hardcode_count;
MSM_TRIG_A2WCNSS_SMD_INT;
+ }
}
static inline void notify_modem_smsm(void)
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_MODEM].smsm;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_MODEM].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_MODEM].smsm_out_hardcode_count;
MSM_TRIG_A2M_SMSM_INT;
+ }
}
static inline void notify_dsp_smsm(void)
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_Q6].smsm;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_Q6].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_Q6].smsm_out_hardcode_count;
MSM_TRIG_A2Q6_SMSM_INT;
+ }
}
static inline void notify_dsps_smsm(void)
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_DSPS].smsm;
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_DSPS].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_DSPS].smsm_out_hardcode_count;
MSM_TRIG_A2DSPS_SMSM_INT;
+ }
}
static inline void notify_wcnss_smsm(void)
@@ -430,11 +462,14 @@
= &private_intr_config[SMD_WCNSS].smsm;
wakeup_v1_riva();
- if (intr->out_base)
+ if (intr->out_base) {
+ ++interrupt_stats[SMD_WCNSS].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- else
+ } else {
+ ++interrupt_stats[SMD_WCNSS].smsm_out_hardcode_count;
MSM_TRIG_A2WCNSS_SMSM_INT;
+ }
}
static void notify_other_smsm(uint32_t smsm_entry, uint32_t notify_mask)
@@ -589,27 +624,28 @@
struct edge_to_pid {
uint32_t local_pid;
uint32_t remote_pid;
+ char subsys_name[SMD_MAX_CH_NAME_LEN];
};
/**
* Maps edge type to local and remote processor ID's.
*/
static struct edge_to_pid edge_to_pids[] = {
- [SMD_APPS_MODEM] = {SMSM_APPS, SMSM_MODEM},
- [SMD_APPS_QDSP] = {SMSM_APPS, SMSM_Q6},
- [SMD_MODEM_QDSP] = {SMSM_MODEM, SMSM_Q6},
- [SMD_APPS_DSPS] = {SMSM_APPS, SMSM_DSPS},
- [SMD_MODEM_DSPS] = {SMSM_MODEM, SMSM_DSPS},
- [SMD_QDSP_DSPS] = {SMSM_Q6, SMSM_DSPS},
- [SMD_APPS_WCNSS] = {SMSM_APPS, SMSM_WCNSS},
- [SMD_MODEM_WCNSS] = {SMSM_MODEM, SMSM_WCNSS},
- [SMD_QDSP_WCNSS] = {SMSM_Q6, SMSM_WCNSS},
- [SMD_DSPS_WCNSS] = {SMSM_DSPS, SMSM_WCNSS},
- [SMD_APPS_Q6FW] = {SMSM_APPS, SMD_MODEM_Q6_FW},
- [SMD_MODEM_Q6FW] = {SMSM_MODEM, SMD_MODEM_Q6_FW},
- [SMD_QDSP_Q6FW] = {SMSM_Q6, SMD_MODEM_Q6_FW},
- [SMD_DSPS_Q6FW] = {SMSM_DSPS, SMD_MODEM_Q6_FW},
- [SMD_WCNSS_Q6FW] = {SMSM_WCNSS, SMD_MODEM_Q6_FW},
+ [SMD_APPS_MODEM] = {SMD_APPS, SMD_MODEM, "modem"},
+ [SMD_APPS_QDSP] = {SMD_APPS, SMD_Q6, "q6"},
+ [SMD_MODEM_QDSP] = {SMD_MODEM, SMD_Q6},
+ [SMD_APPS_DSPS] = {SMD_APPS, SMD_DSPS, "dsps"},
+ [SMD_MODEM_DSPS] = {SMD_MODEM, SMD_DSPS},
+ [SMD_QDSP_DSPS] = {SMD_Q6, SMD_DSPS},
+ [SMD_APPS_WCNSS] = {SMD_APPS, SMD_WCNSS, "wcnss"},
+ [SMD_MODEM_WCNSS] = {SMD_MODEM, SMD_WCNSS},
+ [SMD_QDSP_WCNSS] = {SMD_Q6, SMD_WCNSS},
+ [SMD_DSPS_WCNSS] = {SMD_DSPS, SMD_WCNSS},
+ [SMD_APPS_Q6FW] = {SMD_APPS, SMD_MODEM_Q6_FW},
+ [SMD_MODEM_Q6FW] = {SMD_MODEM, SMD_MODEM_Q6_FW},
+ [SMD_QDSP_Q6FW] = {SMD_Q6, SMD_MODEM_Q6_FW},
+ [SMD_DSPS_Q6FW] = {SMD_DSPS, SMD_MODEM_Q6_FW},
+ [SMD_WCNSS_Q6FW] = {SMD_WCNSS, SMD_MODEM_Q6_FW},
};
struct restart_notifier_block {
@@ -721,6 +757,50 @@
return ret;
}
+/*
+ * Returns a pointer to the subsystem name or NULL if no
+ * subsystem name is available.
+ *
+ * @type - Edge definition
+ */
+const char *smd_edge_to_subsystem(uint32_t type)
+{
+ const char *subsys = NULL;
+
+ if (type < ARRAY_SIZE(edge_to_pids)) {
+ subsys = edge_to_pids[type].subsys_name;
+ if (subsys[0] == 0x0)
+ subsys = NULL;
+ }
+ return subsys;
+}
+EXPORT_SYMBOL(smd_edge_to_subsystem);
+
+/*
+ * Returns a pointer to the subsystem name given the
+ * remote processor ID.
+ *
+ * @pid Remote processor ID
+ * @returns Pointer to subsystem name or NULL if not found
+ */
+const char *smd_pid_to_subsystem(uint32_t pid)
+{
+ const char *subsys = NULL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(edge_to_pids); ++i) {
+ if (pid == edge_to_pids[i].remote_pid &&
+ edge_to_pids[i].subsys_name[0] != 0x0
+ ) {
+ subsys = edge_to_pids[i].subsys_name;
+ break;
+ }
+ }
+
+ return subsys;
+}
+EXPORT_SYMBOL(smd_pid_to_subsystem);
+
static void smd_reset_edge(struct smd_half_channel *ch, unsigned new_state)
{
if (ch->state != SMD_SS_CLOSED) {
@@ -796,9 +876,10 @@
/* notify SMSM processors */
smsm_irq_handler(0, 0);
- MSM_TRIG_A2M_SMSM_INT;
- MSM_TRIG_A2Q6_SMSM_INT;
- MSM_TRIG_A2DSPS_SMSM_INT;
+ notify_modem_smsm();
+ notify_dsp_smsm();
+ notify_dsps_smsm();
+ notify_wcnss_smsm();
}
/* change all remote states to CLOSING */
@@ -1110,15 +1191,24 @@
}
tmp = ch->recv->state;
if (tmp != ch->last_state) {
+ SMx_POWER_INFO("SMD ch%d '%s' State change %d->%d\n",
+ ch->n, ch->name, ch->last_state, tmp);
smd_state_change(ch, ch->last_state, tmp);
state_change = 1;
}
- if (ch_flags) {
+ if (ch_flags & 0x3) {
ch->update_state(ch);
+ SMx_POWER_INFO("SMD ch%d '%s' Data event r%d/w%d\n",
+ ch->n, ch->name,
+ ch->read_avail(ch),
+ ch->fifo_size - ch->write_avail(ch));
ch->notify(ch->priv, SMD_EVENT_DATA);
}
- if (ch_flags & 0x4 && !state_change)
+ if (ch_flags & 0x4 && !state_change) {
+ SMx_POWER_INFO("SMD ch%d '%s' State update\n",
+ ch->n, ch->name);
ch->notify(ch->priv, SMD_EVENT_STATUS);
+ }
}
spin_unlock_irqrestore(&smd_lock, flags);
do_smd_probe();
@@ -1126,6 +1216,8 @@
static irqreturn_t smd_modem_irq_handler(int irq, void *data)
{
+ SMx_POWER_INFO("SMD Int Modem->Apps\n");
+ ++interrupt_stats[SMD_MODEM].smd_in_count;
handle_smd_irq(&smd_ch_list_modem, notify_modem_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
@@ -1133,6 +1225,8 @@
static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
{
+ SMx_POWER_INFO("SMD Int LPASS->Apps\n");
+ ++interrupt_stats[SMD_Q6].smd_in_count;
handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
@@ -1140,6 +1234,8 @@
static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
{
+ SMx_POWER_INFO("SMD Int DSPS->Apps\n");
+ ++interrupt_stats[SMD_DSPS].smd_in_count;
handle_smd_irq(&smd_ch_list_dsps, notify_dsps_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
@@ -1147,6 +1243,8 @@
static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
{
+ SMx_POWER_INFO("SMD Int WCNSS->Apps\n");
+ ++interrupt_stats[SMD_WCNSS].smd_in_count;
handle_smd_irq(&smd_ch_list_wcnss, notify_wcnss_smd);
handle_smd_irq_closing_list();
return IRQ_HANDLED;
@@ -2286,6 +2384,34 @@
return IRQ_HANDLED;
}
+static irqreturn_t smsm_modem_irq_handler(int irq, void *data)
+{
+ SMx_POWER_INFO("SMSM Int Modem->Apps\n");
+ ++interrupt_stats[SMD_MODEM].smsm_in_count;
+ return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_dsp_irq_handler(int irq, void *data)
+{
+ SMx_POWER_INFO("SMSM Int LPASS->Apps\n");
+ ++interrupt_stats[SMD_Q6].smsm_in_count;
+ return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_dsps_irq_handler(int irq, void *data)
+{
+ SMx_POWER_INFO("SMSM Int DSPS->Apps\n");
+ ++interrupt_stats[SMD_DSPS].smsm_in_count;
+ return smsm_irq_handler(irq, data);
+}
+
+static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data)
+{
+ SMx_POWER_INFO("SMSM Int WCNSS->Apps\n");
+ ++interrupt_stats[SMD_WCNSS].smsm_in_count;
+ return smsm_irq_handler(irq, data);
+}
+
int smsm_change_intr_mask(uint32_t smsm_entry,
uint32_t clear_mask, uint32_t set_mask)
{
@@ -2417,6 +2543,9 @@
state_changes = state_info->last_value ^ new_state;
if (state_changes) {
+ SMx_POWER_INFO("SMSM Change %d: %08x->%08x\n",
+ n, state_info->last_value,
+ new_state);
list_for_each_entry(cb_info,
&state_info->callbacks, cb_list) {
@@ -2567,7 +2696,7 @@
pr_err("smd_core_init: "
"enable_irq_wake failed for INT_A9_M2A_0\n");
- r = request_irq(INT_A9_M2A_5, smsm_irq_handler,
+ r = request_irq(INT_A9_M2A_5, smsm_modem_irq_handler,
flags, "smsm_dev", 0);
if (r < 0) {
free_irq(INT_A9_M2A_0, 0);
@@ -2590,8 +2719,8 @@
return r;
}
- r = request_irq(INT_ADSP_A11_SMSM, smsm_irq_handler,
- flags, "smsm_dev", smsm_irq_handler);
+ r = request_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler,
+ flags, "smsm_dev", smsm_dsp_irq_handler);
if (r < 0) {
free_irq(INT_A9_M2A_0, 0);
free_irq(INT_A9_M2A_5, 0);
@@ -2620,7 +2749,7 @@
free_irq(INT_A9_M2A_0, 0);
free_irq(INT_A9_M2A_5, 0);
free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
return r;
}
@@ -2637,7 +2766,7 @@
free_irq(INT_A9_M2A_0, 0);
free_irq(INT_A9_M2A_5, 0);
free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
return r;
}
@@ -2647,13 +2776,13 @@
pr_err("smd_core_init: "
"enable_irq_wake failed for INT_WCNSS_A11\n");
- r = request_irq(INT_WCNSS_A11_SMSM, smsm_irq_handler,
- flags, "smsm_dev", smsm_irq_handler);
+ r = request_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler,
+ flags, "smsm_dev", smsm_wcnss_irq_handler);
if (r < 0) {
free_irq(INT_A9_M2A_0, 0);
free_irq(INT_A9_M2A_5, 0);
free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
return r;
@@ -2666,16 +2795,16 @@
#endif
#if defined(CONFIG_DSPS_SMSM)
- r = request_irq(INT_DSPS_A11_SMSM, smsm_irq_handler,
- flags, "smsm_dev", smsm_irq_handler);
+ r = request_irq(INT_DSPS_A11_SMSM, smsm_dsps_irq_handler,
+ flags, "smsm_dev", smsm_dsps_irq_handler);
if (r < 0) {
free_irq(INT_A9_M2A_0, 0);
free_irq(INT_A9_M2A_5, 0);
free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
- free_irq(INT_WCNSS_A11_SMSM, smsm_irq_handler);
+ free_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler);
return r;
}
@@ -2770,6 +2899,9 @@
cfg->smsm_int.irq_name);
break;
}
+
+ strncpy(edge_to_pids[cfg->edge].subsys_name,
+ cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
}
if (err_ret < 0) {
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index b95a35c..764102d 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -95,6 +95,61 @@
return max;
}
+static int debug_int_stats(char *buf, int max)
+{
+ int i = 0;
+ int subsys;
+ struct interrupt_stat *stats = interrupt_stats;
+ const char *subsys_name;
+
+ i += scnprintf(buf + i, max - i,
+ " Subsystem | In | Out (Hardcoded) |"
+ " Out (Configured) |\n");
+
+ for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
+ subsys_name = smd_pid_to_subsystem(subsys);
+ if (subsys_name) {
+ i += scnprintf(buf + i, max - i,
+ "%-10s %4s | %9u | %9u | %9u |\n",
+ smd_pid_to_subsystem(subsys), "smd",
+ stats->smd_in_count,
+ stats->smd_out_hardcode_count,
+ stats->smd_out_config_count);
+
+ i += scnprintf(buf + i, max - i,
+ "%-10s %4s | %9u | %9u | %9u |\n",
+ smd_pid_to_subsystem(subsys), "smsm",
+ stats->smsm_in_count,
+ stats->smsm_out_hardcode_count,
+ stats->smsm_out_config_count);
+ }
+ ++stats;
+ }
+
+ return i;
+}
+
+static int debug_int_stats_reset(char *buf, int max)
+{
+ int i = 0;
+ int subsys;
+ struct interrupt_stat *stats = interrupt_stats;
+
+ i += scnprintf(buf + i, max - i, "Resetting interrupt stats.\n");
+
+ for (subsys = 0; subsys < NUM_SMD_SUBSYSTEMS; ++subsys) {
+ stats->smd_in_count = 0;
+ stats->smd_out_hardcode_count = 0;
+ stats->smd_out_config_count = 0;
+ stats->smsm_in_count = 0;
+ stats->smsm_out_hardcode_count = 0;
+ stats->smsm_out_config_count = 0;
+ ++stats;
+ }
+
+ return i;
+}
+
static int debug_diag(char *buf, int max)
{
int i = 0;
@@ -694,6 +749,8 @@
debug_create("modem_err_f3", 0444, dent, debug_modem_err_f3);
debug_create("print_diag", 0444, dent, debug_diag);
debug_create("print_f3", 0444, dent, debug_f3);
+ debug_create("int_stats", 0444, dent, debug_int_stats);
+ debug_create("int_stats_reset", 0444, dent, debug_int_stats_reset);
/* NNV: this is google only stuff */
debug_create("build", 0444, dent, debug_read_build_id);
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 63c5fef..158015a 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -66,6 +66,7 @@
int blocking_write;
int is_open;
+ int poll_mode;
unsigned ch_size;
uint open_modem_wait;
@@ -74,6 +75,7 @@
struct completion ch_allocated;
struct wake_lock pa_wake_lock; /* Packet Arrival Wake lock*/
struct work_struct packet_arrival_work;
+ struct spinlock pa_spinlock;
} *smd_pkt_devp[NUM_SMD_PKT_PORTS];
struct class *smd_pkt_classp;
@@ -236,6 +238,7 @@
int pkt_size;
struct smd_pkt_dev *smd_pkt_devp;
struct smd_channel *chl;
+ unsigned long flags;
D(KERN_ERR "%s: read %i bytes\n",
__func__, count);
@@ -316,6 +319,16 @@
D_DUMP_BUFFER("read: ", bytes_read, buf);
mutex_unlock(&smd_pkt_devp->rx_lock);
+ mutex_lock(&smd_pkt_devp->ch_lock);
+ spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
+ if (smd_pkt_devp->poll_mode &&
+ !smd_cur_packet_size(smd_pkt_devp->ch)) {
+ wake_unlock(&smd_pkt_devp->pa_wake_lock);
+ smd_pkt_devp->poll_mode = 0;
+ }
+ spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
+ mutex_unlock(&smd_pkt_devp->ch_lock);
+
D(KERN_ERR "%s: just read %i bytes\n",
__func__, bytes_read);
@@ -409,6 +422,7 @@
if (!smd_pkt_devp)
return POLLERR;
+ smd_pkt_devp->poll_mode = 1;
poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
if (smd_read_avail(smd_pkt_devp->ch))
mask |= POLLIN | POLLRDNORM;
@@ -419,6 +433,7 @@
static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp)
{
int sz;
+ unsigned long flags;
if (!smd_pkt_devp || !smd_pkt_devp->ch)
return;
@@ -437,6 +452,9 @@
/* here we have a packet of size sz ready */
wake_up(&smd_pkt_devp->ch_read_wait_queue);
+ spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
+ wake_lock(&smd_pkt_devp->pa_wake_lock);
+ spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
schedule_work(&smd_pkt_devp->packet_arrival_work);
D(KERN_ERR "%s: after wake_up\n", __func__);
}
@@ -589,7 +607,7 @@
{
int r = 0;
struct smd_pkt_dev *smd_pkt_devp;
- char *peripheral = NULL;
+ const char *peripheral = NULL;
smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
@@ -604,12 +622,8 @@
mutex_lock(&smd_pkt_devp->ch_lock);
if (smd_pkt_devp->ch == 0) {
-
- if (smd_ch_edge[smd_pkt_devp->i] == SMD_APPS_MODEM)
- peripheral = "modem";
- else if (smd_ch_edge[smd_pkt_devp->i] == SMD_APPS_QDSP)
- peripheral = "q6";
-
+ peripheral = smd_edge_to_subsystem(
+ smd_ch_edge[smd_pkt_devp->i]);
if (peripheral) {
smd_pkt_devp->pil = pil_get(peripheral);
if (IS_ERR(smd_pkt_devp->pil)) {
@@ -707,6 +721,7 @@
r = smd_close(smd_pkt_devp->ch);
smd_pkt_devp->ch = 0;
smd_pkt_devp->blocking_write = 0;
+ smd_pkt_devp->poll_mode = 0;
if (smd_pkt_devp->pil)
pil_put(smd_pkt_devp->pil);
}
@@ -776,8 +791,10 @@
init_waitqueue_head(&smd_pkt_devp[i]->ch_read_wait_queue);
init_waitqueue_head(&smd_pkt_devp[i]->ch_write_wait_queue);
smd_pkt_devp[i]->is_open = 0;
+ smd_pkt_devp[i]->poll_mode = 0;
init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue);
+ spin_lock_init(&smd_pkt_devp[i]->pa_spinlock);
mutex_init(&smd_pkt_devp[i]->ch_lock);
mutex_init(&smd_pkt_devp[i]->rx_lock);
mutex_init(&smd_pkt_devp[i]->tx_lock);
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index a4c60e8..e39c57b 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd_private.h
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <mach/msm_smsm.h>
+#include <mach/msm_smd.h>
#define PC_APPS 0
#define PC_MODEM 1
@@ -208,4 +209,15 @@
void smd_diag(void);
+struct interrupt_stat {
+ uint32_t smd_in_count;
+ uint32_t smd_out_hardcode_count;
+ uint32_t smd_out_config_count;
+
+ uint32_t smsm_in_count;
+ uint32_t smsm_out_hardcode_count;
+ uint32_t smsm_out_config_count;
+};
+extern struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
+
#endif
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 4248be4..d856024 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -235,7 +235,7 @@
int res = 0;
unsigned int n = tty->index;
struct smd_tty_info *info;
- char *peripheral = NULL;
+ const char *peripheral = NULL;
if (n >= MAX_SMD_TTYS || !smd_tty[n].smd)
@@ -247,9 +247,7 @@
tty->driver_data = info;
if (info->open_count++ == 0) {
- if (smd_tty[n].smd->edge == SMD_APPS_MODEM)
- peripheral = "modem";
-
+ peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
if (peripheral) {
info->pil = pil_get(peripheral);
if (IS_ERR(info->pil)) {
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 9970c90..59abfe6 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,7 @@
static void riva_fatal_fn(struct work_struct *);
static DECLARE_WORK(riva_fatal_work, riva_fatal_fn);
+static struct delayed_work cancel_vote_work;
static void *riva_ramdump_dev;
static int riva_crash;
static int ss_restart_inprogress;
@@ -97,20 +98,24 @@
smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
}
-/* Subsystem handlers */
-static int riva_shutdown(const struct subsys_data *subsys)
+static void riva_post_bootup(struct work_struct *work)
{
struct platform_device *pdev = wcnss_get_platform_device();
struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
- int ret = -1;
+ pr_debug(MODULE_NAME ": Cancel APPS vote for Iris & Riva\n");
+
+ wcnss_wlan_power(&pdev->dev, pwlanconfig,
+ WCNSS_WLAN_SWITCH_OFF);
+}
+
+/* Subsystem handlers */
+static int riva_shutdown(const struct subsys_data *subsys)
+{
pil_force_shutdown("wcnss");
+ flush_delayed_work(&cancel_vote_work);
- /* proxy vote on behalf of Riva */
- if (pdev && pwlanconfig)
- ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
- WCNSS_WLAN_SWITCH_OFF);
- return ret;
+ return 0;
}
static int riva_powerup(const struct subsys_data *subsys)
@@ -131,6 +136,7 @@
}
ss_restart_inprogress = false;
enable_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
+ schedule_delayed_work(&cancel_vote_work, msecs_to_jiffies(5000));
return ret;
}
@@ -222,6 +228,8 @@
ret = -ENOMEM;
goto out;
}
+ INIT_DELAYED_WORK(&cancel_vote_work, riva_post_bootup);
+
pr_info("%s: module initialized\n", MODULE_NAME);
out:
return ret;
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 3bce534..f748109 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -55,7 +55,7 @@
cmp r1, #2 @ see what cache we have at this level
blt skip @ skip if no cache, or just i-cache
#ifdef CONFIG_PREEMPT
- save_and_disable_irqs r9 @ make cssr&csidr read atomic
+ save_and_disable_irqs_notrace r9 @ make cssr&csidr read atomic
#endif
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
isb @ isb to sych the new cssr&csidr
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 8dcce03..edede47 100755
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1139,3 +1139,5 @@
mpq8064_hrd MACH_MPQ8064_HRD MPQ8064_HRD 3994
mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
+msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037
+msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 371d319..a701773 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -228,6 +228,7 @@
int hsic_ch;
int hsic_device_enabled;
int hsic_device_opened;
+ int hsic_suspend;
int read_len_mdm;
int in_busy_hsic_read_on_mdm;
int in_busy_hsic_write_on_mdm;
@@ -238,6 +239,8 @@
struct workqueue_struct *diag_hsic_wq;
struct work_struct diag_read_mdm_work;
struct work_struct diag_read_hsic_work;
+ struct work_struct diag_disconnect_work;
+ struct work_struct diag_usb_read_complete_work;
struct diag_request *usb_read_mdm_ptr;
struct diag_request *write_ptr_mdm;
#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index efba92b..d9f12ac 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -48,7 +48,7 @@
};
/* The following variables can be specified by module options */
/* for copy buffer */
-static unsigned int itemsize = 2048; /*Size of item in the mempool */
+static unsigned int itemsize = 4096; /*Size of item in the mempool */
static unsigned int poolsize = 10; /*Number of items in the mempool */
/* for hdlc buffer */
static unsigned int itemsize_hdlc = 8192; /*Size of item in the mempool */
@@ -768,6 +768,14 @@
return 0;
}
+ if (payload_size > itemsize) {
+ pr_err("diag: Dropping packet, packet payload size crosses"
+ "4KB limit. Current payload size %d\n",
+ payload_size);
+ driver->dropped_count++;
+ return -EBADMSG;
+ }
+
buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY);
if (!buf_copy) {
driver->dropped_count++;
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index ac5722f..b2080b3 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -102,14 +102,16 @@
driver->write_ptr_mdm);
}
} else {
- pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
+ pr_debug("%s: actual_size: %d\n", __func__, actual_size);
}
/*
* If for some reason there was no hsic data to write to the
* mdm channel, set up another read
*/
- if (!driver->in_busy_hsic_write_on_mdm)
+ if (!driver->in_busy_hsic_write_on_mdm &&
+ driver->usb_mdm_connected &&
+ !driver->hsic_suspend)
queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
}
@@ -127,13 +129,34 @@
if (actual_size < 0)
pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+ if (driver->usb_mdm_connected)
+ queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+}
+
+static int diag_hsic_suspend(void *ctxt)
+{
+ if (driver->in_busy_hsic_write)
+ return -EBUSY;
+
+ driver->hsic_suspend = 1;
+
+ return 0;
+}
+
+static void diag_hsic_resume(void *ctxt)
+{
+ driver->hsic_suspend = 0;
+
+ if (!driver->in_busy_hsic_write_on_mdm && driver->usb_mdm_connected)
+ queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
}
static struct diag_bridge_ops hsic_diag_bridge_ops = {
.ctxt = NULL,
.read_complete_cb = diag_hsic_read_complete_callback,
.write_complete_cb = diag_hsic_write_complete_callback,
+ .suspend = diag_hsic_suspend,
+ .resume = diag_hsic_resume,
};
static int diag_hsic_close(void)
@@ -177,11 +200,11 @@
pr_err("DIAG: HSIC channel open error: %d\n",
err);
} else {
- pr_info("DIAG: opened HSIC channel\n");
+ pr_debug("DIAG: opened HSIC channel\n");
driver->hsic_device_opened = 1;
}
} else {
- pr_info("DIAG: HSIC channel already open\n");
+ pr_debug("DIAG: HSIC channel already open\n");
}
/*
@@ -220,9 +243,7 @@
driver->in_busy_hsic_read = 1;
/* Turn off communication over usb mdm and hsic */
- driver->hsic_ch = 0;
-
- return 0;
+ return diag_hsic_close();
}
/*
@@ -311,10 +332,11 @@
diagfwd_connect_hsic();
break;
case USB_DIAG_DISCONNECT:
- diagfwd_disconnect_hsic();
+ queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
break;
case USB_DIAG_READ_DONE:
- diagfwd_read_complete_hsic(d_req);
+ queue_work(driver->diag_hsic_wq,
+ &driver->diag_usb_read_complete_work);
break;
case USB_DIAG_WRITE_DONE:
diagfwd_write_complete_hsic();
@@ -326,6 +348,16 @@
}
}
+static void diag_usb_read_complete_fn(struct work_struct *w)
+{
+ diagfwd_read_complete_hsic(driver->usb_read_mdm_ptr);
+}
+
+static void diag_disconnect_work_fn(struct work_struct *w)
+{
+ diagfwd_disconnect_hsic();
+}
+
static void diag_read_mdm_work_fn(struct work_struct *work)
{
if (!driver->hsic_ch) {
@@ -380,7 +412,6 @@
sizeof(struct diag_request), GFP_KERNEL);
if (driver->usb_read_mdm_ptr == NULL)
goto err;
- driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
#ifdef CONFIG_DIAG_OVER_USB
INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
#endif
@@ -413,23 +444,22 @@
}
}
- /* The hsic (diag_bridge) platform device driver is enabled */
- err = diag_bridge_open(&hsic_diag_bridge_ops);
- if (err) {
- pr_err("DIAG could not open HSIC channel, err: %d\n", err);
- driver->hsic_device_opened = 0;
- return err;
- }
-
- pr_info("DIAG opened HSIC channel\n");
- driver->hsic_device_opened = 1;
-
/*
* The probe function was called after the usb was connected
* on the legacy channel. Communication over usb mdm and hsic
* needs to be turned on.
*/
- if (driver->usb_connected) {
+ if (driver->usb_mdm_connected) {
+ /* The hsic (diag_bridge) platform device driver is enabled */
+ err = diag_bridge_open(&hsic_diag_bridge_ops);
+ if (err) {
+ pr_err("DIAG could not open HSIC, err: %d\n", err);
+ driver->hsic_device_opened = 0;
+ return err;
+ }
+
+ pr_debug("DIAG opened HSIC channel\n");
+ driver->hsic_device_opened = 1;
driver->hsic_ch = 1;
driver->in_busy_hsic_write_on_mdm = 0;
driver->in_busy_hsic_read_on_mdm = 0;
@@ -448,7 +478,7 @@
static int diag_hsic_remove(struct platform_device *pdev)
{
- pr_info("DIAG: %s called\n", __func__);
+ pr_debug("DIAG: %s called\n", __func__);
diag_hsic_close();
return 0;
}
@@ -487,6 +517,11 @@
pr_debug("DIAG in %s\n", __func__);
+ driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
+ INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
+ INIT_WORK(&(driver->diag_usb_read_complete_work),
+ diag_usb_read_complete_fn);
+
#ifdef CONFIG_DIAG_OVER_USB
driver->mdm_ch = usb_diag_open(DIAG_MDM, driver, diagfwd_hsic_notifier);
if (IS_ERR(driver->mdm_ch)) {
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index bd48925..3d9c9d1 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -749,7 +749,8 @@
}
static int get_img(struct msmfb_data *fbd, unsigned long *start,
- unsigned long *len, struct file **p_file, struct ion_handle **p_ihdl)
+ unsigned long *len, struct file **p_file, int *p_need,
+ struct ion_handle **p_ihdl)
{
int ret = 0;
#ifdef CONFIG_FB
@@ -760,6 +761,8 @@
unsigned long vstart;
#endif
+ *p_need = 0;
+
#ifdef CONFIG_FB
if (fbd->flags & MDP_MEMORY_ID_TYPE_FB) {
file = fget_light(fbd->memory_id, &put_needed);
@@ -770,8 +773,10 @@
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
if (get_fb_phys_info(start, len, fb_num))
ret = -1;
- else
+ else {
*p_file = file;
+ *p_need = put_needed;
+ }
} else
ret = -1;
if (ret)
@@ -822,6 +827,7 @@
struct file *srcp1_file = NULL, *dstp1_file = NULL;
struct ion_handle *srcp0_ihdl = NULL, *dstp0_ihdl = NULL;
struct ion_handle *srcp1_ihdl = NULL, *dstp1_ihdl = NULL;
+ int ps0_need, p_need;
unsigned int in_chroma_paddr = 0, out_chroma_paddr = 0;
unsigned int in_chroma2_paddr = 0;
struct msm_rotator_img_info *img_info;
@@ -872,8 +878,9 @@
goto do_rotate_unlock_mutex;
}
+
rc = get_img(&info.src, (unsigned long *)&in_paddr,
- (unsigned long *)&src_len, &srcp0_file, &srcp0_ihdl);
+ (unsigned long *)&src_len, &srcp0_file, &ps0_need, &srcp0_ihdl);
if (rc) {
pr_err("%s: in get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src.memory_id);
@@ -881,7 +888,7 @@
}
rc = get_img(&info.dst, (unsigned long *)&out_paddr,
- (unsigned long *)&dst_len, &dstp0_file, &dstp0_ihdl);
+ (unsigned long *)&dst_len, &dstp0_file, &p_need, &dstp0_ihdl);
if (rc) {
pr_err("%s: out get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst.memory_id);
@@ -911,7 +918,7 @@
rc = get_img(&info.src_chroma,
(unsigned long *)&in_chroma_paddr,
- (unsigned long *)&src_len, &srcp1_file,
+ (unsigned long *)&src_len, &srcp1_file, &p_need,
&srcp1_ihdl);
if (rc) {
pr_err("%s: in chroma get_img() failed id=0x%08x\n",
@@ -921,7 +928,7 @@
rc = get_img(&info.dst_chroma,
(unsigned long *)&out_chroma_paddr,
- (unsigned long *)&dst_len, &dstp1_file,
+ (unsigned long *)&dst_len, &dstp1_file, &p_need,
&dstp1_ihdl);
if (rc) {
pr_err("%s: out chroma get_img() failed id=0x%08x\n",
@@ -1089,7 +1096,12 @@
put_img(dstp1_file, dstp1_ihdl);
put_img(srcp1_file, srcp1_ihdl);
put_img(dstp0_file, dstp0_ihdl);
- put_img(srcp0_file, srcp0_ihdl);
+
+ /* only source may use frame buffer */
+ if (info.src.flags & MDP_MEMORY_ID_TYPE_FB)
+ fput_light(srcp0_file, ps0_need);
+ else
+ put_img(srcp0_file, srcp0_ihdl);
mutex_unlock(&msm_rotator_dev->rotator_lock);
dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n",
__func__, rc);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index a6c36c8..9b1e548 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -613,6 +613,11 @@
struct ion_iommu_map *iommu_map;
int ret = 0;
+ if (ION_IS_CACHED(flags)) {
+ pr_err("%s: Cannot map iommu as cached.\n", __func__);
+ return -EINVAL;
+ }
+
mutex_lock(&client->lock);
if (!ion_handle_validate(client, handle)) {
pr_err("%s: invalid handle passed to map_kernel.\n",
@@ -631,11 +636,6 @@
goto out;
}
- if (ion_validate_buffer_flags(buffer, flags)) {
- ret = -EEXIST;
- goto out;
- }
-
/*
* If clients don't want a custom iova length, just use whatever
* the buffer size is
@@ -882,7 +882,7 @@
return ret;
}
-static int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
void *uaddr, unsigned long offset, unsigned long len,
unsigned int cmd)
{
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 1d40aef..36758fa 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -271,4 +271,23 @@
void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
void *virt_base, unsigned long flags);
+/**
+ * ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @uaddr - virtual address to operate on.
+ * @offset - offset from physical address.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ * ION_IOC_CLEAN_CACHES
+ * ION_IOC_INV_CACHES
+ * ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *uaddr, unsigned long offset, unsigned long len,
+ unsigned int cmd);
+
#endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index a81dbd3..203b41a 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -43,6 +43,13 @@
}
EXPORT_SYMBOL(msm_ion_unsecure_heap);
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *vaddr, unsigned long len, unsigned int cmd)
+{
+ return ion_do_cache_op(client, handle, vaddr, 0, len, cmd);
+}
+EXPORT_SYMBOL(msm_ion_do_cache_op);
+
static unsigned long msm_ion_get_base(unsigned long size, int memory_type,
unsigned int align)
{
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 73d00b3..ea16c31 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -136,6 +136,9 @@
{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
512, 384, 3},
+ { ADRENO_REV_A203, 0, 1, 1, ANY_ID,
+ "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
+ 512, 384, 3},
{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
512, 384, 3},
@@ -400,11 +403,14 @@
/* 8x50 returns 0 for patch release, but it should be 1 */
/* 8960v3 returns 5 for patch release, but it should be 6 */
+ /* 8x25 returns 0 for minor id, but it should be 1 */
if (cpu_is_qsd8x50())
patchid = 1;
else if (cpu_is_msm8960() &&
SOCINFO_VERSION_MAJOR(soc_platform_version) == 3)
patchid = 6;
+ else if (cpu_is_msm8625() && minorid == 0)
+ minorid = 1;
chipid |= (minorid << 8) | patchid;
@@ -604,6 +610,8 @@
unsigned int soptimestamp;
unsigned int eoptimestamp;
struct adreno_context *drawctxt;
+ struct kgsl_context *context;
+ int next = 0;
KGSL_DRV_ERR(device, "Starting recovery from 3D GPU hang....\n");
rb_buffer = vmalloc(rb->buffer_desc.size);
@@ -672,6 +680,24 @@
drawctxt->flags |= CTXT_FLAGS_GPU_HANG;
+ /*
+ * Set the reset status of all contexts to
+ * INNOCENT_CONTEXT_RESET_EXT except for the bad context
+ * since thats the guilty party
+ */
+ while ((context = idr_get_next(&device->context_idr, &next))) {
+ if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
+ context->reset_status) {
+ if (context->devctxt != drawctxt)
+ context->reset_status =
+ KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+ else
+ context->reset_status =
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+ }
+ next = next + 1;
+ }
+
/* Restore valid commands in ringbuffer */
adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
rb->timestamp = timestamp;
@@ -1248,7 +1274,7 @@
default:
KGSL_DRV_INFO(dev_priv->device,
"invalid ioctl code %08x\n", cmd);
- result = -EINVAL;
+ result = -ENOIOCTLCMD;
break;
}
return result;
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9498b80..74f36c3 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -44,6 +44,7 @@
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
ADRENO_REV_A200 = 200,
+ ADRENO_REV_A203 = 203,
ADRENO_REV_A205 = 205,
ADRENO_REV_A220 = 220,
ADRENO_REV_A225 = 225,
@@ -129,15 +130,19 @@
return (adreno_dev->gpurev == ADRENO_REV_A200);
}
+static inline int adreno_is_a203(struct adreno_device *adreno_dev)
+{
+ return (adreno_dev->gpurev == ADRENO_REV_A203);
+}
+
static inline int adreno_is_a205(struct adreno_device *adreno_dev)
{
- return (adreno_dev->gpurev == ADRENO_REV_A200);
+ return (adreno_dev->gpurev == ADRENO_REV_A205);
}
static inline int adreno_is_a20x(struct adreno_device *adreno_dev)
{
- return (adreno_dev->gpurev == ADRENO_REV_A200 ||
- adreno_dev->gpurev == ADRENO_REV_A205);
+ return (adreno_dev->gpurev <= 209);
}
static inline int adreno_is_a220(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index b53ca8f..68299cf 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,8 @@
#include "a2xx_reg.h"
unsigned int kgsl_cff_dump_enable;
-int kgsl_pm_regs_enabled;
+int adreno_pm_regs_enabled;
+int adreno_pm_ib_enabled;
static struct dentry *pm_d_debugfs;
@@ -46,20 +47,37 @@
static int pm_regs_enabled_set(void *data, u64 val)
{
- kgsl_pm_regs_enabled = val ? 1 : 0;
+ adreno_pm_regs_enabled = val ? 1 : 0;
return 0;
}
static int pm_regs_enabled_get(void *data, u64 *val)
{
- *val = kgsl_pm_regs_enabled;
+ *val = adreno_pm_regs_enabled;
return 0;
}
+static int pm_ib_enabled_set(void *data, u64 val)
+{
+ adreno_pm_ib_enabled = val ? 1 : 0;
+ return 0;
+}
+
+static int pm_ib_enabled_get(void *data, u64 *val)
+{
+ *val = adreno_pm_ib_enabled;
+ return 0;
+}
+
+
DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
pm_regs_enabled_get,
pm_regs_enabled_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
+ pm_ib_enabled_get,
+ pm_ib_enabled_set, "%llu\n");
+
static int kgsl_cff_dump_enable_set(void *data, u64 val)
{
@@ -358,4 +376,6 @@
&pm_dump_fops);
debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
&pm_regs_enabled_fops);
+ debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
+ &pm_ib_enabled_fops);
}
diff --git a/drivers/gpu/msm/adreno_debugfs.h b/drivers/gpu/msm/adreno_debugfs.h
index 0356ac6..5f8d89a 100644
--- a/drivers/gpu/msm/adreno_debugfs.h
+++ b/drivers/gpu/msm/adreno_debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,11 +17,17 @@
int adreno_debugfs_init(struct kgsl_device *device);
-extern int kgsl_pm_regs_enabled;
+extern int adreno_pm_regs_enabled;
+extern int adreno_pm_ib_enabled;
-static inline int kgsl_pmregs_enabled(void)
+static inline int is_adreno_pm_regs_enabled(void)
{
- return kgsl_pm_regs_enabled;
+ return adreno_pm_regs_enabled;
+}
+
+static inline int is_adreno_pm_ib_enabled(void)
+{
+ return adreno_pm_ib_enabled;
}
#else
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 7902f30..f9e498f 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -294,15 +294,6 @@
}
}
-static bool adreno_ib_dump_enabled(void)
-{
-#ifdef CONFIG_MSM_KGSL_PSTMRTMDMP_NO_IB_DUMP
- return 0;
-#else
- return 1;
-#endif
-}
-
struct log_field {
bool show;
const char *display;
@@ -817,7 +808,7 @@
cp_rb_base, cp_rb_rptr, cp_rb_wptr, read_idx);
adreno_dump_rb(device, rb_copy, num_item<<2, read_idx, rb_count);
- if (adreno_ib_dump_enabled()) {
+ if (is_adreno_pm_ib_enabled()) {
for (read_idx = NUM_DWORDS_OF_RINGBUFFER_HISTORY;
read_idx >= 0; --read_idx) {
uint32_t this_cmd = rb_copy[read_idx];
@@ -849,16 +840,17 @@
}
/* Dump the registers if the user asked for it */
-
- if (adreno_is_a20x(adreno_dev))
- adreno_dump_regs(device, a200_registers,
- a200_registers_count);
- else if (adreno_is_a22x(adreno_dev))
- adreno_dump_regs(device, a220_registers,
- a220_registers_count);
- else if (adreno_is_a3xx(adreno_dev))
- adreno_dump_regs(device, a3xx_registers,
- a3xx_registers_count);
+ if (is_adreno_pm_regs_enabled()) {
+ if (adreno_is_a20x(adreno_dev))
+ adreno_dump_regs(device, a200_registers,
+ a200_registers_count);
+ else if (adreno_is_a22x(adreno_dev))
+ adreno_dump_regs(device, a220_registers,
+ a220_registers_count);
+ else if (adreno_is_a3xx(adreno_dev))
+ adreno_dump_regs(device, a3xx_registers,
+ a3xx_registers_count);
+ }
error_vfree:
vfree(rb_copy);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9333dca..b7356ac 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -789,6 +789,40 @@
break;
}
+ case KGSL_PROP_GPU_RESET_STAT:
+ {
+ /* Return reset status of given context and clear it */
+ uint32_t id;
+ struct kgsl_context *context;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+ /* We expect the value passed in to contain the context id */
+ if (copy_from_user(&id, param->value,
+ sizeof(unsigned int))) {
+ result = -EFAULT;
+ break;
+ }
+ context = kgsl_find_context(dev_priv, id);
+ if (!context) {
+ result = -EINVAL;
+ break;
+ }
+ /*
+ * Copy the reset status to value which also serves as
+ * the out parameter
+ */
+ if (copy_to_user(param->value, &(context->reset_status),
+ sizeof(unsigned int))) {
+ result = -EFAULT;
+ break;
+ }
+ /* Clear reset status once its been queried */
+ context->reset_status = KGSL_CTX_STAT_NO_ERROR;
+ break;
+ }
default:
result = dev_priv->device->ftbl->getproperty(
dev_priv->device, param->type,
@@ -990,6 +1024,7 @@
spin_lock(&entry->priv->mem_lock);
list_del(&entry->list);
spin_unlock(&entry->priv->mem_lock);
+ trace_kgsl_mem_timestamp_free(entry, timestamp);
kgsl_mem_entry_put(entry);
}
@@ -1000,12 +1035,18 @@
int result = 0;
struct kgsl_cmdstream_freememontimestamp *param = data;
struct kgsl_mem_entry *entry = NULL;
+ struct kgsl_device *device = dev_priv->device;
+ unsigned int cur;
spin_lock(&dev_priv->process_priv->mem_lock);
entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
spin_unlock(&dev_priv->process_priv->mem_lock);
if (entry) {
+ cur = device->ftbl->readtimestamp(device,
+ KGSL_TIMESTAMP_RETIRED);
+
+ trace_kgsl_mem_timestamp_queue(entry, cur);
result = kgsl_add_event(dev_priv->device, param->timestamp,
kgsl_freemem_event_cb, entry, dev_priv);
} else {
@@ -1084,6 +1125,7 @@
spin_unlock(&private->mem_lock);
if (entry) {
+ trace_kgsl_mem_free(entry);
kgsl_mem_entry_put(entry);
} else {
KGSL_CORE_ERR("invalid gpuaddr %08x\n", param->gpuaddr);
@@ -1184,6 +1226,7 @@
kgsl_mem_entry_attach_process(entry, private);
+ trace_kgsl_mem_alloc(entry);
/* Process specific statistics */
kgsl_process_add_stats(private, entry->memtype, len);
@@ -1618,6 +1661,7 @@
kgsl_process_add_stats(private, entry->memtype, param->len);
kgsl_mem_entry_attach_process(entry, private);
+ trace_kgsl_mem_map(entry, param->fd);
kgsl_check_idle(dev_priv->device);
return result;
@@ -1684,6 +1728,7 @@
param->gpuaddr = entry->memdesc.gpuaddr;
kgsl_process_add_stats(private, entry->memtype, param->size);
+ trace_kgsl_mem_alloc(entry);
} else
kfree(entry);
@@ -1930,7 +1975,7 @@
if (!func) {
KGSL_DRV_INFO(dev_priv->device,
"invalid ioctl code %08x\n", cmd);
- ret = -EINVAL;
+ ret = -ENOIOCTLCMD;
goto done;
}
lock = 1;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2fb1e43..06432f9 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -197,6 +197,11 @@
/* Pointer to the device specific context information */
void *devctxt;
+ /*
+ * Status indicating whether a gpu reset occurred and whether this
+ * context was responsible for causing it
+ */
+ unsigned int reset_status;
};
struct kgsl_process_private {
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 389ed6d..7264c25 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -150,7 +150,7 @@
#endif
MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, user),
#ifdef CONFIG_ION
- MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, ion),
+ MEM_ENTRY_STAT(KGSL_MEM_ENTRY_ION, ion),
#endif
};
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index de39ee4..93fdc08 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -10,7 +10,6 @@
* GNU General Public License for more details.
*/
-#include <linux/vmalloc.h>
#include <linux/time.h>
#include <linux/sysfs.h>
#include <linux/utsname.h>
@@ -299,6 +298,10 @@
/* Freeze the snapshot on a hang until it gets read */
device->snapshot_frozen = (hang) ? 1 : 0;
+ /* log buffer info to aid in ramdump recovery */
+ KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
+ device->snapshot, __pa(device->snapshot),
+ device->snapshot_size);
return 0;
}
EXPORT_SYMBOL(kgsl_device_snapshot);
@@ -448,7 +451,7 @@
int ret;
if (device->snapshot == NULL)
- device->snapshot = vmalloc(KGSL_SNAPSHOT_MEMSIZE);
+ device->snapshot = kzalloc(KGSL_SNAPSHOT_MEMSIZE, GFP_KERNEL);
if (device->snapshot == NULL)
return -ENOMEM;
@@ -491,7 +494,7 @@
kobject_put(&device->snapshot_kobj);
- vfree(device->snapshot);
+ kfree(device->snapshot);
device->snapshot = NULL;
device->snapshot_maxsize = 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 86a9adc..22bc576 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -257,6 +257,122 @@
TP_ARGS(device, state)
);
+TRACE_EVENT(kgsl_mem_alloc,
+
+ TP_PROTO(struct kgsl_mem_entry *mem_entry),
+
+ TP_ARGS(mem_entry),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, gpuaddr)
+ __field(unsigned int, size)
+ ),
+
+ TP_fast_assign(
+ __entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+ __entry->size = mem_entry->memdesc.size;
+ ),
+
+ TP_printk(
+ "gpuaddr=0x%08x size=%d",
+ __entry->gpuaddr, __entry->size
+ )
+);
+
+TRACE_EVENT(kgsl_mem_map,
+
+ TP_PROTO(struct kgsl_mem_entry *mem_entry, int fd),
+
+ TP_ARGS(mem_entry, fd),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, gpuaddr)
+ __field(unsigned int, size)
+ __field(int, fd)
+ __field(int, type)
+ ),
+
+ TP_fast_assign(
+ __entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+ __entry->size = mem_entry->memdesc.size;
+ __entry->fd = fd;
+ __entry->type = mem_entry->memtype;
+ ),
+
+ TP_printk(
+ "gpuaddr=0x%08x size=%d type=%d fd=%d",
+ __entry->gpuaddr, __entry->size,
+ __entry->type, __entry->fd
+ )
+);
+
+TRACE_EVENT(kgsl_mem_free,
+
+ TP_PROTO(struct kgsl_mem_entry *mem_entry),
+
+ TP_ARGS(mem_entry),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, gpuaddr)
+ __field(unsigned int, size)
+ __field(int, type)
+ __field(int, fd)
+ ),
+
+ TP_fast_assign(
+ __entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+ __entry->size = mem_entry->memdesc.size;
+ __entry->type = mem_entry->memtype;
+ ),
+
+ TP_printk(
+ "gpuaddr=0x%08x size=%d type=%d",
+ __entry->gpuaddr, __entry->size, __entry->type
+ )
+);
+
+DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template,
+
+ TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+
+ TP_ARGS(mem_entry, curr_ts),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, gpuaddr)
+ __field(unsigned int, size)
+ __field(int, type)
+ __field(unsigned int, drawctxt_id)
+ __field(unsigned int, curr_ts)
+ __field(unsigned int, free_ts)
+ ),
+
+ TP_fast_assign(
+ __entry->gpuaddr = mem_entry->memdesc.gpuaddr;
+ __entry->size = mem_entry->memdesc.size;
+ __entry->drawctxt_id = 1337;
+ __entry->type = mem_entry->memtype;
+ __entry->curr_ts = curr_ts;
+ __entry->free_ts = mem_entry->free_timestamp;
+ ),
+
+ TP_printk(
+ "gpuaddr=0x%08x size=%d type=%d ctx=%u curr_ts=0x%08x free_ts=0x%08x",
+ __entry->gpuaddr, __entry->size, __entry->type,
+ __entry->drawctxt_id, __entry->curr_ts, __entry->free_ts
+ )
+);
+
+DEFINE_EVENT(kgsl_mem_timestamp_template, kgsl_mem_timestamp_queue,
+ TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+ TP_ARGS(mem_entry, curr_ts)
+);
+
+DEFINE_EVENT(kgsl_mem_timestamp_template, kgsl_mem_timestamp_free,
+ TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned int curr_ts),
+ TP_ARGS(mem_entry, curr_ts)
+);
+
+
#endif /* _KGSL_TRACE_H */
/* This part must be outside protection */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cb3da90..6c43a75 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -339,13 +339,15 @@
*p++ = ADDR_VGV3_LAST << 24;
}
-static void z180_cmdstream_start(struct kgsl_device *device)
+static void z180_cmdstream_start(struct kgsl_device *device, int init_ram)
{
struct z180_device *z180_dev = Z180_DEVICE(device);
unsigned int cmd = VGV3_NEXTCMD_JUMP << VGV3_NEXTCMD_NEXTCMD_FSHIFT;
- z180_dev->timestamp = 0;
- z180_dev->current_timestamp = 0;
+ if (init_ram) {
+ z180_dev->timestamp = 0;
+ z180_dev->current_timestamp = 0;
+ }
addmarker(&z180_dev->ringbuffer, 0);
@@ -566,7 +568,7 @@
if (status)
goto error_clk_off;
- z180_cmdstream_start(device);
+ z180_cmdstream_start(device, init_ram);
mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 40aae69..f18c2d0 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -25,6 +25,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/regulator/consumer.h>
+#include <linux/string.h>
#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
@@ -42,15 +43,32 @@
#define MXT_VER_21 21
#define MXT_VER_22 22
-/* Slave addresses */
-#define MXT_APP_LOW 0x4a
-#define MXT_APP_HIGH 0x4b
-#define MXT_BOOT_LOW 0x24
-#define MXT_BOOT_HIGH 0x25
+/* I2C slave address pairs */
+struct mxt_address_pair {
+ int bootloader;
+ int application;
+};
+
+static const struct mxt_address_pair mxt_slave_addresses[] = {
+ { 0x24, 0x4a },
+ { 0x25, 0x4b },
+ { 0x25, 0x4b },
+ { 0x26, 0x4c },
+ { 0x27, 0x4d },
+ { 0x34, 0x5a },
+ { 0x35, 0x5b },
+ { 0 },
+};
+
+enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
/* Firmware */
#define MXT_FW_NAME "maxtouch.fw"
+/* Firmware frame size including frame data and CRC */
+#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
+#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
+
/* Registers */
#define MXT_FAMILY_ID 0x00
#define MXT_VARIANT_ID 0x01
@@ -215,7 +233,7 @@
#define MXT_RESET_TIME 250 /* msec */
#define MXT_RESET_NOCHGREAD 400 /* msec */
-#define MXT_FWRESET_TIME 175 /* msec */
+#define MXT_FWRESET_TIME 1000 /* msec */
#define MXT_WAKE_TIME 25
@@ -231,6 +249,8 @@
#define MXT_FRAME_CRC_PASS 0x04
#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
#define MXT_BOOT_STATUS_MASK 0x3f
+#define MXT_BOOT_EXTENDED_ID (1 << 5)
+#define MXT_BOOT_ID_MASK 0x1f
/* Touch status */
#define MXT_SUPPRESS (1 << 1)
@@ -299,6 +319,7 @@
struct input_dev *input_dev;
const struct mxt_platform_data *pdata;
const struct mxt_config_info *config_info;
+ enum mxt_device_state state;
struct mxt_object *object_table;
struct mxt_info info;
struct mxt_finger finger[MXT_MAX_FINGER];
@@ -323,6 +344,7 @@
u8 t15_min_reportid;
u8 curr_cfg_version;
int cfg_version_idx;
+ const char *fw_name;
};
static struct dentry *debug_base;
@@ -409,8 +431,91 @@
dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
}
+static int mxt_switch_to_bootloader_address(struct mxt_data *data)
+{
+ int i;
+ struct i2c_client *client = data->client;
+
+ if (data->state == BOOTLOADER) {
+ dev_err(&client->dev, "Already in BOOTLOADER state\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
+ if (mxt_slave_addresses[i].application == client->addr) {
+ dev_info(&client->dev, "Changing to bootloader address: "
+ "%02x -> %02x",
+ client->addr,
+ mxt_slave_addresses[i].bootloader);
+
+ client->addr = mxt_slave_addresses[i].bootloader;
+ data->state = BOOTLOADER;
+ return 0;
+ }
+ }
+
+ dev_err(&client->dev, "Address 0x%02x not found in address table",
+ client->addr);
+ return -EINVAL;
+}
+
+static int mxt_switch_to_appmode_address(struct mxt_data *data)
+{
+ int i;
+ struct i2c_client *client = data->client;
+
+ if (data->state == APPMODE) {
+ dev_err(&client->dev, "Already in APPMODE state\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
+ if (mxt_slave_addresses[i].bootloader == client->addr) {
+ dev_info(&client->dev,
+ "Changing to application mode address: "
+ "0x%02x -> 0x%02x",
+ client->addr,
+ mxt_slave_addresses[i].application);
+
+ client->addr = mxt_slave_addresses[i].application;
+ data->state = APPMODE;
+ return 0;
+ }
+ }
+
+ dev_err(&client->dev, "Address 0x%02x not found in address table",
+ client->addr);
+ return -EINVAL;
+}
+
+static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
+{
+ u8 buf[3];
+
+ if (val | MXT_BOOT_EXTENDED_ID) {
+ dev_dbg(&client->dev,
+ "Retrieving extended mode ID information");
+
+ if (i2c_master_recv(client, &buf[0], 3) != 3) {
+ dev_err(&client->dev, "%s: i2c recv failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_info(&client->dev, "Bootloader ID:%d Version:%d",
+ buf[1], buf[2]);
+
+ return buf[0];
+ } else {
+ dev_info(&client->dev, "Bootloader ID:%d",
+ val & MXT_BOOT_ID_MASK);
+
+ return val;
+ }
+}
+
static int mxt_check_bootloader(struct i2c_client *client,
- unsigned int state)
+ unsigned int state)
{
u8 val;
@@ -422,19 +527,28 @@
switch (state) {
case MXT_WAITING_BOOTLOAD_CMD:
+ val = mxt_get_bootloader_version(client, val);
+ val &= ~MXT_BOOT_STATUS_MASK;
+ break;
case MXT_WAITING_FRAME_DATA:
+ case MXT_APP_CRC_FAIL:
val &= ~MXT_BOOT_STATUS_MASK;
break;
case MXT_FRAME_CRC_PASS:
if (val == MXT_FRAME_CRC_CHECK)
goto recheck;
+ if (val == MXT_FRAME_CRC_FAIL) {
+ dev_err(&client->dev, "Bootloader CRC fail\n");
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
}
if (val != state) {
- dev_err(&client->dev, "Unvalid bootloader mode state\n");
+ dev_err(&client->dev, "Invalid bootloader mode state %X\n",
+ val);
return -EINVAL;
}
@@ -457,7 +571,7 @@
}
static int mxt_fw_write(struct i2c_client *client,
- const u8 *data, unsigned int frame_size)
+ const u8 *data, unsigned int frame_size)
{
if (i2c_master_send(client, data, frame_size) != frame_size) {
dev_err(&client->dev, "%s: i2c send failed\n", __func__);
@@ -735,6 +849,11 @@
int id;
u8 reportid;
+ if (data->state != APPMODE) {
+ dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
+ return IRQ_HANDLED;
+ }
+
do {
if (mxt_read_message(data, &message)) {
dev_err(dev, "Failed to read message\n");
@@ -921,11 +1040,13 @@
if (data->curr_cfg_version == cfg_version ||
!version_match) {
data->config_info = cfg_info;
+ data->fw_name = pdata->config_array[i].fw_name;
return 0;
}
}
}
+ data->fw_name = NULL;
dev_info(&data->client->dev,
"Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
info->family_id, info->variant_id,
@@ -1003,8 +1124,30 @@
struct mxt_object *t15_object;
error = mxt_get_info(data);
- if (error)
- return error;
+ if (error) {
+ /* Try bootloader mode */
+ error = mxt_switch_to_bootloader_address(data);
+ if (error)
+ return error;
+
+ error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
+ if (error)
+ return error;
+
+ dev_err(&client->dev, "Application CRC failure\n");
+ data->state = BOOTLOADER;
+
+ return 0;
+ }
+
+ dev_info(&client->dev,
+ "Family ID: %d Variant ID: %d Version: %d.%d "
+ "Build: 0x%02X Object Num: %d\n",
+ info->family_id, info->variant_id,
+ info->version >> 4, info->version & 0xf,
+ info->build, info->object_num);
+
+ data->state = APPMODE;
data->object_table = kcalloc(info->object_num,
sizeof(struct mxt_object),
@@ -1112,14 +1255,8 @@
info->matrix_ysize = val;
dev_info(&client->dev,
- "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
- info->family_id, info->variant_id, info->version,
- info->build);
-
- dev_info(&client->dev,
- "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
- info->matrix_xsize, info->matrix_ysize,
- info->object_num);
+ "Matrix X Size: %d Matrix Y Size: %d\n",
+ info->matrix_xsize, info->matrix_ysize);
return 0;
@@ -1175,74 +1312,139 @@
return count;
}
+static int strtobyte(const char *data, u8 *value)
+{
+ char str[3];
+
+ str[0] = data[0];
+ str[1] = data[1];
+ str[2] = '\0';
+
+ return kstrtou8(str, 16, value);
+}
+
static int mxt_load_fw(struct device *dev, const char *fn)
{
struct mxt_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
const struct firmware *fw = NULL;
unsigned int frame_size;
+ unsigned int retry = 0;
unsigned int pos = 0;
- int ret;
+ int ret, i, max_frame_size;
+ u8 *frame;
- ret = request_firmware(&fw, fn, dev);
- if (ret) {
- dev_err(dev, "Unable to open firmware %s\n", fn);
- return ret;
+ switch (data->info.family_id) {
+ case MXT224_ID:
+ max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
+ break;
+ case MXT1386_ID:
+ max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
+ break;
+ default:
+ return -EINVAL;
}
- /* Change to the bootloader mode */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+ frame = kmalloc(max_frame_size, GFP_KERNEL);
+ if (!frame) {
+ dev_err(dev, "Unable to allocate memory for frame data\n");
+ return -ENOMEM;
+ }
- mxt_reset_delay(data);
+ ret = request_firmware(&fw, fn, dev);
+ if (ret < 0) {
+ dev_err(dev, "Unable to open firmware %s\n", fn);
+ goto free_frame;
+ }
- /* Change to slave address of bootloader */
- if (client->addr == MXT_APP_LOW)
- client->addr = MXT_BOOT_LOW;
- else
- client->addr = MXT_BOOT_HIGH;
+ if (data->state != BOOTLOADER) {
+ /* Change to the bootloader mode */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+ mxt_reset_delay(data);
+
+ ret = mxt_switch_to_bootloader_address(data);
+ if (ret)
+ goto release_firmware;
+ }
ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
- if (ret)
- goto out;
+ if (ret) {
+ /* Bootloader may still be unlocked from previous update
+ * attempt */
+ ret = mxt_check_bootloader(client,
+ MXT_WAITING_FRAME_DATA);
- /* Unlock bootloader */
- mxt_unlock_bootloader(client);
+ if (ret)
+ goto return_to_app_mode;
+ } else {
+ dev_info(dev, "Unlocking bootloader\n");
+ /* Unlock bootloader */
+ mxt_unlock_bootloader(client);
+ }
while (pos < fw->size) {
ret = mxt_check_bootloader(client,
MXT_WAITING_FRAME_DATA);
if (ret)
- goto out;
+ goto release_firmware;
- frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+ /* Get frame length MSB */
+ ret = strtobyte(fw->data + pos, frame);
+ if (ret)
+ goto release_firmware;
+
+ /* Get frame length LSB */
+ ret = strtobyte(fw->data + pos + 2, frame + 1);
+ if (ret)
+ goto release_firmware;
+
+ frame_size = ((*frame << 8) | *(frame + 1));
/* We should add 2 at frame size as the the firmware data is not
* included the CRC bytes.
*/
frame_size += 2;
+ if (frame_size > max_frame_size) {
+ dev_err(dev, "Invalid frame size - %d\n", frame_size);
+ ret = -EINVAL;
+ goto release_firmware;
+ }
+
+ /* Convert frame data and CRC from hex to binary */
+ for (i = 2; i < frame_size; i++) {
+ ret = strtobyte(fw->data + pos + i * 2, frame + i);
+ if (ret)
+ goto release_firmware;
+ }
+
/* Write one frame to device */
- mxt_fw_write(client, fw->data + pos, frame_size);
+ mxt_fw_write(client, frame, frame_size);
ret = mxt_check_bootloader(client,
MXT_FRAME_CRC_PASS);
- if (ret)
- goto out;
+ if (ret) {
+ retry++;
- pos += frame_size;
+ /* Back off by 20ms per retry */
+ msleep(retry * 20);
- dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+ if (retry > 20)
+ goto release_firmware;
+ } else {
+ retry = 0;
+ pos += frame_size * 2;
+ dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
+ }
}
-out:
+return_to_app_mode:
+ mxt_switch_to_appmode_address(data);
+release_firmware:
release_firmware(fw);
-
- /* Change to slave address of application */
- if (client->addr == MXT_BOOT_LOW)
- client->addr = MXT_APP_LOW;
- else
- client->addr = MXT_APP_HIGH;
+free_frame:
+ kfree(frame);
return ret;
}
@@ -1254,29 +1456,41 @@
struct mxt_data *data = dev_get_drvdata(dev);
int error;
+ /* If fw_name is set, then the existing firmware has an upgrade */
+ if (!data->fw_name) {
+ dev_err(dev, "Firmware name not specifed in platform data\n");
+ return -EINVAL;
+ }
+
+ dev_info(dev, "Upgrading the firmware file to %s\n", data->fw_name);
+
disable_irq(data->irq);
- error = mxt_load_fw(dev, MXT_FW_NAME);
+ error = mxt_load_fw(dev, data->fw_name);
if (error) {
dev_err(dev, "The firmware update failed(%d)\n", error);
count = error;
} else {
- dev_dbg(dev, "The firmware update succeeded\n");
+ dev_info(dev, "The firmware update succeeded\n");
/* Wait for reset */
msleep(MXT_FWRESET_TIME);
+ data->state = INIT;
kfree(data->object_table);
data->object_table = NULL;
+ data->cfg_version_idx = 0;
mxt_initialize(data);
}
- enable_irq(data->irq);
+ if (data->state == APPMODE) {
+ enable_irq(data->irq);
- error = mxt_make_highchg(data);
- if (error)
- return error;
+ error = mxt_make_highchg(data);
+ if (error)
+ return error;
+ }
return count;
}
@@ -1818,6 +2032,7 @@
goto err_free_mem;
}
+ data->state = INIT;
input_dev->name = "atmel_mxt_ts";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
@@ -1941,9 +2156,13 @@
goto err_free_object;
}
- error = mxt_make_highchg(data);
- if (error)
- goto err_free_irq;
+ if (data->state == APPMODE) {
+ error = mxt_make_highchg(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to make high CHG\n");
+ goto err_free_irq;
+ }
+ }
error = input_register_device(input_dev);
if (error)
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 84d441d..78c474e 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -163,6 +163,10 @@
if (!rc)
rc = -ETIMEDOUT;
if (rc < 0) {
+ rcmd = msm_dequeue(queue, list_control);
+ if (!rcmd)
+ free_qcmd(rcmd);
+ kfree(isp_event);
pr_err("%s: wait_event error %d\n", __func__, rc);
return rc;
}
@@ -518,6 +522,7 @@
ctrlcmd.value = (void *)ctrl_data;
memcpy(ctrlcmd.value, ctrl, ctrlcmd.length);
ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
@@ -543,6 +548,7 @@
ctrlcmd.value = (void *)ctrl_data;
memcpy(ctrlcmd.value, queryctrl, ctrlcmd.length);
ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.vnode_id = pcam->vnode_id;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in userspace, and get return value */
@@ -943,7 +949,8 @@
not in use when we free the buffers */
mutex_lock(&pcam->vid_lock);
pcam_inst->streamon = 0;
- rc = msm_server_streamoff(pcam, pcam_inst->my_index);
+ if (g_server_dev.use_count > 0)
+ rc = msm_server_streamoff(pcam, pcam_inst->my_index);
mutex_unlock(&pcam->vid_lock);
if (rc < 0)
pr_err("%s: hw failed to stop streaming\n", __func__);
@@ -1448,6 +1455,7 @@
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
pcam->mctl.client = msm_ion_client_create(-1, "camera");
+ kref_init(&pcam->mctl.refcount);
#endif
/* Should be set to sensor ops if any but right now its OK!! */
if (!pcam->mctl.mctl_open) {
@@ -1502,6 +1510,7 @@
if (pcam->use_count == 1) {
+ msm_queue_init(&g_server_dev.ctrl_q, "control");
rc = msm_send_open_server(pcam->vnode_id);
if (rc < 0) {
mutex_unlock(&pcam->vid_lock);
@@ -1573,6 +1582,14 @@
return rc;
}
+void msm_release_ion_client(struct kref *ref)
+{
+ struct msm_cam_media_controller *mctl = container_of(ref,
+ struct msm_cam_media_controller, refcount);
+ pr_err("%s Calling ion_client_destroy ", __func__);
+ ion_client_destroy(mctl->client);
+}
+
static int msm_close(struct file *f)
{
int rc = 0;
@@ -1581,13 +1598,11 @@
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
pcam = pcam_inst->pcam;
- D("%s\n", __func__);
if (!pcam) {
pr_err("%s NULL pointer of camera device!\n", __func__);
return -EINVAL;
}
-
mutex_lock(&pcam->vid_lock);
pcam_inst->streamon = 0;
pcam->use_count--;
@@ -1610,17 +1625,21 @@
if (rc < 0)
pr_err("msm_cam_server_close_session fails %d\n", rc);
- rc = msm_send_close_server(pcam->vnode_id);
- if (rc < 0)
- pr_err("msm_send_close_server failed %d\n", rc);
+ if (g_server_dev.use_count > 0) {
+ rc = msm_send_close_server(pcam->vnode_id);
+ if (rc < 0)
+ pr_err("msm_send_close_server failed %d\n", rc);
+ }
if (pcam->mctl.mctl_release) {
rc = pcam->mctl.mctl_release(&(pcam->mctl));
if (rc < 0)
pr_err("mctl_release fails %d\n", rc);
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_client_destroy(pcam->mctl.client);
+ kref_put(&pcam->mctl.refcount, msm_release_ion_client);
#endif
+ if (g_server_dev.use_count == 0)
+ mutex_unlock(&g_server_dev.server_lock);
}
mutex_unlock(&pcam->vid_lock);
return rc;
@@ -1879,16 +1898,17 @@
{
int rc;
D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
-
+ mutex_lock(&g_server_dev.server_lock);
rc = nonseekable_open(inode, fp);
if (rc < 0) {
pr_err("%s: nonseekable_open error %d\n", __func__, rc);
+ mutex_unlock(&g_server_dev.server_lock);
return rc;
}
g_server_dev.use_count++;
if (g_server_dev.use_count == 1)
msm_queue_init(&g_server_dev.ctrl_q, "control");
-
+ mutex_unlock(&g_server_dev.server_lock);
return rc;
}
@@ -1909,6 +1929,29 @@
return rc;
}
+static int msm_close_server(struct inode *inode, struct file *fp)
+{
+ mutex_lock(&g_server_dev.server_lock);
+ if (g_server_dev.use_count > 0)
+ g_server_dev.use_count--;
+ mutex_unlock(&g_server_dev.server_lock);
+ if (g_server_dev.use_count == 0) {
+ if (g_server_dev.pcam_active) {
+ struct v4l2_event v4l2_ev;
+ mutex_lock(&g_server_dev.server_lock);
+
+ v4l2_ev.type = V4L2_EVENT_PRIVATE_START
+ + MSM_CAM_APP_NOTIFY_ERROR_EVENT;
+ ktime_get_ts(&v4l2_ev.timestamp);
+ v4l2_event_queue(
+ g_server_dev.pcam_active->pvdev, &v4l2_ev);
+ }
+ msm_queue_drain(&g_server_dev.ctrl_q, list_control);
+ }
+ return 0;
+}
+
+
static long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
unsigned int cmd, unsigned long evt)
{
@@ -2147,10 +2190,19 @@
spin_lock_init(&config_cam->p_mctl->sync.pmem_stats_spinlock);
config_cam->p_mctl->config_device = config_cam;
+ kref_get(&config_cam->p_mctl->refcount);
fp->private_data = config_cam;
return rc;
}
+static int msm_close_config(struct inode *node, struct file *f)
+{
+ struct msm_cam_config_dev *config_cam = f->private_data;
+ D("%s Decrementing ref count of config node ", __func__);
+ kref_put(&config_cam->p_mctl->refcount, msm_release_ion_client);
+ return 0;
+}
+
static struct v4l2_file_operations g_msm_fops = {
.owner = THIS_MODULE,
.open = msm_open,
@@ -2169,6 +2221,7 @@
.open = msm_open_server,
.poll = msm_poll_server,
.unlocked_ioctl = msm_ioctl_server,
+ .release = msm_close_server,
};
static const struct file_operations msm_fops_config = {
@@ -2177,6 +2230,7 @@
.poll = msm_poll_config,
.unlocked_ioctl = msm_ioctl_config,
.mmap = msm_mmap_config,
+ .release = msm_close_config,
};
int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
@@ -2294,6 +2348,7 @@
return rc;
}
+ mutex_init(&g_server_dev.server_lock);
g_server_dev.pcam_active = NULL;
g_server_dev.camera_info.num_cameras = 0;
atomic_set(&g_server_dev.number_pcam_active, 0);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 55c0da1..c90ab44 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -239,6 +239,7 @@
struct pm_qos_request_list pm_qos_req_list;
struct msm_mctl_pp_info pp_info;
struct ion_client *client;
+ struct kref refcount;
/* VFE output mode.
* Used to interpret the Primary/Secondary messages
* to preview/video/main/thumbnail image types*/
@@ -409,6 +410,7 @@
struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
/* info of MCTL nodes successfully probed*/
struct msm_mctl_node_info mctl_node_info;
+ struct mutex server_lock;
};
/* camera server related functions */
@@ -525,6 +527,7 @@
int image_mode, struct msm_frame_buffer *buf);
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
void __user *arg);
+void msm_release_ion_client(struct kref *ref);
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 54458d1..492bcce 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -890,7 +890,7 @@
return rc;
}
pcam_inst->vbqueue_initialized = 0;
-
+ kref_get(&pcam->mctl.refcount);
f->private_data = &pcam_inst->eventHandle;
D("f->private_data = 0x%x, pcam = 0x%x\n",
@@ -961,6 +961,7 @@
v4l2_fh_exit(&pcam_inst->eventHandle);
kfree(pcam_inst);
+ kref_put(&pcam->mctl.refcount, msm_release_ion_client);
f->private_data = NULL;
mutex_unlock(&pcam->mctl_node.dev_lock);
D("%s : X ", __func__);
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index e3d9d2d..6c52e21 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -699,7 +699,8 @@
}
static long venc_set_h264_intra_period(struct video_client_ctx *client_ctx,
- __s32 period) {
+ __s32 period)
+{
struct vcd_property_i_period vcd_property_i_period;
struct vcd_property_codec vcd_property_codec;
struct vcd_property_hdr vcd_property_hdr;
@@ -726,7 +727,7 @@
vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
vcd_property_i_period.p_frames = period - 1;
- vcd_property_i_period.b_frames = 1;
+ vcd_property_i_period.b_frames = 0;
rc = vcd_set_property(client_ctx->vcd_handle,
&vcd_property_hdr, &vcd_property_i_period);
@@ -740,6 +741,47 @@
return rc;
}
+static long venc_get_h264_intra_period(struct video_client_ctx *client_ctx,
+ __s32 *period)
+{
+ struct vcd_property_i_period vcd_property_i_period;
+ struct vcd_property_codec vcd_property_codec;
+ struct vcd_property_hdr vcd_property_hdr;
+ int rc = 0;
+
+ vcd_property_hdr.prop_id = VCD_I_CODEC;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+ rc = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_codec);
+
+ if (rc < 0) {
+ WFD_MSG_ERR("Error getting codec property\n");
+ goto err;
+ }
+
+ if (vcd_property_codec.codec != VCD_CODEC_H264) {
+ rc = -ENOTSUPP;
+ WFD_MSG_ERR("Control not supported for non H264 codec\n");
+ goto err;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_INTRA_PERIOD;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_i_period);
+
+ rc = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_i_period);
+
+ if (rc < 0) {
+ WFD_MSG_ERR("Error getting intra period\n");
+ goto err;
+ }
+
+ *period = vcd_property_i_period.p_frames + 1;
+err:
+ return rc;
+}
+
static long venc_request_frame(struct video_client_ctx *client_ctx, __s32 type)
{
struct vcd_property_req_i_frame vcd_property_req_i_frame;
@@ -950,6 +992,212 @@
return rc;
}
+static long venc_set_qp_value(struct video_client_ctx *client_ctx,
+ __s32 frametype, __s32 qp)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_session_qp vcd_property_session_qp;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
+ vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_session_qp);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get session qp\n");
+ goto err;
+ }
+
+ switch (frametype) {
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ vcd_property_session_qp.i_frame_qp = qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ vcd_property_session_qp.p_frame_qp = qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ vcd_property_session_qp.b_frame_qp = qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+ rc = -ENOTSUPP;
+ goto err;
+ default:
+ rc = -EINVAL;
+ goto err;
+ }
+
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_session_qp);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to set session qp\n");
+ goto err;
+ }
+err:
+ return rc;
+}
+
+static long venc_get_qp_value(struct video_client_ctx *client_ctx,
+ __s32 frametype, __s32 *qp)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_session_qp vcd_property_session_qp;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_SESSION_QP;
+ vcd_property_hdr.sz = sizeof(vcd_property_session_qp);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_session_qp);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get session qp\n");
+ goto err;
+ }
+
+ switch (frametype) {
+ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ *qp = vcd_property_session_qp.i_frame_qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ *qp = vcd_property_session_qp.p_frame_qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ *qp = vcd_property_session_qp.b_frame_qp;
+ break;
+ default:
+ rc = -EINVAL;
+ goto err;
+ }
+
+err:
+ return rc;
+}
+
+static long venc_set_qp_range(struct video_client_ctx *client_ctx,
+ __s32 type, __s32 qp)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_qp_range vcd_property_qp_range;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
+ vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_qp_range);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get qp range\n");
+ goto err;
+ }
+
+ switch (type) {
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ vcd_property_qp_range.min_qp = qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ vcd_property_qp_range.max_qp = qp;
+ break;
+ default:
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_qp_range);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to set qp range\n");
+ goto err;
+ }
+err:
+ return rc;
+}
+
+static long venc_get_qp_range(struct video_client_ctx *client_ctx,
+ __s32 type, __s32 *qp)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_qp_range vcd_property_qp_range;
+ int rc = 0;
+
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ vcd_property_hdr.prop_id = VCD_I_QP_RANGE;
+ vcd_property_hdr.sz = sizeof(vcd_property_qp_range);
+
+ rc = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_qp_range);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to get qp range\n");
+ goto err;
+ }
+
+ switch (type) {
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ *qp = vcd_property_qp_range.min_qp;
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ *qp = vcd_property_qp_range.max_qp;
+ break;
+ default:
+ rc = -EINVAL;
+ goto err;
+ }
+
+ rc = vcd_set_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_property_qp_range);
+
+ if (rc) {
+ WFD_MSG_ERR("Failed to set qp range\n");
+ goto err;
+ }
+err:
+ return rc;
+}
+
static long venc_alloc_input_buffer(struct v4l2_subdev *sd, void *arg)
{
struct mem_region *mregion = arg;
@@ -1220,6 +1468,25 @@
case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
rc = venc_request_frame(client_ctx, ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+ rc = venc_set_qp_value(client_ctx, ctrl->id, ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ rc = venc_set_qp_range(client_ctx, ctrl->id, ctrl->value);
+ break;
default:
WFD_MSG_ERR("Set property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
@@ -1248,6 +1515,28 @@
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
rc = venc_get_codec_profile(client_ctx, ctrl->id, &ctrl->value);
break;
+ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+ rc = venc_get_h264_intra_period(client_ctx, &ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+ rc = venc_get_qp_value(client_ctx, ctrl->id, &ctrl->value);
+ break;
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+ rc = venc_get_qp_range(client_ctx, ctrl->id, &ctrl->value);
+ break;
default:
WFD_MSG_ERR("Get property not suported: %d\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
index 53b6e20..8e385a4 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.c
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -76,10 +76,29 @@
}
}
+static void vsg_encode_helper_func(struct work_struct *task)
+{
+ struct vsg_encode_work *work =
+ container_of(task, struct vsg_encode_work, work);
+
+ /*
+ * Note: don't need to lock for context below as we only
+ * access fields that are "static".
+ */
+ int rc = vsg_encode_frame(work->context, work->buf);
+ if (rc < 0) {
+ mutex_lock(&work->context->mutex);
+ work->context->state = VSG_STATE_ERROR;
+ mutex_unlock(&work->context->mutex);
+ }
+ kfree(work);
+}
+
static void vsg_work_func(struct work_struct *task)
{
struct vsg_work *work =
container_of(task, struct vsg_work, work);
+ struct vsg_encode_work *encode_work;
struct vsg_context *context = work->context;
struct vsg_buf_info *buf_info = NULL, *temp = NULL;
int rc = 0;
@@ -88,8 +107,9 @@
if (list_empty(&context->free_queue.node)) {
WFD_MSG_DBG("%s: queue empty doing nothing\n", __func__);
goto err_skip_encode;
- } else if (context->stopped) {
- WFD_MSG_DBG("%s: vsg is stopped doing nothing\n", __func__);
+ } else if (context->state != VSG_STATE_STARTED) {
+ WFD_MSG_DBG("%s: vsg is stopped or in error state "
+ "doing nothing\n", __func__);
goto err_skip_encode;
}
@@ -114,18 +134,46 @@
}
}
- mutex_unlock(&context->mutex);
- rc = vsg_encode_frame(context, buf_info);
- if (rc < 0) {
- WFD_MSG_ERR("frame encode failed");
- goto err_encode_fail;
+ encode_work = kmalloc(sizeof(*encode_work), GFP_KERNEL);
+ encode_work->buf = buf_info;
+ encode_work->context = context;
+ INIT_WORK(&encode_work->work, vsg_encode_helper_func);
+ rc = queue_work(context->work_queue, &encode_work->work);
+ if (!rc) {
+ WFD_MSG_ERR("Queueing buffer for encode failed\n");
+ kfree(encode_work);
+ encode_work = NULL;
+ goto err_queue_encode_fail;
}
- mutex_lock(&context->mutex);
+
+ buf_info->flags |= VSG_BUF_BEING_ENCODED;
+ if (!(buf_info->flags & VSG_NEVER_SET_LAST_BUFFER)) {
+ bool is_same_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
+ &context->last_buffer->mdp_buf_info,
+ &buf_info->mdp_buf_info);
+
+ if (!context->last_buffer || !is_same_buffer) {
+ struct vsg_buf_info *old_last_buffer =
+ context->last_buffer;
+ bool last_buf_with_us = old_last_buffer &&
+ !(old_last_buffer->flags &
+ VSG_BUF_BEING_ENCODED);
+
+ if (old_last_buffer && last_buf_with_us) {
+ vsg_release_input_buffer(context,
+ old_last_buffer);
+ kfree(old_last_buffer);
+ }
+
+ vsg_set_last_buffer(context, buf_info);
+ }
+ }
list_add_tail(&buf_info->node, &context->busy_queue.node);
err_skip_encode:
mutex_unlock(&context->mutex);
-err_encode_fail:
+err_queue_encode_fail:
kfree(work);
}
@@ -139,7 +187,7 @@
mutex_lock(&context->mutex);
- if (context->stopped)
+ if (context->state != VSG_STATE_STARTED)
goto err_locked;
if (list_empty(&context->free_queue.node)
@@ -256,7 +304,7 @@
context->last_buffer = context->regen_buffer = NULL;
context->send_regen_buffer = false;
context->mode = DEFAULT_MODE;
- context->stopped = false;
+ context->state = VSG_STATE_NONE;
mutex_init(&context->mutex);
sd->dev_priv = context;
@@ -287,6 +335,16 @@
}
context = (struct vsg_context *)sd->dev_priv;
+
+ if (context->state == VSG_STATE_STARTED) {
+ WFD_MSG_ERR("VSG not stopped, start not allowed\n");
+ return -EINPROGRESS;
+ } else if (context->state == VSG_STATE_ERROR) {
+ WFD_MSG_ERR("VSG in error state, not allowed to restart\n");
+ return -ENOTRECOVERABLE;
+ }
+
+ context->state = VSG_STATE_STARTED;
mod_timer(&context->threshold_timer, jiffies +
nsecs_to_jiffies(context->max_frame_interval));
return 0;
@@ -304,7 +362,7 @@
context = (struct vsg_context *)sd->dev_priv;
mutex_lock(&context->mutex);
- context->stopped = true;
+ context->state = VSG_STATE_STOPPED;
{ /*delete pending buffers as we're not going to encode them*/
struct list_head *pos, *next;
list_for_each_safe(pos, next, &context->free_queue.node) {
@@ -371,10 +429,10 @@
if (!is_last_buffer && !is_regen_buffer &&
!(temp->flags & VSG_NEVER_RELEASE)) {
vsg_release_input_buffer(context, temp);
+ kfree(temp);
}
list_del(&temp->node);
- kfree(temp);
}
}
@@ -436,27 +494,26 @@
WFD_MSG_DBG("Return frame with paddr %p\n",
(void *)buf_info->mdp_buf_info.paddr);
+ if (!expected_buffer) {
+ WFD_MSG_ERR("Unexpectedly received buffer from enc with "
+ "paddr %p\n", (void *)buf_info->mdp_buf_info.paddr);
+ goto return_ip_buf_bad_buf;
+ }
+
+ expected_buffer->flags &= ~VSG_BUF_BEING_ENCODED;
if (mdp_buf_info_equals(&expected_buffer->mdp_buf_info,
&buf_info->mdp_buf_info)) {
- list_del(&expected_buffer->node);
-
- if (!(expected_buffer->flags & VSG_NEVER_SET_LAST_BUFFER)) {
- bool is_same_buffer = context->last_buffer &&
- mdp_buf_info_equals(
+ bool is_same_buffer = context->last_buffer &&
+ mdp_buf_info_equals(
&context->last_buffer->mdp_buf_info,
&expected_buffer->mdp_buf_info);
- if (!context->last_buffer || !is_same_buffer) {
- struct vsg_buf_info *old_last_buffer =
- context->last_buffer;
- if (context->last_buffer)
- vsg_release_input_buffer(context,
- context->last_buffer);
- vsg_set_last_buffer(context, expected_buffer);
- kfree(old_last_buffer);
- }
- } else
- WFD_MSG_WARN("Couldn't set the last buffer\n");
+ list_del(&expected_buffer->node);
+ if (!is_same_buffer &&
+ !(expected_buffer->flags & VSG_NEVER_RELEASE)) {
+ vsg_release_input_buffer(context, expected_buffer);
+ kfree(expected_buffer);
+ }
} else {
WFD_MSG_ERR("Returned buffer %p is not latest buffer, "
"expected %p\n",
@@ -497,7 +554,7 @@
*regen_buffer = *buf_info;
regen_buffer->flags = VSG_NEVER_RELEASE | VSG_NEVER_SET_LAST_BUFFER;
context->regen_buffer = regen_buffer;
- WFD_MSG_ERR("setting buffer with paddr %p as scratch buffer\n",
+ WFD_MSG_DBG("setting buffer with paddr %p as scratch buffer\n",
(void *)regen_buffer->mdp_buf_info.paddr);
mutex_unlock(&context->mutex);
set_scratch_buf_err_bad_param:
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.h b/drivers/media/video/msm/wfd/vsg-subdev.h
index 1db45e8..826105c 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.h
+++ b/drivers/media/video/msm/wfd/vsg-subdev.h
@@ -26,6 +26,7 @@
enum vsg_flags {
VSG_NEVER_RELEASE = 1<<0,
VSG_NEVER_SET_LAST_BUFFER = 1<<1,
+ VSG_BUF_BEING_ENCODED = 1<<2,
};
enum vsg_modes {
@@ -33,6 +34,13 @@
VSG_MODE_VFR,
};
+enum vsg_states {
+ VSG_STATE_NONE,
+ VSG_STATE_STARTED,
+ VSG_STATE_STOPPED,
+ VSG_STATE_ERROR
+};
+
struct vsg_buf_info {
struct mdp_buf_info mdp_buf_info;
struct timespec time;
@@ -58,7 +66,7 @@
struct vsg_buf_info *last_buffer, *regen_buffer;
bool send_regen_buffer;
int mode;
- bool stopped;
+ int state;
};
struct vsg_work {
@@ -66,6 +74,12 @@
struct work_struct work;
};
+struct vsg_encode_work {
+ struct vsg_buf_info *buf;
+ struct vsg_context *context;
+ struct work_struct work;
+};
+
#define VSG_OPEN _IO(VSG_MAGIC_IOCTL, 1)
#define VSG_CLOSE _IO(VSG_MAGIC_IOCTL, 2)
#define VSG_START _IO(VSG_MAGIC_IOCTL, 3)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 77ac845..54e1b9a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -879,6 +879,16 @@
voltage leaves the accepatable range which then calls a notifier call
chain.
+config WCD9304_CODEC
+ tristate "WCD9304 Codec"
+ select SLIMBUS
+ select MFD_CORE
+ default n
+ help
+ Enables the WCD9304 core driver. The core driver provides
+ read/write capability to registers which are part of the
+ WCD9304 core and gives the ability to use the WCD9304 codec.
+
config WCD9310_CODEC
tristate "WCD9310 Codec"
select SLIMBUS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index c8fcf5f..fd887ea 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -69,7 +69,8 @@
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
-obj-$(CONFIG_WCD9310_CODEC) += wcd9310-core.o wcd9310-irq.o wcd9310-slimslave.o
+obj-$(CONFIG_WCD9310_CODEC) += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+obj-$(CONFIG_WCD9304_CODEC) += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
ifeq ($(CONFIG_SA1100_ASSABET),y)
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index 8049975..66b98a1 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -754,6 +754,11 @@
}
if (version != PM8XXX_VERSION_8917) {
+ if (pdata->pwm_pdata) {
+ pwm_cell.platform_data = pdata->pwm_pdata;
+ pwm_cell.pdata_size =
+ sizeof(struct pm8xxx_pwm_platform_data);
+ }
ret = mfd_add_devices(pmic->dev, 0, &pwm_cell, 1, NULL, 0);
if (ret) {
pr_err("Failed to add pwm subdevice ret=%d\n", ret);
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 05f02c4..022cfb6 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -64,6 +64,7 @@
#define SSBI_REG_ADDR_LPG_BANK_EN 0x144
#define SSBI_REG_ADDR_LPG_LUT_CFG0 0x145
#define SSBI_REG_ADDR_LPG_LUT_CFG1 0x146
+#define SSBI_REG_ADDR_LPG_TEST 0x147
/* LPG Control 0 */
#define PM8XXX_PWM_1KHZ_COUNT_MASK 0xF0
@@ -137,6 +138,10 @@
/* LPG LUT_CFG1 */
#define PM8XXX_PWM_LUT_READ 0x40
+/* TEST */
+#define PM8XXX_PWM_DTEST_MASK 0x38
+#define PM8XXX_PWM_DTEST_SHIFT 3
+#define PM8XXX_PWM_DTEST_BANK_MASK 0x07
/*
* PWM Frequency = Clock Frequency / (N * T)
@@ -200,6 +205,7 @@
int irq;
struct pm8xxx_pwm_chip *chip;
int bypass_lut;
+ int dtest_mode_supported;
};
struct pm8xxx_pwm_chip {
@@ -638,6 +644,28 @@
return rc;
}
+static int pm8xxx_pwm_set_dtest(struct pwm_device *pwm, int enable)
+{
+ int rc;
+ u8 reg;
+
+ reg = pwm->pwm_id & PM8XXX_PWM_DTEST_BANK_MASK;
+
+ if (enable) {
+ /* Observe LPG_OUT on DTEST1*/
+ reg |= (1 << PM8XXX_PWM_DTEST_SHIFT) &
+ PM8XXX_PWM_DTEST_MASK;
+ }
+
+ rc = pm8xxx_writeb(pwm->chip->dev->parent,
+ SSBI_REG_ADDR_LPG_TEST, reg);
+ if (rc)
+ pr_err("pm8xxx_write(DTEST=0x%x) failed: rc=%d\n",
+ reg, rc);
+
+ return rc;
+}
+
/* APIs */
/**
* pwm_request - request a PWM device
@@ -785,6 +813,8 @@
rc = -EINVAL;
} else {
if (pwm_chip->is_lpg_supported) {
+ if (pwm->dtest_mode_supported)
+ pm8xxx_pwm_set_dtest(pwm, 1);
rc = pm8xxx_pwm_bank_enable(pwm, 1);
pm8xxx_pwm_bank_sel(pwm);
pm8xxx_pwm_start(pwm, 1, 0);
@@ -811,6 +841,8 @@
mutex_lock(&pwm->chip->pwm_mutex);
if (pwm->in_use) {
if (pwm_chip->is_lpg_supported) {
+ if (pwm->dtest_mode_supported)
+ pm8xxx_pwm_set_dtest(pwm, 0);
pm8xxx_pwm_bank_sel(pwm);
pm8xxx_pwm_start(pwm, 0, 0);
pm8xxx_pwm_bank_enable(pwm, 0);
@@ -1030,11 +1062,17 @@
mutex_lock(&pwm->chip->pwm_mutex);
if (start) {
+ if (pwm->dtest_mode_supported)
+ pm8xxx_pwm_set_dtest(pwm, 1);
+
pm8xxx_pwm_bank_enable(pwm, 1);
pm8xxx_pwm_bank_sel(pwm);
pm8xxx_pwm_start(pwm, 1, 1);
} else {
+ if (pwm->dtest_mode_supported)
+ pm8xxx_pwm_set_dtest(pwm, 0);
+
pm8xxx_pwm_bank_sel(pwm);
pm8xxx_pwm_start(pwm, 0, 0);
@@ -1324,8 +1362,9 @@
static int __devinit pm8xxx_pwm_probe(struct platform_device *pdev)
{
+ const struct pm8xxx_pwm_platform_data *pdata = pdev->dev.platform_data;
struct pm8xxx_pwm_chip *chip;
- int i;
+ int i, dtest_channel;
enum pm8xxx_version version;
chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -1334,6 +1373,11 @@
return -ENOMEM;
}
+ if (pdata != NULL)
+ dtest_channel = pdata->dtest_channel;
+ else
+ dtest_channel = -1;
+
mutex_init(&chip->pwm_mutex);
chip->dev = &pdev->dev;
@@ -1374,6 +1418,8 @@
for (i = 0; i < chip->pwm_channels; i++) {
chip->pwm_dev[i].pwm_id = i;
chip->pwm_dev[i].chip = chip;
+ if (i == dtest_channel)
+ chip->pwm_dev[i].dtest_mode_supported = 1;
}
platform_set_drvdata(pdev, chip);
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
deleted file mode 100644
index d1d9132..0000000
--- a/drivers/mfd/wcd9310-core.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/wcd9310/pdata.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/regulator/consumer.h>
-#include <linux/i2c.h>
-#include <sound/soc.h>
-
-#define TABLA_SLIM_GLA_MAX_RETRIES 5
-#define TABLA_REGISTER_START_OFFSET 0x800
-#define TABLA_SLIM_RW_MAX_TRIES 3
-
-#define MAX_TABLA_DEVICE 4
-#define TABLA_I2C_MODE 0x03
-
-struct tabla_i2c {
- struct i2c_client *client;
- struct i2c_msg xfer_msg[2];
- struct mutex xfer_lock;
- int mod_id;
-};
-
-struct tabla_i2c tabla_modules[MAX_TABLA_DEVICE];
-static int tabla_intf;
-
-static int tabla_read(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface_reg)
-{
- int ret;
- u8 *buf = dest;
-
- if (bytes <= 0) {
- dev_err(tabla->dev, "Invalid byte read length %d\n", bytes);
- return -EINVAL;
- }
-
- ret = tabla->read_dev(tabla, reg, bytes, dest, interface_reg);
- if (ret < 0) {
- dev_err(tabla->dev, "Tabla read failed\n");
- return ret;
- } else
- dev_dbg(tabla->dev, "Read 0x%02x from R%d(0x%x)\n",
- *buf, reg, reg);
-
- return 0;
-}
-int tabla_reg_read(struct tabla *tabla, unsigned short reg)
-{
- u8 val;
- int ret;
-
- mutex_lock(&tabla->io_lock);
- ret = tabla_read(tabla, reg, 1, &val, false);
- mutex_unlock(&tabla->io_lock);
-
- if (ret < 0)
- return ret;
- else
- return val;
-}
-EXPORT_SYMBOL_GPL(tabla_reg_read);
-
-static int tabla_write(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface_reg)
-{
- u8 *buf = src;
-
- if (bytes <= 0) {
- pr_err("%s: Error, invalid write length\n", __func__);
- return -EINVAL;
- }
-
- dev_dbg(tabla->dev, "Write %02x to R%d(0x%x)\n",
- *buf, reg, reg);
-
- return tabla->write_dev(tabla, reg, bytes, src, interface_reg);
-}
-
-int tabla_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val)
-{
- int ret;
-
- mutex_lock(&tabla->io_lock);
- ret = tabla_write(tabla, reg, 1, &val, false);
- mutex_unlock(&tabla->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_reg_write);
-
-static u8 tabla_pgd_la;
-static u8 tabla_inf_la;
-
-int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la)
-{
- *pgd_la = tabla_pgd_la;
- *inf_la = tabla_inf_la;
- return 0;
-
-}
-EXPORT_SYMBOL_GPL(tabla_get_logical_addresses);
-
-int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg)
-{
- u8 val;
- int ret;
-
- mutex_lock(&tabla->io_lock);
- ret = tabla_read(tabla, reg, 1, &val, true);
- mutex_unlock(&tabla->io_lock);
-
- if (ret < 0)
- return ret;
- else
- return val;
-}
-EXPORT_SYMBOL_GPL(tabla_interface_reg_read);
-
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val)
-{
- int ret;
-
- mutex_lock(&tabla->io_lock);
- ret = tabla_write(tabla, reg, 1, &val, true);
- mutex_unlock(&tabla->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_interface_reg_write);
-
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf)
-{
- int ret;
-
- mutex_lock(&tabla->io_lock);
-
- ret = tabla_read(tabla, reg, count, buf, false);
-
- mutex_unlock(&tabla->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_bulk_read);
-
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf)
-{
- int ret;
-
- mutex_lock(&tabla->io_lock);
-
- ret = tabla_write(tabla, reg, count, buf, false);
-
- mutex_unlock(&tabla->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(tabla_bulk_write);
-
-static int tabla_slim_read_device(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface)
-{
- int ret;
- struct slim_ele_access msg;
- int slim_read_tries = TABLA_SLIM_RW_MAX_TRIES;
- msg.start_offset = TABLA_REGISTER_START_OFFSET + reg;
- msg.num_bytes = bytes;
- msg.comp = NULL;
-
- while (1) {
- mutex_lock(&tabla->xfer_lock);
- ret = slim_request_val_element(interface ?
- tabla->slim_slave : tabla->slim,
- &msg, dest, bytes);
- mutex_unlock(&tabla->xfer_lock);
- if (likely(ret == 0) || (--slim_read_tries == 0))
- break;
- usleep_range(5000, 5000);
- }
-
- if (ret)
- pr_err("%s: Error, Tabla read failed (%d)\n", __func__, ret);
-
- return ret;
-}
-/* Interface specifies whether the write is to the interface or general
- * registers.
- */
-static int tabla_slim_write_device(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface)
-{
- int ret;
- struct slim_ele_access msg;
- int slim_write_tries = TABLA_SLIM_RW_MAX_TRIES;
- msg.start_offset = TABLA_REGISTER_START_OFFSET + reg;
- msg.num_bytes = bytes;
- msg.comp = NULL;
-
- while (1) {
- mutex_lock(&tabla->xfer_lock);
- ret = slim_change_val_element(interface ?
- tabla->slim_slave : tabla->slim,
- &msg, src, bytes);
- mutex_unlock(&tabla->xfer_lock);
- if (likely(ret == 0) || (--slim_write_tries == 0))
- break;
- usleep_range(5000, 5000);
- }
-
- if (ret)
- pr_err("%s: Error, Tabla write failed (%d)\n", __func__, ret);
-
- return ret;
-}
-
-static struct mfd_cell tabla_devs[] = {
- {
- .name = "tabla_codec",
- },
-};
-
-static struct mfd_cell tabla1x_devs[] = {
- {
- .name = "tabla1x_codec",
- },
-};
-
-static void tabla_bring_up(struct tabla *tabla)
-{
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x4);
- tabla_reg_write(tabla, TABLA_A_CDC_CTL, 0);
- usleep_range(5000, 5000);
- tabla_reg_write(tabla, TABLA_A_CDC_CTL, 3);
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 3);
-}
-
-static void tabla_bring_down(struct tabla *tabla)
-{
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x7);
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x6);
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0xe);
- tabla_reg_write(tabla, TABLA_A_LEAKAGE_CTL, 0x8);
-}
-
-static int tabla_reset(struct tabla *tabla)
-{
- int ret;
-
- if (tabla->reset_gpio) {
- ret = gpio_request(tabla->reset_gpio, "CDC_RESET");
- if (ret) {
- pr_err("%s: Failed to request gpio %d\n", __func__,
- tabla->reset_gpio);
- tabla->reset_gpio = 0;
- return ret;
- }
-
- gpio_direction_output(tabla->reset_gpio, 1);
- msleep(20);
- gpio_direction_output(tabla->reset_gpio, 0);
- msleep(20);
- gpio_direction_output(tabla->reset_gpio, 1);
- msleep(20);
- }
- return 0;
-}
-
-static void tabla_free_reset(struct tabla *tabla)
-{
- if (tabla->reset_gpio) {
- gpio_free(tabla->reset_gpio);
- tabla->reset_gpio = 0;
- }
-}
-
-struct tabla_regulator {
- const char *name;
- int min_uV;
- int max_uV;
- int optimum_uA;
- struct regulator *regulator;
-};
-
-
-/*
- * format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
- *
- * <POWER_SUPPLY_PIN_NAME> from Tabla objective spec
-*/
-
-#define TABLA_CDC_VDDA_CP_CUR_MAX 500000
-#define TABLA_CDC_VDDA_RX_CUR_MAX 20000
-#define TABLA_CDC_VDDA_TX_CUR_MAX 20000
-#define TABLA_VDDIO_CDC_CUR_MAX 5000
-
-#define TABLA_VDDD_CDC_D_CUR_MAX 5000
-#define TABLA_VDDD_CDC_A_CUR_MAX 5000
-
-static struct tabla_regulator tabla_regulators[] = {
- {
- .name = "CDC_VDD_CP",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .optimum_uA = TABLA_CDC_VDDA_CP_CUR_MAX,
- },
- {
- .name = "CDC_VDDA_RX",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .optimum_uA = TABLA_CDC_VDDA_RX_CUR_MAX,
- },
- {
- .name = "CDC_VDDA_TX",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .optimum_uA = TABLA_CDC_VDDA_TX_CUR_MAX,
- },
- {
- .name = "VDDIO_CDC",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .optimum_uA = TABLA_VDDIO_CDC_CUR_MAX,
- },
- {
- .name = "VDDD_CDC_D",
- .min_uV = 1225000,
- .max_uV = 1225000,
- .optimum_uA = TABLA_VDDD_CDC_D_CUR_MAX,
- },
- {
- .name = "CDC_VDDA_A_1P2V",
- .min_uV = 1225000,
- .max_uV = 1225000,
- .optimum_uA = TABLA_VDDD_CDC_A_CUR_MAX,
- },
-};
-
-static int tabla_device_init(struct tabla *tabla, int irq)
-{
- int ret;
- struct mfd_cell *tabla_dev;
- int tabla_dev_size;
-
- mutex_init(&tabla->io_lock);
- mutex_init(&tabla->xfer_lock);
-
- mutex_init(&tabla->pm_lock);
- tabla->wlock_holders = 0;
- tabla->pm_state = TABLA_PM_SLEEPABLE;
- init_waitqueue_head(&tabla->pm_wq);
- wake_lock_init(&tabla->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
-
- dev_set_drvdata(tabla->dev, tabla);
-
- tabla_bring_up(tabla);
-
- ret = tabla_irq_init(tabla);
- if (ret) {
- pr_err("IRQ initialization failed\n");
- goto err;
- }
- tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
- pr_info("%s : Tabla version %u initialized\n",
- __func__, tabla->version);
-
- if (TABLA_IS_1_X(tabla->version)) {
- tabla_dev = tabla1x_devs;
- tabla_dev_size = ARRAY_SIZE(tabla1x_devs);
- } else {
- tabla_dev = tabla_devs;
- tabla_dev_size = ARRAY_SIZE(tabla_devs);
- }
- ret = mfd_add_devices(tabla->dev, -1,
- tabla_dev, tabla_dev_size,
- NULL, 0);
- if (ret != 0) {
- dev_err(tabla->dev, "Failed to add children: %d\n", ret);
- goto err_irq;
- }
-
- tabla->version = tabla_reg_read(tabla, TABLA_A_CHIP_VERSION) & 0x1F;
- pr_info("%s : Tabla version %u initialized\n",
- __func__, tabla->version);
-
- return ret;
-err_irq:
- tabla_irq_exit(tabla);
-err:
- tabla_bring_down(tabla);
- wake_lock_destroy(&tabla->wlock);
- mutex_destroy(&tabla->pm_lock);
- mutex_destroy(&tabla->io_lock);
- mutex_destroy(&tabla->xfer_lock);
- return ret;
-}
-
-static void tabla_device_exit(struct tabla *tabla)
-{
- tabla_irq_exit(tabla);
- tabla_bring_down(tabla);
- tabla_free_reset(tabla);
- mutex_destroy(&tabla->pm_lock);
- wake_lock_destroy(&tabla->wlock);
- mutex_destroy(&tabla->io_lock);
- mutex_destroy(&tabla->xfer_lock);
-}
-
-
-#ifdef CONFIG_DEBUG_FS
-struct tabla *debugTabla;
-
-static struct dentry *debugfs_tabla_dent;
-static struct dentry *debugfs_peek;
-static struct dentry *debugfs_poke;
-
-static unsigned char read_data;
-
-static int codec_debug_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static int get_parameters(char *buf, long int *param1, int num_of_par)
-{
- char *token;
- int base, cnt;
-
- token = strsep(&buf, " ");
-
- for (cnt = 0; cnt < num_of_par; cnt++) {
- if (token != NULL) {
- if ((token[1] == 'x') || (token[1] == 'X'))
- base = 16;
- else
- base = 10;
-
- if (strict_strtoul(token, base, ¶m1[cnt]) != 0)
- return -EINVAL;
-
- token = strsep(&buf, " ");
- } else
- return -EINVAL;
- }
- return 0;
-}
-
-static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- char lbuf[8];
-
- snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
- return simple_read_from_buffer(ubuf, count, ppos, lbuf,
- strnlen(lbuf, 7));
-}
-
-
-static ssize_t codec_debug_write(struct file *filp,
- const char __user *ubuf, size_t cnt, loff_t *ppos)
-{
- char *access_str = filp->private_data;
- char lbuf[32];
- int rc;
- long int param[5];
-
- if (cnt > sizeof(lbuf) - 1)
- return -EINVAL;
-
- rc = copy_from_user(lbuf, ubuf, cnt);
- if (rc)
- return -EFAULT;
-
- lbuf[cnt] = '\0';
-
- if (!strncmp(access_str, "poke", 6)) {
- /* write */
- rc = get_parameters(lbuf, param, 2);
- if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
- (rc == 0))
- tabla_interface_reg_write(debugTabla, param[0],
- param[1]);
- else
- rc = -EINVAL;
- } else if (!strncmp(access_str, "peek", 6)) {
- /* read */
- rc = get_parameters(lbuf, param, 1);
- if ((param[0] <= 0x3FF) && (rc == 0))
- read_data = tabla_interface_reg_read(debugTabla,
- param[0]);
- else
- rc = -EINVAL;
- }
-
- if (rc == 0)
- rc = cnt;
- else
- pr_err("%s: rc = %d\n", __func__, rc);
-
- return rc;
-}
-
-static const struct file_operations codec_debug_ops = {
- .open = codec_debug_open,
- .write = codec_debug_write,
- .read = codec_debug_read
-};
-#endif
-
-static int tabla_enable_supplies(struct tabla *tabla)
-{
- int ret;
- int i;
-
- tabla->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
- ARRAY_SIZE(tabla_regulators),
- GFP_KERNEL);
- if (!tabla->supplies) {
- ret = -ENOMEM;
- goto err;
- }
-
- for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++)
- tabla->supplies[i].supply = tabla_regulators[i].name;
-
- ret = regulator_bulk_get(tabla->dev, ARRAY_SIZE(tabla_regulators),
- tabla->supplies);
- if (ret != 0) {
- dev_err(tabla->dev, "Failed to get supplies: err = %d\n", ret);
- goto err_supplies;
- }
-
- for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
- ret = regulator_set_voltage(tabla->supplies[i].consumer,
- tabla_regulators[i].min_uV, tabla_regulators[i].max_uV);
- if (ret) {
- pr_err("%s: Setting regulator voltage failed for "
- "regulator %s err = %d\n", __func__,
- tabla->supplies[i].supply, ret);
- goto err_get;
- }
-
- ret = regulator_set_optimum_mode(tabla->supplies[i].consumer,
- tabla_regulators[i].optimum_uA);
- if (ret < 0) {
- pr_err("%s: Setting regulator optimum mode failed for "
- "regulator %s err = %d\n", __func__,
- tabla->supplies[i].supply, ret);
- goto err_get;
- }
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(tabla_regulators),
- tabla->supplies);
- if (ret != 0) {
- dev_err(tabla->dev, "Failed to enable supplies: err = %d\n",
- ret);
- goto err_configure;
- }
- return ret;
-
-err_configure:
- for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
- regulator_set_voltage(tabla->supplies[i].consumer, 0,
- tabla_regulators[i].max_uV);
- regulator_set_optimum_mode(tabla->supplies[i].consumer, 0);
- }
-err_get:
- regulator_bulk_free(ARRAY_SIZE(tabla_regulators), tabla->supplies);
-err_supplies:
- kfree(tabla->supplies);
-err:
- return ret;
-}
-
-static void tabla_disable_supplies(struct tabla *tabla)
-{
- int i;
-
- regulator_bulk_disable(ARRAY_SIZE(tabla_regulators),
- tabla->supplies);
- for (i = 0; i < ARRAY_SIZE(tabla_regulators); i++) {
- regulator_set_voltage(tabla->supplies[i].consumer, 0,
- tabla_regulators[i].max_uV);
- regulator_set_optimum_mode(tabla->supplies[i].consumer, 0);
- }
- regulator_bulk_free(ARRAY_SIZE(tabla_regulators), tabla->supplies);
- kfree(tabla->supplies);
-}
-
-int tabla_get_intf_type(void)
-{
- return tabla_intf;
-}
-EXPORT_SYMBOL_GPL(tabla_get_intf_type);
-
-struct tabla_i2c *get_i2c_tabla_device_info(u16 reg)
-{
- u16 mask = 0x0f00;
- int value = 0;
- struct tabla_i2c *tabla = NULL;
- value = ((reg & mask) >> 8) & 0x000f;
- switch (value) {
- case 0:
- tabla = &tabla_modules[0];
- break;
- case 1:
- tabla = &tabla_modules[1];
- break;
- case 2:
- tabla = &tabla_modules[2];
- break;
- case 3:
- tabla = &tabla_modules[3];
- break;
- default:
- break;
- }
- return tabla;
-}
-
-int tabla_i2c_write_device(u16 reg, u8 *value,
- u32 bytes)
-{
-
- struct i2c_msg *msg;
- int ret = 0;
- u8 reg_addr = 0;
- u8 data[bytes + 1];
- struct tabla_i2c *tabla;
-
- tabla = get_i2c_tabla_device_info(reg);
- if (tabla == NULL || tabla->client == NULL) {
- pr_err("failed to get device info\n");
- return -ENODEV;
- }
- reg_addr = (u8)reg;
- msg = &tabla->xfer_msg[0];
- msg->addr = tabla->client->addr;
- msg->len = bytes + 1;
- msg->flags = 0;
- data[0] = reg;
- data[1] = *value;
- msg->buf = data;
- ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 1);
- /* Try again if the write fails */
- if (ret != 1) {
- ret = i2c_transfer(tabla->client->adapter,
- tabla->xfer_msg, 1);
- if (ret != 1) {
- pr_err("failed to write the device\n");
- return ret;
- }
- }
- pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
- return 0;
-}
-
-
-int tabla_i2c_read_device(unsigned short reg,
- int bytes, unsigned char *dest)
-{
- struct i2c_msg *msg;
- int ret = 0;
- u8 reg_addr = 0;
- struct tabla_i2c *tabla;
- u8 i = 0;
-
- tabla = get_i2c_tabla_device_info(reg);
- if (tabla == NULL || tabla->client == NULL) {
- pr_err("failed to get device info\n");
- return -ENODEV;
- }
- for (i = 0; i < bytes; i++) {
- reg_addr = (u8)reg++;
- msg = &tabla->xfer_msg[0];
- msg->addr = tabla->client->addr;
- msg->len = 1;
- msg->flags = 0;
- msg->buf = ®_addr;
-
- msg = &tabla->xfer_msg[1];
- msg->addr = tabla->client->addr;
- msg->len = 1;
- msg->flags = I2C_M_RD;
- msg->buf = dest++;
- ret = i2c_transfer(tabla->client->adapter, tabla->xfer_msg, 2);
-
- /* Try again if read fails first time */
- if (ret != 2) {
- ret = i2c_transfer(tabla->client->adapter,
- tabla->xfer_msg, 2);
- if (ret != 2) {
- pr_err("failed to read tabla register\n");
- return ret;
- }
- }
- }
- return 0;
-}
-
-int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface_reg)
-{
- return tabla_i2c_read_device(reg, bytes, dest);
-}
-
-int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface_reg)
-{
- return tabla_i2c_write_device(reg, src, bytes);
-}
-
-static int __devinit tabla_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct tabla *tabla;
- struct tabla_pdata *pdata = client->dev.platform_data;
- int val = 0;
- int ret = 0;
- static int device_id;
-
- if (device_id > 0) {
- tabla_modules[device_id++].client = client;
- pr_info("probe for other slaves devices of tabla\n");
- return ret;
- }
-
- tabla = kzalloc(sizeof(struct tabla), GFP_KERNEL);
- if (tabla == NULL) {
- pr_err("%s: error, allocation failed\n", __func__);
- ret = -ENOMEM;
- goto fail;
- }
-
- if (!pdata) {
- dev_dbg(&client->dev, "no platform data?\n");
- ret = -EINVAL;
- goto err_tabla;
- }
- if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
- dev_dbg(&client->dev, "can't talk I2C?\n");
- ret = -EIO;
- goto err_tabla;
- }
- tabla->dev = &client->dev;
- tabla->reset_gpio = pdata->reset_gpio;
-
- ret = tabla_enable_supplies(tabla);
- if (ret) {
- pr_err("%s: Fail to enable Tabla supplies\n", __func__);
- goto err_tabla;
- }
-
- usleep_range(5, 5);
- ret = tabla_reset(tabla);
- if (ret) {
- pr_err("%s: Resetting Tabla failed\n", __func__);
- goto err_supplies;
- }
- tabla_modules[device_id++].client = client;
-
- tabla->read_dev = tabla_i2c_read;
- tabla->write_dev = tabla_i2c_write;
- tabla->irq = pdata->irq;
- tabla->irq_base = pdata->irq_base;
-
- /*read the tabla status before initializing the device type*/
- ret = tabla_read(tabla, TABLA_A_CHIP_STATUS, 1, &val, 0);
- if ((ret < 0) || (val != TABLA_I2C_MODE)) {
- pr_err("failed to read the tabla status\n");
- goto err_device_init;
- }
-
- ret = tabla_device_init(tabla, tabla->irq);
- if (ret) {
- pr_err("%s: error, initializing device failed\n", __func__);
- goto err_device_init;
- }
- tabla_intf = TABLA_INTERFACE_TYPE_I2C;
-
- return ret;
-err_device_init:
- tabla_free_reset(tabla);
-err_supplies:
- tabla_disable_supplies(tabla);
-err_tabla:
- kfree(tabla);
-fail:
- return ret;
-}
-
-static int __devexit tabla_i2c_remove(struct i2c_client *client)
-{
- struct tabla *tabla;
-
- pr_debug("exit\n");
- tabla = dev_get_drvdata(&client->dev);
- tabla_device_exit(tabla);
- tabla_disable_supplies(tabla);
- kfree(tabla);
- return 0;
-}
-
-static int tabla_slim_probe(struct slim_device *slim)
-{
- struct tabla *tabla;
- struct tabla_pdata *pdata;
- int ret = 0;
- int sgla_retry_cnt;
-
- dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
- pdata = slim->dev.platform_data;
-
- if (!pdata) {
- dev_err(&slim->dev, "Error, no platform data\n");
- ret = -EINVAL;
- goto err;
- }
-
- tabla = kzalloc(sizeof(struct tabla), GFP_KERNEL);
- if (tabla == NULL) {
- pr_err("%s: error, allocation failed\n", __func__);
- ret = -ENOMEM;
- goto err;
- }
- if (!slim->ctrl) {
- pr_err("Error, no SLIMBUS control data\n");
- ret = -EINVAL;
- goto err_tabla;
- }
- tabla->slim = slim;
- slim_set_clientdata(slim, tabla);
- tabla->reset_gpio = pdata->reset_gpio;
- tabla->dev = &slim->dev;
-
- ret = tabla_enable_supplies(tabla);
- if (ret) {
- pr_err("%s: Fail to enable Tabla supplies\n", __func__);
- goto err_tabla;
- }
- usleep_range(5, 5);
-
- ret = tabla_reset(tabla);
- if (ret) {
- pr_err("%s: Resetting Tabla failed\n", __func__);
- goto err_supplies;
- }
-
- ret = slim_get_logical_addr(tabla->slim, tabla->slim->e_addr,
- ARRAY_SIZE(tabla->slim->e_addr), &tabla->slim->laddr);
- if (ret) {
- pr_err("fail to get slimbus logical address %d\n", ret);
- goto err_reset;
- }
- tabla->read_dev = tabla_slim_read_device;
- tabla->write_dev = tabla_slim_write_device;
- tabla->irq = pdata->irq;
- tabla->irq_base = pdata->irq_base;
- tabla_pgd_la = tabla->slim->laddr;
-
- if (pdata->num_irqs < TABLA_NUM_IRQS) {
- pr_err("%s: Error, not enough interrupt lines allocated\n",
- __func__);
- goto err_reset;
- }
-
- tabla->slim_slave = &pdata->slimbus_slave_device;
-
- ret = slim_add_device(slim->ctrl, tabla->slim_slave);
- if (ret) {
- pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
- goto err_reset;
- }
-
- sgla_retry_cnt = 0;
-
- while (1) {
- ret = slim_get_logical_addr(tabla->slim_slave,
- tabla->slim_slave->e_addr,
- ARRAY_SIZE(tabla->slim_slave->e_addr),
- &tabla->slim_slave->laddr);
- if (ret) {
- if (sgla_retry_cnt++ < TABLA_SLIM_GLA_MAX_RETRIES) {
- /* Give SLIMBUS slave time to report present
- and be ready.
- */
- usleep_range(1000, 1000);
- pr_debug("%s: retry slim_get_logical_addr()\n",
- __func__);
- continue;
- }
- pr_err("fail to get slimbus slave logical address"
- " %d\n", ret);
- goto err_slim_add;
- }
- break;
- }
- tabla_inf_la = tabla->slim_slave->laddr;
- tabla_intf = TABLA_INTERFACE_TYPE_SLIMBUS;
-
- ret = tabla_device_init(tabla, tabla->irq);
- if (ret) {
- pr_err("%s: error, initializing device failed\n", __func__);
- goto err_slim_add;
- }
- tabla_init_slimslave(tabla, tabla_pgd_la);
-#ifdef CONFIG_DEBUG_FS
- debugTabla = tabla;
-
- debugfs_tabla_dent = debugfs_create_dir
- ("wcd9310_slimbus_interface_device", 0);
- if (!IS_ERR(debugfs_tabla_dent)) {
- debugfs_peek = debugfs_create_file("peek",
- S_IFREG | S_IRUGO, debugfs_tabla_dent,
- (void *) "peek", &codec_debug_ops);
-
- debugfs_poke = debugfs_create_file("poke",
- S_IFREG | S_IRUGO, debugfs_tabla_dent,
- (void *) "poke", &codec_debug_ops);
- }
-#endif
-
- return ret;
-
-err_slim_add:
- slim_remove_device(tabla->slim_slave);
-err_reset:
- tabla_free_reset(tabla);
-err_supplies:
- tabla_disable_supplies(tabla);
-err_tabla:
- kfree(tabla);
-err:
- return ret;
-}
-
-static int tabla_slim_remove(struct slim_device *pdev)
-{
- struct tabla *tabla;
-
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove(debugfs_peek);
- debugfs_remove(debugfs_poke);
- debugfs_remove(debugfs_tabla_dent);
-#endif
-
- tabla = slim_get_devicedata(pdev);
- tabla_deinit_slimslave(tabla);
- tabla_disable_supplies(tabla);
- slim_remove_device(tabla->slim_slave);
- tabla_device_exit(tabla);
- return 0;
-}
-
-static int tabla_resume(struct tabla *tabla)
-{
- int ret = 0;
-
- pr_debug("%s: enter\n", __func__);
- mutex_lock(&tabla->pm_lock);
- if (tabla->pm_state == TABLA_PM_ASLEEP) {
- pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
- tabla->pm_state, tabla->wlock_holders);
- tabla->pm_state = TABLA_PM_SLEEPABLE;
- } else {
- pr_warn("%s: system is already awake, state %d wlock %d\n",
- __func__, tabla->pm_state, tabla->wlock_holders);
- }
- mutex_unlock(&tabla->pm_lock);
- wake_up_all(&tabla->pm_wq);
-
- return ret;
-}
-
-static int tabla_slim_resume(struct slim_device *sldev)
-{
- struct tabla *tabla = slim_get_devicedata(sldev);
- return tabla_resume(tabla);
-}
-
-static int tabla_i2c_resume(struct i2c_client *i2cdev)
-{
- struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
- return tabla_resume(tabla);
-}
-
-static int tabla_suspend(struct tabla *tabla, pm_message_t pmesg)
-{
- int ret = 0;
-
- pr_debug("%s: enter\n", __func__);
- /* wake_lock() can be called after this suspend chain call started.
- * thus suspend can be called while wlock is being held */
- mutex_lock(&tabla->pm_lock);
- if (tabla->pm_state == TABLA_PM_SLEEPABLE) {
- pr_debug("%s: suspending system, state %d, wlock %d\n",
- __func__, tabla->pm_state, tabla->wlock_holders);
- tabla->pm_state = TABLA_PM_ASLEEP;
- } else if (tabla->pm_state == TABLA_PM_AWAKE) {
- /* unlock to wait for pm_state == TABLA_PM_SLEEPABLE
- * then set to TABLA_PM_ASLEEP */
- pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
- __func__, tabla->pm_state, tabla->wlock_holders);
- mutex_unlock(&tabla->pm_lock);
- if (!(wait_event_timeout(tabla->pm_wq,
- tabla_pm_cmpxchg(tabla,
- TABLA_PM_SLEEPABLE,
- TABLA_PM_ASLEEP) ==
- TABLA_PM_SLEEPABLE,
- HZ))) {
- pr_debug("%s: suspend failed state %d, wlock %d\n",
- __func__, tabla->pm_state,
- tabla->wlock_holders);
- ret = -EBUSY;
- } else {
- pr_debug("%s: done, state %d, wlock %d\n", __func__,
- tabla->pm_state, tabla->wlock_holders);
- }
- mutex_lock(&tabla->pm_lock);
- } else if (tabla->pm_state == TABLA_PM_ASLEEP) {
- pr_warn("%s: system is already suspended, state %d, wlock %dn",
- __func__, tabla->pm_state, tabla->wlock_holders);
- }
- mutex_unlock(&tabla->pm_lock);
-
- return ret;
-}
-
-static int tabla_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
-{
- struct tabla *tabla = slim_get_devicedata(sldev);
- return tabla_suspend(tabla, pmesg);
-}
-
-static int tabla_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
-{
- struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
- return tabla_suspend(tabla, pmesg);
-}
-
-static const struct slim_device_id slimtest_id[] = {
- {"tabla-slim", 0},
- {}
-};
-
-static struct slim_driver tabla_slim_driver = {
- .driver = {
- .name = "tabla-slim",
- .owner = THIS_MODULE,
- },
- .probe = tabla_slim_probe,
- .remove = tabla_slim_remove,
- .id_table = slimtest_id,
- .resume = tabla_slim_resume,
- .suspend = tabla_slim_suspend,
-};
-
-static const struct slim_device_id slimtest2x_id[] = {
- {"tabla2x-slim", 0},
- {}
-};
-
-static struct slim_driver tabla2x_slim_driver = {
- .driver = {
- .name = "tabla2x-slim",
- .owner = THIS_MODULE,
- },
- .probe = tabla_slim_probe,
- .remove = tabla_slim_remove,
- .id_table = slimtest2x_id,
- .resume = tabla_slim_resume,
- .suspend = tabla_slim_suspend,
-};
-
-#define TABLA_I2C_TOP_LEVEL 0
-#define TABLA_I2C_ANALOG 1
-#define TABLA_I2C_DIGITAL_1 2
-#define TABLA_I2C_DIGITAL_2 3
-
-static struct i2c_device_id tabla_id_table[] = {
- {"tabla top level", TABLA_I2C_TOP_LEVEL},
- {"tabla analog", TABLA_I2C_TOP_LEVEL},
- {"tabla digital1", TABLA_I2C_TOP_LEVEL},
- {"tabla digital2", TABLA_I2C_TOP_LEVEL},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, tabla_id_table);
-
-static struct i2c_driver tabla_i2c_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "tabla-i2c-core",
- },
- .id_table = tabla_id_table,
- .probe = tabla_i2c_probe,
- .remove = __devexit_p(tabla_i2c_remove),
- .resume = tabla_i2c_resume,
- .suspend = tabla_i2c_suspend,
-};
-
-static int __init tabla_init(void)
-{
- int ret1, ret2, ret3;
-
- ret1 = slim_driver_register(&tabla_slim_driver);
- if (ret1 != 0)
- pr_err("Failed to register tabla SB driver: %d\n", ret1);
-
- ret2 = slim_driver_register(&tabla2x_slim_driver);
- if (ret2 != 0)
- pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
-
- ret3 = i2c_add_driver(&tabla_i2c_driver);
- if (ret3 != 0)
- pr_err("failed to add the I2C driver\n");
-
- return (ret1 && ret2 && ret3) ? -1 : 0;
-}
-module_init(tabla_init);
-
-static void __exit tabla_exit(void)
-{
-}
-module_exit(tabla_exit);
-
-MODULE_DESCRIPTION("Tabla core driver");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
deleted file mode 100644
index c6a9c23..0000000
--- a/drivers/mfd/wcd9310-irq.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/irq.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/interrupt.h>
-
-#define BYTE_BIT_MASK(nr) (1UL << ((nr) % BITS_PER_BYTE))
-#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
-
-struct tabla_irq {
- bool level;
-};
-
-static struct tabla_irq tabla_irqs[TABLA_NUM_IRQS] = {
- [0] = { .level = 1},
-/* All other tabla interrupts are edge triggered */
-};
-
-static inline int irq_to_tabla_irq(struct tabla *tabla, int irq)
-{
- return irq - tabla->irq_base;
-}
-
-static void tabla_irq_lock(struct irq_data *data)
-{
- struct tabla *tabla = irq_data_get_irq_chip_data(data);
- mutex_lock(&tabla->irq_lock);
-}
-
-static void tabla_irq_sync_unlock(struct irq_data *data)
-{
- struct tabla *tabla = irq_data_get_irq_chip_data(data);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(tabla->irq_masks_cur); i++) {
- /* If there's been a change in the mask write it back
- * to the hardware.
- */
- if (tabla->irq_masks_cur[i] != tabla->irq_masks_cache[i]) {
- tabla->irq_masks_cache[i] = tabla->irq_masks_cur[i];
- tabla_reg_write(tabla, TABLA_A_INTR_MASK0+i,
- tabla->irq_masks_cur[i]);
- }
- }
-
- mutex_unlock(&tabla->irq_lock);
-}
-
-static void tabla_irq_enable(struct irq_data *data)
-{
- struct tabla *tabla = irq_data_get_irq_chip_data(data);
- int tabla_irq = irq_to_tabla_irq(tabla, data->irq);
- tabla->irq_masks_cur[BIT_BYTE(tabla_irq)] &=
- ~(BYTE_BIT_MASK(tabla_irq));
-}
-
-static void tabla_irq_disable(struct irq_data *data)
-{
- struct tabla *tabla = irq_data_get_irq_chip_data(data);
- int tabla_irq = irq_to_tabla_irq(tabla, data->irq);
- tabla->irq_masks_cur[BIT_BYTE(tabla_irq)] |= BYTE_BIT_MASK(tabla_irq);
-}
-
-static struct irq_chip tabla_irq_chip = {
- .name = "tabla",
- .irq_bus_lock = tabla_irq_lock,
- .irq_bus_sync_unlock = tabla_irq_sync_unlock,
- .irq_disable = tabla_irq_disable,
- .irq_enable = tabla_irq_enable,
-};
-
-enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
- enum tabla_pm_state n)
-{
- enum tabla_pm_state old;
- mutex_lock(&tabla->pm_lock);
- old = tabla->pm_state;
- if (old == o)
- tabla->pm_state = n;
- mutex_unlock(&tabla->pm_lock);
- return old;
-}
-EXPORT_SYMBOL_GPL(tabla_pm_cmpxchg);
-
-void tabla_lock_sleep(struct tabla *tabla)
-{
- enum tabla_pm_state os;
-
- /* tabla_{lock/unlock}_sleep will be called by tabla_irq_thread
- * and its subroutines only motly.
- * but btn0_lpress_fn is not tabla_irq_thread's subroutine and
- * it can race with tabla_irq_thread.
- * so need to embrace wlock_holders with mutex.
- */
- mutex_lock(&tabla->pm_lock);
- if (tabla->wlock_holders++ == 0)
- wake_lock(&tabla->wlock);
- mutex_unlock(&tabla->pm_lock);
- while (!wait_event_timeout(tabla->pm_wq,
- ((os = tabla_pm_cmpxchg(tabla, TABLA_PM_SLEEPABLE,
- TABLA_PM_AWAKE)) ==
- TABLA_PM_SLEEPABLE ||
- (os == TABLA_PM_AWAKE)),
- 5 * HZ)) {
- pr_err("%s: system didn't resume within 5000ms, state %d, "
- "wlock %d\n", __func__, tabla->pm_state,
- tabla->wlock_holders);
- WARN_ON_ONCE(1);
- }
- wake_up_all(&tabla->pm_wq);
-}
-EXPORT_SYMBOL_GPL(tabla_lock_sleep);
-
-void tabla_unlock_sleep(struct tabla *tabla)
-{
- mutex_lock(&tabla->pm_lock);
- if (--tabla->wlock_holders == 0) {
- tabla->pm_state = TABLA_PM_SLEEPABLE;
- wake_unlock(&tabla->wlock);
- }
- mutex_unlock(&tabla->pm_lock);
- wake_up_all(&tabla->pm_wq);
-}
-EXPORT_SYMBOL_GPL(tabla_unlock_sleep);
-
-static irqreturn_t tabla_irq_thread(int irq, void *data)
-{
- int ret;
- struct tabla *tabla = data;
- u8 status[TABLA_NUM_IRQ_REGS];
- unsigned int i;
-
- tabla_lock_sleep(tabla);
- ret = tabla_bulk_read(tabla, TABLA_A_INTR_STATUS0,
- TABLA_NUM_IRQ_REGS, status);
- if (ret < 0) {
- dev_err(tabla->dev, "Failed to read interrupt status: %d\n",
- ret);
- tabla_unlock_sleep(tabla);
- return IRQ_NONE;
- }
- /* Apply masking */
- for (i = 0; i < TABLA_NUM_IRQ_REGS; i++)
- status[i] &= ~tabla->irq_masks_cur[i];
-
- /* Find out which interrupt was triggered and call that interrupt's
- * handler function
- */
- for (i = 0; i < TABLA_NUM_IRQS; i++) {
- if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
- if ((i <= TABLA_IRQ_MBHC_INSERTION) &&
- (i >= TABLA_IRQ_MBHC_REMOVAL)) {
- tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
- BIT_BYTE(i), BYTE_BIT_MASK(i));
- if (tabla_get_intf_type() ==
- TABLA_INTERFACE_TYPE_I2C)
- tabla_reg_write(tabla,
- TABLA_A_INTR_MODE, 0x02);
- handle_nested_irq(tabla->irq_base + i);
- } else {
- handle_nested_irq(tabla->irq_base + i);
- tabla_reg_write(tabla, TABLA_A_INTR_CLEAR0 +
- BIT_BYTE(i), BYTE_BIT_MASK(i));
- if (tabla_get_intf_type() ==
- TABLA_INTERFACE_TYPE_I2C)
- tabla_reg_write(tabla,
- TABLA_A_INTR_MODE, 0x02);
- }
- break;
- }
- }
- tabla_unlock_sleep(tabla);
-
- return IRQ_HANDLED;
-}
-
-int tabla_irq_init(struct tabla *tabla)
-{
- int ret;
- unsigned int i, cur_irq;
-
- mutex_init(&tabla->irq_lock);
-
- if (!tabla->irq) {
- dev_warn(tabla->dev,
- "No interrupt specified, no interrupts\n");
- tabla->irq_base = 0;
- return 0;
- }
-
- if (!tabla->irq_base) {
- dev_err(tabla->dev,
- "No interrupt base specified, no interrupts\n");
- return 0;
- }
- /* Mask the individual interrupt sources */
- for (i = 0, cur_irq = tabla->irq_base; i < TABLA_NUM_IRQS; i++,
- cur_irq++) {
-
- irq_set_chip_data(cur_irq, tabla);
-
- if (tabla_irqs[i].level)
- irq_set_chip_and_handler(cur_irq, &tabla_irq_chip,
- handle_level_irq);
- else
- irq_set_chip_and_handler(cur_irq, &tabla_irq_chip,
- handle_edge_irq);
-
- irq_set_nested_thread(cur_irq, 1);
-
- /* ARM needs us to explicitly flag the IRQ as valid
- * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
-#else
- set_irq_noprobe(cur_irq);
-#endif
-
- tabla->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
- tabla->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
- tabla->irq_level[BIT_BYTE(i)] |= tabla_irqs[i].level <<
- (i % BITS_PER_BYTE);
- }
- for (i = 0; i < TABLA_NUM_IRQ_REGS; i++) {
- /* Initialize interrupt mask and level registers */
- tabla_reg_write(tabla, TABLA_A_INTR_LEVEL0 + i,
- tabla->irq_level[i]);
- tabla_reg_write(tabla, TABLA_A_INTR_MASK0 + i,
- tabla->irq_masks_cur[i]);
- }
-
- ret = request_threaded_irq(tabla->irq, NULL, tabla_irq_thread,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "tabla", tabla);
- if (ret != 0)
- dev_err(tabla->dev, "Failed to request IRQ %d: %d\n",
- tabla->irq, ret);
- else {
- ret = enable_irq_wake(tabla->irq);
- if (ret == 0) {
- ret = device_init_wakeup(tabla->dev, 1);
- if (ret) {
- dev_err(tabla->dev, "Failed to init device"
- "wakeup : %d\n", ret);
- disable_irq_wake(tabla->irq);
- }
- } else
- dev_err(tabla->dev, "Failed to set wake interrupt on"
- " IRQ %d: %d\n", tabla->irq, ret);
- if (ret)
- free_irq(tabla->irq, tabla);
- }
-
- if (ret)
- mutex_destroy(&tabla->irq_lock);
-
- return ret;
-}
-
-void tabla_irq_exit(struct tabla *tabla)
-{
- if (tabla->irq) {
- disable_irq_wake(tabla->irq);
- free_irq(tabla->irq, tabla);
- device_init_wakeup(tabla->dev, 0);
- }
- mutex_destroy(&tabla->irq_lock);
-}
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
new file mode 100644
index 0000000..59a4283
--- /dev/null
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -0,0 +1,1126 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+#include <sound/soc.h>
+
+#define WCD9XXX_SLIM_GLA_MAX_RETRIES 5
+#define WCD9XXX_REGISTER_START_OFFSET 0x800
+#define WCD9XXX_SLIM_RW_MAX_TRIES 3
+
+#define MAX_WCD9XXX_DEVICE 4
+#define WCD9XXX_I2C_MODE 0x03
+
+struct wcd9xxx_i2c {
+ struct i2c_client *client;
+ struct i2c_msg xfer_msg[2];
+ struct mutex xfer_lock;
+ int mod_id;
+};
+
+struct wcd9xxx_i2c wcd9xxx_modules[MAX_WCD9XXX_DEVICE];
+static int wcd9xxx_intf;
+
+static int wcd9xxx_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *dest, bool interface_reg)
+{
+ int ret;
+ u8 *buf = dest;
+
+ if (bytes <= 0) {
+ dev_err(wcd9xxx->dev, "Invalid byte read length %d\n", bytes);
+ return -EINVAL;
+ }
+
+ ret = wcd9xxx->read_dev(wcd9xxx, reg, bytes, dest, interface_reg);
+ if (ret < 0) {
+ dev_err(wcd9xxx->dev, "Codec read failed\n");
+ return ret;
+ } else
+ dev_dbg(wcd9xxx->dev, "Read 0x%02x from R%d(0x%x)\n",
+ *buf, reg, reg);
+
+ return 0;
+}
+int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+{
+ u8 val;
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+ ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false);
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_reg_read);
+
+static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *src, bool interface_reg)
+{
+ u8 *buf = src;
+
+ if (bytes <= 0) {
+ pr_err("%s: Error, invalid write length\n", __func__);
+ return -EINVAL;
+ }
+
+ dev_dbg(wcd9xxx->dev, "Write %02x to R%d(0x%x)\n",
+ *buf, reg, reg);
+
+ return wcd9xxx->write_dev(wcd9xxx, reg, bytes, src, interface_reg);
+}
+
+int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ u8 val)
+{
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+ ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, false);
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_reg_write);
+
+static u8 wcd9xxx_pgd_la;
+static u8 wcd9xxx_inf_la;
+
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg)
+{
+ u8 val;
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+ ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, true);
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_read);
+
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ u8 val)
+{
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+ ret = wcd9xxx_write(wcd9xxx, reg, 1, &val, true);
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_interface_reg_write);
+
+int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int count, u8 *buf)
+{
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+
+ ret = wcd9xxx_read(wcd9xxx, reg, count, buf, false);
+
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_bulk_read);
+
+int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int count, u8 *buf)
+{
+ int ret;
+
+ mutex_lock(&wcd9xxx->io_lock);
+
+ ret = wcd9xxx_write(wcd9xxx, reg, count, buf, false);
+
+ mutex_unlock(&wcd9xxx->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_bulk_write);
+
+static int wcd9xxx_slim_read_device(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *dest, bool interface)
+{
+ int ret;
+ struct slim_ele_access msg;
+ int slim_read_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+ msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+ msg.num_bytes = bytes;
+ msg.comp = NULL;
+
+ while (1) {
+ mutex_lock(&wcd9xxx->xfer_lock);
+ ret = slim_request_val_element(interface ?
+ wcd9xxx->slim_slave : wcd9xxx->slim,
+ &msg, dest, bytes);
+ mutex_unlock(&wcd9xxx->xfer_lock);
+ if (likely(ret == 0) || (--slim_read_tries == 0))
+ break;
+ usleep_range(5000, 5000);
+ }
+
+ if (ret)
+ pr_err("%s: Error, Codec read failed (%d)\n", __func__, ret);
+
+ return ret;
+}
+/* Interface specifies whether the write is to the interface or general
+ * registers.
+ */
+static int wcd9xxx_slim_write_device(struct wcd9xxx *wcd9xxx,
+ unsigned short reg, int bytes, void *src, bool interface)
+{
+ int ret;
+ struct slim_ele_access msg;
+ int slim_write_tries = WCD9XXX_SLIM_RW_MAX_TRIES;
+ msg.start_offset = WCD9XXX_REGISTER_START_OFFSET + reg;
+ msg.num_bytes = bytes;
+ msg.comp = NULL;
+
+ while (1) {
+ mutex_lock(&wcd9xxx->xfer_lock);
+ ret = slim_change_val_element(interface ?
+ wcd9xxx->slim_slave : wcd9xxx->slim,
+ &msg, src, bytes);
+ mutex_unlock(&wcd9xxx->xfer_lock);
+ if (likely(ret == 0) || (--slim_write_tries == 0))
+ break;
+ usleep_range(5000, 5000);
+ }
+
+ if (ret)
+ pr_err("%s: Error, Codec write failed (%d)\n", __func__, ret);
+
+ return ret;
+}
+
+static struct mfd_cell tabla1x_devs[] = {
+ {
+ .name = "tabla1x_codec",
+ },
+};
+
+static struct mfd_cell tabla_devs[] = {
+ {
+ .name = "tabla_codec",
+ },
+};
+
+static struct mfd_cell sitar_devs[] = {
+ {
+ .name = "sitar_codec",
+ },
+};
+
+static void wcd9xxx_bring_up(struct wcd9xxx *wcd9xxx)
+{
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x4);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 0);
+ usleep_range(5000, 5000);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_CDC_CTL, 3);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 3);
+}
+
+static void wcd9xxx_bring_down(struct wcd9xxx *wcd9xxx)
+{
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x7);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x6);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0xe);
+ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_LEAKAGE_CTL, 0x8);
+}
+
+static int wcd9xxx_reset(struct wcd9xxx *wcd9xxx)
+{
+ int ret;
+
+ if (wcd9xxx->reset_gpio) {
+ ret = gpio_request(wcd9xxx->reset_gpio, "CDC_RESET");
+ if (ret) {
+ pr_err("%s: Failed to request gpio %d\n", __func__,
+ wcd9xxx->reset_gpio);
+ wcd9xxx->reset_gpio = 0;
+ return ret;
+ }
+
+ gpio_direction_output(wcd9xxx->reset_gpio, 1);
+ msleep(20);
+ gpio_direction_output(wcd9xxx->reset_gpio, 0);
+ msleep(20);
+ gpio_direction_output(wcd9xxx->reset_gpio, 1);
+ msleep(20);
+ }
+ return 0;
+}
+
+static void wcd9xxx_free_reset(struct wcd9xxx *wcd9xxx)
+{
+ if (wcd9xxx->reset_gpio) {
+ gpio_free(wcd9xxx->reset_gpio);
+ wcd9xxx->reset_gpio = 0;
+ }
+}
+
+static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx, int irq)
+{
+ int ret;
+ u8 idbyte_0, idbyte_1, idbyte_2, idbyte_3;
+ struct mfd_cell *wcd9xxx_dev = NULL;
+ int wcd9xxx_dev_size = 0;
+
+ mutex_init(&wcd9xxx->io_lock);
+ mutex_init(&wcd9xxx->xfer_lock);
+
+ mutex_init(&wcd9xxx->pm_lock);
+ wcd9xxx->wlock_holders = 0;
+ wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+ init_waitqueue_head(&wcd9xxx->pm_wq);
+ wake_lock_init(&wcd9xxx->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
+
+ dev_set_drvdata(wcd9xxx->dev, wcd9xxx);
+
+ wcd9xxx_bring_up(wcd9xxx);
+
+ ret = wcd9xxx_irq_init(wcd9xxx);
+ if (ret) {
+ pr_err("IRQ initialization failed\n");
+ goto err;
+ }
+
+ idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
+ idbyte_1 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_1);
+ idbyte_2 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2);
+ idbyte_3 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_3);
+
+ wcd9xxx->version = wcd9xxx_reg_read(wcd9xxx,
+ WCD9XXX_A_CHIP_VERSION) & 0x1F;
+ pr_info("%s : Codec version %u initialized\n",
+ __func__, wcd9xxx->version);
+ pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
+ idbyte_0, idbyte_1, idbyte_2, idbyte_3);
+
+ if (!strncmp(wcd9xxx->slim->name, "tabla", 5)) {
+ if (TABLA_IS_1_X(wcd9xxx->version)) {
+ wcd9xxx_dev = tabla1x_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
+ } else {
+ wcd9xxx_dev = tabla_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
+ }
+ } else {
+ wcd9xxx_dev = sitar_devs;
+ wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
+ }
+
+ ret = mfd_add_devices(wcd9xxx->dev, -1,
+ wcd9xxx_dev, wcd9xxx_dev_size,
+ NULL, 0);
+ if (ret != 0) {
+ dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
+ goto err_irq;
+ }
+ return ret;
+err_irq:
+ wcd9xxx_irq_exit(wcd9xxx);
+err:
+ wcd9xxx_bring_down(wcd9xxx);
+ wake_lock_destroy(&wcd9xxx->wlock);
+ mutex_destroy(&wcd9xxx->pm_lock);
+ mutex_destroy(&wcd9xxx->io_lock);
+ mutex_destroy(&wcd9xxx->xfer_lock);
+ return ret;
+}
+
+static void wcd9xxx_device_exit(struct wcd9xxx *wcd9xxx)
+{
+ wcd9xxx_irq_exit(wcd9xxx);
+ wcd9xxx_bring_down(wcd9xxx);
+ wcd9xxx_free_reset(wcd9xxx);
+ mutex_destroy(&wcd9xxx->pm_lock);
+ wake_lock_destroy(&wcd9xxx->wlock);
+ mutex_destroy(&wcd9xxx->io_lock);
+ mutex_destroy(&wcd9xxx->xfer_lock);
+ slim_remove_device(wcd9xxx->slim_slave);
+ kfree(wcd9xxx);
+}
+
+
+#ifdef CONFIG_DEBUG_FS
+struct wcd9xxx *debugCodec;
+
+static struct dentry *debugfs_wcd9xxx_dent;
+static struct dentry *debugfs_peek;
+static struct dentry *debugfs_poke;
+
+static unsigned char read_data;
+
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static int get_parameters(char *buf, long int *param1, int num_of_par)
+{
+ char *token;
+ int base, cnt;
+
+ token = strsep(&buf, " ");
+
+ for (cnt = 0; cnt < num_of_par; cnt++) {
+ if (token != NULL) {
+ if ((token[1] == 'x') || (token[1] == 'X'))
+ base = 16;
+ else
+ base = 10;
+
+ if (strict_strtoul(token, base, ¶m1[cnt]) != 0)
+ return -EINVAL;
+
+ token = strsep(&buf, " ");
+ } else
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char lbuf[8];
+
+ snprintf(lbuf, sizeof(lbuf), "0x%x\n", read_data);
+ return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+ strnlen(lbuf, 7));
+}
+
+
+static ssize_t codec_debug_write(struct file *filp,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char *access_str = filp->private_data;
+ char lbuf[32];
+ int rc;
+ long int param[5];
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+
+ if (!strncmp(access_str, "poke", 6)) {
+ /* write */
+ rc = get_parameters(lbuf, param, 2);
+ if ((param[0] <= 0x3FF) && (param[1] <= 0xFF) &&
+ (rc == 0))
+ wcd9xxx_interface_reg_write(debugCodec, param[0],
+ param[1]);
+ else
+ rc = -EINVAL;
+ } else if (!strncmp(access_str, "peek", 6)) {
+ /* read */
+ rc = get_parameters(lbuf, param, 1);
+ if ((param[0] <= 0x3FF) && (rc == 0))
+ read_data = wcd9xxx_interface_reg_read(debugCodec,
+ param[0]);
+ else
+ rc = -EINVAL;
+ }
+
+ if (rc == 0)
+ rc = cnt;
+ else
+ pr_err("%s: rc = %d\n", __func__, rc);
+
+ return rc;
+}
+
+static const struct file_operations codec_debug_ops = {
+ .open = codec_debug_open,
+ .write = codec_debug_write,
+ .read = codec_debug_read
+};
+#endif
+
+static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx)
+{
+ int ret;
+ int i;
+ struct wcd9xxx_pdata *pdata = wcd9xxx->slim->dev.platform_data;
+
+ wcd9xxx->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+ ARRAY_SIZE(pdata->regulator),
+ GFP_KERNEL);
+ if (!wcd9xxx->supplies) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++)
+ wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+
+ ret = regulator_bulk_get(wcd9xxx->dev, ARRAY_SIZE(pdata->regulator),
+ wcd9xxx->supplies);
+ if (ret != 0) {
+ dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
+ ret);
+ goto err_supplies;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
+ pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+ if (ret) {
+ pr_err("%s: Setting regulator voltage failed for "
+ "regulator %s err = %d\n", __func__,
+ wcd9xxx->supplies[i].supply, ret);
+ goto err_get;
+ }
+
+ ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
+ pdata->regulator[i].optimum_uA);
+ if (ret < 0) {
+ pr_err("%s: Setting regulator optimum mode failed for "
+ "regulator %s err = %d\n", __func__,
+ wcd9xxx->supplies[i].supply, ret);
+ goto err_get;
+ }
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(pdata->regulator),
+ wcd9xxx->supplies);
+ if (ret != 0) {
+ dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
+ ret);
+ goto err_configure;
+ }
+ return ret;
+
+err_configure:
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uV);
+ regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
+ }
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+err_supplies:
+ kfree(wcd9xxx->supplies);
+err:
+ return ret;
+}
+
+static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx)
+{
+ int i;
+ struct wcd9xxx_pdata *pdata = wcd9xxx->slim->dev.platform_data;
+
+ regulator_bulk_disable(ARRAY_SIZE(pdata->regulator),
+ wcd9xxx->supplies);
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
+ pdata->regulator[i].max_uV);
+ regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
+ }
+ regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+ kfree(wcd9xxx->supplies);
+}
+
+int wcd9xxx_get_intf_type(void)
+{
+ return wcd9xxx_intf;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_get_intf_type);
+
+struct wcd9xxx_i2c *get_i2c_wcd9xxx_device_info(u16 reg)
+{
+ u16 mask = 0x0f00;
+ int value = 0;
+ struct wcd9xxx_i2c *wcd9xxx = NULL;
+ value = ((reg & mask) >> 8) & 0x000f;
+ switch (value) {
+ case 0:
+ wcd9xxx = &wcd9xxx_modules[0];
+ break;
+ case 1:
+ wcd9xxx = &wcd9xxx_modules[1];
+ break;
+ case 2:
+ wcd9xxx = &wcd9xxx_modules[2];
+ break;
+ case 3:
+ wcd9xxx = &wcd9xxx_modules[3];
+ break;
+ default:
+ break;
+ }
+ return wcd9xxx;
+}
+
+int wcd9xxx_i2c_write_device(u16 reg, u8 *value,
+ u32 bytes)
+{
+
+ struct i2c_msg *msg;
+ int ret = 0;
+ u8 reg_addr = 0;
+ u8 data[bytes + 1];
+ struct wcd9xxx_i2c *wcd9xxx;
+
+ wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
+ if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
+ pr_err("failed to get device info\n");
+ return -ENODEV;
+ }
+ reg_addr = (u8)reg;
+ msg = &wcd9xxx->xfer_msg[0];
+ msg->addr = wcd9xxx->client->addr;
+ msg->len = bytes + 1;
+ msg->flags = 0;
+ data[0] = reg;
+ data[1] = *value;
+ msg->buf = data;
+ ret = i2c_transfer(wcd9xxx->client->adapter, wcd9xxx->xfer_msg, 1);
+ /* Try again if the write fails */
+ if (ret != 1) {
+ ret = i2c_transfer(wcd9xxx->client->adapter,
+ wcd9xxx->xfer_msg, 1);
+ if (ret != 1) {
+ pr_err("failed to write the device\n");
+ return ret;
+ }
+ }
+ pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
+ return 0;
+}
+
+
+int wcd9xxx_i2c_read_device(unsigned short reg,
+ int bytes, unsigned char *dest)
+{
+ struct i2c_msg *msg;
+ int ret = 0;
+ u8 reg_addr = 0;
+ struct wcd9xxx_i2c *wcd9xxx;
+ u8 i = 0;
+
+ wcd9xxx = get_i2c_wcd9xxx_device_info(reg);
+ if (wcd9xxx == NULL || wcd9xxx->client == NULL) {
+ pr_err("failed to get device info\n");
+ return -ENODEV;
+ }
+ for (i = 0; i < bytes; i++) {
+ reg_addr = (u8)reg++;
+ msg = &wcd9xxx->xfer_msg[0];
+ msg->addr = wcd9xxx->client->addr;
+ msg->len = 1;
+ msg->flags = 0;
+ msg->buf = ®_addr;
+
+ msg = &wcd9xxx->xfer_msg[1];
+ msg->addr = wcd9xxx->client->addr;
+ msg->len = 1;
+ msg->flags = I2C_M_RD;
+ msg->buf = dest++;
+ ret = i2c_transfer(wcd9xxx->client->adapter,
+ wcd9xxx->xfer_msg, 2);
+
+ /* Try again if read fails first time */
+ if (ret != 2) {
+ ret = i2c_transfer(wcd9xxx->client->adapter,
+ wcd9xxx->xfer_msg, 2);
+ if (ret != 2) {
+ pr_err("failed to read wcd9xxx register\n");
+ return ret;
+ }
+ }
+ }
+ return 0;
+}
+
+int wcd9xxx_i2c_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *dest, bool interface_reg)
+{
+ return wcd9xxx_i2c_read_device(reg, bytes, dest);
+}
+
+int wcd9xxx_i2c_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *src, bool interface_reg)
+{
+ return wcd9xxx_i2c_write_device(reg, src, bytes);
+}
+
+static int __devinit wcd9xxx_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct wcd9xxx *wcd9xxx;
+ struct wcd9xxx_pdata *pdata = client->dev.platform_data;
+ int val = 0;
+ int ret = 0;
+ static int device_id;
+
+ if (device_id > 0) {
+ wcd9xxx_modules[device_id++].client = client;
+ pr_info("probe for other slaves devices of tabla\n");
+ return ret;
+ }
+
+ wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
+ if (wcd9xxx == NULL) {
+ pr_err("%s: error, allocation failed\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (!pdata) {
+ dev_dbg(&client->dev, "no platform data?\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) {
+ dev_dbg(&client->dev, "can't talk I2C?\n");
+ ret = -EIO;
+ goto fail;
+ }
+ dev_set_drvdata(&client->dev, wcd9xxx);
+ wcd9xxx->dev = &client->dev;
+ wcd9xxx->reset_gpio = pdata->reset_gpio;
+
+ ret = wcd9xxx_enable_supplies(wcd9xxx);
+ if (ret) {
+ pr_err("%s: Fail to enable Codec supplies\n", __func__);
+ goto err_codec;
+ }
+
+ usleep_range(5, 5);
+ ret = wcd9xxx_reset(wcd9xxx);
+ if (ret) {
+ pr_err("%s: Resetting Codec failed\n", __func__);
+ goto err_supplies;
+ }
+ wcd9xxx_modules[device_id++].client = client;
+
+ wcd9xxx->read_dev = wcd9xxx_i2c_read;
+ wcd9xxx->write_dev = wcd9xxx_i2c_write;
+ wcd9xxx->irq = pdata->irq;
+ wcd9xxx->irq_base = pdata->irq_base;
+
+ /*read the tabla status before initializing the device type*/
+ ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+ if ((ret < 0) || (val != WCD9XXX_I2C_MODE)) {
+ pr_err("failed to read the wcd9xxx status\n");
+ goto err_device_init;
+ }
+
+ ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
+ if (ret) {
+ pr_err("%s: error, initializing device failed\n", __func__);
+ goto err_device_init;
+ }
+ wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
+
+ return ret;
+err_device_init:
+ wcd9xxx_free_reset(wcd9xxx);
+err_supplies:
+ wcd9xxx_disable_supplies(wcd9xxx);
+err_codec:
+ kfree(wcd9xxx);
+fail:
+ return ret;
+}
+
+static int __devexit wcd9xxx_i2c_remove(struct i2c_client *client)
+{
+ struct wcd9xxx *wcd9xxx;
+
+ pr_debug("exit\n");
+ wcd9xxx = dev_get_drvdata(&client->dev);
+ wcd9xxx_disable_supplies(wcd9xxx);
+ wcd9xxx_device_exit(wcd9xxx);
+ return 0;
+}
+
+static int wcd9xxx_slim_probe(struct slim_device *slim)
+{
+ struct wcd9xxx *wcd9xxx;
+ struct wcd9xxx_pdata *pdata;
+ int ret = 0;
+ int sgla_retry_cnt;
+
+ dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
+ pdata = slim->dev.platform_data;
+
+ if (!pdata) {
+ dev_err(&slim->dev, "Error, no platform data\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ wcd9xxx = kzalloc(sizeof(struct wcd9xxx), GFP_KERNEL);
+ if (wcd9xxx == NULL) {
+ pr_err("%s: error, allocation failed\n", __func__);
+ ret = -ENOMEM;
+ goto err;
+ }
+ if (!slim->ctrl) {
+ pr_err("Error, no SLIMBUS control data\n");
+ ret = -EINVAL;
+ goto err_codec;
+ }
+ wcd9xxx->slim = slim;
+ slim_set_clientdata(slim, wcd9xxx);
+ wcd9xxx->reset_gpio = pdata->reset_gpio;
+ wcd9xxx->dev = &slim->dev;
+
+ ret = wcd9xxx_enable_supplies(wcd9xxx);
+ if (ret)
+ goto err_codec;
+ usleep_range(5, 5);
+
+ ret = wcd9xxx_reset(wcd9xxx);
+ if (ret) {
+ pr_err("%s: Resetting Codec failed\n", __func__);
+ goto err_supplies;
+ }
+
+ ret = slim_get_logical_addr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
+ ARRAY_SIZE(wcd9xxx->slim->e_addr), &wcd9xxx->slim->laddr);
+ if (ret) {
+ pr_err("fail to get slimbus logical address %d\n", ret);
+ goto err_reset;
+ }
+ wcd9xxx->read_dev = wcd9xxx_slim_read_device;
+ wcd9xxx->write_dev = wcd9xxx_slim_write_device;
+ wcd9xxx->irq = pdata->irq;
+ wcd9xxx->irq_base = pdata->irq_base;
+ wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
+
+ if (pdata->num_irqs < TABLA_NUM_IRQS) {
+ pr_err("%s: Error, not enough interrupt lines allocated\n",
+ __func__);
+ goto err_reset;
+ }
+
+ wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
+
+ ret = slim_add_device(slim->ctrl, wcd9xxx->slim_slave);
+ if (ret) {
+ pr_err("%s: error, adding SLIMBUS device failed\n", __func__);
+ goto err_reset;
+ }
+
+ sgla_retry_cnt = 0;
+
+ while (1) {
+ ret = slim_get_logical_addr(wcd9xxx->slim_slave,
+ wcd9xxx->slim_slave->e_addr,
+ ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
+ &wcd9xxx->slim_slave->laddr);
+ if (ret) {
+ if (sgla_retry_cnt++ < WCD9XXX_SLIM_GLA_MAX_RETRIES) {
+ /* Give SLIMBUS slave time to report present
+ and be ready.
+ */
+ usleep_range(1000, 1000);
+ pr_debug("%s: retry slim_get_logical_addr()\n",
+ __func__);
+ continue;
+ }
+ pr_err("fail to get slimbus slave logical address"
+ " %d\n", ret);
+ goto err_slim_add;
+ }
+ break;
+ }
+ wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
+ wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
+
+ ret = wcd9xxx_device_init(wcd9xxx, wcd9xxx->irq);
+ if (ret) {
+ pr_err("%s: error, initializing device failed\n", __func__);
+ goto err_slim_add;
+ }
+ wcd9xxx_init_slimslave(wcd9xxx, wcd9xxx_pgd_la);
+#ifdef CONFIG_DEBUG_FS
+ debugCodec = wcd9xxx;
+
+ debugfs_wcd9xxx_dent = debugfs_create_dir
+ ("wcd9310_slimbus_interface_device", 0);
+ if (!IS_ERR(debugfs_wcd9xxx_dent)) {
+ debugfs_peek = debugfs_create_file("peek",
+ S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
+ (void *) "peek", &codec_debug_ops);
+
+ debugfs_poke = debugfs_create_file("poke",
+ S_IFREG | S_IRUGO, debugfs_wcd9xxx_dent,
+ (void *) "poke", &codec_debug_ops);
+ }
+#endif
+
+ return ret;
+
+err_slim_add:
+ slim_remove_device(wcd9xxx->slim_slave);
+err_reset:
+ wcd9xxx_free_reset(wcd9xxx);
+err_supplies:
+ wcd9xxx_disable_supplies(wcd9xxx);
+err_codec:
+ kfree(wcd9xxx);
+err:
+ return ret;
+}
+static int wcd9xxx_slim_remove(struct slim_device *pdev)
+{
+ struct wcd9xxx *wcd9xxx;
+
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(debugfs_peek);
+ debugfs_remove(debugfs_poke);
+ debugfs_remove(debugfs_wcd9xxx_dent);
+#endif
+ wcd9xxx = slim_get_devicedata(pdev);
+ wcd9xxx_deinit_slimslave(wcd9xxx);
+ slim_remove_device(wcd9xxx->slim_slave);
+ wcd9xxx_disable_supplies(wcd9xxx);
+ wcd9xxx_device_exit(wcd9xxx);
+ return 0;
+}
+
+static int wcd9xxx_resume(struct wcd9xxx *wcd9xxx)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ mutex_lock(&wcd9xxx->pm_lock);
+ if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
+ pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+ wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+ } else {
+ pr_warn("%s: system is already awake, state %d wlock %d\n",
+ __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ }
+ mutex_unlock(&wcd9xxx->pm_lock);
+ wake_up_all(&wcd9xxx->pm_wq);
+
+ return ret;
+}
+
+static int wcd9xxx_slim_resume(struct slim_device *sldev)
+{
+ struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+ return wcd9xxx_resume(wcd9xxx);
+}
+
+static int wcd9xxx_i2c_resume(struct i2c_client *i2cdev)
+{
+ struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
+ if (wcd9xxx)
+ return wcd9xxx_resume(wcd9xxx);
+ else
+ return 0;
+}
+
+static int wcd9xxx_suspend(struct wcd9xxx *wcd9xxx, pm_message_t pmesg)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ /* wake_lock() can be called after this suspend chain call started.
+ * thus suspend can be called while wlock is being held */
+ mutex_lock(&wcd9xxx->pm_lock);
+ if (wcd9xxx->pm_state == WCD9XXX_PM_SLEEPABLE) {
+ pr_debug("%s: suspending system, state %d, wlock %d\n",
+ __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ wcd9xxx->pm_state = WCD9XXX_PM_ASLEEP;
+ } else if (wcd9xxx->pm_state == WCD9XXX_PM_AWAKE) {
+ /* unlock to wait for pm_state == WCD9XXX_PM_SLEEPABLE
+ * then set to WCD9XXX_PM_ASLEEP */
+ pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+ __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ mutex_unlock(&wcd9xxx->pm_lock);
+ if (!(wait_event_timeout(wcd9xxx->pm_wq,
+ wcd9xxx_pm_cmpxchg(wcd9xxx,
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_ASLEEP) ==
+ WCD9XXX_PM_SLEEPABLE,
+ HZ))) {
+ pr_debug("%s: suspend failed state %d, wlock %d\n",
+ __func__, wcd9xxx->pm_state,
+ wcd9xxx->wlock_holders);
+ ret = -EBUSY;
+ } else {
+ pr_debug("%s: done, state %d, wlock %d\n", __func__,
+ wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ }
+ mutex_lock(&wcd9xxx->pm_lock);
+ } else if (wcd9xxx->pm_state == WCD9XXX_PM_ASLEEP) {
+ pr_warn("%s: system is already suspended, state %d, wlock %dn",
+ __func__, wcd9xxx->pm_state, wcd9xxx->wlock_holders);
+ }
+ mutex_unlock(&wcd9xxx->pm_lock);
+
+ return ret;
+}
+
+static int wcd9xxx_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+ struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+ return wcd9xxx_suspend(wcd9xxx, pmesg);
+}
+
+static int wcd9xxx_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
+{
+ struct wcd9xxx *wcd9xxx = dev_get_drvdata(&i2cdev->dev);
+ if (wcd9xxx)
+ return wcd9xxx_suspend(wcd9xxx, pmesg);
+ else
+ return 0;
+}
+
+static const struct slim_device_id sitar_slimtest_id[] = {
+ {"sitar-slim", 0},
+ {}
+};
+static struct slim_driver sitar_slim_driver = {
+ .driver = {
+ .name = "sitar-slim",
+ .owner = THIS_MODULE,
+ },
+ .probe = wcd9xxx_slim_probe,
+ .remove = wcd9xxx_slim_remove,
+ .id_table = sitar_slimtest_id,
+ .resume = wcd9xxx_slim_resume,
+ .suspend = wcd9xxx_slim_suspend,
+};
+
+static const struct slim_device_id slimtest_id[] = {
+ {"tabla-slim", 0},
+ {}
+};
+
+static struct slim_driver tabla_slim_driver = {
+ .driver = {
+ .name = "tabla-slim",
+ .owner = THIS_MODULE,
+ },
+ .probe = wcd9xxx_slim_probe,
+ .remove = wcd9xxx_slim_remove,
+ .id_table = slimtest_id,
+ .resume = wcd9xxx_slim_resume,
+ .suspend = wcd9xxx_slim_suspend,
+};
+
+static const struct slim_device_id slimtest2x_id[] = {
+ {"tabla2x-slim", 0},
+ {}
+};
+
+static struct slim_driver tabla2x_slim_driver = {
+ .driver = {
+ .name = "tabla2x-slim",
+ .owner = THIS_MODULE,
+ },
+ .probe = wcd9xxx_slim_probe,
+ .remove = wcd9xxx_slim_remove,
+ .id_table = slimtest2x_id,
+ .resume = wcd9xxx_slim_resume,
+ .suspend = wcd9xxx_slim_suspend,
+};
+
+#define TABLA_I2C_TOP_LEVEL 0
+#define TABLA_I2C_ANALOG 1
+#define TABLA_I2C_DIGITAL_1 2
+#define TABLA_I2C_DIGITAL_2 3
+
+static struct i2c_device_id tabla_id_table[] = {
+ {"tabla top level", TABLA_I2C_TOP_LEVEL},
+ {"tabla analog", TABLA_I2C_TOP_LEVEL},
+ {"tabla digital1", TABLA_I2C_TOP_LEVEL},
+ {"tabla digital2", TABLA_I2C_TOP_LEVEL},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, tabla_id_table);
+
+static struct i2c_driver tabla_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tabla-i2c-core",
+ },
+ .id_table = tabla_id_table,
+ .probe = wcd9xxx_i2c_probe,
+ .remove = __devexit_p(wcd9xxx_i2c_remove),
+ .resume = wcd9xxx_i2c_resume,
+ .suspend = wcd9xxx_i2c_suspend,
+};
+
+static int __init wcd9xxx_init(void)
+{
+ int ret1, ret2, ret3, ret4;
+
+ ret1 = slim_driver_register(&tabla_slim_driver);
+ if (ret1 != 0)
+ pr_err("Failed to register tabla SB driver: %d\n", ret1);
+
+ ret2 = slim_driver_register(&tabla2x_slim_driver);
+ if (ret2 != 0)
+ pr_err("Failed to register tabla2x SB driver: %d\n", ret2);
+
+ ret3 = i2c_add_driver(&tabla_i2c_driver);
+ if (ret3 != 0)
+ pr_err("failed to add the I2C driver\n");
+
+ ret4 = slim_driver_register(&sitar_slim_driver);
+ if (ret1 != 0)
+ pr_err("Failed to register sitar SB driver: %d\n", ret4);
+
+ return (ret1 && ret2 && ret3 && ret4) ? -1 : 0;
+}
+module_init(wcd9xxx_init);
+
+static void __exit wcd9xxx_exit(void)
+{
+}
+module_exit(wcd9xxx_exit);
+
+MODULE_DESCRIPTION("Codec core driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
new file mode 100644
index 0000000..86c01ee
--- /dev/null
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
+#include <linux/interrupt.h>
+
+#define BYTE_BIT_MASK(nr) (1UL << ((nr) % BITS_PER_BYTE))
+#define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
+
+struct wcd9xxx_irq {
+ bool level;
+};
+
+static struct wcd9xxx_irq wcd9xxx_irqs[TABLA_NUM_IRQS] = {
+ [0] = { .level = 1},
+/* All other wcd9xxx interrupts are edge triggered */
+};
+
+static inline int irq_to_wcd9xxx_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+ return irq - wcd9xxx->irq_base;
+}
+
+static void wcd9xxx_irq_lock(struct irq_data *data)
+{
+ struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+ mutex_lock(&wcd9xxx->irq_lock);
+}
+
+static void wcd9xxx_irq_sync_unlock(struct irq_data *data)
+{
+ struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wcd9xxx->irq_masks_cur); i++) {
+ /* If there's been a change in the mask write it back
+ * to the hardware.
+ */
+ if (wcd9xxx->irq_masks_cur[i] != wcd9xxx->irq_masks_cache[i]) {
+ wcd9xxx->irq_masks_cache[i] = wcd9xxx->irq_masks_cur[i];
+ wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_MASK0+i,
+ wcd9xxx->irq_masks_cur[i]);
+ }
+ }
+
+ mutex_unlock(&wcd9xxx->irq_lock);
+}
+
+static void wcd9xxx_irq_enable(struct irq_data *data)
+{
+ struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+ int wcd9xxx_irq = irq_to_wcd9xxx_irq(wcd9xxx, data->irq);
+ wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)] &=
+ ~(BYTE_BIT_MASK(wcd9xxx_irq));
+}
+
+static void wcd9xxx_irq_disable(struct irq_data *data)
+{
+ struct wcd9xxx *wcd9xxx = irq_data_get_irq_chip_data(data);
+ int wcd9xxx_irq = irq_to_wcd9xxx_irq(wcd9xxx, data->irq);
+ wcd9xxx->irq_masks_cur[BIT_BYTE(wcd9xxx_irq)]
+ |= BYTE_BIT_MASK(wcd9xxx_irq);
+}
+
+static struct irq_chip wcd9xxx_irq_chip = {
+ .name = "wcd9xxx",
+ .irq_bus_lock = wcd9xxx_irq_lock,
+ .irq_bus_sync_unlock = wcd9xxx_irq_sync_unlock,
+ .irq_disable = wcd9xxx_irq_disable,
+ .irq_enable = wcd9xxx_irq_enable,
+};
+
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
+ enum wcd9xxx_pm_state o,
+ enum wcd9xxx_pm_state n)
+{
+ enum wcd9xxx_pm_state old;
+ mutex_lock(&wcd9xxx->pm_lock);
+ old = wcd9xxx->pm_state;
+ if (old == o)
+ wcd9xxx->pm_state = n;
+ mutex_unlock(&wcd9xxx->pm_lock);
+ return old;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_pm_cmpxchg);
+
+void wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx)
+{
+ enum wcd9xxx_pm_state os;
+
+ /* wcd9xxx_{lock/unlock}_sleep will be called by wcd9xxx_irq_thread
+ * and its subroutines only motly.
+ * but btn0_lpress_fn is not wcd9xxx_irq_thread's subroutine and
+ * it can race with wcd9xxx_irq_thread.
+ * so need to embrace wlock_holders with mutex.
+ */
+ mutex_lock(&wcd9xxx->pm_lock);
+ if (wcd9xxx->wlock_holders++ == 0)
+ wake_lock(&wcd9xxx->wlock);
+ mutex_unlock(&wcd9xxx->pm_lock);
+ while (!wait_event_timeout(wcd9xxx->pm_wq,
+ ((os = wcd9xxx_pm_cmpxchg(wcd9xxx, WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE)) ==
+ WCD9XXX_PM_SLEEPABLE ||
+ (os == WCD9XXX_PM_AWAKE)),
+ 5 * HZ)) {
+ pr_err("%s: system didn't resume within 5000ms, state %d, "
+ "wlock %d\n", __func__, wcd9xxx->pm_state,
+ wcd9xxx->wlock_holders);
+ WARN_ON_ONCE(1);
+ }
+ wake_up_all(&wcd9xxx->pm_wq);
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_lock_sleep);
+
+void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx)
+{
+ mutex_lock(&wcd9xxx->pm_lock);
+ if (--wcd9xxx->wlock_holders == 0) {
+ wcd9xxx->pm_state = WCD9XXX_PM_SLEEPABLE;
+ wake_unlock(&wcd9xxx->wlock);
+ }
+ mutex_unlock(&wcd9xxx->pm_lock);
+ wake_up_all(&wcd9xxx->pm_wq);
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_unlock_sleep);
+
+static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
+{
+ int ret;
+ struct wcd9xxx *wcd9xxx = data;
+ u8 status[WCD9XXX_NUM_IRQ_REGS];
+ unsigned int i;
+
+ wcd9xxx_lock_sleep(wcd9xxx);
+ ret = wcd9xxx_bulk_read(wcd9xxx, TABLA_A_INTR_STATUS0,
+ WCD9XXX_NUM_IRQ_REGS, status);
+ if (ret < 0) {
+ dev_err(wcd9xxx->dev, "Failed to read interrupt status: %d\n",
+ ret);
+ wcd9xxx_unlock_sleep(wcd9xxx);
+ return IRQ_NONE;
+ }
+ /* Apply masking */
+ for (i = 0; i < WCD9XXX_NUM_IRQ_REGS; i++)
+ status[i] &= ~wcd9xxx->irq_masks_cur[i];
+
+ /* Find out which interrupt was triggered and call that interrupt's
+ * handler function
+ */
+ for (i = 0; i < TABLA_NUM_IRQS; i++) {
+ if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
+ if ((i <= TABLA_IRQ_MBHC_INSERTION) &&
+ (i >= TABLA_IRQ_MBHC_REMOVAL)) {
+ wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_CLEAR0 +
+ BIT_BYTE(i), BYTE_BIT_MASK(i));
+ if (wcd9xxx_get_intf_type() ==
+ WCD9XXX_INTERFACE_TYPE_I2C)
+ wcd9xxx_reg_write(wcd9xxx,
+ TABLA_A_INTR_MODE, 0x02);
+ handle_nested_irq(wcd9xxx->irq_base + i);
+ } else {
+ handle_nested_irq(wcd9xxx->irq_base + i);
+ wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_CLEAR0 +
+ BIT_BYTE(i), BYTE_BIT_MASK(i));
+ if (wcd9xxx_get_intf_type() ==
+ WCD9XXX_INTERFACE_TYPE_I2C)
+ wcd9xxx_reg_write(wcd9xxx,
+ TABLA_A_INTR_MODE, 0x02);
+ }
+ break;
+ }
+ }
+ wcd9xxx_unlock_sleep(wcd9xxx);
+
+ return IRQ_HANDLED;
+}
+
+int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx)
+{
+ int ret;
+ unsigned int i, cur_irq;
+
+ mutex_init(&wcd9xxx->irq_lock);
+
+ if (!wcd9xxx->irq) {
+ dev_warn(wcd9xxx->dev,
+ "No interrupt specified, no interrupts\n");
+ wcd9xxx->irq_base = 0;
+ return 0;
+ }
+
+ if (!wcd9xxx->irq_base) {
+ dev_err(wcd9xxx->dev,
+ "No interrupt base specified, no interrupts\n");
+ return 0;
+ }
+ /* Mask the individual interrupt sources */
+ for (i = 0, cur_irq = wcd9xxx->irq_base; i < TABLA_NUM_IRQS; i++,
+ cur_irq++) {
+
+ irq_set_chip_data(cur_irq, wcd9xxx);
+
+ if (wcd9xxx_irqs[i].level)
+ irq_set_chip_and_handler(cur_irq, &wcd9xxx_irq_chip,
+ handle_level_irq);
+ else
+ irq_set_chip_and_handler(cur_irq, &wcd9xxx_irq_chip,
+ handle_edge_irq);
+
+ irq_set_nested_thread(cur_irq, 1);
+
+ /* ARM needs us to explicitly flag the IRQ as valid
+ * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ set_irq_noprobe(cur_irq);
+#endif
+
+ wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+ wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
+ wcd9xxx->irq_level[BIT_BYTE(i)] |= wcd9xxx_irqs[i].level <<
+ (i % BITS_PER_BYTE);
+ }
+ for (i = 0; i < WCD9XXX_NUM_IRQ_REGS; i++) {
+ /* Initialize interrupt mask and level registers */
+ wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_LEVEL0 + i,
+ wcd9xxx->irq_level[i]);
+ wcd9xxx_reg_write(wcd9xxx, TABLA_A_INTR_MASK0 + i,
+ wcd9xxx->irq_masks_cur[i]);
+ }
+
+ ret = request_threaded_irq(wcd9xxx->irq, NULL, wcd9xxx_irq_thread,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wcd9xxx", wcd9xxx);
+ if (ret != 0)
+ dev_err(wcd9xxx->dev, "Failed to request IRQ %d: %d\n",
+ wcd9xxx->irq, ret);
+ else {
+ ret = enable_irq_wake(wcd9xxx->irq);
+ if (ret == 0) {
+ ret = device_init_wakeup(wcd9xxx->dev, 1);
+ if (ret) {
+ dev_err(wcd9xxx->dev, "Failed to init device"
+ "wakeup : %d\n", ret);
+ disable_irq_wake(wcd9xxx->irq);
+ }
+ } else
+ dev_err(wcd9xxx->dev, "Failed to set wake interrupt on"
+ " IRQ %d: %d\n", wcd9xxx->irq, ret);
+ if (ret)
+ free_irq(wcd9xxx->irq, wcd9xxx);
+ }
+
+ if (ret)
+ mutex_destroy(&wcd9xxx->irq_lock);
+
+ return ret;
+}
+
+void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx)
+{
+ if (wcd9xxx->irq) {
+ disable_irq_wake(wcd9xxx->irq);
+ free_irq(wcd9xxx->irq, wcd9xxx);
+ device_init_wakeup(wcd9xxx->dev, 0);
+ }
+ mutex_destroy(&wcd9xxx->irq_lock);
+}
diff --git a/drivers/mfd/wcd9310-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
similarity index 72%
rename from drivers/mfd/wcd9310-slimslave.c
rename to drivers/mfd/wcd9xxx-slimslave.c
index 12ac27f..acef55e 100644
--- a/drivers/mfd/wcd9310-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -11,45 +11,47 @@
*/
#include <linux/slab.h>
#include <linux/mutex.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
-struct tabla_slim_sch_rx {
+struct wcd9xxx_slim_sch_rx {
u32 sph;
u32 ch_num;
u16 ch_h;
u16 grph;
};
-struct tabla_slim_sch_tx {
+struct wcd9xxx_slim_sch_tx {
u32 sph;
u32 ch_num;
u16 ch_h;
u16 grph;
};
-struct tabla_slim_sch {
- struct tabla_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
- struct tabla_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
+struct wcd9xxx_slim_sch {
+ struct wcd9xxx_slim_sch_rx rx[SLIM_MAX_RX_PORTS];
+ struct wcd9xxx_slim_sch_tx tx[SLIM_MAX_TX_PORTS];
};
-static struct tabla_slim_sch sh_ch;
+static struct wcd9xxx_slim_sch sh_ch;
-static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la);
-static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la);
-static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab);
-static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab);
+static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
+ u8 wcd9xxx_pgd_la);
+static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
+ u8 wcd9xxx_pgd_la);
+static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx);
+static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx);
-int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la)
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la)
{
int ret = 0;
- ret = tabla_alloc_slim_sh_ch_rx(tabla, tabla_pgd_la);
+ ret = wcd9xxx_alloc_slim_sh_ch_rx(wcd9xxx, wcd9xxx_pgd_la);
if (ret) {
pr_err("%s: Failed to alloc rx slimbus shared channels\n",
__func__);
goto rx_err;
}
- ret = tabla_alloc_slim_sh_ch_tx(tabla, tabla_pgd_la);
+ ret = wcd9xxx_alloc_slim_sh_ch_tx(wcd9xxx, wcd9xxx_pgd_la);
if (ret) {
pr_err("%s: Failed to alloc tx slimbus shared channels\n",
__func__);
@@ -57,21 +59,21 @@
}
return 0;
tx_err:
- tabla_dealloc_slim_sh_ch_rx(tabla);
+ wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
rx_err:
return ret;
}
-int tabla_deinit_slimslave(struct tabla *tabla)
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx)
{
int ret = 0;
- ret = tabla_dealloc_slim_sh_ch_rx(tabla);
+ ret = wcd9xxx_dealloc_slim_sh_ch_rx(wcd9xxx);
if (ret < 0) {
pr_err("%s: fail to dealloc rx slim ports\n", __func__);
goto err;
}
- ret = tabla_dealloc_slim_sh_ch_tx(tabla);
+ ret = wcd9xxx_dealloc_slim_sh_ch_tx(wcd9xxx);
if (ret < 0) {
pr_err("%s: fail to dealloc tx slim ports\n", __func__);
goto err;
@@ -80,13 +82,13 @@
return ret;
}
-int tabla_get_channel(struct tabla *tabla,
+int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
unsigned int *rx_ch,
unsigned int *tx_ch)
{
int ch_idx = 0;
- struct tabla_slim_sch_rx *rx = sh_ch.rx;
- struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++)
rx_ch[ch_idx] = rx[ch_idx].ch_num;
@@ -95,23 +97,23 @@
return 0;
}
-static int tabla_alloc_slim_sh_ch_rx(struct tabla *tabla, u8 tabla_pgd_la)
+static int wcd9xxx_alloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx,
+ u8 wcd9xxx_pgd_la)
{
int ret = 0;
u8 ch_idx ;
u16 slave_port_id = 0;
- struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
- /* DSP requires channel number to be between 128 and 255. For RX port
- * use channel numbers from 138 to 144, for TX port
- * use channel numbers from 128 to 137
+ /*
+ * DSP requires channel number to be between 128 and 255.
*/
- pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+ pr_debug("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
for (ch_idx = 0; ch_idx < SLIM_MAX_RX_PORTS; ch_idx++) {
slave_port_id = (ch_idx + 1 +
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS);
rx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
- ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+ ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
&rx[ch_idx].sph, SLIM_SINK);
if (ret < 0) {
pr_err("%s: slave port failure id[%d] ret[%d]\n",
@@ -119,7 +121,7 @@
goto err;
}
- ret = slim_query_ch(tabla->slim, rx[ch_idx].ch_num,
+ ret = slim_query_ch(wcd9xxx->slim, rx[ch_idx].ch_num,
&rx[ch_idx].ch_h);
if (ret < 0) {
pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
@@ -131,14 +133,15 @@
return ret;
}
-static int tabla_alloc_slim_sh_ch_tx(struct tabla *tabla, u8 tabla_pgd_la)
+static int wcd9xxx_alloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx,
+ u8 wcd9xxx_pgd_la)
{
int ret = 0;
u8 ch_idx ;
- struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
u16 slave_port_id = 0;
- pr_debug("%s: pgd_la[%d]\n", __func__, tabla_pgd_la);
+ pr_err("%s: pgd_la[%d]\n", __func__, wcd9xxx_pgd_la);
/* DSP requires channel number to be between 128 and 255. For RX port
* use channel numbers from 138 to 144, for TX port
* use channel numbers from 128 to 137
@@ -146,14 +149,14 @@
for (ch_idx = 0; ch_idx < SLIM_MAX_TX_PORTS; ch_idx++) {
slave_port_id = ch_idx;
tx[ch_idx].ch_num = slave_port_id + BASE_CH_NUM;
- ret = slim_get_slaveport(tabla_pgd_la, slave_port_id,
+ ret = slim_get_slaveport(wcd9xxx_pgd_la, slave_port_id,
&tx[ch_idx].sph, SLIM_SRC);
if (ret < 0) {
pr_err("%s: slave port failure id[%d] ret[%d]\n",
__func__, slave_port_id, ret);
goto err;
}
- ret = slim_query_ch(tabla->slim, tx[ch_idx].ch_num,
+ ret = slim_query_ch(wcd9xxx->slim, tx[ch_idx].ch_num,
&tx[ch_idx].ch_h);
if (ret < 0) {
pr_err("%s: slim_query_ch failed ch-num[%d] ret[%d]\n",
@@ -165,14 +168,14 @@
return ret;
}
-static int tabla_dealloc_slim_sh_ch_rx(struct tabla *tab)
+static int wcd9xxx_dealloc_slim_sh_ch_rx(struct wcd9xxx *wcd9xxx)
{
int idx = 0;
int ret = 0;
- struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
/* slim_dealloc_ch */
for (idx = 0; idx < SLIM_MAX_RX_PORTS; idx++) {
- ret = slim_dealloc_ch(tab->slim, rx[idx].ch_h);
+ ret = slim_dealloc_ch(wcd9xxx->slim, rx[idx].ch_h);
if (ret < 0) {
pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
__func__, ret, rx[idx].ch_h);
@@ -182,14 +185,14 @@
return ret;
}
-static int tabla_dealloc_slim_sh_ch_tx(struct tabla *tab)
+static int wcd9xxx_dealloc_slim_sh_ch_tx(struct wcd9xxx *wcd9xxx)
{
int idx = 0;
int ret = 0;
- struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
/* slim_dealloc_ch */
for (idx = 0; idx < SLIM_MAX_TX_PORTS; idx++) {
- ret = slim_dealloc_ch(tab->slim, tx[idx].ch_h);
+ ret = slim_dealloc_ch(wcd9xxx->slim, tx[idx].ch_h);
if (ret < 0) {
pr_err("%s: slim_dealloc_ch fail ret[%d] ch_h[%d]\n",
__func__, ret, tx[idx].ch_h);
@@ -200,7 +203,7 @@
}
/* Enable slimbus slave device for RX path */
-int tabla_cfg_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt, unsigned int rate)
{
u8 i = 0;
@@ -211,15 +214,15 @@
u8 payload_rx = 0, wm_payload = 0;
int ret, idx = 0;
unsigned short multi_chan_cfg_reg_addr;
- struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
struct slim_ch prop;
/* Configure slave interface device */
- pr_debug("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
+ pr_err("%s: ch_cnt[%d] rate=%d\n", __func__, ch_cnt, rate);
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM -
- SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
+ SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
ch_h[i] = rx[idx].ch_h;
sph[i] = rx[idx].sph;
slave_port_id = idx + 1;
@@ -249,7 +252,8 @@
multi_chan_cfg_reg_addr =
SB_PGD_RX_PORT_MULTI_CHANNEL_0(slave_port_id);
/* write to interface device */
- ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ ret = wcd9xxx_interface_reg_write(wcd9xxx,
+ multi_chan_cfg_reg_addr,
payload_rx);
if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -262,7 +266,7 @@
wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
SLAVE_PORT_WATER_MARK_SHIFT) +
SLAVE_PORT_ENABLE;
- ret = tabla_interface_reg_write(tab,
+ ret = wcd9xxx_interface_reg_write(wcd9xxx,
SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
wm_payload);
if (ret < 0) {
@@ -279,7 +283,7 @@
prop.ratem = (rate/4000);
prop.sampleszbits = 16;
- ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+ ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
true, &grph);
if (ret < 0) {
pr_err("%s: slim_define_ch failed ret[%d]\n",
@@ -287,7 +291,7 @@
goto err;
}
for (i = 0; i < ch_cnt; i++) {
- ret = slim_connect_sink(tab->slim, &sph[i],
+ ret = slim_connect_sink(wcd9xxx->slim, &sph[i],
1, ch_h[i]);
if (ret < 0) {
pr_err("%s: slim_connect_sink failed ret[%d]\n",
@@ -296,7 +300,7 @@
}
}
/* slim_control_ch */
- ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+ ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
true);
if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n",
@@ -312,14 +316,14 @@
err_close_slim_sch:
/* release all acquired handles */
- tabla_close_slim_sch_rx(tab, ch_num, ch_cnt);
+ wcd9xxx_close_slim_sch_rx(wcd9xxx, ch_num, ch_cnt);
err:
return ret;
}
-EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_rx);
+EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_rx);
/* Enable slimbus slave device for RX path */
-int tabla_cfg_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt, unsigned int rate)
{
u8 i = 0;
@@ -331,7 +335,7 @@
int ret = 0;
unsigned short multi_chan_cfg_reg_addr;
- struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
struct slim_ch prop;
pr_debug("%s: ch_cnt[%d] rate[%d]\n", __func__, ch_cnt, rate);
@@ -366,7 +370,8 @@
multi_chan_cfg_reg_addr =
SB_PGD_TX_PORT_MULTI_CHANNEL_0(slave_port_id);
/* write to interface device */
- ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ ret = wcd9xxx_interface_reg_write(wcd9xxx,
+ multi_chan_cfg_reg_addr,
payload_tx_0);
if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -378,7 +383,8 @@
multi_chan_cfg_reg_addr =
SB_PGD_TX_PORT_MULTI_CHANNEL_1(slave_port_id);
/* ports 8,9 */
- ret = tabla_interface_reg_write(tab, multi_chan_cfg_reg_addr,
+ ret = wcd9xxx_interface_reg_write(wcd9xxx,
+ multi_chan_cfg_reg_addr,
payload_tx_1);
if (ret < 0) {
pr_err("%s:Intf-dev fail reg[%d] payload[%d] ret[%d]\n",
@@ -391,7 +397,7 @@
wm_payload = (SLAVE_PORT_WATER_MARK_VALUE <<
SLAVE_PORT_WATER_MARK_SHIFT) +
SLAVE_PORT_ENABLE;
- ret = tabla_interface_reg_write(tab,
+ ret = wcd9xxx_interface_reg_write(wcd9xxx,
SB_PGD_PORT_CFG_BYTE_ADDR(slave_port_id),
wm_payload);
if (ret < 0) {
@@ -408,7 +414,7 @@
prop.auxf = SLIM_CH_AUXF_NOT_APPLICABLE;
prop.ratem = (rate/4000);
prop.sampleszbits = 16;
- ret = slim_define_ch(tab->slim, &prop, ch_h, ch_cnt,
+ ret = slim_define_ch(wcd9xxx->slim, &prop, ch_h, ch_cnt,
true, &grph);
if (ret < 0) {
pr_err("%s: slim_define_ch failed ret[%d]\n",
@@ -416,7 +422,7 @@
goto err;
}
for (i = 0; i < ch_cnt; i++) {
- ret = slim_connect_src(tab->slim, sph[i],
+ ret = slim_connect_src(wcd9xxx->slim, sph[i],
ch_h[i]);
if (ret < 0) {
pr_err("%s: slim_connect_src failed ret[%d]\n",
@@ -425,7 +431,7 @@
}
}
/* slim_control_ch */
- ret = slim_control_ch(tab->slim, grph, SLIM_CH_ACTIVATE,
+ ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_ACTIVATE,
true);
if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n",
@@ -439,21 +445,21 @@
return 0;
err:
/* release all acquired handles */
- tabla_close_slim_sch_tx(tab, ch_num, ch_cnt);
+ wcd9xxx_close_slim_sch_tx(wcd9xxx, ch_num, ch_cnt);
return ret;
}
-EXPORT_SYMBOL_GPL(tabla_cfg_slim_sch_tx);
+EXPORT_SYMBOL_GPL(wcd9xxx_cfg_slim_sch_tx);
-int tabla_close_slim_sch_rx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt)
{
u16 grph = 0;
u32 sph[SLIM_MAX_RX_PORTS] = {0};
int i = 0 , idx = 0;
int ret = 0;
- struct tabla_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
- pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+ pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM -
SB_PGD_OFFSET_OF_RX_SLAVE_DEV_PORTS - 1);
@@ -462,13 +468,13 @@
}
/* slim_disconnect_port */
- ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+ ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
if (ret < 0) {
pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
__func__, ret);
}
/* slim_control_ch (REMOVE) */
- ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+ ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n",
__func__, ret);
@@ -482,31 +488,31 @@
err:
return ret;
}
-EXPORT_SYMBOL_GPL(tabla_close_slim_sch_rx);
+EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_rx);
-int tabla_close_slim_sch_tx(struct tabla *tab, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int ch_cnt)
{
u16 grph = 0;
u32 sph[SLIM_MAX_TX_PORTS] = {0};
int ret = 0;
int i = 0 , idx = 0;
- struct tabla_slim_sch_tx *tx = sh_ch.tx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
- pr_debug("%s: ch_cnt[%d]\n", __func__, ch_cnt);
+ pr_err("%s: ch_cnt[%d]\n", __func__, ch_cnt);
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM);
sph[i] = tx[idx].sph;
grph = tx[idx].grph;
}
/* slim_disconnect_port */
- ret = slim_disconnect_ports(tab->slim, sph, ch_cnt);
+ ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
if (ret < 0) {
pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
__func__, ret);
}
/* slim_control_ch (REMOVE) */
- ret = slim_control_ch(tab->slim, grph, SLIM_CH_REMOVE, true);
+ ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n",
__func__, ret);
@@ -519,4 +525,4 @@
err:
return ret;
}
-EXPORT_SYMBOL_GPL(tabla_close_slim_sch_tx);
+EXPORT_SYMBOL_GPL(wcd9xxx_close_slim_sch_tx);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index e4c3152..a8f9f35 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -199,7 +199,7 @@
};
static int __qseecom_is_svc_unique(struct qseecom_dev_handle *data,
- struct qseecom_register_listener_req svc)
+ struct qseecom_register_listener_req *svc)
{
struct qseecom_registered_listener_list *ptr;
int unique = 1;
@@ -207,7 +207,7 @@
spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
list_for_each_entry(ptr, &qseecom.registered_listener_list_head, list) {
- if (ptr->svc.listener_id == svc.listener_id) {
+ if (ptr->svc.listener_id == svc->listener_id) {
pr_err("Service id: %u is already registered\n",
ptr->svc.listener_id);
unique = 0;
@@ -333,16 +333,12 @@
pr_err("copy_from_user failed\n");
return ret;
}
-
- if (!__qseecom_is_svc_unique(data, rcvd_lstnr)) {
+ data->listener.id = 0;
+ data->service = true;
+ if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
pr_err("Service is not unique and is already registered\n");
- return ret;
- }
-
- ret = copy_to_user(argp, &rcvd_lstnr, sizeof(rcvd_lstnr));
- if (ret) {
- pr_err("copy_to_user failed\n");
- return ret;
+ data->released = true;
+ return -EBUSY;
}
new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
@@ -360,13 +356,14 @@
kzfree(new_entry);
return -ENOMEM;
}
+
data->listener.id = rcvd_lstnr.listener_id;
- data->service = true;
init_waitqueue_head(&new_entry->rcv_req_wq);
spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
list_add_tail(&new_entry->list, &qseecom.registered_listener_list_head);
spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+
return ret;
}
@@ -743,6 +740,7 @@
break;
} else {
ptr_app->ref_cnt--;
+ data->released = true;
break;
}
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e364eac..0d2b11d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2877,15 +2877,22 @@
* Select the 3/4 of the range and configure the DLL with the
* selected DLL clock output phase.
*/
-static u8 find_most_appropriate_phase(struct msmsdcc_host *host,
+static int find_most_appropriate_phase(struct msmsdcc_host *host,
u8 *phase_table, u8 total_phases)
{
- u8 ret, ranges[16][16] = { {0}, {0} };
+ int ret;
+ u8 ranges[16][16] = { {0}, {0} };
u8 phases_per_row[16] = {0};
int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
bool phase_0_found = false, phase_15_found = false;
+ if (total_phases > 16) {
+ pr_err("%s: %s: invalid argument: total_phases=%d\n",
+ mmc_hostname(host->mmc), __func__, total_phases);
+ return -EINVAL;
+ }
+
for (cnt = 0; cnt < total_phases; cnt++) {
ranges[row_index][col_index] = phase_table[cnt];
phases_per_row[row_index] += 1;
@@ -2943,7 +2950,7 @@
}
i = ((curr_max * 3) / 4) - 1;
- ret = ranges[selected_row_index][i];
+ ret = (int)ranges[selected_row_index][i];
return ret;
}
@@ -3022,8 +3029,13 @@
} while (++phase < 16);
if (tuned_phase_cnt) {
- phase = find_most_appropriate_phase(host, tuned_phases,
+ rc = find_most_appropriate_phase(host, tuned_phases,
tuned_phase_cnt);
+ if (rc < 0)
+ goto kfree;
+ else
+ phase = (u8)rc;
+
/*
* Finally set the selected phase in delay
* line hw block.
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index b693b18..5a016bb 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -264,19 +264,10 @@
{
int retval = 0;
- retval = usb_autopm_get_interface(dev->intf);
- if (retval < 0) {
- dev_err(dev->devicep, "%s Resumption fail\n", __func__);
- goto done_nopm;
- }
-
retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (retval < 0)
dev_err(dev->devicep, "%s Intr submit %d\n", __func__, retval);
- usb_autopm_put_interface(dev->intf);
-
-done_nopm:
return retval;
}
@@ -342,35 +333,19 @@
}
static int rmnet_usb_ctrl_write_cmd(struct rmnet_ctrl_dev *dev)
{
- int retval = 0;
struct usb_device *udev;
if (!is_dev_connected(dev))
return -ENODEV;
udev = interface_to_usbdev(dev->intf);
- retval = usb_autopm_get_interface(dev->intf);
- if (retval < 0) {
- dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
- __func__, retval);
-
- /*
- * Revisit if (retval == -EPERM)
- * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND);
- */
-
- return retval;
- }
dev->set_ctrl_line_state_cnt++;
- retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
USB_CDC_REQ_SET_CONTROL_LINE_STATE,
(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE),
dev->cbits_tomdm,
dev->intf->cur_altsetting->desc.bInterfaceNumber,
NULL, 0, USB_CTRL_SET_TIMEOUT);
- usb_autopm_put_interface(dev->intf);
-
- return retval;
}
static void ctrl_write_callback(struct urb *urb)
@@ -428,7 +403,7 @@
(unsigned char *)out_ctlreq, (void *)buf, size,
ctrl_write_callback, dev);
- result = usb_autopm_get_interface_async(dev->intf);
+ result = usb_autopm_get_interface(dev->intf);
if (result < 0) {
dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
__func__, result);
@@ -450,7 +425,7 @@
dev_err(dev->devicep, "%s: Submit URB error %d\n",
__func__, result);
dev->snd_encap_cmd_cnt--;
- usb_autopm_put_interface_async(dev->intf);
+ usb_autopm_put_interface(dev->intf);
usb_unanchor_urb(sndurb);
usb_free_urb(sndurb);
kfree(out_ctlreq);
@@ -573,7 +548,7 @@
ctrl_read:
if (!is_dev_connected(dev)) {
- dev_err(dev->devicep, "%s: Device not connected\n",
+ dev_dbg(dev->devicep, "%s: Device not connected\n",
__func__);
return -ENETRESET;
}
@@ -662,6 +637,8 @@
static int rmnet_ctrl_tiocmset(struct rmnet_ctrl_dev *dev, unsigned int set,
unsigned int clear)
{
+ int retval;
+
mutex_lock(&dev->dev_lock);
if (set & TIOCM_DTR)
dev->cbits_tomdm |= ACM_CTRL_DTR;
@@ -681,7 +658,17 @@
mutex_unlock(&dev->dev_lock);
- return rmnet_usb_ctrl_write_cmd(dev);
+ retval = usb_autopm_get_interface(dev->intf);
+ if (retval < 0) {
+ dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
+ __func__, retval);
+ return retval;
+ }
+
+ retval = rmnet_usb_ctrl_write_cmd(dev);
+
+ usb_autopm_put_interface(dev->intf);
+ return retval;
}
static int rmnet_ctrl_tiocmget(struct rmnet_ctrl_dev *dev)
@@ -774,6 +761,10 @@
dev->tx_ctrl_err_cnt = 0;
dev->set_ctrl_line_state_cnt = 0;
+ ret = rmnet_usb_ctrl_write_cmd(dev);
+ if (ret < 0)
+ return ret;
+
dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->inturb) {
dev_err(dev->devicep, "Error allocating int urb\n");
@@ -799,19 +790,15 @@
dev->intf->cur_altsetting->desc.bInterfaceNumber;
dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
- interval =
- max((int)int_in->desc.bInterval,
- (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL);
+ interval = max((int)int_in->desc.bInterval,
+ (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL
+ : FS_LS_INTERVAL);
usb_fill_int_urb(dev->inturb, udev,
dev->int_pipe,
dev->intbuf, wMaxPacketSize,
notification_available_cb, dev, interval);
- ret = rmnet_usb_ctrl_write_cmd(dev);
- if (ret < 0)
- return ret;
-
return rmnet_usb_ctrl_start_rx(dev);
}
@@ -828,6 +815,8 @@
dev->intf = NULL;
mutex_unlock(&dev->dev_lock);
+ wake_up(&dev->read_wait_queue);
+
usb_free_urb(dev->inturb);
dev->inturb = NULL;
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index ffdfce1..1eb6845 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -148,7 +148,6 @@
retval = usbnet_resume(iface);
if (!retval) {
-
if (oldstate & PM_EVENT_SUSPEND)
retval = rmnet_usb_ctrl_start(dev);
}
@@ -260,6 +259,12 @@
return 1;
}
+static int rmnet_usb_manage_power(struct usbnet *dev, int on)
+{
+ dev->intf->needs_remote_wakeup = on;
+ return 0;
+}
+
static int rmnet_change_mtu(struct net_device *dev, int new_mtu)
{
if (0 > new_mtu || RMNET_DATA_LEN < new_mtu)
@@ -494,12 +499,14 @@
/*bit position represents interface number*/
#define PID9034_IFACE_MASK 0xF0
#define PID9048_IFACE_MASK 0x1E0
+#define PID904C_IFACE_MASK 0x1C0
static const struct driver_info rmnet_info_pid9034 = {
.description = "RmNET net device",
.bind = rmnet_usb_bind,
.tx_fixup = rmnet_usb_tx_fixup,
.rx_fixup = rmnet_usb_rx_fixup,
+ .manage_power = rmnet_usb_manage_power,
.data = PID9034_IFACE_MASK,
};
@@ -508,9 +515,19 @@
.bind = rmnet_usb_bind,
.tx_fixup = rmnet_usb_tx_fixup,
.rx_fixup = rmnet_usb_rx_fixup,
+ .manage_power = rmnet_usb_manage_power,
.data = PID9048_IFACE_MASK,
};
+static const struct driver_info rmnet_info_pid904c = {
+ .description = "RmNET net device",
+ .bind = rmnet_usb_bind,
+ .tx_fixup = rmnet_usb_tx_fixup,
+ .rx_fixup = rmnet_usb_rx_fixup,
+ .manage_power = rmnet_usb_manage_power,
+ .data = PID904C_IFACE_MASK,
+};
+
static const struct usb_device_id vidpids[] = {
{
USB_DEVICE(0x05c6, 0x9034), /* MDM9x15*/
@@ -520,6 +537,10 @@
USB_DEVICE(0x05c6, 0x9048), /* MDM9x15*/
.driver_info = (unsigned long)&rmnet_info_pid9048,
},
+ {
+ USB_DEVICE(0x05c6, 0x904c), /* MDM9x15*/
+ .driver_info = (unsigned long)&rmnet_info_pid904c,
+ },
{ }, /* Terminating entry */
};
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index 9f2a396..2032b46 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -19,62 +19,93 @@
#include <linux/slab.h>
#include <linux/module.h>
-/**
- * Allocate resources for a child of a spmi-container node.
- */
-static int of_spmi_allocate_resources(struct spmi_controller *ctrl,
- struct spmi_boardinfo *info,
- struct device_node *node,
- uint32_t num_reg)
+struct of_spmi_dev_info {
+ struct spmi_controller *ctrl;
+ struct spmi_boardinfo b_info;
+};
+
+struct of_spmi_res_info {
+ struct device_node *node;
+ uint32_t num_reg;
+ uint32_t num_irq;
+};
+
+static void of_spmi_sum_resources(struct of_spmi_res_info *r_info, bool has_reg)
{
- int i, num_irq = 0;
+ struct of_irq oirq;
uint64_t size;
uint32_t flags;
+
+ while (of_irq_map_one(r_info->node, r_info->num_irq, &oirq) == 0)
+ r_info->num_irq++;
+
+ if (!has_reg)
+ return;
+
+ /*
+ * We can't use of_address_to_resource here since it includes
+ * address translation; and address translation assumes that no
+ * parent buses have a size-cell of 0. But SPMI does have a
+ * size-cell of 0.
+ */
+ while (of_get_address(r_info->node, r_info->num_reg,
+ &size, &flags) != NULL)
+ r_info->num_reg++;
+}
+
+/**
+ * Allocate resources for a child of a spmi-slave node.
+ */
+static int of_spmi_allocate_resources(struct of_spmi_dev_info *d_info,
+ struct of_spmi_res_info *r_info)
+
+{
+ uint32_t num_irq = r_info->num_irq, num_reg = r_info->num_reg;
+ int i;
struct resource *res;
const __be32 *addrp;
- struct of_irq oirq;
-
- while (of_irq_map_one(node, num_irq, &oirq) == 0)
- num_irq++;
+ uint64_t size;
+ uint32_t flags;
if (num_irq || num_reg) {
res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
if (!res)
return -ENOMEM;
- info->num_resources = num_reg + num_irq;
- info->resource = res;
+ d_info->b_info.num_resources = num_reg + num_irq;
+ d_info->b_info.resource = res;
for (i = 0; i < num_reg; i++, res++) {
/* Addresses are always 16 bits */
- addrp = of_get_address(node, i, &size, &flags);
+ addrp = of_get_address(r_info->node, i, &size, &flags);
BUG_ON(!addrp);
res->start = be32_to_cpup(addrp);
res->end = res->start + size - 1;
res->flags = flags;
}
- WARN_ON(of_irq_to_resource_table(node, res, num_irq) !=
+ WARN_ON(of_irq_to_resource_table(r_info->node, res, num_irq) !=
num_irq);
}
return 0;
}
-static int of_spmi_create_device(struct spmi_controller *ctrl,
- struct spmi_boardinfo *info,
- struct device_node *node)
+static int of_spmi_create_device(struct of_spmi_dev_info *d_info,
+ struct device_node *node)
{
+ struct spmi_controller *ctrl = d_info->ctrl;
+ struct spmi_boardinfo *b_info = &d_info->b_info;
void *result;
int rc;
- rc = of_modalias_node(node, info->name, sizeof(info->name));
+ rc = of_modalias_node(node, b_info->name, sizeof(b_info->name));
if (rc < 0) {
dev_err(&ctrl->dev, "of_spmi modalias failure on %s\n",
node->full_name);
return rc;
}
- info->of_node = of_node_get(node);
- result = spmi_new_device(ctrl, info);
+ b_info->of_node = of_node_get(node);
+ result = spmi_new_device(ctrl, b_info);
if (result == NULL) {
dev_err(&ctrl->dev, "of_spmi: Failure registering %s\n",
@@ -86,32 +117,26 @@
return 0;
}
-static void of_spmi_walk_container_children(struct spmi_controller *ctrl,
- struct spmi_boardinfo *info,
- struct device_node *container)
+static void of_spmi_walk_slave_container(struct of_spmi_dev_info *d_info,
+ struct device_node *container)
{
+ struct spmi_controller *ctrl = d_info->ctrl;
struct device_node *node;
- uint64_t size;
- uint32_t flags, num_reg = 0;
int rc;
for_each_child_of_node(container, node) {
- /*
- * We can't use of_address_to_resource here since it includes
- * address translation; and address translation assumes that no
- * parent buses have a size-cell of 0. But SPMI does have a
- * size-cell of 0.
- */
- while (of_get_address(node, num_reg, &size, &flags) != NULL)
- num_reg++;
+ struct of_spmi_res_info r_info;
- rc = of_spmi_allocate_resources(ctrl, info, node, num_reg);
+ r_info.node = node;
+ of_spmi_sum_resources(&r_info, 1);
+
+ rc = of_spmi_allocate_resources(d_info, &r_info);
if (rc) {
dev_err(&ctrl->dev, "%s: unable to allocate"
" resources\n", __func__);
return;
}
- rc = of_spmi_create_device(ctrl, info, node);
+ rc = of_spmi_create_device(d_info, node);
if (rc) {
dev_err(&ctrl->dev, "%s: unable to create device for"
" node %s\n", __func__, node->full_name);
@@ -129,7 +154,7 @@
return -ENODEV;
for_each_child_of_node(ctrl->dev.of_node, node) {
- struct spmi_boardinfo info = {};
+ struct of_spmi_dev_info d_info = {};
const __be32 *slave_id;
int len, rc;
@@ -140,16 +165,21 @@
continue;
}
- info.slave_id = be32_to_cpup(slave_id);
+ d_info.b_info.slave_id = be32_to_cpup(slave_id);
+ d_info.ctrl = ctrl;
- if (of_get_property(node, "spmi-dev-container", NULL)) {
- of_spmi_walk_container_children(ctrl, &info, node);
+ if (of_get_property(node, "spmi-slave-container", NULL)) {
+ of_spmi_walk_slave_container(&d_info, node);
continue;
} else {
- rc = of_spmi_allocate_resources(ctrl, &info, node, 0);
+ struct of_spmi_res_info r_info;
+
+ r_info.node = node;
+ of_spmi_sum_resources(&r_info, 0);
+ rc = of_spmi_allocate_resources(&d_info, &r_info);
if (rc)
continue;
- of_spmi_create_device(ctrl, &info, node);
+ of_spmi_create_device(&d_info, node);
}
}
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 709583a..f157ff3 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -25,8 +25,10 @@
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/mutex.h>
#define BMS_CONTROL 0x224
+#define BMS_S1_DELAY 0x225
#define BMS_OUTPUT0 0x230
#define BMS_OUTPUT1 0x231
#define BMS_TOLERANCES 0x232
@@ -97,7 +99,7 @@
unsigned int batt_id_channel;
unsigned int pmic_bms_irq[PM_BMS_MAX_INTS];
DECLARE_BITMAP(enabled_irqs, PM_BMS_MAX_INTS);
- spinlock_t bms_output_lock;
+ struct mutex bms_output_lock;
spinlock_t bms_100_lock;
struct single_row_lut *adjusted_fcc_temp_lut;
unsigned int charging_began;
@@ -353,14 +355,6 @@
return -EINVAL;
}
- /* make sure the bms registers are locked */
- rc = pm8xxx_readb(chip->dev->parent, BMS_CONTROL, ®);
- if (rc) {
- pr_err("fail to read BMS_OUTPUT0 for type %d rc = %d\n",
- type, rc);
- return rc;
- }
-
rc = pm_bms_masked_write(chip, BMS_CONTROL, SELECT_OUTPUT_DATA,
type << SELECT_OUTPUT_TYPE_SHIFT);
if (rc) {
@@ -775,12 +769,56 @@
return 100;
}
+#define BMS_MODE_BIT BIT(6)
+#define EN_VBAT_BIT BIT(5)
+#define OVERRIDE_MODE_DELAY_MS 20
+int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+ int *vbat_uv)
+{
+ int16_t vsense_raw;
+ int16_t vbat_raw;
+ int vsense_uv;
+
+ if (the_chip == NULL) {
+ pr_err("Called to early\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&the_chip->bms_output_lock);
+
+ pm8xxx_writeb(the_chip->dev->parent, BMS_S1_DELAY, 0x00);
+ pm_bms_masked_write(the_chip, BMS_CONTROL,
+ BMS_MODE_BIT | EN_VBAT_BIT, BMS_MODE_BIT | EN_VBAT_BIT);
+
+ msleep(OVERRIDE_MODE_DELAY_MS);
+
+ pm_bms_lock_output_data(the_chip);
+ pm_bms_read_output_data(the_chip, VSENSE_AVG, &vsense_raw);
+ pm_bms_read_output_data(the_chip, VBATT_AVG, &vbat_raw);
+ pm_bms_unlock_output_data(the_chip);
+ pm_bms_masked_write(the_chip, BMS_CONTROL,
+ BMS_MODE_BIT | EN_VBAT_BIT, 0);
+
+ pm8xxx_writeb(the_chip->dev->parent, BMS_S1_DELAY, 0x0B);
+
+ mutex_unlock(&the_chip->bms_output_lock);
+
+ convert_vbatt_raw_to_uv(the_chip, vbat_raw, vbat_uv);
+ convert_vsense_to_uv(the_chip, vsense_raw, &vsense_uv);
+ *ibat_ua = vsense_uv * 1000 / (int)the_chip->r_sense;
+
+ pr_debug("vsense_raw = 0x%x vbat_raw = 0x%x"
+ " ibat_ua = %d vbat_uv = %d\n",
+ (uint16_t)vsense_raw, (uint16_t)vbat_raw,
+ *ibat_ua, *vbat_uv);
+ return 0;
+}
+EXPORT_SYMBOL(pm8921_bms_get_simultaneous_battery_voltage_and_current);
+
static int read_soc_params_raw(struct pm8921_bms_chip *chip,
struct pm8921_soc_params *raw)
{
- unsigned long flags;
-
- spin_lock_irqsave(&chip->bms_output_lock, flags);
+ mutex_lock(&chip->bms_output_lock);
pm_bms_lock_output_data(chip);
pm_bms_read_output_data(chip,
@@ -794,7 +832,7 @@
read_cc(chip, &raw->cc);
pm_bms_unlock_output_data(chip);
- spin_unlock_irqrestore(&chip->bms_output_lock, flags);
+ mutex_unlock(&chip->bms_output_lock);
convert_vbatt_raw_to_uv(chip,
raw->vbatt_for_rbatt_raw, &raw->vbatt_for_rbatt_uv);
@@ -808,6 +846,18 @@
if (raw->last_good_ocv_uv)
last_ocv_uv = raw->last_good_ocv_uv;
+ pr_debug("0p625 = %duV\n", chip->xoadc_v0625);
+ pr_debug("1p25 = %duV\n", chip->xoadc_v125);
+
+ pr_debug("vbatt_for_rbatt_raw = 0x%x, vbatt_for_rbatt= %duV\n",
+ raw->vbatt_for_rbatt_raw, raw->vbatt_for_rbatt_uv);
+ pr_debug("ocv_for_rbatt_raw = 0x%x, ocv_for_rbatt= %duV\n",
+ raw->ocv_for_rbatt_raw, raw->ocv_for_rbatt_uv);
+ pr_debug("vsense_for_rbatt_raw = 0x%x, vsense_for_rbatt= %duV\n",
+ raw->vsense_for_rbatt_raw, raw->vsense_for_rbatt_uv);
+ pr_debug("last_good_ocv_raw= 0x%x, last_good_ocv_uv= %duV\n",
+ raw->last_good_ocv_raw, raw->last_good_ocv_uv);
+ pr_debug("cc_raw= 0x%x\n", raw->cc);
return 0;
}
@@ -1077,8 +1127,14 @@
- unusable_charge_uah;
pr_debug("RUC = %duAh\n", remaining_usable_charge_uah);
- soc = (remaining_usable_charge_uah * 100)
- / (fcc_uah - unusable_charge_uah);
+ if (fcc_uah - unusable_charge_uah <= 0) {
+ pr_warn("FCC = %duAh, UUC = %duAh forcing soc = 0\n",
+ fcc_uah, unusable_charge_uah);
+ soc = 0;
+ } else {
+ soc = (remaining_usable_charge_uah * 100)
+ / (fcc_uah - unusable_charge_uah);
+ }
if (soc > 100)
soc = 100;
@@ -1162,12 +1218,18 @@
calib_hkadc(chip);
}
+void pm8921_bms_calibrate_hkadc(void)
+{
+ schedule_work(&the_chip->calib_hkadc_work);
+}
+
static void calibrate_ccadc_work(struct work_struct *work)
{
struct pm8921_bms_chip *chip = container_of(work,
struct pm8921_bms_chip, calib_ccadc_work.work);
pm8xxx_calib_ccadc();
+ calib_hkadc(chip);
schedule_delayed_work(&chip->calib_ccadc_work,
round_jiffies_relative(msecs_to_jiffies
(chip->calib_delay_ms)));
@@ -1176,14 +1238,13 @@
int pm8921_bms_get_vsense_avg(int *result)
{
int rc = -EINVAL;
- unsigned long flags;
if (the_chip) {
- spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+ mutex_lock(&the_chip->bms_output_lock);
pm_bms_lock_output_data(the_chip);
rc = read_vsense_avg(the_chip, result);
pm_bms_unlock_output_data(the_chip);
- spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
+ mutex_unlock(&the_chip->bms_output_lock);
}
pr_err("called before initialization\n");
@@ -1193,7 +1254,6 @@
int pm8921_bms_get_battery_current(int *result_ua)
{
- unsigned long flags;
int vsense;
if (!the_chip) {
@@ -1205,15 +1265,15 @@
return -EINVAL;
}
- spin_lock_irqsave(&the_chip->bms_output_lock, flags);
+ mutex_lock(&the_chip->bms_output_lock);
pm_bms_lock_output_data(the_chip);
read_vsense_avg(the_chip, &vsense);
pm_bms_unlock_output_data(the_chip);
- spin_unlock_irqrestore(&the_chip->bms_output_lock, flags);
- pr_debug("vsense=%d\n", vsense);
+ mutex_unlock(&the_chip->bms_output_lock);
+ pr_debug("vsense=%duV\n", vsense);
/* cast for signed division */
*result_ua = vsense * 1000 / (int)the_chip->r_sense;
-
+ pr_debug("ibat=%duA\n", *result_ua);
return 0;
}
EXPORT_SYMBOL(pm8921_bms_get_battery_current);
@@ -1621,13 +1681,14 @@
return 0;
}
-enum {
+enum bms_request_operation {
CALC_RBATT,
CALC_FCC,
CALC_PC,
CALC_SOC,
CALIB_HKADC,
CALIB_CCADC,
+ GET_VBAT_VSENSE_SIMULTANEOUS,
};
static int test_batt_temp = 5;
@@ -1678,6 +1739,7 @@
{
int param = (int)data;
int ret = 0;
+ int ibat_ua, vbat_uv;
struct pm8921_soc_params raw;
read_soc_params_raw(the_chip, &raw);
@@ -1711,6 +1773,13 @@
*val = 0;
pm8xxx_calib_ccadc();
break;
+ case GET_VBAT_VSENSE_SIMULTANEOUS:
+ /* reading this will call simultaneous vbat and vsense */
+ *val =
+ pm8921_bms_get_simultaneous_battery_voltage_and_current(
+ &ibat_ua,
+ &vbat_uv);
+ break;
default:
ret = -EINVAL;
}
@@ -1854,6 +1923,9 @@
debugfs_create_file("calib_ccadc", 0644, chip->dent,
(void *)CALIB_CCADC, &calc_fops);
+ debugfs_create_file("simultaneous", 0644, chip->dent,
+ (void *)GET_VBAT_VSENSE_SIMULTANEOUS, &calc_fops);
+
for (i = 0; i < ARRAY_SIZE(bms_irq_data); i++) {
if (chip->pmic_bms_irq[bms_irq_data[i].irq_id])
debugfs_create_file(bms_irq_data[i].name, 0444,
@@ -1881,7 +1953,7 @@
pr_err("Cannot allocate pm_bms_chip\n");
return -ENOMEM;
}
- spin_lock_init(&chip->bms_output_lock);
+ mutex_init(&chip->bms_output_lock);
spin_lock_init(&chip->bms_100_lock);
chip->dev = &pdev->dev;
chip->r_sense = pdata->r_sense;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index aca724a..60d4e64 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -256,9 +256,9 @@
int thermal_levels;
struct delayed_work update_heartbeat_work;
struct delayed_work eoc_work;
- struct delayed_work unplug_wrkarnd_restore_work;
+ struct work_struct unplug_ovp_fet_open_work;
struct delayed_work unplug_check_work;
- struct wake_lock unplug_wrkarnd_restore_wake_lock;
+ struct wake_lock unplug_ovp_fet_open_wake_lock;
struct wake_lock eoc_wake_lock;
enum pm8921_chg_cold_thr cold_thr;
enum pm8921_chg_hot_thr hot_thr;
@@ -417,23 +417,28 @@
#define PM8921_CHG_V_MIN_MV 3240
#define PM8921_CHG_V_STEP_MV 20
-#define PM8921_CHG_V_STEP_10_MV_BIT BIT(7)
+#define PM8921_CHG_V_STEP_10MV_OFFSET_BIT BIT(7)
#define PM8921_CHG_VDDMAX_MAX 4500
#define PM8921_CHG_VDDMAX_MIN 3400
#define PM8921_CHG_V_MASK 0x7F
static int __pm_chg_vddmax_set(struct pm8921_chg_chip *chip, int voltage)
{
- int remainder, voltage_20_step;
+ int remainder;
u8 temp = 0;
- voltage_20_step = voltage;
- remainder = voltage % 20;
- if (remainder >= 10) {
- voltage_20_step += 10;
- temp = PM8921_CHG_V_STEP_10_MV_BIT;
+ if (voltage < PM8921_CHG_VDDMAX_MIN
+ || voltage > PM8921_CHG_VDDMAX_MAX) {
+ pr_err("bad mV=%d asked to set\n", voltage);
+ return -EINVAL;
}
- temp |= (voltage_20_step - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+ temp = (voltage - PM8921_CHG_V_MIN_MV) / PM8921_CHG_V_STEP_MV;
+
+ remainder = voltage % 20;
+ if (remainder >= 10) {
+ temp |= PM8921_CHG_V_STEP_10MV_OFFSET_BIT;
+ }
+
pr_debug("voltage=%d setting %02x\n", voltage, temp);
return pm8xxx_writeb(chip->dev->parent, CHG_VDD_MAX, temp);
}
@@ -449,10 +454,10 @@
*voltage = 0;
return rc;
}
- temp &= PM8921_CHG_V_MASK;
- *voltage = (int)temp * PM8921_CHG_V_STEP_MV + PM8921_CHG_V_MIN_MV;
- if (temp & PM8921_CHG_V_STEP_10_MV_BIT)
- *voltage = *voltage - 10;
+ *voltage = (int)(temp & PM8921_CHG_V_MASK) * PM8921_CHG_V_STEP_MV
+ + PM8921_CHG_V_MIN_MV;
+ if (temp & PM8921_CHG_V_STEP_10MV_OFFSET_BIT)
+ *voltage = *voltage + 10;
return 0;
}
@@ -841,6 +846,56 @@
temp);
}
+static void disable_input_voltage_regulation(struct pm8921_chg_chip *chip)
+{
+ u8 temp;
+ int rc;
+
+ rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
+ if (rc) {
+ pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
+ return;
+ }
+ rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
+ if (rc) {
+ pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
+ return;
+ }
+ /* set the input voltage disable bit and the write bit */
+ temp |= 0x81;
+ rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+ if (rc) {
+ pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
+ return;
+ }
+}
+
+static void enable_input_voltage_regulation(struct pm8921_chg_chip *chip)
+{
+ u8 temp;
+ int rc;
+
+ rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
+ if (rc) {
+ pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
+ return;
+ }
+ rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
+ if (rc) {
+ pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
+ return;
+ }
+ /* unset the input voltage disable bit */
+ temp &= 0xFE;
+ /* set the write bit */
+ temp |= 0x80;
+ rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+ if (rc) {
+ pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
+ return;
+ }
+}
+
static int64_t read_battery_id(struct pm8921_chg_chip *chip)
{
int rc;
@@ -1623,7 +1678,11 @@
schedule_delayed_work(&chip->unplug_check_work,
round_jiffies_relative(msecs_to_jiffies
(UNPLUG_CHECK_WAIT_PERIOD_MS)));
+ pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
+ } else {
+ pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
}
+ enable_input_voltage_regulation(chip);
bms_notify_check(chip);
}
@@ -1702,26 +1761,94 @@
wake_lock(&chip->eoc_wake_lock);
}
-#define WRITE_BANK_4 0xC0
-static void unplug_wrkarnd_restore_worker(struct work_struct *work)
+static void turn_off_usb_ovp_fet(struct pm8921_chg_chip *chip)
{
u8 temp;
int rc;
- struct delayed_work *dwork = to_delayed_work(work);
- struct pm8921_chg_chip *chip = container_of(dwork,
- struct pm8921_chg_chip,
- unplug_wrkarnd_restore_work);
- pr_debug("restoring vin_min to %d mV\n", chip->vin_min);
- rc = pm_chg_vinmin_set(the_chip, chip->vin_min);
-
- temp = WRITE_BANK_4 | 0xA;
- rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0x30);
if (rc) {
- pr_err("Error %d writing %d to addr %d\n", rc,
- temp, CHG_BUCK_CTRL_TEST3);
+ pr_err("Failed to write 0x30 to USB_OVP_TEST rc = %d\n", rc);
+ return;
}
- wake_unlock(&chip->unplug_wrkarnd_restore_wake_lock);
+ rc = pm8xxx_readb(chip->dev->parent, USB_OVP_TEST, &temp);
+ if (rc) {
+ pr_err("Failed to read from USB_OVP_TEST rc = %d\n", rc);
+ return;
+ }
+ /* set ovp fet disable bit and the write bit */
+ temp |= 0x81;
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, temp);
+ if (rc) {
+ pr_err("Failed to write 0x%x USB_OVP_TEST rc=%d\n", temp, rc);
+ return;
+ }
+}
+
+static void turn_on_usb_ovp_fet(struct pm8921_chg_chip *chip)
+{
+ u8 temp;
+ int rc;
+
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, 0x30);
+ if (rc) {
+ pr_err("Failed to write 0x30 to USB_OVP_TEST rc = %d\n", rc);
+ return;
+ }
+ rc = pm8xxx_readb(chip->dev->parent, USB_OVP_TEST, &temp);
+ if (rc) {
+ pr_err("Failed to read from USB_OVP_TEST rc = %d\n", rc);
+ return;
+ }
+ /* unset ovp fet disable bit and set the write bit */
+ temp &= 0xFE;
+ temp |= 0x80;
+ rc = pm8xxx_writeb(chip->dev->parent, USB_OVP_TEST, temp);
+ if (rc) {
+ pr_err("Failed to write 0x%x to USB_OVP_TEST rc = %d\n",
+ temp, rc);
+ return;
+ }
+}
+
+static int param_open_ovp_counter = 10;
+module_param(param_open_ovp_counter, int, 0644);
+
+#define WRITE_BANK_4 0xC0
+#define USB_OVP_DEBOUNCE_TIME 0x06
+static void unplug_ovp_fet_open_worker(struct work_struct *work)
+{
+ struct pm8921_chg_chip *chip = container_of(work,
+ struct pm8921_chg_chip,
+ unplug_ovp_fet_open_work);
+ int chg_gone, usb_chg_plugged_in;
+ int count = 0;
+
+ while (count++ < param_open_ovp_counter) {
+ pm_chg_masked_write(chip, USB_OVP_CONTROL,
+ USB_OVP_DEBOUNCE_TIME, 0x0);
+ usleep(10);
+ usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+ chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+ pr_debug("OVP FET count = %d chg_gone=%d, usb_valid = %d\n",
+ count, chg_gone, usb_chg_plugged_in);
+
+ /* note usb_chg_plugged_in=0 => chg_gone=1 */
+ if (chg_gone == 1 && usb_chg_plugged_in == 1) {
+ pr_debug("since chg_gone = 1 dis ovp_fet for 20msec\n");
+ turn_off_usb_ovp_fet(chip);
+
+ msleep(20);
+
+ turn_on_usb_ovp_fet(chip);
+ } else {
+ pm_chg_masked_write(chip, USB_OVP_CONTROL,
+ USB_OVP_DEBOUNCE_TIME, 0x1);
+ pr_debug("Exit count=%d chg_gone=%d, usb_valid=%d\n",
+ count, chg_gone, usb_chg_plugged_in);
+ return;
+ }
+ }
}
static irqreturn_t usbin_valid_irq_handler(int irq, void *data)
{
@@ -1799,8 +1926,7 @@
static irqreturn_t vcp_irq_handler(int irq, void *data)
{
- pr_warning("VCP triggered BATDET forced on\n");
- pr_debug("state_changed_to=%d\n", pm_chg_get_fsm_state(data));
+ pr_debug("fsm_state=%d\n", pm_chg_get_fsm_state(data));
return IRQ_HANDLED;
}
@@ -1867,6 +1993,29 @@
return IRQ_HANDLED;
}
+static int param_vin_disable_counter = 5;
+module_param(param_vin_disable_counter, int, 0644);
+
+static void attempt_reverse_boost_fix(struct pm8921_chg_chip *chip,
+ int count, int usb_ma)
+{
+ pm8921_charger_vbus_draw(500);
+ pr_debug("count = %d iusb=500mA\n", count);
+ disable_input_voltage_regulation(chip);
+ pr_debug("count = %d disable_input_regulation\n", count);
+
+ msleep(20);
+
+ pr_debug("count = %d end sleep 20ms chg_gone=%d, usb_valid = %d\n",
+ count,
+ pm_chg_get_rt_status(chip, CHG_GONE_IRQ),
+ is_usb_chg_plugged_in(chip));
+ pr_debug("count = %d restoring input regulation and usb_ma = %d\n",
+ count, usb_ma);
+ enable_input_voltage_regulation(chip);
+ pm8921_charger_vbus_draw(usb_ma);
+}
+
#define VIN_ACTIVE_BIT BIT(0)
#define UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US 200
#define VIN_MIN_INCREASE_MV 100
@@ -1877,6 +2026,8 @@
struct pm8921_chg_chip, unplug_check_work);
u8 reg_loop;
int ibat, usb_chg_plugged_in;
+ int usb_ma;
+ int chg_gone = 0;
usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
if (!usb_chg_plugged_in) {
@@ -1888,8 +2039,25 @@
);
return;
}
+
+ pm_chg_iusbmax_get(chip, &usb_ma);
+ if (usb_ma == 500) {
+ pr_debug("Stopping Unplug Check Worker since USB == 500mA\n");
+ disable_input_voltage_regulation(chip);
+ return;
+ }
+
+ if (usb_ma <= 100) {
+ pr_debug(
+ "Unenumerated yet or suspended usb_ma = %d skipping\n",
+ usb_ma);
+ goto check_again_later;
+ }
+ if (pm8921_chg_is_enabled(chip, CHG_GONE_IRQ))
+ pr_debug("chg gone irq is enabled\n");
+
reg_loop = pm_chg_get_regulation_loop(chip);
- pr_debug("reg_loop=0x%x\n", reg_loop);
+ pr_debug("reg_loop=0x%x usb_ma = %d\n", reg_loop, usb_ma);
if (reg_loop & VIN_ACTIVE_BIT) {
ibat = get_prop_batt_current(chip);
@@ -1897,28 +2065,28 @@
pr_debug("ibat = %d fsm = %d reg_loop = 0x%x\n",
ibat, pm_chg_get_fsm_state(chip), reg_loop);
if (ibat > 0) {
- int err;
- u8 temp;
+ int count = 0;
- temp = WRITE_BANK_4 | 0xE;
- err = pm8xxx_writeb(chip->dev->parent,
- CHG_BUCK_CTRL_TEST3, temp);
- if (err) {
- pr_err("Error %d writing %d to addr %d\n", err,
- temp, CHG_BUCK_CTRL_TEST3);
+ while (count++ < param_vin_disable_counter
+ && usb_chg_plugged_in == 1) {
+ attempt_reverse_boost_fix(chip, count, usb_ma);
+ usb_chg_plugged_in
+ = is_usb_chg_plugged_in(chip);
}
-
- pm_chg_vinmin_set(chip,
- chip->vin_min + VIN_MIN_INCREASE_MV);
-
- wake_lock(&chip->unplug_wrkarnd_restore_wake_lock);
- schedule_delayed_work(
- &chip->unplug_wrkarnd_restore_work,
- round_jiffies_relative(usecs_to_jiffies
- (UNPLUG_WRKARND_RESTORE_WAIT_PERIOD_US)));
}
}
+ usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+ chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+
+ if (chg_gone == 1 && usb_chg_plugged_in == 1) {
+ /* run the worker directly */
+ pr_debug(" ver5 step: chg_gone=%d, usb_valid = %d\n",
+ chg_gone, usb_chg_plugged_in);
+ schedule_work(&chip->unplug_ovp_fet_open_work);
+ }
+
+check_again_later:
schedule_delayed_work(&chip->unplug_check_work,
round_jiffies_relative(msecs_to_jiffies
(UNPLUG_CHECK_WAIT_PERIOD_MS)));
@@ -2008,6 +2176,13 @@
static irqreturn_t chg_gone_irq_handler(int irq, void *data)
{
struct pm8921_chg_chip *chip = data;
+ int chg_gone, usb_chg_plugged_in;
+
+ usb_chg_plugged_in = is_usb_chg_plugged_in(chip);
+ chg_gone = pm_chg_get_rt_status(chip, CHG_GONE_IRQ);
+
+ pr_debug("chg_gone=%d, usb_valid = %d\n", chg_gone, usb_chg_plugged_in);
+ schedule_work(&chip->unplug_ovp_fet_open_work);
pr_debug("Chg gone fsm_state=%d\n", pm_chg_get_fsm_state(data));
power_supply_changed(&chip->batt_psy);
@@ -2540,6 +2715,7 @@
schedule_delayed_work(&chip->unplug_check_work,
round_jiffies_relative(msecs_to_jiffies
(UNPLUG_CHECK_WAIT_PERIOD_MS)));
+ pm8921_chg_enable_irq(chip, CHG_GONE_IRQ);
}
pm8921_chg_enable_irq(chip, DCIN_VALID_IRQ);
@@ -2621,7 +2797,8 @@
CHG_IRQ(CHGHOT_IRQ, IRQF_TRIGGER_RISING, chghot_irq_handler),
CHG_IRQ(BATTTEMP_COLD_IRQ, IRQF_TRIGGER_RISING,
batttemp_cold_irq_handler),
- CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING, chg_gone_irq_handler),
+ CHG_IRQ(CHG_GONE_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ chg_gone_irq_handler),
CHG_IRQ(BAT_TEMP_OK_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
bat_temp_ok_irq_handler),
CHG_IRQ(COARSE_DET_LOW_IRQ, IRQF_TRIGGER_RISING,
@@ -3320,11 +3497,11 @@
the_chip = chip;
wake_lock_init(&chip->eoc_wake_lock, WAKE_LOCK_SUSPEND, "pm8921_eoc");
- wake_lock_init(&chip->unplug_wrkarnd_restore_wake_lock,
+ wake_lock_init(&chip->unplug_ovp_fet_open_wake_lock,
WAKE_LOCK_SUSPEND, "pm8921_unplug_wrkarnd");
INIT_DELAYED_WORK(&chip->eoc_work, eoc_worker);
- INIT_DELAYED_WORK(&chip->unplug_wrkarnd_restore_work,
- unplug_wrkarnd_restore_worker);
+ INIT_WORK(&chip->unplug_ovp_fet_open_work,
+ unplug_ovp_fet_open_worker);
INIT_DELAYED_WORK(&chip->unplug_check_work, unplug_check_worker);
rc = request_irqs(chip, pdev);
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 7768eed..6d12c7e 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -25,5 +25,13 @@
bool "MSM QPNP"
help
Say 'y' here to include support for the Qualcomm QPNP
+
+config MSM_QPNP_INT
+ depends on SPARSE_IRQ
+ depends on ARCH_MSMCOPPER
+ depends on OF_SPMI
+ bool "MSM QPNP INT"
+ help
+ Say 'y' here to include support for the Qualcomm QPNP interrupt
support. QPNP is a SPMI based PMIC implementation.
endif
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 659e886..d59a610 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_SPMI) += spmi.o
obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o
obj-$(CONFIG_MSM_QPNP) += qpnp.o
+obj-$(CONFIG_MSM_QPNP_INT) += qpnp-int.o
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
new file mode 100644
index 0000000..2998c01
--- /dev/null
+++ b/drivers/spmi/qpnp-int.c
@@ -0,0 +1,510 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/spmi.h>
+#include <linux/radix-tree.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <mach/qpnp-int.h>
+
+#define QPNPINT_MAX_BUSSES 1
+
+/* 16 slave_ids, 256 per_ids per slave, and 8 ints per per_id */
+#define QPNPINT_NR_IRQS (16 * 256 * 8)
+
+enum qpnpint_regs {
+ QPNPINT_REG_RT_STS = 0x10,
+ QPNPINT_REG_SET_TYPE = 0x11,
+ QPNPINT_REG_POLARITY_HIGH = 0x12,
+ QPNPINT_REG_POLARITY_LOW = 0x13,
+ QPNPINT_REG_LATCHED_CLR = 0x14,
+ QPNPINT_REG_EN_SET = 0x15,
+ QPNPINT_REG_EN_CLR = 0x16,
+ QPNPINT_REG_LATCHED_STS = 0x18,
+};
+
+struct q_perip_data {
+ uint8_t type; /* bitmap */
+ uint8_t pol_high; /* bitmap */
+ uint8_t pol_low; /* bitmap */
+ uint8_t int_en; /* bitmap */
+ uint8_t use_count;
+};
+
+struct q_irq_data {
+ uint32_t priv_d; /* data to optimize arbiter interactions */
+ struct q_chip_data *chip_d;
+ struct q_perip_data *per_d;
+ uint8_t mask_shift;
+ uint8_t spmi_slave;
+ uint16_t spmi_offset;
+};
+
+struct q_chip_data {
+ int bus_nr;
+ struct irq_domain domain;
+ struct qpnp_local_int cb;
+ struct spmi_controller *spmi_ctrl;
+ struct radix_tree_root per_tree;
+};
+
+static struct q_chip_data chip_data[QPNPINT_MAX_BUSSES] __read_mostly;
+
+/**
+ * qpnpint_encode_hwirq - translate between qpnp_irq_spec and
+ * hwirq representation.
+ *
+ * slave_offset = (addr->slave * 256 * 8);
+ * perip_offset = slave_offset + (addr->perip * 8);
+ * return perip_offset + addr->irq;
+ */
+static inline int qpnpint_encode_hwirq(struct qpnp_irq_spec *spec)
+{
+ uint32_t hwirq;
+
+ if (spec->slave > 15 || spec->irq > 7)
+ return -EINVAL;
+
+ hwirq = (spec->slave << 11);
+ hwirq |= (spec->per << 3);
+ hwirq |= spec->irq;
+
+ return hwirq;
+}
+/**
+ * qpnpint_decode_hwirq - translate between hwirq and
+ * qpnp_irq_spec representation.
+ */
+static inline int qpnpint_decode_hwirq(unsigned long hwirq,
+ struct qpnp_irq_spec *spec)
+{
+ if (hwirq > 65535)
+ return -EINVAL;
+
+ spec->slave = (hwirq >> 11) & 0xF;
+ spec->per = (hwirq >> 3) & 0xFF;
+ spec->irq = hwirq & 0x7;
+ return 0;
+}
+
+static int qpnpint_spmi_write(struct q_irq_data *irq_d, uint8_t reg,
+ void *buf, uint32_t len)
+{
+ struct q_chip_data *chip_d = irq_d->chip_d;
+ int rc;
+
+ if (!chip_d->spmi_ctrl)
+ return -ENODEV;
+
+ rc = spmi_ext_register_writel(chip_d->spmi_ctrl, irq_d->spmi_slave,
+ irq_d->spmi_offset + reg, buf, len);
+ return rc;
+}
+
+static void qpnpint_irq_mask(struct irq_data *d)
+{
+ struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+ struct q_chip_data *chip_d = irq_d->chip_d;
+ struct q_perip_data *per_d = irq_d->per_d;
+ struct qpnp_irq_spec q_spec;
+ int rc;
+
+ pr_debug("hwirq %lu irq: %d\n", d->hwirq, d->irq);
+
+ if (chip_d->cb.mask) {
+ rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+ if (rc)
+ pr_err("%s: decode failed on hwirq %lu\n",
+ __func__, d->hwirq);
+ else
+ chip_d->cb.mask(chip_d->spmi_ctrl, &q_spec,
+ irq_d->priv_d);
+ }
+
+ per_d->int_en &= ~irq_d->mask_shift;
+
+ rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_CLR,
+ (u8 *)&irq_d->mask_shift, 1);
+ if (rc)
+ pr_err("%s: spmi failure on irq %d\n",
+ __func__, d->irq);
+}
+
+static void qpnpint_irq_mask_ack(struct irq_data *d)
+{
+ struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+ struct q_chip_data *chip_d = irq_d->chip_d;
+ struct q_perip_data *per_d = irq_d->per_d;
+ struct qpnp_irq_spec q_spec;
+ int rc;
+
+ pr_debug("hwirq %lu irq: %d mask: 0x%x\n", d->hwirq, d->irq,
+ irq_d->mask_shift);
+
+ if (chip_d->cb.mask) {
+ rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+ if (rc)
+ pr_err("%s: decode failed on hwirq %lu\n",
+ __func__, d->hwirq);
+ else
+ chip_d->cb.mask(chip_d->spmi_ctrl, &q_spec,
+ irq_d->priv_d);
+ }
+
+ per_d->int_en &= ~irq_d->mask_shift;
+
+ rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_CLR,
+ &irq_d->mask_shift, 1);
+ if (rc)
+ pr_err("%s: spmi failure on irq %d\n",
+ __func__, d->irq);
+
+ rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_LATCHED_CLR,
+ &irq_d->mask_shift, 1);
+ if (rc)
+ pr_err("%s: spmi failure on irq %d\n",
+ __func__, d->irq);
+}
+
+static void qpnpint_irq_unmask(struct irq_data *d)
+{
+ struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+ struct q_chip_data *chip_d = irq_d->chip_d;
+ struct q_perip_data *per_d = irq_d->per_d;
+ struct qpnp_irq_spec q_spec;
+ int rc;
+
+ pr_debug("hwirq %lu irq: %d\n", d->hwirq, d->irq);
+
+ if (chip_d->cb.unmask) {
+ rc = qpnpint_decode_hwirq(d->hwirq, &q_spec);
+ if (rc)
+ pr_err("%s: decode failed on hwirq %lu\n",
+ __func__, d->hwirq);
+ else
+ chip_d->cb.unmask(chip_d->spmi_ctrl, &q_spec,
+ irq_d->priv_d);
+ }
+
+ per_d->int_en |= irq_d->mask_shift;
+ rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_EN_SET,
+ &irq_d->mask_shift, 1);
+ if (rc)
+ pr_err("%s: spmi failure on irq %d\n",
+ __func__, d->irq);
+}
+
+static int qpnpint_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+ struct q_irq_data *irq_d = irq_data_get_irq_chip_data(d);
+ struct q_perip_data *per_d = irq_d->per_d;
+ int rc;
+ u8 buf[3];
+
+ pr_debug("hwirq %lu irq: %d flow: 0x%x\n", d->hwirq,
+ d->irq, flow_type);
+
+ per_d->pol_high &= ~irq_d->mask_shift;
+ per_d->pol_low &= ~irq_d->mask_shift;
+ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+ per_d->type |= irq_d->mask_shift; /* edge trig */
+ if (flow_type & IRQF_TRIGGER_RISING)
+ per_d->pol_high |= irq_d->mask_shift;
+ if (flow_type & IRQF_TRIGGER_FALLING)
+ per_d->pol_low |= irq_d->mask_shift;
+ } else {
+ if ((flow_type & IRQF_TRIGGER_HIGH) &&
+ (flow_type & IRQF_TRIGGER_LOW))
+ return -EINVAL;
+ per_d->type &= ~irq_d->mask_shift; /* level trig */
+ if (flow_type & IRQF_TRIGGER_HIGH)
+ per_d->pol_high |= irq_d->mask_shift;
+ else
+ per_d->pol_high &= ~irq_d->mask_shift;
+ }
+
+ buf[0] = per_d->type;
+ buf[1] = per_d->pol_high;
+ buf[2] = per_d->pol_low;
+
+ rc = qpnpint_spmi_write(irq_d, QPNPINT_REG_SET_TYPE, &buf, 3);
+ if (rc)
+ pr_err("%s: spmi failure on irq %d\n",
+ __func__, d->irq);
+ return rc;
+}
+
+static struct irq_chip qpnpint_chip = {
+ .name = "qpnp-int",
+ .irq_mask = qpnpint_irq_mask,
+ .irq_mask_ack = qpnpint_irq_mask_ack,
+ .irq_unmask = qpnpint_irq_unmask,
+ .irq_set_type = qpnpint_irq_set_type,
+};
+
+static int qpnpint_init_irq_data(struct q_chip_data *chip_d,
+ struct q_irq_data *irq_d,
+ unsigned long hwirq)
+{
+ struct qpnp_irq_spec q_spec;
+ int rc;
+
+ irq_d->mask_shift = 1 << (hwirq & 0x7);
+ rc = qpnpint_decode_hwirq(hwirq, &q_spec);
+ if (rc < 0)
+ return rc;
+ irq_d->spmi_slave = q_spec.slave;
+ irq_d->spmi_offset = q_spec.per << 8;
+ irq_d->per_d->use_count++;
+ irq_d->chip_d = chip_d;
+
+ if (chip_d->cb.register_priv_data)
+ rc = chip_d->cb.register_priv_data(chip_d->spmi_ctrl, &q_spec,
+ &irq_d->priv_d);
+ return rc;
+}
+
+static struct q_irq_data *qpnpint_alloc_irq_data(
+ struct q_chip_data *chip_d,
+ unsigned long hwirq)
+{
+ struct q_irq_data *irq_d;
+ struct q_perip_data *per_d;
+
+ irq_d = kzalloc(sizeof(struct q_irq_data), GFP_KERNEL);
+ if (!irq_d)
+ return ERR_PTR(-ENOMEM);
+
+ /**
+ * The Peripheral Tree is keyed from the slave + per_id. We're
+ * ignoring the irq bits here since this peripheral structure
+ * should be common for all irqs on the same peripheral.
+ */
+ per_d = radix_tree_lookup(&chip_d->per_tree, (hwirq & ~0x7));
+ if (!per_d) {
+ per_d = kzalloc(sizeof(struct q_perip_data), GFP_KERNEL);
+ if (!per_d)
+ return ERR_PTR(-ENOMEM);
+ radix_tree_insert(&chip_d->per_tree,
+ (hwirq & ~0x7), per_d);
+ }
+ irq_d->per_d = per_d;
+
+ return irq_d;
+}
+
+static int qpnpint_register_int(uint32_t busno, unsigned long hwirq)
+{
+ int irq, rc;
+ struct irq_domain *domain;
+ struct q_irq_data *irq_d;
+
+ pr_debug("busno = %u hwirq = %lu\n", busno, hwirq);
+
+ if (hwirq < 0 || hwirq >= 32768) {
+ pr_err("%s: hwirq %lu out of qpnp interrupt bounds\n",
+ __func__, hwirq);
+ return -EINVAL;
+ }
+
+ if (busno < 0 || busno > QPNPINT_MAX_BUSSES) {
+ pr_err("%s: invalid bus number %d\n", __func__, busno);
+ return -EINVAL;
+ }
+
+ domain = &chip_data[busno].domain;
+ irq = irq_domain_to_irq(domain, hwirq);
+
+ rc = irq_alloc_desc_at(irq, numa_node_id());
+ if (rc < 0) {
+ if (rc != -EEXIST)
+ pr_err("%s: failed to alloc irq at %d with "
+ "rc %d\n", __func__, irq, rc);
+ return rc;
+ }
+ irq_d = qpnpint_alloc_irq_data(&chip_data[busno], hwirq);
+ if (IS_ERR(irq_d)) {
+ pr_err("%s: failed to alloc irq data %d with "
+ "rc %d\n", __func__, irq, rc);
+ rc = PTR_ERR(irq_d);
+ goto register_err_cleanup;
+ }
+ rc = qpnpint_init_irq_data(&chip_data[busno], irq_d, hwirq);
+ if (rc) {
+ pr_err("%s: failed to init irq data %d with "
+ "rc %d\n", __func__, irq, rc);
+ goto register_err_cleanup;
+ }
+
+ irq_domain_register_irq(domain, hwirq);
+
+ irq_set_chip_and_handler(irq,
+ &qpnpint_chip,
+ handle_level_irq);
+ irq_set_chip_data(irq, irq_d);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ irq_set_noprobe(irq);
+#endif
+ return 0;
+
+register_err_cleanup:
+ irq_free_desc(irq);
+ if (!IS_ERR(irq_d)) {
+ if (irq_d->per_d->use_count == 1)
+ kfree(irq_d->per_d);
+ else
+ irq_d->per_d->use_count--;
+ kfree(irq_d);
+ }
+ return rc;
+}
+
+static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ struct qpnp_irq_spec addr;
+ struct q_chip_data *chip_d = d->priv;
+ int ret;
+
+ pr_debug("%s: intspec[0] 0x%x intspec[1] 0x%x intspec[2] 0x%x\n",
+ __func__, intspec[0], intspec[1], intspec[2]);
+
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize != 3)
+ return -EINVAL;
+
+ addr.irq = intspec[2] & 0x7;
+ addr.per = intspec[1] & 0xFF;
+ addr.slave = intspec[0] & 0xF;
+
+ ret = qpnpint_encode_hwirq(&addr);
+ if (ret < 0) {
+ pr_err("%s: invalid intspec\n", __func__);
+ return ret;
+ }
+ *out_hwirq = ret;
+ *out_type = IRQ_TYPE_NONE;
+
+ /**
+ * Register the interrupt if it's not already registered.
+ * This implies that mapping a qpnp interrupt allocates
+ * resources.
+ */
+ ret = qpnpint_register_int(chip_d->bus_nr, *out_hwirq);
+ if (ret && ret != -EEXIST) {
+ pr_err("%s: Cannot register hwirq %lu\n", __func__, *out_hwirq);
+ return ret;
+ }
+
+ return 0;
+}
+
+const struct irq_domain_ops qpnpint_irq_domain_ops = {
+ .dt_translate = qpnpint_irq_domain_dt_translate,
+};
+
+int qpnpint_register_controller(unsigned int busno,
+ struct qpnp_local_int *li_cb)
+{
+ if (busno >= QPNPINT_MAX_BUSSES)
+ return -EINVAL;
+ chip_data[busno].cb = *li_cb;
+ chip_data[busno].spmi_ctrl = spmi_busnum_to_ctrl(busno);
+ if (!chip_data[busno].spmi_ctrl)
+ return -ENOENT;
+
+ return 0;
+}
+EXPORT_SYMBOL(qpnpint_register_controller);
+
+int qpnpint_handle_irq(struct spmi_controller *spmi_ctrl,
+ struct qpnp_irq_spec *spec)
+{
+ struct irq_domain *domain;
+ unsigned long hwirq, busno;
+ int irq;
+
+ pr_debug("spec slave = %u per = %u irq = %u\n",
+ spec->slave, spec->per, spec->irq);
+
+ if (!spec || !spmi_ctrl)
+ return -EINVAL;
+
+ busno = spmi_ctrl->nr;
+ if (busno >= QPNPINT_MAX_BUSSES)
+ return -EINVAL;
+
+ hwirq = qpnpint_encode_hwirq(spec);
+ if (hwirq < 0) {
+ pr_err("%s: invalid irq spec passed\n", __func__);
+ return -EINVAL;
+ }
+
+ domain = &chip_data[busno].domain;
+ irq = irq_domain_to_irq(domain, hwirq);
+
+ generic_handle_irq(irq);
+
+ return 0;
+}
+EXPORT_SYMBOL(qpnpint_handle_irq);
+
+/**
+ * This assumes that there's a relationship between the order of the interrupt
+ * controllers specified to of_irq_match() is the SPMI device topology. If
+ * this ever turns out to be a bad assumption, then of_irq_init_cb_t should
+ * be modified to pass a parameter to this function.
+ */
+static int qpnpint_cnt __initdata;
+
+int __init qpnpint_of_init(struct device_node *node, struct device_node *parent)
+{
+ struct q_chip_data *chip_d = &chip_data[qpnpint_cnt];
+ struct irq_domain *domain = &chip_d->domain;
+
+ INIT_RADIX_TREE(&chip_d->per_tree, GFP_ATOMIC);
+
+ domain->irq_base = irq_domain_find_free_range(0, QPNPINT_NR_IRQS);
+ domain->nr_irq = QPNPINT_NR_IRQS;
+ domain->of_node = of_node_get(node);
+ domain->priv = chip_d;
+ domain->ops = &qpnpint_irq_domain_ops;
+ irq_domain_add(domain);
+
+ pr_info("irq_base = %d\n", domain->irq_base);
+
+ qpnpint_cnt++;
+
+ return 0;
+}
+EXPORT_SYMBOL(qpnpint_of_init);
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index f49769d..04dd590 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -639,7 +639,7 @@
/* enable TX & RX */
msm_hsl_write(port, data, regmap[vid][UARTDM_CR]);
- msm_hsl_write(port, RESET_STALE_INT, UARTDM_CR_ADDR);
+ msm_hsl_write(port, RESET_STALE_INT, regmap[vid][UARTDM_CR]);
/* turn on RX and CTS interrupts */
msm_hsl_port->imr = UARTDM_ISR_RXSTALE_BMSK
| UARTDM_ISR_DELTA_CTS_BMSK | UARTDM_ISR_RXLEV_BMSK;
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index aab5b98..9794918 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -82,6 +82,7 @@
urb->status, urb->actual_length);
if (urb->status == -EPROTO) {
+ dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
/* save error so that subsequent read/write returns ESHUTDOWN */
dev->err = urb->status;
return;
@@ -119,27 +120,36 @@
if (dev->err)
return -ESHUTDOWN;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
dev_err(&dev->udev->dev, "unable to allocate urb\n");
return -ENOMEM;
}
+ ret = usb_autopm_get_interface(dev->ifc);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
+ usb_free_urb(urb);
+ return ret;
+ }
+
pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
diag_bridge_read_cb, dev);
usb_anchor_urb(urb, &dev->submitted);
dev->pending_reads++;
- ret = usb_submit_urb(urb, GFP_ATOMIC);
+ ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
dev->pending_reads--;
usb_unanchor_urb(urb);
usb_free_urb(urb);
+ usb_autopm_put_interface(dev->ifc);
return ret;
}
+ usb_autopm_put_interface(dev->ifc);
usb_free_urb(urb);
return 0;
@@ -153,7 +163,10 @@
dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ usb_autopm_put_interface_async(dev->ifc);
+
if (urb->status == -EPROTO) {
+ dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
/* save error so that subsequent read/write returns ESHUTDOWN */
dev->err = urb->status;
return;
@@ -191,24 +204,32 @@
if (dev->err)
return -ESHUTDOWN;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
err("unable to allocate urb");
return -ENOMEM;
}
+ ret = usb_autopm_get_interface(dev->ifc);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
+ usb_free_urb(urb);
+ return ret;
+ }
+
pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
diag_bridge_write_cb, dev);
usb_anchor_urb(urb, &dev->submitted);
dev->pending_writes++;
- ret = usb_submit_urb(urb, GFP_ATOMIC);
+ ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
dev->pending_writes--;
usb_unanchor_urb(urb);
usb_free_urb(urb);
+ usb_autopm_put_interface(dev->ifc);
return ret;
}
@@ -381,6 +402,37 @@
usb_set_intfdata(ifc, NULL);
}
+static int diag_bridge_suspend(struct usb_interface *ifc, pm_message_t message)
+{
+ struct diag_bridge *dev = usb_get_intfdata(ifc);
+ struct diag_bridge_ops *cbs = dev->ops;
+ int ret = 0;
+
+ if (cbs && cbs->suspend) {
+ ret = cbs->suspend(cbs->ctxt);
+ if (ret) {
+ dev_dbg(&dev->udev->dev,
+ "%s: diag veto'd suspend\n", __func__);
+ return ret;
+ }
+
+ usb_kill_anchored_urbs(&dev->submitted);
+ }
+
+ return ret;
+}
+
+static int diag_bridge_resume(struct usb_interface *ifc)
+{
+ struct diag_bridge *dev = usb_get_intfdata(ifc);
+ struct diag_bridge_ops *cbs = dev->ops;
+
+
+ if (cbs && cbs->resume)
+ cbs->resume(cbs->ctxt);
+
+ return 0;
+}
#define VALID_INTERFACE_NUM 0
static const struct usb_device_id diag_bridge_ids[] = {
@@ -390,6 +442,8 @@
.driver_info = VALID_INTERFACE_NUM, },
{ USB_DEVICE(0x5c6, 0x9048),
.driver_info = VALID_INTERFACE_NUM, },
+ { USB_DEVICE(0x5c6, 0x904C),
+ .driver_info = VALID_INTERFACE_NUM, },
{} /* terminating entry */
};
@@ -399,7 +453,10 @@
.name = "diag_bridge",
.probe = diag_bridge_probe,
.disconnect = diag_bridge_disconnect,
+ .suspend = diag_bridge_suspend,
+ .resume = diag_bridge_resume,
.id_table = diag_bridge_ids,
+ .supports_autosuspend = 1,
};
static int __init diag_bridge_init(void)
@@ -408,8 +465,7 @@
ret = usb_register(&diag_bridge_driver);
if (ret) {
- err("%s: unable to register diag driver",
- __func__);
+ err("%s: unable to register diag driver", __func__);
return ret;
}
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 584503a..c23c7b1 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,8 +38,9 @@
#define ACM_CTRL_DTR (1 << 0)
#define DEFAULT_READ_URB_LENGTH 4096
-struct ctrl_bridge {
+#define SUSPENDED BIT(0)
+struct ctrl_bridge {
struct usb_device *udev;
struct usb_interface *intf;
@@ -51,11 +52,14 @@
void *readbuf;
struct usb_anchor tx_submitted;
+ struct usb_anchor tx_deferred;
struct usb_ctrlrequest *in_ctlreq;
struct bridge *brdg;
struct platform_device *pdev;
+ unsigned long flags;
+
/* input control lines (DSR, CTS, CD, RI) */
unsigned int cbits_tohost;
@@ -68,7 +72,6 @@
unsigned int resp_avail;
unsigned int set_ctrl_line_sts;
unsigned int notify_ser_state;
-
};
static struct ctrl_bridge *__dev[MAX_BRIDGE_DEVICES];
@@ -157,11 +160,14 @@
if (resubmit_urb) {
/*re- submit int urb to check response available*/
+ usb_anchor_urb(dev->inturb, &dev->tx_submitted);
status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
- if (status)
+ if (status) {
dev_err(&udev->dev,
"%s: Error re-submitting Int URB %d\n",
__func__, status);
+ usb_unanchor_urb(dev->inturb);
+ }
}
}
@@ -210,11 +216,13 @@
DEFAULT_READ_URB_LENGTH,
resp_avail_cb, dev);
+ usb_anchor_urb(dev->readurb, &dev->tx_submitted);
status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
if (status) {
dev_err(&udev->dev,
"%s: Error submitting Read URB %d\n",
__func__, status);
+ usb_unanchor_urb(dev->readurb);
goto resubmit_int_urb;
}
return;
@@ -238,52 +246,42 @@
}
resubmit_int_urb:
+ usb_anchor_urb(urb, &dev->tx_submitted);
status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
+ if (status) {
dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
__func__, status);
+ usb_unanchor_urb(urb);
+ }
}
int ctrl_bridge_start_read(struct ctrl_bridge *dev)
{
- int retval = 0;
- struct usb_device *udev;
+ int retval = 0;
- udev = interface_to_usbdev(dev->intf);
-
- retval = usb_autopm_get_interface_async(dev->intf);
- if (retval < 0) {
- dev_err(&udev->dev, "%s resumption fail\n", __func__);
- goto done_nopm;
+ if (!dev->inturb) {
+ dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__);
+ return -ENODEV;
}
- retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
- if (retval < 0)
- dev_err(&udev->dev, "%s intr submit %d\n", __func__, retval);
+ if (!dev->inturb->anchor) {
+ usb_anchor_urb(dev->inturb, &dev->tx_submitted);
+ retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
+ if (retval < 0) {
+ dev_err(&dev->udev->dev,
+ "%s error submitting int urb %d\n",
+ __func__, retval);
+ usb_unanchor_urb(dev->inturb);
+ }
+ }
- usb_autopm_put_interface_async(dev->intf);
-done_nopm:
return retval;
}
-static int ctrl_bridge_stop_read(struct ctrl_bridge *dev)
-{
- if (dev->readurb) {
- dev_dbg(&dev->udev->dev, "killing rcv urb\n");
- usb_unlink_urb(dev->readurb);
- }
-
- if (dev->inturb) {
- dev_dbg(&dev->udev->dev, "killing int urb\n");
- usb_unlink_urb(dev->inturb);
- }
-
- return 0;
-}
-
int ctrl_bridge_open(struct bridge *brdg)
{
struct ctrl_bridge *dev;
+ int ret;
if (!brdg) {
err("bridge is null\n");
@@ -306,7 +304,16 @@
dev->set_ctrl_line_sts = 0;
dev->notify_ser_state = 0;
- return ctrl_bridge_start_read(dev);
+ ret = usb_autopm_get_interface(dev->intf);
+ if (ret < 0) {
+ dev_err(&dev->udev->dev, "%s autopm_get fail: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = ctrl_bridge_start_read(dev);
+ usb_autopm_put_interface(dev->intf);
+ return ret;
}
EXPORT_SYMBOL(ctrl_bridge_open);
@@ -325,7 +332,6 @@
ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
usb_unlink_anchored_urbs(&dev->tx_submitted);
- ctrl_bridge_stop_read(dev);
dev->brdg = NULL;
}
@@ -423,6 +429,11 @@
goto free_ctrlreq;
}
+ if (test_bit(SUSPENDED, &dev->flags)) {
+ usb_anchor_urb(writeurb, &dev->tx_deferred);
+ goto deferred;
+ }
+
usb_anchor_urb(writeurb, &dev->tx_submitted);
result = usb_submit_urb(writeurb, GFP_ATOMIC);
if (result < 0) {
@@ -431,7 +442,7 @@
usb_autopm_put_interface_async(dev->intf);
goto unanchor_urb;
}
-
+deferred:
return size;
unanchor_urb:
@@ -458,14 +469,16 @@
if (!dev)
return -ENODEV;
+ set_bit(SUSPENDED, &dev->flags);
usb_kill_anchored_urbs(&dev->tx_submitted);
- return ctrl_bridge_stop_read(dev);
+ return 0;
}
int ctrl_bridge_resume(unsigned int id)
{
struct ctrl_bridge *dev;
+ struct urb *urb;
if (id >= MAX_BRIDGE_DEVICES)
return -EINVAL;
@@ -474,7 +487,28 @@
if (!dev)
return -ENODEV;
- return ctrl_bridge_start_read(dev);
+ if (!test_and_clear_bit(SUSPENDED, &dev->flags))
+ return 0;
+
+ /* submit pending write requests */
+ while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
+ int ret;
+ usb_anchor_urb(urb, &dev->tx_submitted);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ usb_unanchor_urb(urb);
+ kfree(urb->setup_packet);
+ kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ usb_autopm_put_interface_async(dev->intf);
+ }
+ }
+
+ /* if the bridge is open, resume reading */
+ if (dev->brdg)
+ return ctrl_bridge_start_read(dev);
+
+ return 0;
}
#if defined(CONFIG_DEBUG_FS)
@@ -505,7 +539,8 @@
"set ctrlline sts cnt: %u\n"
"notify ser state cnt: %u\n"
"cbits_tomdm: %d\n"
- "cbits_tohost: %d\n",
+ "cbits_tohost: %d\n"
+ "suspended: %d\n",
dev->pdev->name, dev,
dev->snd_encap_cmd,
dev->get_encap_res,
@@ -513,8 +548,8 @@
dev->set_ctrl_line_sts,
dev->notify_ser_state,
dev->cbits_tomdm,
- dev->cbits_tohost);
-
+ dev->cbits_tohost,
+ test_bit(SUSPENDED, &dev->flags));
}
ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -608,6 +643,7 @@
dev->intf = ifc;
init_usb_anchor(&dev->tx_submitted);
+ init_usb_anchor(&dev->tx_deferred);
/*use max pkt size from ep desc*/
ep = &dev->intf->cur_altsetting->endpoint[0].desc;
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 687c8c5..a77d98f 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -61,6 +61,8 @@
struct data_bridge {
struct usb_interface *intf;
struct usb_device *udev;
+ int id;
+
unsigned int bulk_in;
unsigned int bulk_out;
int err;
@@ -543,6 +545,9 @@
struct urb *urb;
int retval;
+ if (!test_and_clear_bit(SUSPENDED, &dev->flags))
+ return 0;
+
while ((urb = usb_get_from_anchor(&dev->delayed))) {
usb_anchor_urb(urb, &dev->tx_active);
atomic_inc(&dev->pending_txurbs);
@@ -559,8 +564,6 @@
dev->txurb_drp_cnt--;
}
- clear_bit(SUSPENDED, &dev->flags);
-
if (dev->brdg)
queue_work(dev->wq, &dev->process_rx_w);
@@ -572,16 +575,16 @@
int retval = 0;
int oldstate;
struct data_bridge *dev = usb_get_intfdata(iface);
- struct bridge *brdg = dev->brdg;
oldstate = iface->dev.power.power_state.event;
iface->dev.power.power_state.event = PM_EVENT_ON;
- retval = data_bridge_resume(dev);
- if (!retval) {
- if (oldstate & PM_EVENT_SUSPEND && brdg)
- retval = ctrl_bridge_resume(brdg->ch_id);
+ if (oldstate & PM_EVENT_SUSPEND) {
+ retval = data_bridge_resume(dev);
+ if (!retval)
+ retval = ctrl_bridge_resume(dev->id);
}
+
return retval;
}
@@ -603,19 +606,13 @@
{
int retval;
struct data_bridge *dev = usb_get_intfdata(intf);
- struct bridge *brdg = dev->brdg;
retval = data_bridge_suspend(dev, message);
if (!retval) {
- if (message.event & PM_EVENT_SUSPEND) {
- if (brdg)
- retval = ctrl_bridge_suspend(brdg->ch_id);
- intf->dev.power.power_state.event = message.event;
- }
- } else {
- dev_dbg(&dev->udev->dev, "%s: device is busy,cannot suspend\n",
- __func__);
+ retval = ctrl_bridge_suspend(dev->id);
+ intf->dev.power.power_state.event = message.event;
}
+
return retval;
}
@@ -646,7 +643,7 @@
skb_queue_head_init(&dev->rx_done);
dev->wq = bridge_wq;
-
+ dev->id = id;
dev->udev = interface_to_usbdev(iface);
dev->intf = iface;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 6964835..dd07d4e 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -67,6 +67,7 @@
static DECLARE_COMPLETION(pmic_vbus_init);
static struct msm_otg *the_msm_otg;
static bool debug_aca_enabled;
+static bool debug_bus_voting_enabled;
/* Prevent idle power collapse(pc) while operating in peripheral mode */
static void otg_pm_qos_update_latency(struct msm_otg *dev, int vote)
@@ -1155,7 +1156,7 @@
*/
otg_pm_qos_update_latency(motg, 1);
/* Configure BUS performance parameters for MAX bandwidth */
- if (motg->bus_perf_client) {
+ if (motg->bus_perf_client && debug_bus_voting_enabled) {
ret = msm_bus_scale_client_update_request(
motg->bus_perf_client, 1);
if (ret)
@@ -2232,13 +2233,64 @@
.release = single_release,
};
+static int msm_otg_bus_show(struct seq_file *s, void *unused)
+{
+ if (debug_bus_voting_enabled)
+ seq_printf(s, "enabled\n");
+ else
+ seq_printf(s, "disabled\n");
+
+ return 0;
+}
+
+static int msm_otg_bus_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, msm_otg_bus_show, inode->i_private);
+}
+
+static ssize_t msm_otg_bus_write(struct file *file, const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[8];
+ int ret;
+ struct seq_file *s = file->private_data;
+ struct msm_otg *motg = s->private;
+
+ memset(buf, 0x00, sizeof(buf));
+
+ if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ return -EFAULT;
+
+ if (!strncmp(buf, "enable", 6)) {
+ /* Do not vote here. Let OTG statemachine decide when to vote */
+ debug_bus_voting_enabled = true;
+ } else {
+ debug_bus_voting_enabled = false;
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 0);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to devote "
+ "for bus bw %d\n", __func__, ret);
+ }
+ }
+
+ return count;
+}
+
+const struct file_operations msm_otg_bus_fops = {
+ .open = msm_otg_bus_open,
+ .read = seq_read,
+ .write = msm_otg_bus_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static struct dentry *msm_otg_dbg_root;
-static struct dentry *msm_otg_dbg_mode;
-static struct dentry *msm_otg_chg_type;
-static struct dentry *msm_otg_dbg_aca;
static int msm_otg_debugfs_init(struct msm_otg *motg)
{
+ struct dentry *msm_otg_dentry;
msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL);
@@ -2248,35 +2300,43 @@
if (motg->pdata->mode == USB_OTG &&
motg->pdata->otg_control == OTG_USER_CONTROL) {
- msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO |
+ msm_otg_dentry = debugfs_create_file("mode", S_IRUGO |
S_IWUSR, msm_otg_dbg_root, motg,
&msm_otg_mode_fops);
- if (!msm_otg_dbg_mode) {
+ if (!msm_otg_dentry) {
debugfs_remove(msm_otg_dbg_root);
msm_otg_dbg_root = NULL;
return -ENODEV;
}
}
- msm_otg_chg_type = debugfs_create_file("chg_type", S_IRUGO,
+ msm_otg_dentry = debugfs_create_file("chg_type", S_IRUGO,
msm_otg_dbg_root, motg,
&msm_otg_chg_fops);
- if (!msm_otg_chg_type) {
+ if (!msm_otg_dentry) {
debugfs_remove_recursive(msm_otg_dbg_root);
return -ENODEV;
}
- msm_otg_dbg_aca = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
+ msm_otg_dentry = debugfs_create_file("aca", S_IRUGO | S_IWUSR,
msm_otg_dbg_root, motg,
&msm_otg_aca_fops);
- if (!msm_otg_dbg_aca) {
+ if (!msm_otg_dentry) {
debugfs_remove_recursive(msm_otg_dbg_root);
return -ENODEV;
}
+ msm_otg_dentry = debugfs_create_file("bus_voting", S_IRUGO | S_IWUSR,
+ msm_otg_dbg_root, motg,
+ &msm_otg_bus_fops);
+
+ if (!msm_otg_dentry) {
+ debugfs_remove_recursive(msm_otg_dbg_root);
+ return -ENODEV;
+ }
return 0;
}
@@ -2642,6 +2702,8 @@
if (!motg->bus_perf_client)
dev_err(motg->otg.dev, "%s: Failed to register BUS "
"scaling client!!\n", __func__);
+ else
+ debug_bus_voting_enabled = true;
}
return 0;
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index b29a974..44e887c 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -1,7 +1,7 @@
/*
* Qualcomm Serial USB driver
*
- * Copyright (c) 2008 QUALCOMM Incorporated.
+ * Copyright (c) 2008, 2012 QUALCOMM Incorporated.
* Copyright (c) 2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (c) 2009 Novell Inc.
*
@@ -82,7 +82,8 @@
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
- {USB_DEVICE(0x05c6, 0x9048)},
+ {USB_DEVICE(0x05c6, 0x9048)}, /* MDM9x15 device */
+ {USB_DEVICE(0x05c6, 0x904C)}, /* MDM9x15 device */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index ef357db..96d9487 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -2475,12 +2475,6 @@
goto error;
}
- /*
- * A small delay is needed here to avoid device crash observed
- * during reauthentication in MSM8960
- */
- msleep(20);
-
/* 0x0168 HDCP_RCVPORT_DATA12
[23:8] BSTATUS
[7:0] BCAPS */
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 6c5a9f9..d374b4c 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -738,6 +738,11 @@
#ifdef CONFIG_MSM_BUS_SCALING
int mdp_bus_scale_update_request(uint32_t index);
+#else
+static inline int mdp_bus_scale_update_request(uint32_t index)
+{
+ return 0;
+}
#endif
#ifdef MDP_HW_VSYNC
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 3ca8c9c..033a73c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -402,7 +402,8 @@
pipe->op_mode |= MDP4_OP_SCALEY_EN;
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
- if (pipe->alpha_enable && pipe->dst_h > pipe->src_h)
+ if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+ pipe->alpha_enable && pipe->dst_h > pipe->src_h)
pipe->op_mode |= MDP4_OP_SCALEY_PIXEL_RPT;
else if (pipe->dst_h <= (pipe->src_h / 4))
pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE;
@@ -424,7 +425,8 @@
pipe->op_mode |= MDP4_OP_SCALEX_EN;
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
- if (pipe->alpha_enable && pipe->dst_w > pipe->src_w)
+ if (pipe->flags & MDP_BACKEND_COMPOSITION &&
+ pipe->alpha_enable && pipe->dst_w > pipe->src_w)
pipe->op_mode |= MDP4_OP_SCALEX_PIXEL_RPT;
else if (pipe->dst_w <= (pipe->src_w / 4))
pipe->op_mode |= MDP4_OP_SCALEX_MN_PHASE;
@@ -1385,14 +1387,8 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
- if (data) {
- if (pipe_cnt == 1) {
- mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
-#ifdef CONFIG_MSM_BUS_SCALING
- mdp_bus_scale_update_request(2);
-#endif
- }
- }
+ if (data && pipe_cnt == 1)
+ mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
}
void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
@@ -1891,7 +1887,7 @@
static int get_img(struct msmfb_data *img, struct fb_info *info,
unsigned long *start, unsigned long *len, struct file **srcp_file,
- struct ion_handle **srcp_ihdl)
+ int *p_need, struct ion_handle **srcp_ihdl)
{
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -1901,6 +1897,8 @@
#ifdef CONFIG_ANDROID_PMEM
unsigned long vstart;
#endif
+ *p_need = 0;
+
if (img->flags & MDP_BLIT_SRC_GEM) {
*srcp_file = NULL;
return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
@@ -1916,8 +1914,10 @@
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
if (get_fb_phys_info(start, len, fb_num))
ret = -1;
- else
+ else {
*srcp_file = file;
+ *p_need = put_needed;
+ }
} else
ret = -1;
if (ret)
@@ -2034,9 +2034,7 @@
#define OVERLAY_720P_TILE_SIZE 0x0E6000
#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
-#ifdef CONFIG_MSM_BUS_SCALING
#define OVERLAY_BUS_SCALE_TABLE_BASE 6
-#endif
static int mdp4_overlay_is_rgb_type(int format)
{
@@ -2058,7 +2056,7 @@
static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
struct msm_fb_data_type *mfd)
{
- int is_fg;
+ int is_fg, i, cnt;
if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
is_fg = 1;
@@ -2069,9 +2067,10 @@
if (req->flags & MDP_DEINTERLACE)
return OVERLAY_PERF_LEVEL1;
- if (ctrl->plist[OVERLAY_PIPE_VG1].pipe_used &&
- ctrl->plist[OVERLAY_PIPE_VG2].pipe_used)
- return OVERLAY_PERF_LEVEL1;
+ for (i = 0, cnt = 0; i < OVERLAY_PIPE_MAX; i++) {
+ if (ctrl->plist[i].pipe_used && ++cnt > 2)
+ return OVERLAY_PERF_LEVEL1;
+ }
if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
@@ -2114,6 +2113,8 @@
if (old_perf_level != cur_perf_level) {
mdp_set_core_clk(cur_perf_level);
old_perf_level = cur_perf_level;
+ mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
+ - cur_perf_level);
}
}
@@ -2140,6 +2141,21 @@
mfd->ov0_blt_state = mfd->use_ov0_blt;
}
+static void mdp4_overlay1_update_blt_mode(struct msm_fb_data_type *mfd)
+{
+ if (mfd->ov1_blt_state == mfd->use_ov1_blt)
+ return;
+ if (mfd->use_ov1_blt) {
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+ mdp4_dtv_overlay_blt_start(mfd);
+ pr_debug("%s overlay1 writeback is enabled\n", __func__);
+ } else {
+ mdp4_dtv_overlay_blt_stop(mfd);
+ pr_debug("%s overlay1 writeback is disabled\n", __func__);
+ }
+ mfd->ov1_blt_state = mfd->use_ov1_blt;
+}
+
static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
struct msm_fb_data_type *mfd, uint32 perf_level)
{
@@ -2150,7 +2166,8 @@
clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
if ((mfd->panel_info.type == LCDC_PANEL) ||
- (mfd->panel_info.type == MIPI_VIDEO_PANEL))
+ (mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
+ (mfd->panel_info.type == DTV_PANEL))
pull_mode = 1;
if (pull_mode && (req->src_rect.h > req->dst_rect.h ||
@@ -2169,7 +2186,8 @@
if (req->dst_rect.x != 0)
use_blt = 1;
}
- if (mfd->panel_info.xres > 1280)
+ if ((mfd->panel_info.xres > 1280) &&
+ (mfd->panel_info.type != DTV_PANEL))
use_blt = 1;
}
return use_blt;
@@ -2197,8 +2215,6 @@
return -EINTR;
}
- perf_level = mdp4_overlay_get_perf_level(req, mfd);
-
mixer = mfd->panel_info.pdest; /* DISPLAY_1 or DISPLAY_2 */
ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
@@ -2209,6 +2225,8 @@
return ret;
}
+ perf_level = mdp4_overlay_get_perf_level(req, mfd);
+
if (mixer == MDP4_MIXER0) {
u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
@@ -2252,8 +2270,12 @@
}
if (ctrl->panel_mode & MDP4_PANEL_DTV &&
- pipe->mixer_num == MDP4_MIXER1)
+ pipe->mixer_num == MDP4_MIXER1) {
+ u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
mdp4_overlay_dtv_set(mfd, pipe);
+ mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
+ mfd->use_ov1_blt |= (use_blt << (pipe->pipe_ndx-1));
+ }
if (new_perf_level != perf_level) {
u32 old_level = new_perf_level;
@@ -2282,13 +2304,6 @@
}
mutex_unlock(&mfd->dma->ov_mutex);
-#ifdef CONFIG_MSM_BUS_SCALING
- if (pipe->mixer_num == MDP4_MIXER0) {
- mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
- - perf_level);
- }
-#endif
-
return 0;
}
@@ -2333,8 +2348,7 @@
#endif
}
- if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt &&
- !(ctrl->panel_mode & (MDP4_PANEL_MDDI | MDP4_PANEL_DSI_CMD))) {
+ if (mfd->mdp_rev >= MDP_REV_42 && !mfd->use_ov0_blt) {
ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
} else {
mdp4_mixer_stage_down(pipe);
@@ -2344,6 +2358,11 @@
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
if (mfd->panel_power_on)
mdp4_dsi_cmd_overlay_restore();
+ } else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ if (mfd->panel_power_on)
+ mdp4_overlay_dsi_video_vsync_push(mfd,
+ pipe);
}
#else
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
@@ -2354,13 +2373,24 @@
mdp4_mddi_overlay_restore();
}
#endif
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ if (mfd->panel_power_on)
+ mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+ }
mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
mdp4_overlay_update_blt_mode(mfd);
if (!mfd->use_ov0_blt)
mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
} else { /* mixer1, DTV, ATV */
- if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ if (ctrl->panel_mode & MDP4_PANEL_DTV) {
mdp4_overlay_dtv_unset(mfd, pipe);
+ mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
+ mdp4_overlay1_update_blt_mode(mfd);
+ if (!mfd->use_ov1_blt)
+ mdp4_free_writeback_buf(mfd,
+ MDP4_MIXER1);
+ }
}
}
@@ -2377,8 +2407,6 @@
mdp4_overlay_pipe_free(pipe);
- mdp4_set_perf_level();
-
mutex_unlock(&mfd->dma->ov_mutex);
return 0;
@@ -2439,6 +2467,9 @@
mdp4_mixer_stage_commit(pipe->mixer_num);
+ if (mfd->use_ov1_blt)
+ mdp4_overlay1_update_blt_mode(mfd);
+
mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
mutex_unlock(&mfd->dma->ov_mutex);
@@ -2456,6 +2487,7 @@
struct file *srcp1_file = NULL, *srcp2_file = NULL;
struct ion_handle *srcp0_ihdl = NULL;
struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
+ int ps0_need, p_need;
uint32_t overlay_version = 0;
int ret = 0;
@@ -2475,7 +2507,7 @@
return -EINTR;
img = &req->data;
- get_img(img, info, &start, &len, &srcp0_file, &srcp0_ihdl);
+ get_img(img, info, &start, &len, &srcp0_file, &ps0_need, &srcp0_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: pmem Error\n", __func__);
@@ -2494,7 +2526,7 @@
if (overlay_version > 0) {
img = &req->plane1_data;
get_img(img, info, &start, &len, &srcp1_file,
- &srcp1_ihdl);
+ &p_need, &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane1\n", __func__);
@@ -2526,7 +2558,7 @@
if (overlay_version > 0) {
img = &req->plane1_data;
get_img(img, info, &start, &len, &srcp1_file,
- &srcp1_ihdl);
+ &p_need, &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane1\n", __func__);
@@ -2537,7 +2569,7 @@
img = &req->plane2_data;
get_img(img, info, &start, &len, &srcp2_file,
- &srcp2_ihdl);
+ &p_need, &srcp2_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane2\n", __func__);
@@ -2580,6 +2612,9 @@
if (mfd->use_ov0_blt)
mdp4_overlay_update_blt_mode(mfd);
+ if (mfd->use_ov1_blt)
+ mdp4_overlay1_update_blt_mode(mfd);
+
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
} else {
@@ -2605,8 +2640,11 @@
} else if (pipe->mixer_num == MDP4_MIXER1) {
ctrl->mixer1_played++;
/* enternal interface */
- if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ if (ctrl->panel_mode & MDP4_PANEL_DTV) {
mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+ if (!mfd->use_ov1_blt)
+ mdp4_overlay1_update_blt_mode(mfd);
+ }
} else {
/* primary interface */
@@ -2659,9 +2697,13 @@
if (srcp2_file)
put_pmem_file(srcp2_file);
#endif
+ /* only source may use frame buffer */
+ if (img->flags & MDP_MEMORY_ID_TYPE_FB)
+ fput_light(srcp0_file, ps0_need);
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- if (!IS_ERR_OR_NULL(srcp0_ihdl))
+ else if (!IS_ERR_OR_NULL(srcp0_ihdl))
ion_free(mfd->iclient, srcp0_ihdl);
+
if (!IS_ERR_OR_NULL(srcp1_ihdl))
ion_free(mfd->iclient, srcp1_ihdl);
if (!IS_ERR_OR_NULL(srcp2_ihdl))
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 590ad65..d5c08e8 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -301,7 +301,7 @@
/* MSP_BORDER_COLOR */
MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
(0x0 & 0xFFF)); /* 12-bit R */
- mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
} else {
switch (mfd->ibuf.bpp) {
case 2:
@@ -369,6 +369,9 @@
{
int result = 0;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+
if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
pipe->pipe_type == OVERLAY_TYPE_RGB) {
result = mdp4_dtv_stop(mfd);
@@ -593,13 +596,11 @@
void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
{
- mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
mdp4_dtv_do_blt(mfd, 1);
}
void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
{
- mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
mdp4_dtv_do_blt(mfd, 0);
}
diff --git a/drivers/video/msm/mipi_tc358764_dsi2lvds.c b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
index fcb5163..1624534 100644
--- a/drivers/video/msm/mipi_tc358764_dsi2lvds.c
+++ b/drivers/video/msm/mipi_tc358764_dsi2lvds.c
@@ -226,10 +226,14 @@
static u32 d2l_3d_gpio_enable;
static u32 d2l_3d_gpio_mode;
static int d2l_enable_3d;
+static struct i2c_client *d2l_i2c_client;
+static struct i2c_driver d2l_i2c_slave_driver;
static int mipi_d2l_init(void);
static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
bool enable, bool mode);
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg);
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val);
/**
* Read a bridge register
@@ -296,6 +300,20 @@
mipi_d2l_read_reg(mfd, SYSSTAT); /* 0x500 */
}
+static void mipi_d2l_read_status_via_i2c(struct i2c_client *client)
+{
+ u32 tmp = 0;
+
+ tmp = d2l_i2c_read_reg(client, DSIERRCNT);
+ d2l_i2c_write_reg(client, DSIERRCNT, 0xFFFF0000);
+
+ d2l_i2c_read_reg(client, DSI_LANESTATUS0); /* 0x214 */
+ d2l_i2c_read_reg(client, DSI_LANESTATUS1); /* 0x218 */
+ d2l_i2c_read_reg(client, DSI_INTSTATUS); /* 0x220 */
+ d2l_i2c_read_reg(client, SYSSTAT); /* 0x500 */
+
+ d2l_i2c_write_reg(client, DSIERRCNT, tmp);
+}
/**
* Init the D2L bridge via the DSI interface for Video.
*
@@ -315,12 +333,19 @@
u32 vpctrl;
u32 htime1;
u32 vtime1;
+ u32 htime2;
+ u32 vtime2;
u32 ppi_tx_rx_ta; /* BTA Bus-Turn-Around */
u32 lvcfg;
u32 hbpr; /* Horizontal Back Porch */
u32 hpw; /* Horizontal Pulse Width */
u32 vbpr; /* Vertical Back Porch */
u32 vpw; /* Vertical Pulse Width */
+
+ u32 hfpr; /* Horizontal Front Porch */
+ u32 hsize; /* Horizontal Active size */
+ u32 vfpr; /* Vertical Front Porch */
+ u32 vsize; /* Vertical Active size */
bool vesa_rgb888 = false;
lanes_enable = 0x01; /* clock-lane enable */
@@ -345,8 +370,12 @@
return -EINVAL;
}
- pr_debug("%s.xres=%d.yres=%d.\n",
- __func__, mfd->panel_info.xres, mfd->panel_info.yres);
+ pr_debug("%s.xres=%d.yres=%d.fps=%d.dst_format=%d.\n",
+ __func__,
+ mfd->panel_info.xres,
+ mfd->panel_info.yres,
+ mfd->panel_info.mipi.frame_rate,
+ mfd->panel_info.mipi.dst_format);
hbpr = mfd->panel_info.lcdc.h_back_porch;
hpw = mfd->panel_info.lcdc.h_pulse_width;
@@ -355,6 +384,15 @@
htime1 = (hbpr << 16) + hpw;
vtime1 = (vbpr << 16) + vpw;
+
+ hfpr = mfd->panel_info.lcdc.h_front_porch;
+ hsize = mfd->panel_info.xres;
+ vfpr = mfd->panel_info.lcdc.v_front_porch;
+ vsize = mfd->panel_info.yres;
+
+ htime2 = (hfpr << 16) + hsize;
+ vtime2 = (vfpr << 16) + vsize;
+
lvcfg = 0x0003; /* PCLK=DCLK/3, Dual Link, LVEN */
vpctrl = 0x01000120; /* Output RGB888 , Event-Mode , */
ppi_tx_rx_ta = 0x00040004;
@@ -403,6 +441,8 @@
mipi_d2l_write_reg(mfd, VPCTRL, vpctrl); /* RGB888 + Event mode */
mipi_d2l_write_reg(mfd, HTIM1, htime1);
mipi_d2l_write_reg(mfd, VTIM1, vtime1);
+ mipi_d2l_write_reg(mfd, HTIM2, htime2);
+ mipi_d2l_write_reg(mfd, VTIM2, vtime2);
mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
mipi_d2l_write_reg(mfd, LVCFG, lvcfg); /* Enables LVDS tx */
@@ -539,6 +579,9 @@
mipi_d2l_enable_3d(mfd, false, false);
+ /* Add I2C driver only after DSI-CLK is running */
+ i2c_add_driver(&d2l_i2c_slave_driver);
+
pr_info("%s.ret=%d.\n", __func__, ret);
return ret;
@@ -589,6 +632,103 @@
.set_backlight = mipi_d2l_set_backlight,
};
+static u32 d2l_i2c_read_reg(struct i2c_client *client, u16 reg)
+{
+ int rc;
+ u32 val = 0;
+ u8 buf[6];
+
+ if (client == NULL) {
+ pr_err("%s.invalid i2c client.\n", __func__);
+ return -EINVAL;
+ }
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+
+ rc = i2c_master_send(client, buf, sizeof(reg));
+ rc = i2c_master_recv(client, buf, 4);
+
+ if (rc >= 0) {
+ val = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+ } else
+ pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+ return val;
+}
+
+static u32 d2l_i2c_write_reg(struct i2c_client *client, u16 reg, u32 val)
+{
+ int rc;
+ u8 buf[6];
+
+ if (client == NULL) {
+ pr_err("%s.invalid i2c client.\n", __func__);
+ return -EINVAL;
+ }
+
+ buf[0] = reg >> 8;
+ buf[1] = reg & 0xFF;
+
+ buf[2] = (val >> 0) & 0xFF;
+ buf[3] = (val >> 8) & 0xFF;
+ buf[4] = (val >> 16) & 0xFF;
+ buf[5] = (val >> 24) & 0xFF;
+
+ rc = i2c_master_send(client, buf, sizeof(buf));
+
+ if (rc >= 0)
+ pr_debug("%s.reg=0x%x.val=0x%x.\n", __func__, reg, val);
+ else
+ pr_err("%s.fail.reg=0x%x.\n", __func__, reg);
+
+ return val;
+}
+
+static int __devinit d2l_i2c_slave_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ static const u32 i2c_funcs = I2C_FUNC_I2C;
+
+ d2l_i2c_client = client;
+
+ if (!i2c_check_functionality(client->adapter, i2c_funcs)) {
+ pr_err("%s.i2c_check_functionality failed.\n", __func__);
+ return -ENOSYS;
+ } else {
+ pr_debug("%s.i2c_check_functionality OK.\n", __func__);
+ }
+
+ d2l_i2c_read_reg(client, IDREG);
+
+ mipi_d2l_read_status_via_i2c(d2l_i2c_client);
+
+ return 0;
+}
+
+static __devexit int d2l_i2c_slave_remove(struct i2c_client *client)
+{
+ d2l_i2c_client = NULL;
+
+ return 0;
+}
+
+static const struct i2c_device_id d2l_i2c_id[] = {
+ {"tc358764-i2c", 0},
+ {}
+};
+
+static struct i2c_driver d2l_i2c_slave_driver = {
+ .driver = {
+ .name = "tc358764-i2c",
+ .owner = THIS_MODULE
+ },
+ .probe = d2l_i2c_slave_probe,
+ .remove = __devexit_p(d2l_i2c_slave_remove),
+ .id_table = d2l_i2c_id,
+};
+
static int mipi_d2l_enable_3d(struct msm_fb_data_type *mfd,
bool enable, bool mode)
{
@@ -630,6 +770,8 @@
mipi_d2l_enable_3d(d2l_mfd, true, false);
else if (data == 0)
mipi_d2l_enable_3d(d2l_mfd, false, false);
+ else if (data == 9)
+ mipi_d2l_read_status_via_i2c(d2l_i2c_client);
else
pr_err("%s.Invalid value=%d.\n", __func__, data);
}
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index 3b000ec..0f40c77 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -11,6 +11,7 @@
*
*/
#include <linux/clk.h>
+#include <mach/clk.h>
#include "msm_fb.h"
#include "mdp.h"
#include "mdp4.h"
@@ -634,6 +635,10 @@
hdmi_msm_clk(0);
udelay(5);
hdmi_msm_clk(1);
+
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_ASSERT);
+ udelay(20);
+ clk_reset(hdmi_msm_state->hdmi_app_clk, CLK_RESET_DEASSERT);
}
void hdmi_msm_init_phy(int video_format)
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 593f10b..2962393 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -188,40 +188,14 @@
};
#endif
-#define PANEL_NAME_MAX_LEN 30
static struct msm_fb_platform_data *msm_fb_pdata;
-static char prim_panel_name[PANEL_NAME_MAX_LEN];
-static char ext_panel_name[PANEL_NAME_MAX_LEN];
-module_param_string(prim_display, prim_panel_name, sizeof(prim_panel_name) , 0);
-module_param_string(ext_display, ext_panel_name, sizeof(ext_panel_name) , 0);
int msm_fb_detect_client(const char *name)
{
int ret = 0;
- u32 len;
#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
u32 id;
#endif
- len = strnlen(name, PANEL_NAME_MAX_LEN);
- if (strnlen(prim_panel_name, PANEL_NAME_MAX_LEN)) {
- MSM_FB_DEBUG("\n name = %s, prim_display = %s",
- name, prim_panel_name);
- if (!strncmp((char *)prim_panel_name, name, len))
- return 0;
- else
- ret = -EPERM;
- }
- if (strnlen(ext_panel_name, PANEL_NAME_MAX_LEN)) {
- MSM_FB_DEBUG("\n name = %s, ext_display = %s",
- name, ext_panel_name);
- if (!strncmp((char *)ext_panel_name, name, len))
- return 0;
- else
- ret = -EPERM;
- }
-
- if (ret)
- return ret;
ret = -EPERM;
if (msm_fb_pdata && msm_fb_pdata->detect_client) {
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 9837f07..a4b46ea 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -177,6 +177,7 @@
u32 mem_hid;
u32 mdp_rev;
u32 use_ov0_blt, ov0_blt_state;
+ u32 use_ov1_blt, ov1_blt_state;
u32 writeback_state;
};
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index bfaac82..f685cd5 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -2024,8 +2024,8 @@
}
client_index = vid_dec_get_empty_client_index();
- if (client_index == -1) {
- ERR("%s() : No free clients client_index == -1\n", __func__);
+ if (client_index < 0) {
+ ERR("%s() : No free clients client_index < 0\n", __func__);
goto client_failure;
}
client_ctx = &vid_dec_device_p->vdec_clients[client_index];
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index 500ee6b..3ac41bc 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -37,6 +37,8 @@
u8 variant_id;
u8 version;
u8 build;
+ /* Points to the firmware name to be upgraded to */
+ const char *fw_name;
};
/* The platform data for the Atmel maXTouch touchscreen driver */
diff --git a/include/linux/ion.h b/include/linux/ion.h
index caed2a2..ca1f198 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -493,6 +493,23 @@
*/
int msm_ion_unsecure_heap(int heap_id);
+/**
+ * msm_ion_do_cache_op - do cache operations.
+ *
+ * @client - pointer to ION client.
+ * @handle - pointer to buffer handle.
+ * @vaddr - virtual address to operate on.
+ * @len - Length of data to do cache operation on.
+ * @cmd - Cache operation to perform:
+ * ION_IOC_CLEAN_CACHES
+ * ION_IOC_INV_CACHES
+ * ION_IOC_CLEAN_INV_CACHES
+ *
+ * Returns 0 on success
+ */
+int msm_ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *vaddr, unsigned long len, unsigned int cmd);
+
#else
static inline struct ion_client *ion_client_create(struct ion_device *dev,
unsigned int heap_mask, const char *name)
@@ -604,6 +621,14 @@
{
return -ENODEV;
}
+
+static inline int msm_ion_do_cache_op(struct ion_client *client,
+ struct ion_handle *handle, void *vaddr,
+ unsigned long len, unsigned int cmd)
+{
+ return -ENODEV;
+}
+
#endif /* CONFIG_ION */
#endif /* __KERNEL__ */
diff --git a/include/linux/mfd/Kbuild b/include/linux/mfd/Kbuild
index 1acc78f..bba647c 100644
--- a/include/linux/mfd/Kbuild
+++ b/include/linux/mfd/Kbuild
@@ -1,3 +1,3 @@
header-y += timpani-audio.h
header-y += msm-adie-codec.h
-header-y += wcd9310/
+header-y += wcd9xxx/
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index e2d4d93..818eeca 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -175,6 +175,16 @@
* track of chargecycles
*/
void pm8921_bms_charging_end(int is_battery_full);
+
+void pm8921_bms_calibrate_hkadc(void);
+/**
+ * pm8921_bms_get_simultaneous_battery_voltage_and_current
+ * - function to take simultaneous vbat and vsense readings
+ * this puts the bms in override mode but keeps coulumb couting
+ * on. Useful when ir compensation needs to be implemented
+ */
+int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+ int *vbat_uv);
#else
static inline int pm8921_bms_get_vsense_avg(int *result)
{
@@ -198,6 +208,14 @@
static inline void pm8921_bms_charging_end(int is_battery_full)
{
}
+static inline void pm8921_bms_calibrate_hkadc(void)
+{
+}
+static inline int pm8921_bms_get_simultaneous_battery_voltage_and_current(
+ int *ibat_ua, int *vbat_uv)
+{
+ return -ENXIO;
+}
#endif
#endif
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index 22293fe..bdaee74 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -142,6 +142,7 @@
struct pm8xxx_led_platform_data *leds_pdata;
struct pm8xxx_vibrator_platform_data *vibrator_pdata;
struct pm8xxx_ccadc_platform_data *ccadc_pdata;
+ struct pm8xxx_pwm_platform_data *pwm_pdata;
};
#endif
diff --git a/include/linux/mfd/pm8xxx/pwm.h b/include/linux/mfd/pm8xxx/pwm.h
index 9169e90..09b165e 100644
--- a/include/linux/mfd/pm8xxx/pwm.h
+++ b/include/linux/mfd/pm8xxx/pwm.h
@@ -19,7 +19,6 @@
#define PM8XXX_PWM_PERIOD_MIN 7 /* usec: 19.2M, n=6, m=0, pre=2 */
#define PM8XXX_PWM_PERIOD_MAX (384 * USEC_PER_SEC) /* 1K, n=9, m=7, pre=6 */
-
#define PM_PWM_LUT_SIZE 64
#define PM_PWM_LUT_DUTY_TIME_MAX 512 /* ms */
#define PM_PWM_LUT_PAUSE_MAX (7000 * PM_PWM_LUT_DUTY_TIME_MAX)
@@ -92,6 +91,14 @@
};
/**
+ * struct pm8xxx_pwm_platform_data - PWM platform data
+ * dtest_channel - Enable LPG DTEST mode for this LPG channel
+ */
+struct pm8xxx_pwm_platform_data {
+ int dtest_channel;
+};
+
+/**
* pm8xxx_pwm_config_period - change PWM period
*
* @pwm: the PWM device
diff --git a/include/linux/mfd/wcd9310/Kbuild b/include/linux/mfd/wcd9310/Kbuild
deleted file mode 100644
index 2702ec6..0000000
--- a/include/linux/mfd/wcd9310/Kbuild
+++ /dev/null
@@ -1 +0,0 @@
-header-y += registers.h
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
deleted file mode 100644
index 8605ac6..0000000
--- a/include/linux/mfd/wcd9310/core.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef __MFD_TABLA_CORE_H__
-#define __MFD_TABLA_CORE_H__
-
-#include <linux/interrupt.h>
-#include <linux/wakelock.h>
-
-#define TABLA_NUM_IRQ_REGS 3
-
-#define TABLA_SLIM_NUM_PORT_REG 3
-
-#define TABLA_INTERFACE_TYPE_SLIMBUS 0x00
-#define TABLA_INTERFACE_TYPE_I2C 0x01
-
-#define TABLA_VERSION_1_0 0
-#define TABLA_VERSION_1_1 1
-#define TABLA_VERSION_2_0 2
-#define TABLA_IS_1_X(ver) \
- (((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
-#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
-
-enum {
- TABLA_IRQ_SLIMBUS = 0,
- TABLA_IRQ_MBHC_REMOVAL,
- TABLA_IRQ_MBHC_SHORT_TERM,
- TABLA_IRQ_MBHC_PRESS,
- TABLA_IRQ_MBHC_RELEASE,
- TABLA_IRQ_MBHC_POTENTIAL,
- TABLA_IRQ_MBHC_INSERTION,
- TABLA_IRQ_BG_PRECHARGE,
- TABLA_IRQ_PA1_STARTUP,
- TABLA_IRQ_PA2_STARTUP,
- TABLA_IRQ_PA3_STARTUP,
- TABLA_IRQ_PA4_STARTUP,
- TABLA_IRQ_PA5_STARTUP,
- TABLA_IRQ_MICBIAS1_PRECHARGE,
- TABLA_IRQ_MICBIAS2_PRECHARGE,
- TABLA_IRQ_MICBIAS3_PRECHARGE,
- TABLA_IRQ_HPH_PA_OCPL_FAULT,
- TABLA_IRQ_HPH_PA_OCPR_FAULT,
- TABLA_IRQ_EAR_PA_OCPL_FAULT,
- TABLA_IRQ_HPH_L_PA_STARTUP,
- TABLA_IRQ_HPH_R_PA_STARTUP,
- TABLA_IRQ_EAR_PA_STARTUP,
- TABLA_NUM_IRQS,
-};
-
-enum tabla_pm_state {
- TABLA_PM_SLEEPABLE,
- TABLA_PM_AWAKE,
- TABLA_PM_ASLEEP,
-};
-
-struct tabla {
- struct device *dev;
- struct slim_device *slim;
- struct slim_device *slim_slave;
- struct mutex io_lock;
- struct mutex xfer_lock;
- struct mutex irq_lock;
- u8 version;
-
- unsigned int irq_base;
- unsigned int irq;
- u8 irq_masks_cur[TABLA_NUM_IRQ_REGS];
- u8 irq_masks_cache[TABLA_NUM_IRQ_REGS];
- u8 irq_level[TABLA_NUM_IRQ_REGS];
-
- int reset_gpio;
-
- int (*read_dev)(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface_reg);
- int (*write_dev)(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface_reg);
-
- struct regulator_bulk_data *supplies;
-
- enum tabla_pm_state pm_state;
- struct mutex pm_lock;
- /* pm_wq notifies change of pm_state */
- wait_queue_head_t pm_wq;
- struct wake_lock wlock;
- int wlock_holders;
-};
-
-int tabla_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
-int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg, int count,
- u8 *buf);
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg, int count,
- u8 *buf);
-int tabla_irq_init(struct tabla *tabla);
-void tabla_irq_exit(struct tabla *tabla);
-int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
-int tabla_get_intf_type(void);
-
-void tabla_lock_sleep(struct tabla *tabla);
-void tabla_unlock_sleep(struct tabla *tabla);
-enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
- enum tabla_pm_state n);
-
-static inline int tabla_request_irq(struct tabla *tabla, int irq,
- irq_handler_t handler, const char *name,
- void *data)
-{
- if (!tabla->irq_base)
- return -EINVAL;
- return request_threaded_irq(tabla->irq_base + irq, NULL, handler,
- IRQF_TRIGGER_RISING, name,
- data);
-}
-static inline void tabla_free_irq(struct tabla *tabla, int irq, void *data)
-{
- if (!tabla->irq_base)
- return;
- free_irq(tabla->irq_base + irq, data);
-}
-static inline void tabla_enable_irq(struct tabla *tabla, int irq)
-{
- if (!tabla->irq_base)
- return;
- enable_irq(tabla->irq_base + irq);
-}
-static inline void tabla_disable_irq(struct tabla *tabla, int irq)
-{
- if (!tabla->irq_base)
- return;
- disable_irq_nosync(tabla->irq_base + irq);
-}
-
-#endif
diff --git a/include/linux/mfd/wcd9xxx/Kbuild b/include/linux/mfd/wcd9xxx/Kbuild
new file mode 100644
index 0000000..acfab6e
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/Kbuild
@@ -0,0 +1,2 @@
+header-y += wcd9xxx_registers.h
+header-y += wcd9310_registers.h
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
new file mode 100644
index 0000000..0d99e37
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -0,0 +1,177 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MFD_TABLA_CORE_H__
+#define __MFD_TABLA_CORE_H__
+
+#include <linux/interrupt.h>
+#include <linux/wakelock.h>
+
+#define WCD9XXX_NUM_IRQ_REGS 3
+
+#define WCD9XXX_SLIM_NUM_PORT_REG 3
+
+#define WCD9XXX_INTERFACE_TYPE_SLIMBUS 0x00
+#define WCD9XXX_INTERFACE_TYPE_I2C 0x01
+
+#define TABLA_VERSION_1_0 0
+#define TABLA_VERSION_1_1 1
+#define TABLA_VERSION_2_0 2
+#define TABLA_IS_1_X(ver) \
+ (((ver == TABLA_VERSION_1_0) || (ver == TABLA_VERSION_1_1)) ? 1 : 0)
+#define TABLA_IS_2_0(ver) ((ver == TABLA_VERSION_2_0) ? 1 : 0)
+
+enum {
+ TABLA_IRQ_SLIMBUS = 0,
+ TABLA_IRQ_MBHC_REMOVAL,
+ TABLA_IRQ_MBHC_SHORT_TERM,
+ TABLA_IRQ_MBHC_PRESS,
+ TABLA_IRQ_MBHC_RELEASE,
+ TABLA_IRQ_MBHC_POTENTIAL,
+ TABLA_IRQ_MBHC_INSERTION,
+ TABLA_IRQ_BG_PRECHARGE,
+ TABLA_IRQ_PA1_STARTUP,
+ TABLA_IRQ_PA2_STARTUP,
+ TABLA_IRQ_PA3_STARTUP,
+ TABLA_IRQ_PA4_STARTUP,
+ TABLA_IRQ_PA5_STARTUP,
+ TABLA_IRQ_MICBIAS1_PRECHARGE,
+ TABLA_IRQ_MICBIAS2_PRECHARGE,
+ TABLA_IRQ_MICBIAS3_PRECHARGE,
+ TABLA_IRQ_HPH_PA_OCPL_FAULT,
+ TABLA_IRQ_HPH_PA_OCPR_FAULT,
+ TABLA_IRQ_EAR_PA_OCPL_FAULT,
+ TABLA_IRQ_HPH_L_PA_STARTUP,
+ TABLA_IRQ_HPH_R_PA_STARTUP,
+ TABLA_IRQ_EAR_PA_STARTUP,
+ TABLA_NUM_IRQS,
+};
+
+enum {
+ SITAR_IRQ_SLIMBUS = 0,
+ SITAR_IRQ_MBHC_REMOVAL,
+ SITAR_IRQ_MBHC_SHORT_TERM,
+ SITAR_IRQ_MBHC_PRESS,
+ SITAR_IRQ_MBHC_RELEASE,
+ SITAR_IRQ_MBHC_POTENTIAL,
+ SITAR_IRQ_MBHC_INSERTION,
+ SITAR_IRQ_BG_PRECHARGE,
+ SITAR_IRQ_PA1_STARTUP,
+ SITAR_IRQ_PA2_STARTUP,
+ SITAR_IRQ_PA3_STARTUP,
+ SITAR_IRQ_PA4_STARTUP,
+ SITAR_IRQ_PA5_STARTUP,
+ SITAR_IRQ_MICBIAS1_PRECHARGE,
+ SITAR_IRQ_MICBIAS2_PRECHARGE,
+ SITAR_IRQ_MICBIAS3_PRECHARGE,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT,
+ SITAR_IRQ_HPH_PA_OCPR_FAULT,
+ SITAR_IRQ_EAR_PA_OCPL_FAULT,
+ SITAR_IRQ_HPH_L_PA_STARTUP,
+ SITAR_IRQ_HPH_R_PA_STARTUP,
+ SITAR_IRQ_EAR_PA_STARTUP,
+ SITAR_NUM_IRQS,
+};
+
+
+enum wcd9xxx_pm_state {
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE,
+ WCD9XXX_PM_ASLEEP,
+};
+
+struct wcd9xxx {
+ struct device *dev;
+ struct slim_device *slim;
+ struct slim_device *slim_slave;
+ struct mutex io_lock;
+ struct mutex xfer_lock;
+ struct mutex irq_lock;
+ u8 version;
+
+ unsigned int irq_base;
+ unsigned int irq;
+ u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS];
+ u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS];
+ u8 irq_level[WCD9XXX_NUM_IRQ_REGS];
+
+ int reset_gpio;
+
+ int (*read_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *dest, bool interface_reg);
+ int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int bytes, void *src, bool interface_reg);
+
+ struct regulator_bulk_data *supplies;
+
+ enum wcd9xxx_pm_state pm_state;
+ struct mutex pm_lock;
+ /* pm_wq notifies change of pm_state */
+ wait_queue_head_t pm_wq;
+ struct wake_lock wlock;
+ int wlock_holders;
+ int num_rx_port;
+ int num_tx_port;
+};
+
+int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
+int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ u8 val);
+int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
+int wcd9xxx_interface_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ u8 val);
+int wcd9xxx_bulk_read(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int count, u8 *buf);
+int wcd9xxx_bulk_write(struct wcd9xxx *wcd9xxx, unsigned short reg,
+ int count, u8 *buf);
+int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx);
+void wcd9xxx_irq_exit(struct wcd9xxx *wcd9xxx);
+int wcd9xxx_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
+int wcd9xxx_get_intf_type(void);
+
+void wcd9xxx_lock_sleep(struct wcd9xxx *wcd9xxx);
+void wcd9xxx_unlock_sleep(struct wcd9xxx *wcd9xxx);
+enum wcd9xxx_pm_state wcd9xxx_pm_cmpxchg(struct wcd9xxx *wcd9xxx,
+ enum wcd9xxx_pm_state o,
+ enum wcd9xxx_pm_state n);
+
+static inline int wcd9xxx_request_irq(struct wcd9xxx *wcd9xxx, int irq,
+ irq_handler_t handler, const char *name,
+ void *data)
+{
+ if (!wcd9xxx->irq_base)
+ return -EINVAL;
+ return request_threaded_irq(wcd9xxx->irq_base + irq, NULL, handler,
+ IRQF_TRIGGER_RISING, name,
+ data);
+}
+static inline void wcd9xxx_free_irq(struct wcd9xxx *wcd9xxx,
+ int irq, void *data)
+{
+ if (!wcd9xxx->irq_base)
+ return;
+ free_irq(wcd9xxx->irq_base + irq, data);
+}
+static inline void wcd9xxx_enable_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+ if (!wcd9xxx->irq_base)
+ return;
+ enable_irq(wcd9xxx->irq_base + irq);
+}
+static inline void wcd9xxx_disable_irq(struct wcd9xxx *wcd9xxx, int irq)
+{
+ if (!wcd9xxx->irq_base)
+ return;
+ disable_irq_nosync(wcd9xxx->irq_base + irq);
+}
+
+#endif
diff --git a/include/linux/mfd/wcd9310/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
similarity index 71%
rename from include/linux/mfd/wcd9310/pdata.h
rename to include/linux/mfd/wcd9xxx/pdata.h
index af801f0..db76294 100644
--- a/include/linux/mfd/wcd9310/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,15 @@
#include <linux/slimbus/slimbus.h>
+#define SITAR_LDOH_1P95_V 0x0
+#define SITAR_LDOH_2P35_V 0x1
+#define SITAR_LDOH_2P75_V 0x2
+#define SITAR_LDOH_2P85_V 0x3
+
+#define SITAR_CFILT1_SEL 0x0
+#define SITAR_CFILT2_SEL 0x1
+#define SITAR_CFILT3_SEL 0x2
+
#define TABLA_LDOH_1P95_V 0x0
#define TABLA_LDOH_2P35_V 0x1
#define TABLA_LDOH_2P75_V 0x2
@@ -51,7 +60,7 @@
#define TABLA_DCYCLE_3839 0xE
#define TABLA_DCYCLE_4095 0xF
-struct tabla_amic {
+struct wcd9xxx_amic {
/*legacy mode, txfe_enable and txfe_buff take 7 input
* each bit represent the channel / TXFE number
* and numbered as below
@@ -75,7 +84,7 @@
* If ldoh_v = 2.85 250 mv < cfiltx_mv < 2700 mv
*/
-struct tabla_micbias_setting {
+struct wcd9xxx_micbias_setting {
u8 ldoh_v;
u32 cfilt1_mv; /* in mv */
u32 cfilt2_mv; /* in mv */
@@ -86,7 +95,7 @@
u8 bias4_cfilt_sel;
};
-struct tabla_ocp_setting {
+struct wcd9xxx_ocp_setting {
unsigned int use_pdata:1; /* 0 - use sys default as recommended */
unsigned int num_attempts:4; /* up to 15 attempts */
unsigned int run_time:4; /* in duty cycle */
@@ -94,15 +103,39 @@
unsigned int hph_ocp_limit:3; /* Headphone OCP current limit */
};
-struct tabla_pdata {
+#define MAX_REGULATOR 6
+/*
+ * format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
+ *
+ * <POWER_SUPPLY_PIN_NAME> from Tabla objective spec
+*/
+
+#define WCD9XXX_CDC_VDDA_CP_CUR_MAX 500000
+#define WCD9XXX_CDC_VDDA_RX_CUR_MAX 20000
+#define WCD9XXX_CDC_VDDA_TX_CUR_MAX 20000
+#define WCD9XXX_VDDIO_CDC_CUR_MAX 5000
+
+#define WCD9XXX_VDDD_CDC_D_CUR_MAX 5000
+#define WCD9XXX_VDDD_CDC_A_CUR_MAX 5000
+
+struct wcd9xxx_regulator {
+ const char *name;
+ int min_uV;
+ int max_uV;
+ int optimum_uA;
+ struct regulator *regulator;
+};
+
+struct wcd9xxx_pdata {
int irq;
int irq_base;
int num_irqs;
int reset_gpio;
- struct tabla_amic amic_settings;
+ struct wcd9xxx_amic amic_settings;
struct slim_device slimbus_slave_device;
- struct tabla_micbias_setting micbias;
- struct tabla_ocp_setting ocp;
+ struct wcd9xxx_micbias_setting micbias;
+ struct wcd9xxx_ocp_setting ocp;
+ struct wcd9xxx_regulator regulator[MAX_REGULATOR];
};
#endif
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
new file mode 100644
index 0000000..df54e02
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -0,0 +1,742 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef SITAR_CODEC_DIGITAL_H
+#define SITAR_CODEC_DIGITAL_H
+
+#define SITAR_A_PIN_CTL_OE0 (0x10)
+#define SITAR_A_PIN_CTL_OE0__POR (0x00000000)
+#define SITAR_A_PIN_CTL_OE1 (0x11)
+#define SITAR_A_PIN_CTL_OE1__POR (0x00000000)
+#define SITAR_A_PIN_CTL_DATA0 (0x12)
+#define SITAR_A_PIN_CTL_DATA0__POR (0x00000000)
+#define SITAR_A_PIN_CTL_DATA1 (0x13)
+#define SITAR_A_PIN_CTL_DATA1__POR (0x00000000)
+#define SITAR_A_HDRIVE_GENERIC (0x18)
+#define SITAR_A_HDRIVE_GENERIC__POR (0x00000000)
+#define SITAR_A_HDRIVE_OVERRIDE (0x19)
+#define SITAR_A_HDRIVE_OVERRIDE__POR (0x00000008)
+#define SITAR_A_ANA_CSR_WAIT_STATE (0x20)
+#define SITAR_A_ANA_CSR_WAIT_STATE__POR (0x00000044)
+#define SITAR_A_PROCESS_MONITOR_CTL0 (0x40)
+#define SITAR_A_PROCESS_MONITOR_CTL0__POR (0x00000080)
+#define SITAR_A_PROCESS_MONITOR_CTL1 (0x41)
+#define SITAR_A_PROCESS_MONITOR_CTL1__POR (0x00000000)
+#define SITAR_A_PROCESS_MONITOR_CTL2 (0x42)
+#define SITAR_A_PROCESS_MONITOR_CTL2__POR (0x00000000)
+#define SITAR_A_PROCESS_MONITOR_CTL3 (0x43)
+#define SITAR_A_PROCESS_MONITOR_CTL3__POR (0x00000001)
+#define SITAR_A_QFUSE_CTL (0x48)
+#define SITAR_A_QFUSE_CTL__POR (0x00000000)
+#define SITAR_A_QFUSE_STATUS (0x49)
+#define SITAR_A_QFUSE_STATUS__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT0 (0x4A)
+#define SITAR_A_QFUSE_DATA_OUT0__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT1 (0x4B)
+#define SITAR_A_QFUSE_DATA_OUT1__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT2 (0x4C)
+#define SITAR_A_QFUSE_DATA_OUT2__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT3 (0x4D)
+#define SITAR_A_QFUSE_DATA_OUT3__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT4 (0x4E)
+#define SITAR_A_QFUSE_DATA_OUT4__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT5 (0x4F)
+#define SITAR_A_QFUSE_DATA_OUT5__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT6 (0x50)
+#define SITAR_A_QFUSE_DATA_OUT6__POR (0x00000000)
+#define SITAR_A_QFUSE_DATA_OUT7 (0x51)
+#define SITAR_A_QFUSE_DATA_OUT7__POR (0x00000000)
+#define SITAR_A_CDC_CTL (0x80)
+#define SITAR_A_CDC_CTL__POR (0x00000000)
+#define SITAR_A_LEAKAGE_CTL (0x88)
+#define SITAR_A_LEAKAGE_CTL__POR (0x00000004)
+#define SITAR_A_INTR_MODE (0x90)
+#define SITAR_A_INTR_MODE__POR (0x00000000)
+#define SITAR_A_INTR_MASK0 (0x94)
+#define SITAR_A_INTR_MASK0__POR (0x000000ff)
+#define SITAR_A_INTR_MASK1 (0x95)
+#define SITAR_A_INTR_MASK1__POR (0x000000ff)
+#define SITAR_A_INTR_MASK2 (0x96)
+#define SITAR_A_INTR_MASK2__POR (0x000000ff)
+#define SITAR_A_INTR_STATUS0 (0x98)
+#define SITAR_A_INTR_STATUS0__POR (0x00000000)
+#define SITAR_A_INTR_STATUS1 (0x99)
+#define SITAR_A_INTR_STATUS1__POR (0x00000000)
+#define SITAR_A_INTR_STATUS2 (0x9A)
+#define SITAR_A_INTR_STATUS2__POR (0x00000000)
+#define SITAR_A_INTR_CLEAR0 (0x9C)
+#define SITAR_A_INTR_CLEAR0__POR (0x00000000)
+#define SITAR_A_INTR_CLEAR1 (0x9D)
+#define SITAR_A_INTR_CLEAR1__POR (0x00000000)
+#define SITAR_A_INTR_CLEAR2 (0x9E)
+#define SITAR_A_INTR_CLEAR2__POR (0x00000000)
+#define SITAR_A_INTR_LEVEL0 (0xA0)
+#define SITAR_A_INTR_LEVEL0__POR (0x00000001)
+#define SITAR_A_INTR_LEVEL1 (0xA1)
+#define SITAR_A_INTR_LEVEL1__POR (0x00000000)
+#define SITAR_A_INTR_LEVEL2 (0xA2)
+#define SITAR_A_INTR_LEVEL2__POR (0x00000000)
+#define SITAR_A_INTR_TEST0 (0xA4)
+#define SITAR_A_INTR_TEST0__POR (0x00000000)
+#define SITAR_A_INTR_TEST1 (0xA5)
+#define SITAR_A_INTR_TEST1__POR (0x00000000)
+#define SITAR_A_INTR_TEST2 (0xA6)
+#define SITAR_A_INTR_TEST2__POR (0x00000000)
+#define SITAR_A_INTR_SET0 (0xA8)
+#define SITAR_A_INTR_SET0__POR (0x00000000)
+#define SITAR_A_INTR_SET1 (0xA9)
+#define SITAR_A_INTR_SET1__POR (0x00000000)
+#define SITAR_A_INTR_SET2 (0xAA)
+#define SITAR_A_INTR_SET2__POR (0x00000000)
+#define SITAR_A_CDC_TX_I2S_SCK_MODE (0xC0)
+#define SITAR_A_CDC_TX_I2S_SCK_MODE__POR (0x00000000)
+#define SITAR_A_CDC_TX_I2S_WS_MODE (0xC1)
+#define SITAR_A_CDC_TX_I2S_WS_MODE__POR (0x00000000)
+#define SITAR_A_CDC_DMIC_DATA0_MODE (0xC4)
+#define SITAR_A_CDC_DMIC_DATA0_MODE__POR (0x00000000)
+#define SITAR_A_CDC_DMIC_CLK0_MODE (0xC5)
+#define SITAR_A_CDC_DMIC_CLK0_MODE__POR (0x00000000)
+#define SITAR_A_CDC_DMIC_DATA1_MODE (0xC6)
+#define SITAR_A_CDC_DMIC_DATA1_MODE__POR (0x00000000)
+#define SITAR_A_CDC_DMIC_CLK1_MODE (0xC7)
+#define SITAR_A_CDC_DMIC_CLK1_MODE__POR (0x00000000)
+#define SITAR_A_CDC_TX_I2S_SD0_MODE (0xC8)
+#define SITAR_A_CDC_TX_I2S_SD0_MODE__POR (0x00000000)
+#define SITAR_A_CDC_INTR_MODE (0xC9)
+#define SITAR_A_CDC_INTR_MODE__POR (0x00000000)
+#define SITAR_A_CDC_RX_I2S_SD0_MODE (0xCA)
+#define SITAR_A_CDC_RX_I2S_SD0_MODE__POR (0x00000000)
+#define SITAR_A_CDC_RX_I2S_SD1_MODE (0xCB)
+#define SITAR_A_CDC_RX_I2S_SD1_MODE__POR (0x00000000)
+#define SITAR_A_BIAS_REF_CTL (0x100)
+#define SITAR_A_BIAS_REF_CTL__POR (0x0000001c)
+#define SITAR_A_BIAS_CENTRAL_BG_CTL (0x101)
+#define SITAR_A_BIAS_CENTRAL_BG_CTL__POR (0x00000050)
+#define SITAR_A_BIAS_PRECHRG_CTL (0x102)
+#define SITAR_A_BIAS_PRECHRG_CTL__POR (0x00000007)
+#define SITAR_A_BIAS_CURR_CTL_1 (0x103)
+#define SITAR_A_BIAS_CURR_CTL_1__POR (0x00000052)
+#define SITAR_A_BIAS_CURR_CTL_2 (0x104)
+#define SITAR_A_BIAS_CURR_CTL_2__POR (0x00000000)
+#define SITAR_A_BIAS_OSC_BG_CTL (0x105)
+#define SITAR_A_BIAS_OSC_BG_CTL__POR (0x00000016)
+#define SITAR_A_CLK_BUFF_EN1 (0x108)
+#define SITAR_A_CLK_BUFF_EN1__POR (0x00000004)
+#define SITAR_A_CLK_BUFF_EN2 (0x109)
+#define SITAR_A_CLK_BUFF_EN2__POR (0x00000002)
+#define SITAR_A_LDO_H_MODE_1 (0x110)
+#define SITAR_A_LDO_H_MODE_1__POR (0x00000065)
+#define SITAR_A_LDO_H_MODE_2 (0x111)
+#define SITAR_A_LDO_H_MODE_2__POR (0x000000a8)
+#define SITAR_A_LDO_H_LOOP_CTL (0x112)
+#define SITAR_A_LDO_H_LOOP_CTL__POR (0x0000006b)
+#define SITAR_A_LDO_H_COMP_1 (0x113)
+#define SITAR_A_LDO_H_COMP_1__POR (0x00000084)
+#define SITAR_A_LDO_H_COMP_2 (0x114)
+#define SITAR_A_LDO_H_COMP_2__POR (0x000000e0)
+#define SITAR_A_LDO_H_BIAS_1 (0x115)
+#define SITAR_A_LDO_H_BIAS_1__POR (0x0000006d)
+#define SITAR_A_LDO_H_BIAS_2 (0x116)
+#define SITAR_A_LDO_H_BIAS_2__POR (0x000000a5)
+#define SITAR_A_LDO_H_BIAS_3 (0x117)
+#define SITAR_A_LDO_H_BIAS_3__POR (0x00000060)
+#define SITAR_A_MICB_CFILT_1_CTL (0x128)
+#define SITAR_A_MICB_CFILT_1_CTL__POR (0x00000040)
+#define SITAR_A_MICB_CFILT_1_VAL (0x129)
+#define SITAR_A_MICB_CFILT_1_VAL__POR (0x00000080)
+#define SITAR_A_MICB_CFILT_1_PRECHRG (0x12A)
+#define SITAR_A_MICB_CFILT_1_PRECHRG__POR (0x00000038)
+#define SITAR_A_MICB_1_CTL (0x12B)
+#define SITAR_A_MICB_1_CTL__POR (0x00000016)
+#define SITAR_A_MICB_1_INT_RBIAS (0x12C)
+#define SITAR_A_MICB_1_INT_RBIAS__POR (0x00000024)
+#define SITAR_A_MICB_1_MBHC (0x12D)
+#define SITAR_A_MICB_1_MBHC__POR (0x00000001)
+#define SITAR_A_MICB_CFILT_2_CTL (0x12E)
+#define SITAR_A_MICB_CFILT_2_CTL__POR (0x00000040)
+#define SITAR_A_MICB_CFILT_2_VAL (0x12F)
+#define SITAR_A_MICB_CFILT_2_VAL__POR (0x00000080)
+#define SITAR_A_MICB_CFILT_2_PRECHRG (0x130)
+#define SITAR_A_MICB_CFILT_2_PRECHRG__POR (0x00000038)
+#define SITAR_A_MICB_2_CTL (0x131)
+#define SITAR_A_MICB_2_CTL__POR (0x00000016)
+#define SITAR_A_MICB_2_INT_RBIAS (0x132)
+#define SITAR_A_MICB_2_INT_RBIAS__POR (0x00000024)
+#define SITAR_A_MICB_2_MBHC (0x133)
+#define SITAR_A_MICB_2_MBHC__POR (0x00000002)
+#define SITAR_A_TX_COM_BIAS (0x14C)
+#define SITAR_A_TX_COM_BIAS__POR (0x000000e0)
+#define SITAR_A_MBHC_SCALING_MUX_1 (0x14E)
+#define SITAR_A_MBHC_SCALING_MUX_1__POR (0x00000000)
+#define SITAR_A_MBHC_SCALING_MUX_2 (0x14F)
+#define SITAR_A_MBHC_SCALING_MUX_2__POR (0x00000080)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_1 (0x151)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_1__POR (0x00000000)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_2 (0x152)
+#define SITAR_A_TX_SUP_SWITCH_CTRL_2__POR (0x00000080)
+#define SITAR_A_TX_1_2_EN (0x153)
+#define SITAR_A_TX_1_2_EN__POR (0x00000000)
+#define SITAR_A_TX_1_2_TEST_EN (0x154)
+#define SITAR_A_TX_1_2_TEST_EN__POR (0x000000cc)
+#define SITAR_A_TX_1_2_ADC_CH1 (0x155)
+#define SITAR_A_TX_1_2_ADC_CH1__POR (0x00000044)
+#define SITAR_A_TX_1_2_ADC_CH2 (0x156)
+#define SITAR_A_TX_1_2_ADC_CH2__POR (0x00000044)
+#define SITAR_A_TX_1_2_ATEST_REFCTRL (0x157)
+#define SITAR_A_TX_1_2_ATEST_REFCTRL__POR (0x00000000)
+#define SITAR_A_TX_1_2_TEST_CTL (0x158)
+#define SITAR_A_TX_1_2_TEST_CTL__POR (0x00000038)
+#define SITAR_A_TX_1_2_TEST_BLOCK_EN (0x159)
+#define SITAR_A_TX_1_2_TEST_BLOCK_EN__POR (0x000000fc)
+#define SITAR_A_TX_1_2_TXFE_CLKDIV (0x15A)
+#define SITAR_A_TX_1_2_TXFE_CLKDIV__POR (0x000000ee)
+#define SITAR_A_TX_1_2_SAR_ERR_CH1 (0x15B)
+#define SITAR_A_TX_1_2_SAR_ERR_CH1__POR (0x00000000)
+#define SITAR_A_TX_1_2_SAR_ERR_CH2 (0x15C)
+#define SITAR_A_TX_1_2_SAR_ERR_CH2__POR (0x00000000)
+#define SITAR_A_TX_3_EN (0x15D)
+#define SITAR_A_TX_3_EN__POR (0x00000000)
+#define SITAR_A_TX_3_TEST_EN (0x15E)
+#define SITAR_A_TX_3_TEST_EN__POR (0x000000cc)
+#define SITAR_A_TX_3_ADC (0x15F)
+#define SITAR_A_TX_3_ADC__POR (0x00000044)
+#define SITAR_A_TX_3_MBHC_ATEST_REFCTRL (0x161)
+#define SITAR_A_TX_3_MBHC_ATEST_REFCTRL__POR (0x00000000)
+#define SITAR_A_TX_3_TEST_CTL (0x162)
+#define SITAR_A_TX_3_TEST_CTL__POR (0x00000038)
+#define SITAR_A_TX_3_TEST_BLOCK_EN (0x163)
+#define SITAR_A_TX_3_TEST_BLOCK_EN__POR (0x000000fc)
+#define SITAR_A_TX_3_TXFE_CKDIV (0x164)
+#define SITAR_A_TX_3_TXFE_CKDIV__POR (0x000000ee)
+#define SITAR_A_TX_3_SAR_ERR (0x165)
+#define SITAR_A_TX_3_SAR_ERR__POR (0x00000000)
+#define SITAR_A_TX_4_MBHC_EN (0x171)
+#define SITAR_A_TX_4_MBHC_EN__POR (0x0000000c)
+#define SITAR_A_TX_4_MBHC_ADC (0x173)
+#define SITAR_A_TX_4_MBHC_ADC__POR (0x00000044)
+#define SITAR_A_TX_4_MBHC_TEST_CTL (0x174)
+#define SITAR_A_TX_4_MBHC_TEST_CTL__POR (0x00000038)
+#define SITAR_A_TX_4_MBHC_SAR_ERR (0x175)
+#define SITAR_A_TX_4_MBHC_SAR_ERR__POR (0x00000000)
+#define SITAR_A_TX_4_TXFE_CLKDIV (0x176)
+#define SITAR_A_TX_4_TXFE_CLKDIV__POR (0x0000001c)
+#define SITAR_A_AUX_COM_CTL (0x180)
+#define SITAR_A_AUX_COM_CTL__POR (0x00000034)
+#define SITAR_A_AUX_COM_ATEST (0x181)
+#define SITAR_A_AUX_COM_ATEST__POR (0x00000000)
+#define SITAR_A_AUX_L_EN (0x182)
+#define SITAR_A_AUX_L_EN__POR (0x00000000)
+#define SITAR_A_AUX_L_GAIN (0x183)
+#define SITAR_A_AUX_L_GAIN__POR (0x0000001f)
+#define SITAR_A_AUX_L_PA_CONN (0x184)
+#define SITAR_A_AUX_L_PA_CONN__POR (0x00000000)
+#define SITAR_A_AUX_L_PA_CONN_INV (0x185)
+#define SITAR_A_AUX_L_PA_CONN_INV__POR (0x00000000)
+#define SITAR_A_AUX_R_EN (0x186)
+#define SITAR_A_AUX_R_EN__POR (0x00000000)
+#define SITAR_A_AUX_R_GAIN (0x187)
+#define SITAR_A_AUX_R_GAIN__POR (0x0000001f)
+#define SITAR_A_AUX_R_PA_CONN (0x188)
+#define SITAR_A_AUX_R_PA_CONN__POR (0x00000000)
+#define SITAR_A_AUX_R_PA_CONN_INV (0x189)
+#define SITAR_A_AUX_R_PA_CONN_INV__POR (0x00000000)
+#define SITAR_A_CP_EN (0x192)
+#define SITAR_A_CP_EN__POR (0x000000e6)
+#define SITAR_A_CP_CLK (0x193)
+#define SITAR_A_CP_CLK__POR (0x00000029)
+#define SITAR_A_CP_STATIC (0x194)
+#define SITAR_A_CP_STATIC__POR (0x00000010)
+#define SITAR_A_CP_DCC1 (0x195)
+#define SITAR_A_CP_DCC1__POR (0x00000052)
+#define SITAR_A_CP_DCC3 (0x196)
+#define SITAR_A_CP_DCC3__POR (0x00000001)
+#define SITAR_A_CP_ATEST (0x197)
+#define SITAR_A_CP_ATEST__POR (0x00000000)
+#define SITAR_A_CP_DTEST (0x198)
+#define SITAR_A_CP_DTEST__POR (0x00000000)
+#define SITAR_A_RX_COM_TIMER_DIV (0x19E)
+#define SITAR_A_RX_COM_TIMER_DIV__POR (0x000000e8)
+#define SITAR_A_RX_COM_OCP_CTL (0x19F)
+#define SITAR_A_RX_COM_OCP_CTL__POR (0x0000001f)
+#define SITAR_A_RX_COM_OCP_COUNT (0x1A0)
+#define SITAR_A_RX_COM_OCP_COUNT__POR (0x00000077)
+#define SITAR_A_RX_COM_DAC_CTL (0x1A1)
+#define SITAR_A_RX_COM_DAC_CTL__POR (0x00000000)
+#define SITAR_A_RX_COM_BIAS (0x1A2)
+#define SITAR_A_RX_COM_BIAS__POR (0x00000000)
+#define SITAR_A_RX_HPH_BIAS_PA (0x1A6)
+#define SITAR_A_RX_HPH_BIAS_PA__POR (0x00000057)
+#define SITAR_A_RX_HPH_BIAS_LDO (0x1A7)
+#define SITAR_A_RX_HPH_BIAS_LDO__POR (0x00000056)
+#define SITAR_A_RX_HPH_BIAS_CNP (0x1A8)
+#define SITAR_A_RX_HPH_BIAS_CNP__POR (0x0000008a)
+#define SITAR_A_RX_HPH_BIAS_WG (0x1A9)
+#define SITAR_A_RX_HPH_BIAS_WG__POR (0x00000060)
+#define SITAR_A_RX_HPH_OCP_CTL (0x1AA)
+#define SITAR_A_RX_HPH_OCP_CTL__POR (0x000000e8)
+#define SITAR_A_RX_HPH_CNP_EN (0x1AB)
+#define SITAR_A_RX_HPH_CNP_EN__POR (0x00000080)
+#define SITAR_A_RX_HPH_CNP_WG_CTL (0x1AC)
+#define SITAR_A_RX_HPH_CNP_WG_CTL__POR (0x000000dc)
+#define SITAR_A_RX_HPH_CNP_WG_TIME (0x1AD)
+#define SITAR_A_RX_HPH_CNP_WG_TIME__POR (0x00000028)
+#define SITAR_A_RX_HPH_L_GAIN (0x1AE)
+#define SITAR_A_RX_HPH_L_GAIN__POR (0x00000000)
+#define SITAR_A_RX_HPH_L_TEST (0x1AF)
+#define SITAR_A_RX_HPH_L_TEST__POR (0x00000001)
+#define SITAR_A_RX_HPH_L_PA_CTL (0x1B0)
+#define SITAR_A_RX_HPH_L_PA_CTL__POR (0x00000040)
+#define SITAR_A_RX_HPH_L_DAC_CTL (0x1B1)
+#define SITAR_A_RX_HPH_L_DAC_CTL__POR (0x00000000)
+#define SITAR_A_RX_HPH_L_ATEST (0x1B2)
+#define SITAR_A_RX_HPH_L_ATEST__POR (0x00000000)
+#define SITAR_A_RX_HPH_L_STATUS (0x1B3)
+#define SITAR_A_RX_HPH_L_STATUS__POR (0x00000004)
+#define SITAR_A_RX_HPH_R_GAIN (0x1B4)
+#define SITAR_A_RX_HPH_R_GAIN__POR (0x00000000)
+#define SITAR_A_RX_HPH_R_TEST (0x1B5)
+#define SITAR_A_RX_HPH_R_TEST__POR (0x00000001)
+#define SITAR_A_RX_HPH_R_PA_CTL (0x1B6)
+#define SITAR_A_RX_HPH_R_PA_CTL__POR (0x00000040)
+#define SITAR_A_RX_HPH_R_DAC_CTL (0x1B7)
+#define SITAR_A_RX_HPH_R_DAC_CTL__POR (0x00000000)
+#define SITAR_A_RX_HPH_R_ATEST (0x1B8)
+#define SITAR_A_RX_HPH_R_ATEST__POR (0x00000000)
+#define SITAR_A_RX_HPH_R_STATUS (0x1B9)
+#define SITAR_A_RX_HPH_R_STATUS__POR (0x00000004)
+#define SITAR_A_RX_EAR_BIAS_PA (0x1BA)
+#define SITAR_A_RX_EAR_BIAS_PA__POR (0x000000a6)
+#define SITAR_A_RX_EAR_BIAS_CMBUFF (0x1BB)
+#define SITAR_A_RX_EAR_BIAS_CMBUFF__POR (0x000000a0)
+#define SITAR_A_RX_EAR_EN (0x1BC)
+#define SITAR_A_RX_EAR_EN__POR (0x00000000)
+#define SITAR_A_RX_EAR_GAIN (0x1BD)
+#define SITAR_A_RX_EAR_GAIN__POR (0x00000002)
+#define SITAR_A_RX_EAR_CMBUFF (0x1BE)
+#define SITAR_A_RX_EAR_CMBUFF__POR (0x00000004)
+#define SITAR_A_RX_EAR_ICTL (0x1BF)
+#define SITAR_A_RX_EAR_ICTL__POR (0x00000040)
+#define SITAR_A_RX_EAR_CCOMP (0x1C0)
+#define SITAR_A_RX_EAR_CCOMP__POR (0x00000008)
+#define SITAR_A_RX_EAR_VCM (0x1C1)
+#define SITAR_A_RX_EAR_VCM__POR (0x00000003)
+#define SITAR_A_RX_EAR_CNP (0x1C2)
+#define SITAR_A_RX_EAR_CNP__POR (0x000000f2)
+#define SITAR_A_RX_EAR_ATEST (0x1C3)
+#define SITAR_A_RX_EAR_ATEST__POR (0x00000000)
+#define SITAR_A_RX_EAR_STATUS (0x1C5)
+#define SITAR_A_RX_EAR_STATUS__POR (0x00000004)
+#define SITAR_A_RX_LINE_BIAS_PA (0x1C6)
+#define SITAR_A_RX_LINE_BIAS_PA__POR (0x000000aa)
+#define SITAR_A_RX_LINE_BIAS_LDO (0x1C7)
+#define SITAR_A_RX_LINE_BIAS_LDO__POR (0x00000086)
+#define SITAR_A_RX_LINE_BIAS_CNP1 (0x1C8)
+#define SITAR_A_RX_LINE_BIAS_CNP1__POR (0x00000060)
+#define SITAR_A_RX_LINE_COM (0x1C9)
+#define SITAR_A_RX_LINE_COM__POR (0x00000000)
+#define SITAR_A_RX_LINE_CNP_EN (0x1CA)
+#define SITAR_A_RX_LINE_CNP_EN__POR (0x00000080)
+#define SITAR_A_RX_LINE_CNP_WG_CTL (0x1CB)
+#define SITAR_A_RX_LINE_CNP_WG_CTL__POR (0x000000dc)
+#define SITAR_A_RX_LINE_CNP_WG_TIME (0x1CC)
+#define SITAR_A_RX_LINE_CNP_WG_TIME__POR (0x00000028)
+#define SITAR_A_RX_LINE_1_GAIN (0x1CD)
+#define SITAR_A_RX_LINE_1_GAIN__POR (0x00000000)
+#define SITAR_A_RX_LINE_1_TEST (0x1CE)
+#define SITAR_A_RX_LINE_1_TEST__POR (0x00000001)
+#define SITAR_A_RX_LINE_1_DAC_CTL (0x1CF)
+#define SITAR_A_RX_LINE_1_DAC_CTL__POR (0x00000000)
+#define SITAR_A_RX_LINE_1_STATUS (0x1D0)
+#define SITAR_A_RX_LINE_1_STATUS__POR (0x00000004)
+#define SITAR_A_RX_LINE_2_GAIN (0x1D1)
+#define SITAR_A_RX_LINE_2_GAIN__POR (0x00000000)
+#define SITAR_A_RX_LINE_2_TEST (0x1D2)
+#define SITAR_A_RX_LINE_2_TEST__POR (0x00000001)
+#define SITAR_A_RX_LINE_2_DAC_CTL (0x1D3)
+#define SITAR_A_RX_LINE_2_DAC_CTL__POR (0x00000000)
+#define SITAR_A_RX_LINE_2_STATUS (0x1D4)
+#define SITAR_A_RX_LINE_2_STATUS__POR (0x00000004)
+#define SITAR_A_RX_LINE_BIAS_CNP2 (0x1E1)
+#define SITAR_A_RX_LINE_BIAS_CNP2__POR (0x0000008a)
+#define SITAR_A_RX_LINE_OCP_CTL (0x1E2)
+#define SITAR_A_RX_LINE_OCP_CTL__POR (0x000000e8)
+#define SITAR_A_RX_LINE_1_PA_CTL (0x1E3)
+#define SITAR_A_RX_LINE_1_PA_CTL__POR (0x00000040)
+#define SITAR_A_RX_LINE_2_PA_CTL (0x1E4)
+#define SITAR_A_RX_LINE_2_PA_CTL__POR (0x00000040)
+#define SITAR_A_RX_LINE_CNP_DBG (0x1EC)
+#define SITAR_A_RX_LINE_CNP_DBG__POR (0x00000000)
+#define SITAR_A_MBHC_HPH (0x1ED)
+#define SITAR_A_MBHC_HPH__POR (0x00000048)
+#define SITAR_A_RC_OSC_FREQ (0x1F7)
+#define SITAR_A_RC_OSC_FREQ__POR (0x00000046)
+#define SITAR_A_RC_OSC_TEST (0x1F8)
+#define SITAR_A_RC_OSC_TEST__POR (0x0000000a)
+#define SITAR_A_RC_OSC_STATUS (0x1F9)
+#define SITAR_A_RC_OSC_STATUS__POR (0x0000001c)
+#define SITAR_A_RC_OSC_TUNER (0x1FA)
+#define SITAR_A_RC_OSC_TUNER__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_CTL (0x200)
+#define SITAR_A_CDC_ANC1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_SHIFT (0x201)
+#define SITAR_A_CDC_ANC1_SHIFT__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B1_CTL (0x202)
+#define SITAR_A_CDC_ANC1_IIR_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B2_CTL (0x203)
+#define SITAR_A_CDC_ANC1_IIR_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B3_CTL (0x204)
+#define SITAR_A_CDC_ANC1_IIR_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_IIR_B4_CTL (0x205)
+#define SITAR_A_CDC_ANC1_IIR_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B1_CTL (0x206)
+#define SITAR_A_CDC_ANC1_LPF_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B2_CTL (0x207)
+#define SITAR_A_CDC_ANC1_LPF_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_LPF_B3_CTL (0x208)
+#define SITAR_A_CDC_ANC1_LPF_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_SPARE (0x209)
+#define SITAR_A_CDC_ANC1_SPARE__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_SMLPF_CTL (0x20A)
+#define SITAR_A_CDC_ANC1_SMLPF_CTL__POR (0x00000000)
+#define SITAR_A_CDC_ANC1_DCFLT_CTL (0x20B)
+#define SITAR_A_CDC_ANC1_DCFLT_CTL__POR (0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_TIMER (0x220)
+#define SITAR_A_CDC_TX1_VOL_CTL_TIMER__POR (0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_GAIN (0x221)
+#define SITAR_A_CDC_TX1_VOL_CTL_GAIN__POR (0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG (0x222)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG__POR (0x00000000)
+#define SITAR_A_CDC_TX1_MUX_CTL (0x223)
+#define SITAR_A_CDC_TX1_MUX_CTL__POR (0x00000008)
+#define SITAR_A_CDC_TX1_CLK_FS_CTL (0x224)
+#define SITAR_A_CDC_TX1_CLK_FS_CTL__POR (0x00000003)
+#define SITAR_A_CDC_TX1_DMIC_CTL (0x225)
+#define SITAR_A_CDC_TX1_DMIC_CTL__POR (0x00000000)
+#define SITAR_A_CDC_SRC1_PDA_CFG (0x2A0)
+#define SITAR_A_CDC_SRC1_PDA_CFG__POR (0x00000000)
+#define SITAR_A_CDC_SRC1_FS_CTL (0x2A1)
+#define SITAR_A_CDC_SRC1_FS_CTL__POR (0x0000001b)
+
+#define SITAR_A_CDC_RX1_B1_CTL (0x000002B0)
+#define SITAR_A_CDC_RX1_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX2_B1_CTL (0x000002B8)
+#define SITAR_A_CDC_RX2_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX3_B1_CTL (0x000002C0)
+#define SITAR_A_CDC_RX3_B1_CTL__POR (0x00000000)
+
+#define SITAR_A_CDC_RX1_B2_CTL (0x000002B1)
+#define SITAR_A_CDC_RX1_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX2_B2_CTL (0x000002B9)
+#define SITAR_A_CDC_RX2_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX3_B2_CTL (0x000002C1)
+#define SITAR_A_CDC_RX3_B2_CTL__POR (0x00000000)
+
+#define SITAR_A_CDC_RX1_B3_CTL (0x000002B2)
+#define SITAR_A_CDC_RX1_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX2_B3_CTL (0x000002BA)
+#define SITAR_A_CDC_RX2_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX3_B3_CTL (0x000002C2)
+#define SITAR_A_CDC_RX3_B3_CTL__POR (0x00000000)
+
+#define SITAR_A_CDC_RX1_B4_CTL (0x000002B3)
+#define SITAR_A_CDC_RX1_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX2_B4_CTL (0x000002BB)
+#define SITAR_A_CDC_RX2_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX3_B4_CTL (0x000002C3)
+#define SITAR_A_CDC_RX3_B4_CTL__POR (0x00000000)
+
+#define SITAR_A_CDC_RX1_B5_CTL (0x000002B4)
+#define SITAR_A_CDC_RX1_B5_CTL__POR (0x00000060)
+#define SITAR_A_CDC_RX2_B5_CTL (0x000002BC)
+#define SITAR_A_CDC_RX2_B5_CTL__POR (0x00000060)
+#define SITAR_A_CDC_RX3_B5_CTL (0x000002C4)
+#define SITAR_A_CDC_RX3_B5_CTL__POR (0x00000060)
+
+#define SITAR_A_CDC_RX1_B6_CTL (0x000002B5)
+#define SITAR_A_CDC_RX1_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX2_B6_CTL (0x000002BD)
+#define SITAR_A_CDC_RX2_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX3_B6_CTL (0x000002C5)
+#define SITAR_A_CDC_RX3_B6_CTL__POR (0x00000000)
+
+
+#define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL (0x2B6)
+#define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL (0x2B7)
+#define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_ANC_RESET_CTL (0x300)
+#define SITAR_A_CDC_CLK_ANC_RESET_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_RX_RESET_CTL (0x301)
+#define SITAR_A_CDC_CLK_RX_RESET_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_TX_RESET_B1_CTL (0x302)
+#define SITAR_A_CDC_CLK_TX_RESET_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_TX_RESET_B2_CTL (0x303)
+#define SITAR_A_CDC_CLK_TX_RESET_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_DMIC_CTL (0x304)
+#define SITAR_A_CDC_CLK_DMIC_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_RX_I2S_CTL (0x305)
+#define SITAR_A_CDC_CLK_RX_I2S_CTL__POR (0x00000003)
+#define SITAR_A_CDC_CLK_TX_I2S_CTL (0x306)
+#define SITAR_A_CDC_CLK_TX_I2S_CTL__POR (0x00000003)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL (0x307)
+#define SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL (0x308)
+#define SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_OTHR_CTL (0x30A)
+#define SITAR_A_CDC_CLK_OTHR_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL (0x30B)
+#define SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_ANC_CLK_EN_CTL (0x30C)
+#define SITAR_A_CDC_CLK_ANC_CLK_EN_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_RX_B1_CTL (0x30D)
+#define SITAR_A_CDC_CLK_RX_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_RX_B2_CTL (0x30E)
+#define SITAR_A_CDC_CLK_RX_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_MCLK_CTL (0x30F)
+#define SITAR_A_CDC_CLK_MCLK_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_PDM_CTL (0x310)
+#define SITAR_A_CDC_CLK_PDM_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_SD_CTL (0x311)
+#define SITAR_A_CDC_CLK_SD_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLK_LP_CTL (0x312)
+#define SITAR_A_CDC_CLK_LP_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL (0x320)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR (0x00000007)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL (0x321)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR (0x00000013)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL (0x322)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR (0x0000001b)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL (0x323)
+#define SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR (0x0000007f)
+#define SITAR_A_CDC_CLSG_GAIN_THRESH_CTL (0x324)
+#define SITAR_A_CDC_CLSG_GAIN_THRESH_CTL__POR (0x00000026)
+#define SITAR_A_CDC_CLSG_TIMER_B1_CFG (0x325)
+#define SITAR_A_CDC_CLSG_TIMER_B1_CFG__POR (0x0000000a)
+#define SITAR_A_CDC_CLSG_TIMER_B2_CFG (0x326)
+#define SITAR_A_CDC_CLSG_TIMER_B2_CFG__POR (0x00000000)
+#define SITAR_A_CDC_CLSG_CTL (0x327)
+#define SITAR_A_CDC_CLSG_CTL__POR (0x00000013)
+#define SITAR_A_CDC_IIR1_GAIN_B1_CTL (0x340)
+#define SITAR_A_CDC_IIR1_GAIN_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B2_CTL (0x341)
+#define SITAR_A_CDC_IIR1_GAIN_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B3_CTL (0x342)
+#define SITAR_A_CDC_IIR1_GAIN_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B4_CTL (0x343)
+#define SITAR_A_CDC_IIR1_GAIN_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B5_CTL (0x344)
+#define SITAR_A_CDC_IIR1_GAIN_B5_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B6_CTL (0x345)
+#define SITAR_A_CDC_IIR1_GAIN_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B7_CTL (0x346)
+#define SITAR_A_CDC_IIR1_GAIN_B7_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_GAIN_B8_CTL (0x347)
+#define SITAR_A_CDC_IIR1_GAIN_B8_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_CTL (0x348)
+#define SITAR_A_CDC_IIR1_CTL__POR (0x00000040)
+#define SITAR_A_CDC_IIR1_GAIN_TIMER_CTL (0x349)
+#define SITAR_A_CDC_IIR1_GAIN_TIMER_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B1_CTL (0x34A)
+#define SITAR_A_CDC_IIR1_COEF_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B2_CTL (0x34B)
+#define SITAR_A_CDC_IIR1_COEF_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B3_CTL (0x34C)
+#define SITAR_A_CDC_IIR1_COEF_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B4_CTL (0x34D)
+#define SITAR_A_CDC_IIR1_COEF_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_IIR1_COEF_B5_CTL (0x34E)
+#define SITAR_A_CDC_IIR1_COEF_B5_CTL__POR (0x00000000)
+#define SITAR_A_CDC_TOP_GAIN_UPDATE (0x360)
+#define SITAR_A_CDC_TOP_GAIN_UPDATE__POR (0x00000000)
+#define SITAR_A_CDC_TOP_RDAC_DOUT_CTL (0x361)
+#define SITAR_A_CDC_TOP_RDAC_DOUT_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B1_CTL (0x368)
+#define SITAR_A_CDC_DEBUG_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B2_CTL (0x369)
+#define SITAR_A_CDC_DEBUG_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B3_CTL (0x36A)
+#define SITAR_A_CDC_DEBUG_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B4_CTL (0x36B)
+#define SITAR_A_CDC_DEBUG_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B5_CTL (0x36C)
+#define SITAR_A_CDC_DEBUG_B5_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B6_CTL (0x36D)
+#define SITAR_A_CDC_DEBUG_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_DEBUG_B7_CTL (0x36E)
+#define SITAR_A_CDC_DEBUG_B7_CTL__POR (0x00000000)
+#define SITAR_A_CDC_COMP1_B1_CTL (0x370)
+#define SITAR_A_CDC_COMP1_B1_CTL__POR (0x00000030)
+#define SITAR_A_CDC_COMP1_B2_CTL (0x371)
+#define SITAR_A_CDC_COMP1_B2_CTL__POR (0x000000b5)
+#define SITAR_A_CDC_COMP1_B3_CTL (0x372)
+#define SITAR_A_CDC_COMP1_B3_CTL__POR (0x00000028)
+#define SITAR_A_CDC_COMP1_B4_CTL (0x373)
+#define SITAR_A_CDC_COMP1_B4_CTL__POR (0x0000003c)
+#define SITAR_A_CDC_COMP1_B5_CTL (0x374)
+#define SITAR_A_CDC_COMP1_B5_CTL__POR (0x0000001f)
+#define SITAR_A_CDC_COMP1_B6_CTL (0x375)
+#define SITAR_A_CDC_COMP1_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS (0x376)
+#define SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS__POR (0x00000003)
+#define SITAR_A_CDC_COMP1_FS_CFG (0x377)
+#define SITAR_A_CDC_COMP1_FS_CFG__POR (0x0000001b)
+#define SITAR_A_CDC_CONN_RX1_B1_CTL (0x380)
+#define SITAR_A_CDC_CONN_RX1_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX1_B2_CTL (0x381)
+#define SITAR_A_CDC_CONN_RX1_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX1_B3_CTL (0x382)
+#define SITAR_A_CDC_CONN_RX1_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B1_CTL (0x383)
+#define SITAR_A_CDC_CONN_RX2_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B2_CTL (0x384)
+#define SITAR_A_CDC_CONN_RX2_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX2_B3_CTL (0x385)
+#define SITAR_A_CDC_CONN_RX2_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B1_CTL (0x386)
+#define SITAR_A_CDC_CONN_RX3_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B2_CTL (0x387)
+#define SITAR_A_CDC_CONN_RX3_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX3_B3_CTL (0x388)
+#define SITAR_A_CDC_CONN_RX3_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_ANC_B1_CTL (0x391)
+#define SITAR_A_CDC_CONN_ANC_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_ANC_B2_CTL (0x392)
+#define SITAR_A_CDC_CONN_ANC_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_B1_CTL (0x393)
+#define SITAR_A_CDC_CONN_TX_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_B2_CTL (0x394)
+#define SITAR_A_CDC_CONN_TX_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B1_CTL (0x397)
+#define SITAR_A_CDC_CONN_EQ1_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B2_CTL (0x398)
+#define SITAR_A_CDC_CONN_EQ1_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B3_CTL (0x399)
+#define SITAR_A_CDC_CONN_EQ1_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ1_B4_CTL (0x39A)
+#define SITAR_A_CDC_CONN_EQ1_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B1_CTL (0x39B)
+#define SITAR_A_CDC_CONN_EQ2_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B2_CTL (0x39C)
+#define SITAR_A_CDC_CONN_EQ2_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B3_CTL (0x39D)
+#define SITAR_A_CDC_CONN_EQ2_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_EQ2_B4_CTL (0x39E)
+#define SITAR_A_CDC_CONN_EQ2_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_SRC1_B1_CTL (0x39F)
+#define SITAR_A_CDC_CONN_SRC1_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_SRC1_B2_CTL (0x3A0)
+#define SITAR_A_CDC_CONN_SRC1_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_SRC2_B1_CTL (0x3A1)
+#define SITAR_A_CDC_CONN_SRC2_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_SRC2_B2_CTL (0x3A2)
+#define SITAR_A_CDC_CONN_SRC2_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B1_CTL (0x3A3)
+#define SITAR_A_CDC_CONN_TX_SB_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B2_CTL (0x3A4)
+#define SITAR_A_CDC_CONN_TX_SB_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B3_CTL (0x3A5)
+#define SITAR_A_CDC_CONN_TX_SB_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B4_CTL (0x3A6)
+#define SITAR_A_CDC_CONN_TX_SB_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_TX_SB_B5_CTL (0x3A7)
+#define SITAR_A_CDC_CONN_TX_SB_B5_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX_SB_B1_CTL (0x3AE)
+#define SITAR_A_CDC_CONN_RX_SB_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_RX_SB_B2_CTL (0x3AF)
+#define SITAR_A_CDC_CONN_RX_SB_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_CLSG_CTL (0x3B0)
+#define SITAR_A_CDC_CONN_CLSG_CTL__POR (0x00000000)
+#define SITAR_A_CDC_CONN_SPARE (0x3B1)
+#define SITAR_A_CDC_CONN_SPARE__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_EN_CTL (0x3C0)
+#define SITAR_A_CDC_MBHC_EN_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_FIR_B1_CFG (0x3C1)
+#define SITAR_A_CDC_MBHC_FIR_B1_CFG__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_FIR_B2_CFG (0x3C2)
+#define SITAR_A_CDC_MBHC_FIR_B2_CFG__POR (0x00000006)
+#define SITAR_A_CDC_MBHC_TIMER_B1_CTL (0x3C3)
+#define SITAR_A_CDC_MBHC_TIMER_B1_CTL__POR (0x00000003)
+#define SITAR_A_CDC_MBHC_TIMER_B2_CTL (0x3C4)
+#define SITAR_A_CDC_MBHC_TIMER_B2_CTL__POR (0x00000009)
+#define SITAR_A_CDC_MBHC_TIMER_B3_CTL (0x3C5)
+#define SITAR_A_CDC_MBHC_TIMER_B3_CTL__POR (0x0000001e)
+#define SITAR_A_CDC_MBHC_TIMER_B4_CTL (0x3C6)
+#define SITAR_A_CDC_MBHC_TIMER_B4_CTL__POR (0x00000045)
+#define SITAR_A_CDC_MBHC_TIMER_B5_CTL (0x3C7)
+#define SITAR_A_CDC_MBHC_TIMER_B5_CTL__POR (0x00000004)
+#define SITAR_A_CDC_MBHC_TIMER_B6_CTL (0x3C8)
+#define SITAR_A_CDC_MBHC_TIMER_B6_CTL__POR (0x00000078)
+#define SITAR_A_CDC_MBHC_B1_STATUS (0x3C9)
+#define SITAR_A_CDC_MBHC_B1_STATUS__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_B2_STATUS (0x3CA)
+#define SITAR_A_CDC_MBHC_B2_STATUS__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_B3_STATUS (0x3CB)
+#define SITAR_A_CDC_MBHC_B3_STATUS__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_B4_STATUS (0x3CC)
+#define SITAR_A_CDC_MBHC_B4_STATUS__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_B5_STATUS (0x3CD)
+#define SITAR_A_CDC_MBHC_B5_STATUS__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_B1_CTL (0x3CE)
+#define SITAR_A_CDC_MBHC_B1_CTL__POR (0x000000c0)
+#define SITAR_A_CDC_MBHC_B2_CTL (0x3CF)
+#define SITAR_A_CDC_MBHC_B2_CTL__POR (0x0000005d)
+#define SITAR_A_CDC_MBHC_VOLT_B1_CTL (0x3D0)
+#define SITAR_A_CDC_MBHC_VOLT_B1_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B2_CTL (0x3D1)
+#define SITAR_A_CDC_MBHC_VOLT_B2_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B3_CTL (0x3D2)
+#define SITAR_A_CDC_MBHC_VOLT_B3_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B4_CTL (0x3D3)
+#define SITAR_A_CDC_MBHC_VOLT_B4_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B5_CTL (0x3D4)
+#define SITAR_A_CDC_MBHC_VOLT_B5_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B6_CTL (0x3D5)
+#define SITAR_A_CDC_MBHC_VOLT_B6_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B7_CTL (0x3D6)
+#define SITAR_A_CDC_MBHC_VOLT_B7_CTL__POR (0x000000ff)
+#define SITAR_A_CDC_MBHC_VOLT_B8_CTL (0x3D7)
+#define SITAR_A_CDC_MBHC_VOLT_B8_CTL__POR (0x00000007)
+#define SITAR_A_CDC_MBHC_VOLT_B9_CTL (0x3D8)
+#define SITAR_A_CDC_MBHC_VOLT_B9_CTL__POR (0x000000ff)
+#define SITAR_A_CDC_MBHC_VOLT_B10_CTL (0x3D9)
+#define SITAR_A_CDC_MBHC_VOLT_B10_CTL__POR (0x0000007f)
+#define SITAR_A_CDC_MBHC_VOLT_B11_CTL (0x3DA)
+#define SITAR_A_CDC_MBHC_VOLT_B11_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_VOLT_B12_CTL (0x3DB)
+#define SITAR_A_CDC_MBHC_VOLT_B12_CTL__POR (0x00000080)
+#define SITAR_A_CDC_MBHC_CLK_CTL (0x3DC)
+#define SITAR_A_CDC_MBHC_CLK_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_INT_CTL (0x3DD)
+#define SITAR_A_CDC_MBHC_INT_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_DEBUG_CTL (0x3DE)
+#define SITAR_A_CDC_MBHC_DEBUG_CTL__POR (0x00000000)
+#define SITAR_A_CDC_MBHC_SPARE (0x3DF)
+#define SITAR_A_CDC_MBHC_SPARE__POR (0x00000000)
+/* SLIMBUS Slave Registers */
+#define SITAR_SLIM_PGD_PORT_INT_EN0 (0x30)
+#define SITAR_SLIM_PGD_PORT_INT_STATUS0 (0x34)
+#define SITAR_SLIM_PGD_PORT_INT_CLR0 (0x38)
+#define SITAR_SLIM_PGD_PORT_INT_SOURCE0 (0x60)
+
+/* Macros for Packing Register Writes into a U32 */
+#define SITAR_PACKED_REG_SIZE sizeof(u32)
+
+#define SITAR_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+ ((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+
+#define SITAR_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+ do { \
+ ((reg) = ((packed >> 16) & (0xffff))); \
+ ((mask) = ((packed >> 8) & (0xff))); \
+ ((val) = ((packed) & (0xff))); \
+ } while (0);
+#endif
diff --git a/include/linux/mfd/wcd9310/registers.h b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
similarity index 95%
rename from include/linux/mfd/wcd9310/registers.h
rename to include/linux/mfd/wcd9xxx/wcd9310_registers.h
index ef27c08..d2736ea 100644
--- a/include/linux/mfd/wcd9310/registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
@@ -1,29 +1,41 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
#ifndef TABLA_CODEC_DIGITAL_H
#define TABLA_CODEC_DIGITAL_H
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
-#define TABLA_A_CHIP_CTL (0x00)
-#define TABLA_A_CHIP_CTL__POR (0x00000000)
-#define TABLA_A_CHIP_STATUS (0x01)
-#define TABLA_A_CHIP_STATUS__POR (0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_0 (0x04)
-#define TABLA_A_CHIP_ID_BYTE_0__POR (0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_1 (0x05)
-#define TABLA_A_CHIP_ID_BYTE_1__POR (0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_2 (0x06)
-#define TABLA_A_CHIP_ID_BYTE_2__POR (0x00000000)
-#define TABLA_A_CHIP_ID_BYTE_3 (0x07)
-#define TABLA_A_CHIP_ID_BYTE_3__POR (0x00000001)
-#define TABLA_A_CHIP_VERSION (0x08)
-#define TABLA_A_CHIP_VERSION__POR (0x00000020)
-#define TABLA_A_SB_VERSION (0x09)
-#define TABLA_A_SB_VERSION__POR (0x00000010)
-#define TABLA_A_SLAVE_ID_1 (0x0C)
-#define TABLA_A_SLAVE_ID_1__POR (0x00000077)
-#define TABLA_A_SLAVE_ID_2 (0x0D)
-#define TABLA_A_SLAVE_ID_2__POR (0x00000066)
-#define TABLA_A_SLAVE_ID_3 (0x0E)
-#define TABLA_A_SLAVE_ID_3__POR (0x00000055)
+#define TABLA_A_CHIP_CTL WCD9XXX_A_CHIP_CTL
+#define TABLA_A_CHIP_CTL__POR WCD9XXX_A_CHIP_CTL__POR
+#define TABLA_A_CHIP_STATUS WCD9XXX_A_CHIP_STATUS
+#define TABLA_A_CHIP_STATUS__POR WCD9XXX_A_CHIP_STATUS__POR
+#define TABLA_A_CHIP_ID_BYTE_0 WCD9XXX_A_CHIP_ID_BYTE_0
+#define TABLA_A_CHIP_ID_BYTE_0__POR WCD9XXX_A_CHIP_ID_BYTE_0__POR
+#define TABLA_A_CHIP_ID_BYTE_1 WCD9XXX_A_CHIP_ID_BYTE_1
+#define TABLA_A_CHIP_ID_BYTE_1__POR WCD9XXX_A_CHIP_ID_BYTE_1__POR
+#define TABLA_A_CHIP_ID_BYTE_2 WCD9XXX_A_CHIP_ID_BYTE_2
+#define TABLA_A_CHIP_ID_BYTE_2__POR WCD9XXX_A_CHIP_ID_BYTE_2__POR
+#define TABLA_A_CHIP_ID_BYTE_3 WCD9XXX_A_CHIP_ID_BYTE_3
+#define TABLA_A_CHIP_ID_BYTE_3__POR WCD9XXX_A_CHIP_ID_BYTE_3__POR
+#define TABLA_A_CHIP_VERSION WCD9XXX_A_CHIP_VERSION
+#define TABLA_A_CHIP_VERSION__POR WCD9XXX_A_CHIP_VERSION__POR
+#define TABLA_A_SB_VERSION WCD9XXX_A_SB_VERSION
+#define TABLA_A_SB_VERSION__POR WCD9XXX_A_SB_VERSION__POR
+#define TABLA_A_SLAVE_ID_1 WCD9XXX_A_SLAVE_ID_1
+#define TABLA_A_SLAVE_ID_1__POR WCD9XXX_A_SLAVE_ID_1__POR
+#define TABLA_A_SLAVE_ID_2 WCD9XXX_A_SLAVE_ID_2
+#define TABLA_A_SLAVE_ID_2__POR WCD9XXX_A_SLAVE_ID_2__POR
+#define TABLA_A_SLAVE_ID_3 WCD9XXX_A_SLAVE_ID_3
+#define TABLA_A_SLAVE_ID_3__POR WCD9XXX_A_SLAVE_ID_3__POR
#define TABLA_A_PIN_CTL_OE0 (0x10)
#define TABLA_A_PIN_CTL_OE0__POR (0x00000000)
#define TABLA_A_PIN_CTL_OE1 (0x11)
@@ -58,10 +70,10 @@
#define TABLA_A_QFUSE_DATA_OUT2__POR (0x00000000)
#define TABLA_A_QFUSE_DATA_OUT3 (0x4D)
#define TABLA_A_QFUSE_DATA_OUT3__POR (0x00000000)
-#define TABLA_A_CDC_CTL (0x80)
-#define TABLA_A_CDC_CTL__POR (0x00000000)
-#define TABLA_A_LEAKAGE_CTL (0x88)
-#define TABLA_A_LEAKAGE_CTL__POR (0x00000004)
+#define TABLA_A_CDC_CTL WCD9XXX_A_CDC_CTL
+#define TABLA_A_CDC_CTL__POR WCD9XXX_A_CDC_CTL__POR
+#define TABLA_A_LEAKAGE_CTL WCD9XXX_A_LEAKAGE_CTL
+#define TABLA_A_LEAKAGE_CTL__POR WCD9XXX_A_LEAKAGE_CTL__POR
#define TABLA_A_INTR_MODE (0x90)
#define TABLA_A_INTR_MODE__POR (0x00000000)
#define TABLA_A_INTR_MASK0 (0x94)
diff --git a/include/linux/mfd/wcd9310/wcd9310-slimslave.h b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
similarity index 84%
rename from include/linux/mfd/wcd9310/wcd9310-slimslave.h
rename to include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
index 0bbf96f..fcd3bd3 100644
--- a/include/linux/mfd/wcd9310/wcd9310-slimslave.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
@@ -14,7 +14,7 @@
#define __WCD9310_SLIMSLAVE_H_
#include <linux/slimbus/slimbus.h>
-#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
/* Local to the core only */
#define SLIM_MAX_RX_PORTS 7
@@ -84,19 +84,19 @@
#define BASE_CH_NUM 128
-int tabla_init_slimslave(struct tabla *tabla, u8 tabla_pgd_la);
+int wcd9xxx_init_slimslave(struct wcd9xxx *wcd9xxx, u8 wcd9xxx_pgd_la);
-int tabla_deinit_slimslave(struct tabla *tabla);
+int wcd9xxx_deinit_slimslave(struct wcd9xxx *wcd9xxx);
-int tabla_cfg_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int tot_ch, unsigned int rate);
-int tabla_cfg_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_cfg_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int tot_ch, unsigned int rate);
-int tabla_close_slim_sch_rx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_rx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int tot_ch);
-int tabla_close_slim_sch_tx(struct tabla *tabla, unsigned int *ch_num,
+int wcd9xxx_close_slim_sch_tx(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
unsigned int tot_ch);
-int tabla_get_channel(struct tabla *tabla,
+int wcd9xxx_get_channel(struct wcd9xxx *wcd9xxx,
unsigned int *rx_ch,
unsigned int *tx_ch);
#endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
new file mode 100644
index 0000000..c66e953
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -0,0 +1,42 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef WCD9XXX_CODEC_DIGITAL_H
+
+#define WCD9XXX_CODEC_DIGITAL_H
+
+#define WCD9XXX_A_CHIP_CTL (0x00)
+#define WCD9XXX_A_CHIP_CTL__POR (0x00000000)
+#define WCD9XXX_A_CHIP_STATUS (0x01)
+#define WCD9XXX_A_CHIP_STATUS__POR (0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_0 (0x04)
+#define WCD9XXX_A_CHIP_ID_BYTE_0__POR (0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_1 (0x05)
+#define WCD9XXX_A_CHIP_ID_BYTE_1__POR (0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_2 (0x06)
+#define WCD9XXX_A_CHIP_ID_BYTE_2__POR (0x00000000)
+#define WCD9XXX_A_CHIP_ID_BYTE_3 (0x07)
+#define WCD9XXX_A_CHIP_ID_BYTE_3__POR (0x00000001)
+#define WCD9XXX_A_CHIP_VERSION (0x08)
+#define WCD9XXX_A_CHIP_VERSION__POR (0x00000020)
+#define WCD9XXX_A_SB_VERSION (0x09)
+#define WCD9XXX_A_SB_VERSION__POR (0x00000010)
+#define WCD9XXX_A_SLAVE_ID_1 (0x0C)
+#define WCD9XXX_A_SLAVE_ID_1__POR (0x00000077)
+#define WCD9XXX_A_SLAVE_ID_2 (0x0D)
+#define WCD9XXX_A_SLAVE_ID_2__POR (0x00000066)
+#define WCD9XXX_A_SLAVE_ID_3 (0x0E)
+#define WCD9XXX_A_SLAVE_ID_3__POR (0x00000055)
+#define WCD9XXX_A_CDC_CTL (0x80)
+#define WCD9XXX_A_CDC_CTL__POR (0x00000000)
+#define WCD9XXX_A_LEAKAGE_CTL (0x88)
+#define WCD9XXX_A_LEAKAGE_CTL__POR (0x00000004)
+#endif
diff --git a/include/linux/msm_audio.h b/include/linux/msm_audio.h
index 30d74ce..8a35ca0 100644
--- a/include/linux/msm_audio.h
+++ b/include/linux/msm_audio.h
@@ -90,6 +90,9 @@
#define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \
struct msm_acdb_cmd_device)
+#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 97, unsigned)
+#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 98, unsigned)
+
#define AUDIO_MAX_COMMON_IOCTL_NUM 100
@@ -166,6 +169,11 @@
uint32_t unused[2];
};
+struct msm_audio_ion_info {
+ int fd;
+ void *vaddr;
+};
+
struct msm_audio_pmem_info {
int fd;
void *vaddr;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 5e39f89..69ff05b 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -34,6 +34,16 @@
#define KGSL_CLK_MEM_IFACE 0x00000010
#define KGSL_CLK_AXI 0x00000020
+/*
+ * Reset status values for context
+ */
+enum kgsl_ctx_reset_stat {
+ KGSL_CTX_STAT_NO_ERROR = 0x00000000,
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT = 0x00000001,
+ KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT = 0x00000002,
+ KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT = 0x00000003
+};
+
#define KGSL_MAX_PWRLEVELS 5
#define KGSL_CONVERT_TO_MBPS(val) \
@@ -110,6 +120,7 @@
KGSL_PROP_MMU_ENABLE = 0x00000006,
KGSL_PROP_INTERRUPT_WAITS = 0x00000007,
KGSL_PROP_VERSION = 0x00000008,
+ KGSL_PROP_GPU_RESET_STAT = 0x00000009
};
struct kgsl_shadowprop {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 07d5af6..6442faa 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -140,6 +140,7 @@
#define MDP_OV_PLAY_NOWAIT 0x00200000
#define MDP_SOURCE_ROTATED_90 0x00100000
#define MDP_DPP_HSIC 0x00080000
+#define MDP_BACKEND_COMPOSITION 0x00040000
#define MDP_BORDERFILL_SUPPORTED 0x00010000
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 867bd8a..6a7f99b 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -342,6 +342,7 @@
#define MSM_CAM_RESP_MAX 8
#define MSM_CAM_APP_NOTIFY_EVENT 0
+#define MSM_CAM_APP_NOTIFY_ERROR_EVENT 1
/* this one is used to send ctrl/status up to config thread */
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index d08f528..0fabc5b 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -15,6 +15,9 @@
#include <mach/qdsp6v2/apr.h>
#include <mach/msm_subsystem_map.h>
#include <sound/apr_audio.h>
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#include <linux/ion.h>
+#endif
#define IN 0x000
#define OUT 0x001
@@ -94,10 +97,15 @@
struct audio_buffer {
dma_addr_t phys;
void *data;
- struct msm_mapped_buffer *mem_buffer;
uint32_t used;
uint32_t size;/* size of buffer */
uint32_t actual_size; /* actual number of bytes read by DSP */
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ struct ion_handle *handle;
+ struct ion_client *client;
+#else
+ struct msm_mapped_buffer *mem_buffer;
+#endif
};
struct audio_aio_write_param {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9662795..a3d5e34 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -569,7 +569,7 @@
struct hci_chan *ampchan = l2cap_pi(sk)->ampchan;
l2cap_pi(sk)->ampchan = NULL;
if (!hci_chan_put(ampchan))
- l2cap_deaggregate(l2cap_pi(sk)->ampchan, l2cap_pi(sk));
+ l2cap_deaggregate(ampchan, l2cap_pi(sk));
}
sk->sk_state = BT_CLOSED;
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 0d41625..11e1a67 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -8,9 +8,10 @@
use strict;
use constant BEFORE_SHORTTEXT => 0;
-use constant IN_SHORTTEXT => 1;
-use constant AFTER_SHORTTEXT => 2;
-use constant CHECK_NEXT_SHORTTEXT => 3;
+use constant IN_SHORTTEXT_BLANKLINE => 1;
+use constant IN_SHORTTEXT => 2;
+use constant AFTER_SHORTTEXT => 3;
+use constant CHECK_NEXT_SHORTTEXT => 4;
use constant SHORTTEXT_LIMIT => 75;
my $P = $0;
@@ -1233,6 +1234,7 @@
my $shorttext = BEFORE_SHORTTEXT;
my $shorttext_exspc = 0;
+ my $commit_text_present = 0;
sanitise_line_reset();
cleanup_continuation_headers();
@@ -1416,8 +1418,24 @@
my $hereprev = "$here\n$prevrawline\n$rawline\n";
if ($shorttext != AFTER_SHORTTEXT) {
+ if ($shorttext == IN_SHORTTEXT_BLANKLINE && $line=~/\S/) {
+ # the subject line was just processed,
+ # a blank line must be next
+ WARN("non-blank line after summary line\n" . $herecurr);
+ $shorttext = IN_SHORTTEXT;
+ # this non-blank line may or may not be commit text -
+ # a warning has been generated so assume it is commit
+ # text and move on
+ $commit_text_present = 1;
+ # fall through and treat this line as IN_SHORTTEXT
+ }
if ($shorttext == IN_SHORTTEXT) {
if ($line=~/^---/ || $line=~/^diff.*/) {
+ if ($commit_text_present == 0) {
+ WARN("please add commit text explaining " .
+ "*why* the change is needed\n" .
+ $herecurr);
+ }
$shorttext = AFTER_SHORTTEXT;
} elsif (length($line) > (SHORTTEXT_LIMIT +
$shorttext_exspc)
@@ -1427,7 +1445,22 @@
WARN("commit text line over " .
SHORTTEXT_LIMIT .
" characters\n" . $herecurr);
+ } elsif ($line=~/^\s*[\x21-\x39\x3b-\x7e]+:/) {
+ # this is a tag, there must be commit
+ # text by now
+ if ($commit_text_present == 0) {
+ WARN("please add commit text explaining " .
+ "*why* the change is needed\n" .
+ $herecurr);
+ # prevent duplicate warnings
+ $commit_text_present = 1;
+ }
+ } elsif ($line=~/\S/) {
+ $commit_text_present = 1;
}
+ } elsif ($shorttext == IN_SHORTTEXT_BLANKLINE) {
+ # case of non-blank line in this state handled above
+ $shorttext = IN_SHORTTEXT;
} elsif ($shorttext == CHECK_NEXT_SHORTTEXT) {
# The Subject line doesn't have to be the last header in the patch.
# Avoid moving to the IN_SHORTTEXT state until clear of all headers.
@@ -1435,16 +1468,25 @@
# text which looks like a header is definitely a header.
if ($line!~/^[\x21-\x39\x3b-\x7e]+:/) {
$shorttext = IN_SHORTTEXT;
-# Check for Subject line followed by a blank line.
+ # Check for Subject line followed by a blank line.
if (length($line) != 0) {
WARN("non-blank line after " .
"summary line\n" .
$sublinenr . $here .
"\n" . $subjectline .
"\n" . $line . "\n");
+ # this non-blank line may or may not
+ # be commit text - a warning has been
+ # generated so assume it is commit
+ # text and move on
+ $commit_text_present = 1;
}
}
+ # The next two cases are BEFORE_SHORTTEXT.
} elsif ($line=~/^Subject: \[[^\]]*\] (.*)/) {
+ # This is the subject line. Go to
+ # CHECK_NEXT_SHORTTEXT to wait for the commit
+ # text to show up.
$shorttext = CHECK_NEXT_SHORTTEXT;
$subjectline = $line;
$sublinenr = "#$linenr & ";
@@ -1455,7 +1497,10 @@
" characters\n" . $herecurr);
}
} elsif ($line=~/^ (.*)/) {
- $shorttext = IN_SHORTTEXT;
+ # Indented format, this must be the summary
+ # line (i.e. git show). There will be no more
+ # headers so we are now in the shorttext.
+ $shorttext = IN_SHORTTEXT_BLANKLINE;
$shorttext_exspc = 4;
if (length($1) > SHORTTEXT_LIMIT) {
WARN("summary line over " .
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 0104f1a..d3d393d 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -44,6 +44,8 @@
"alignment.c:720",
"async.c:122",
"async.c:270",
+ "block.c:835",
+ "block.c:836",
"dir.c:43",
"dm.c:1053",
"dm.c:1080",
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b923a25..88181a6 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -250,6 +250,9 @@
config SND_SOC_UDA1380
tristate
+config SND_SOC_WCD9304
+ tristate
+
config SND_SOC_WCD9310
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 78740ab..0bd7255 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -38,6 +38,7 @@
snd-soc-twl6040-objs := twl6040.o
snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
+snd-soc-wcd9304-objs := wcd9304.o wcd9304-tables.o
snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
@@ -132,6 +133,7 @@
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
+obj-$(CONFIG_SND_SOC_WCD9304) += snd-soc-wcd9304.o
obj-$(CONFIG_SND_SOC_WCD9310) += snd-soc-wcd9310.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
diff --git a/sound/soc/codecs/wcd9304-tables.c b/sound/soc/codecs/wcd9304-tables.c
new file mode 100644
index 0000000..823f926
--- /dev/null
+++ b/sound/soc/codecs/wcd9304-tables.c
@@ -0,0 +1,720 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9304_registers.h>
+#include "wcd9304.h"
+
+const u8 sitar_reg_defaults[SITAR_CACHE_SIZE] = {
+ [WCD9XXX_A_CHIP_CTL] = WCD9XXX_A_CHIP_CTL__POR,
+ [WCD9XXX_A_CHIP_STATUS] = WCD9XXX_A_CHIP_STATUS__POR,
+ [WCD9XXX_A_CHIP_ID_BYTE_0] = WCD9XXX_A_CHIP_ID_BYTE_0__POR,
+ [WCD9XXX_A_CHIP_ID_BYTE_1] = WCD9XXX_A_CHIP_ID_BYTE_1__POR,
+ [WCD9XXX_A_CHIP_ID_BYTE_2] = WCD9XXX_A_CHIP_ID_BYTE_2__POR,
+ [WCD9XXX_A_CHIP_ID_BYTE_3] = WCD9XXX_A_CHIP_ID_BYTE_3__POR,
+ [WCD9XXX_A_CHIP_VERSION] = WCD9XXX_A_CHIP_VERSION__POR,
+ [WCD9XXX_A_SB_VERSION] = WCD9XXX_A_SB_VERSION__POR,
+ [WCD9XXX_A_SLAVE_ID_1] = WCD9XXX_A_SLAVE_ID_1__POR,
+ [WCD9XXX_A_SLAVE_ID_2] = WCD9XXX_A_SLAVE_ID_2__POR,
+ [WCD9XXX_A_SLAVE_ID_3] = WCD9XXX_A_SLAVE_ID_3__POR,
+ [SITAR_A_PIN_CTL_OE0] = SITAR_A_PIN_CTL_OE0__POR,
+ [SITAR_A_PIN_CTL_OE1] = SITAR_A_PIN_CTL_OE1__POR,
+ [SITAR_A_PIN_CTL_DATA0] = SITAR_A_PIN_CTL_DATA0__POR,
+ [SITAR_A_PIN_CTL_DATA1] = SITAR_A_PIN_CTL_DATA1__POR,
+ [SITAR_A_HDRIVE_GENERIC] = SITAR_A_HDRIVE_GENERIC__POR,
+ [SITAR_A_HDRIVE_OVERRIDE] = SITAR_A_HDRIVE_OVERRIDE__POR,
+ [SITAR_A_ANA_CSR_WAIT_STATE] = SITAR_A_ANA_CSR_WAIT_STATE__POR,
+ [SITAR_A_PROCESS_MONITOR_CTL0] = SITAR_A_PROCESS_MONITOR_CTL0__POR,
+ [SITAR_A_PROCESS_MONITOR_CTL1] = SITAR_A_PROCESS_MONITOR_CTL1__POR,
+ [SITAR_A_PROCESS_MONITOR_CTL2] = SITAR_A_PROCESS_MONITOR_CTL2__POR,
+ [SITAR_A_PROCESS_MONITOR_CTL3] = SITAR_A_PROCESS_MONITOR_CTL3__POR,
+ [SITAR_A_QFUSE_CTL] = SITAR_A_QFUSE_CTL__POR,
+ [SITAR_A_QFUSE_STATUS] = SITAR_A_QFUSE_STATUS__POR,
+ [SITAR_A_QFUSE_DATA_OUT0] = SITAR_A_QFUSE_DATA_OUT0__POR,
+ [SITAR_A_QFUSE_DATA_OUT1] = SITAR_A_QFUSE_DATA_OUT1__POR,
+ [SITAR_A_QFUSE_DATA_OUT2] = SITAR_A_QFUSE_DATA_OUT2__POR,
+ [SITAR_A_QFUSE_DATA_OUT3] = SITAR_A_QFUSE_DATA_OUT3__POR,
+ [SITAR_A_CDC_CTL] = SITAR_A_CDC_CTL__POR,
+ [SITAR_A_LEAKAGE_CTL] = SITAR_A_LEAKAGE_CTL__POR,
+ [SITAR_A_INTR_MODE] = SITAR_A_INTR_MODE__POR,
+ [SITAR_A_INTR_MASK0] = SITAR_A_INTR_MASK0__POR,
+ [SITAR_A_INTR_MASK1] = SITAR_A_INTR_MASK1__POR,
+ [SITAR_A_INTR_MASK2] = SITAR_A_INTR_MASK2__POR,
+ [SITAR_A_INTR_STATUS0] = SITAR_A_INTR_STATUS0__POR,
+ [SITAR_A_INTR_STATUS1] = SITAR_A_INTR_STATUS1__POR,
+ [SITAR_A_INTR_STATUS2] = SITAR_A_INTR_STATUS2__POR,
+ [SITAR_A_INTR_CLEAR0] = SITAR_A_INTR_CLEAR0__POR,
+ [SITAR_A_INTR_CLEAR1] = SITAR_A_INTR_CLEAR1__POR,
+ [SITAR_A_INTR_CLEAR2] = SITAR_A_INTR_CLEAR2__POR,
+ [SITAR_A_INTR_LEVEL0] = SITAR_A_INTR_LEVEL0__POR,
+ [SITAR_A_INTR_LEVEL1] = SITAR_A_INTR_LEVEL1__POR,
+ [SITAR_A_INTR_LEVEL2] = SITAR_A_INTR_LEVEL2__POR,
+ [SITAR_A_INTR_TEST0] = SITAR_A_INTR_TEST0__POR,
+ [SITAR_A_INTR_TEST1] = SITAR_A_INTR_TEST1__POR,
+ [SITAR_A_INTR_TEST2] = SITAR_A_INTR_TEST2__POR,
+ [SITAR_A_INTR_SET0] = SITAR_A_INTR_SET0__POR,
+ [SITAR_A_INTR_SET1] = SITAR_A_INTR_SET1__POR,
+ [SITAR_A_INTR_SET2] = SITAR_A_INTR_SET2__POR,
+ [SITAR_A_CDC_TX_I2S_SCK_MODE] = SITAR_A_CDC_TX_I2S_SCK_MODE__POR,
+ [SITAR_A_CDC_TX_I2S_WS_MODE] = SITAR_A_CDC_TX_I2S_WS_MODE__POR,
+ [SITAR_A_CDC_DMIC_DATA0_MODE] = SITAR_A_CDC_DMIC_DATA0_MODE__POR,
+ [SITAR_A_CDC_DMIC_CLK0_MODE] = SITAR_A_CDC_DMIC_CLK0_MODE__POR,
+ [SITAR_A_CDC_DMIC_DATA1_MODE] = SITAR_A_CDC_DMIC_DATA1_MODE__POR,
+ [SITAR_A_CDC_DMIC_CLK1_MODE] = SITAR_A_CDC_DMIC_CLK1_MODE__POR,
+ [SITAR_A_CDC_TX_I2S_SD0_MODE] = SITAR_A_CDC_TX_I2S_SD0_MODE__POR,
+ [SITAR_A_CDC_INTR_MODE] = SITAR_A_CDC_INTR_MODE__POR,
+ [SITAR_A_CDC_RX_I2S_SD0_MODE] = SITAR_A_CDC_RX_I2S_SD0_MODE__POR,
+ [SITAR_A_CDC_RX_I2S_SD1_MODE] = SITAR_A_CDC_RX_I2S_SD1_MODE__POR,
+ [SITAR_A_BIAS_REF_CTL] = SITAR_A_BIAS_REF_CTL__POR,
+ [SITAR_A_BIAS_CENTRAL_BG_CTL] = SITAR_A_BIAS_CENTRAL_BG_CTL__POR,
+ [SITAR_A_BIAS_PRECHRG_CTL] = SITAR_A_BIAS_PRECHRG_CTL__POR,
+ [SITAR_A_BIAS_CURR_CTL_1] = SITAR_A_BIAS_CURR_CTL_1__POR,
+ [SITAR_A_BIAS_CURR_CTL_2] = SITAR_A_BIAS_CURR_CTL_2__POR,
+ [SITAR_A_BIAS_OSC_BG_CTL] = SITAR_A_BIAS_OSC_BG_CTL__POR,
+ [SITAR_A_CLK_BUFF_EN1] = SITAR_A_CLK_BUFF_EN1__POR,
+ [SITAR_A_CLK_BUFF_EN2] = SITAR_A_CLK_BUFF_EN2__POR,
+ [SITAR_A_LDO_H_MODE_1] = SITAR_A_LDO_H_MODE_1__POR,
+ [SITAR_A_LDO_H_MODE_2] = SITAR_A_LDO_H_MODE_2__POR,
+ [SITAR_A_LDO_H_LOOP_CTL] = SITAR_A_LDO_H_LOOP_CTL__POR,
+ [SITAR_A_LDO_H_COMP_1] = SITAR_A_LDO_H_COMP_1__POR,
+ [SITAR_A_LDO_H_COMP_2] = SITAR_A_LDO_H_COMP_2__POR,
+ [SITAR_A_LDO_H_BIAS_1] = SITAR_A_LDO_H_BIAS_1__POR,
+ [SITAR_A_LDO_H_BIAS_2] = SITAR_A_LDO_H_BIAS_2__POR,
+ [SITAR_A_LDO_H_BIAS_3] = SITAR_A_LDO_H_BIAS_3__POR,
+ [SITAR_A_MICB_CFILT_1_CTL] = SITAR_A_MICB_CFILT_1_CTL__POR,
+ [SITAR_A_MICB_CFILT_1_VAL] = SITAR_A_MICB_CFILT_1_VAL__POR,
+ [SITAR_A_MICB_CFILT_1_PRECHRG] = SITAR_A_MICB_CFILT_1_PRECHRG__POR,
+ [SITAR_A_MICB_1_CTL] = SITAR_A_MICB_1_CTL__POR,
+ [SITAR_A_MICB_1_INT_RBIAS] = SITAR_A_MICB_1_INT_RBIAS__POR,
+ [SITAR_A_MICB_1_MBHC] = SITAR_A_MICB_1_MBHC__POR,
+ [SITAR_A_MICB_CFILT_2_CTL] = SITAR_A_MICB_CFILT_2_CTL__POR,
+ [SITAR_A_MICB_CFILT_2_VAL] = SITAR_A_MICB_CFILT_2_VAL__POR,
+ [SITAR_A_MICB_CFILT_2_PRECHRG] = SITAR_A_MICB_CFILT_2_PRECHRG__POR,
+ [SITAR_A_MICB_2_CTL] = SITAR_A_MICB_2_CTL__POR,
+ [SITAR_A_MICB_2_INT_RBIAS] = SITAR_A_MICB_2_INT_RBIAS__POR,
+ [SITAR_A_MICB_2_MBHC] = SITAR_A_MICB_2_MBHC__POR,
+ [SITAR_A_TX_COM_BIAS] = SITAR_A_TX_COM_BIAS__POR,
+ [SITAR_A_MBHC_SCALING_MUX_1] = SITAR_A_MBHC_SCALING_MUX_1__POR,
+ [SITAR_A_MBHC_SCALING_MUX_2] = SITAR_A_MBHC_SCALING_MUX_2__POR,
+ [SITAR_A_TX_SUP_SWITCH_CTRL_1] = SITAR_A_TX_SUP_SWITCH_CTRL_1__POR,
+ [SITAR_A_TX_SUP_SWITCH_CTRL_2] = SITAR_A_TX_SUP_SWITCH_CTRL_2__POR,
+ [SITAR_A_TX_1_2_EN] = SITAR_A_TX_1_2_EN__POR,
+ [SITAR_A_TX_1_2_TEST_EN] = SITAR_A_TX_1_2_TEST_EN__POR,
+ [SITAR_A_TX_1_2_ADC_CH1] = SITAR_A_TX_1_2_ADC_CH1__POR,
+ [SITAR_A_TX_1_2_ADC_CH2] = SITAR_A_TX_1_2_ADC_CH2__POR,
+ [SITAR_A_TX_1_2_ATEST_REFCTRL] = SITAR_A_TX_1_2_ATEST_REFCTRL__POR,
+ [SITAR_A_TX_1_2_TEST_CTL] = SITAR_A_TX_1_2_TEST_CTL__POR,
+ [SITAR_A_TX_1_2_TEST_BLOCK_EN] = SITAR_A_TX_1_2_TEST_BLOCK_EN__POR,
+ [SITAR_A_TX_1_2_TXFE_CLKDIV] = SITAR_A_TX_1_2_TXFE_CLKDIV__POR,
+ [SITAR_A_TX_1_2_SAR_ERR_CH1] = SITAR_A_TX_1_2_SAR_ERR_CH1__POR,
+ [SITAR_A_TX_1_2_SAR_ERR_CH2] = SITAR_A_TX_1_2_SAR_ERR_CH2__POR,
+ [SITAR_A_TX_3_EN] = SITAR_A_TX_3_EN__POR,
+ [SITAR_A_TX_3_TEST_EN] = SITAR_A_TX_3_TEST_EN__POR,
+ [SITAR_A_TX_3_ADC] = SITAR_A_TX_3_ADC__POR,
+ [SITAR_A_TX_3_MBHC_ATEST_REFCTRL] =
+ SITAR_A_TX_3_MBHC_ATEST_REFCTRL__POR,
+ [SITAR_A_TX_3_TEST_CTL] = SITAR_A_TX_3_TEST_CTL__POR,
+ [SITAR_A_TX_3_TEST_BLOCK_EN] = SITAR_A_TX_3_TEST_BLOCK_EN__POR,
+ [SITAR_A_TX_3_TXFE_CKDIV] = SITAR_A_TX_3_TXFE_CKDIV__POR,
+ [SITAR_A_TX_3_SAR_ERR] = SITAR_A_TX_3_SAR_ERR__POR,
+ [SITAR_A_TX_4_MBHC_EN] = SITAR_A_TX_4_MBHC_EN__POR,
+ [SITAR_A_TX_4_MBHC_ADC] = SITAR_A_TX_4_MBHC_ADC__POR,
+ [SITAR_A_TX_4_MBHC_TEST_CTL] = SITAR_A_TX_4_MBHC_TEST_CTL__POR,
+ [SITAR_A_TX_4_MBHC_SAR_ERR] = SITAR_A_TX_4_MBHC_SAR_ERR__POR,
+ [SITAR_A_TX_4_TXFE_CLKDIV] = SITAR_A_TX_4_TXFE_CLKDIV__POR,
+ [SITAR_A_AUX_COM_CTL] = SITAR_A_AUX_COM_CTL__POR,
+ [SITAR_A_AUX_COM_ATEST] = SITAR_A_AUX_COM_ATEST__POR,
+ [SITAR_A_AUX_L_EN] = SITAR_A_AUX_L_EN__POR,
+ [SITAR_A_AUX_L_GAIN] = SITAR_A_AUX_L_GAIN__POR,
+ [SITAR_A_AUX_L_PA_CONN] = SITAR_A_AUX_L_PA_CONN__POR,
+ [SITAR_A_AUX_L_PA_CONN_INV] = SITAR_A_AUX_L_PA_CONN_INV__POR,
+ [SITAR_A_AUX_R_EN] = SITAR_A_AUX_R_EN__POR,
+ [SITAR_A_AUX_R_GAIN] = SITAR_A_AUX_R_GAIN__POR,
+ [SITAR_A_AUX_R_PA_CONN] = SITAR_A_AUX_R_PA_CONN__POR,
+ [SITAR_A_AUX_R_PA_CONN_INV] = SITAR_A_AUX_R_PA_CONN_INV__POR,
+ [SITAR_A_CP_EN] = SITAR_A_CP_EN__POR,
+ [SITAR_A_CP_CLK] = SITAR_A_CP_CLK__POR,
+ [SITAR_A_CP_STATIC] = SITAR_A_CP_STATIC__POR,
+ [SITAR_A_CP_DCC1] = SITAR_A_CP_DCC1__POR,
+ [SITAR_A_CP_DCC3] = SITAR_A_CP_DCC3__POR,
+ [SITAR_A_CP_ATEST] = SITAR_A_CP_ATEST__POR,
+ [SITAR_A_CP_DTEST] = SITAR_A_CP_DTEST__POR,
+ [SITAR_A_RX_COM_TIMER_DIV] = SITAR_A_RX_COM_TIMER_DIV__POR,
+ [SITAR_A_RX_COM_OCP_CTL] = SITAR_A_RX_COM_OCP_CTL__POR,
+ [SITAR_A_RX_COM_OCP_COUNT] = SITAR_A_RX_COM_OCP_COUNT__POR,
+ [SITAR_A_RX_COM_DAC_CTL] = SITAR_A_RX_COM_DAC_CTL__POR,
+ [SITAR_A_RX_COM_BIAS] = SITAR_A_RX_COM_BIAS__POR,
+ [SITAR_A_RX_HPH_BIAS_PA] = SITAR_A_RX_HPH_BIAS_PA__POR,
+ [SITAR_A_RX_HPH_BIAS_LDO] = SITAR_A_RX_HPH_BIAS_LDO__POR,
+ [SITAR_A_RX_HPH_BIAS_CNP] = SITAR_A_RX_HPH_BIAS_CNP__POR,
+ [SITAR_A_RX_HPH_BIAS_WG] = SITAR_A_RX_HPH_BIAS_WG__POR,
+ [SITAR_A_RX_HPH_OCP_CTL] = SITAR_A_RX_HPH_OCP_CTL__POR,
+ [SITAR_A_RX_HPH_CNP_EN] = SITAR_A_RX_HPH_CNP_EN__POR,
+ [SITAR_A_RX_HPH_CNP_WG_CTL] = SITAR_A_RX_HPH_CNP_WG_CTL__POR,
+ [SITAR_A_RX_HPH_CNP_WG_TIME] = SITAR_A_RX_HPH_CNP_WG_TIME__POR,
+ [SITAR_A_RX_HPH_L_GAIN] = SITAR_A_RX_HPH_L_GAIN__POR,
+ [SITAR_A_RX_HPH_L_TEST] = SITAR_A_RX_HPH_L_TEST__POR,
+ [SITAR_A_RX_HPH_L_PA_CTL] = SITAR_A_RX_HPH_L_PA_CTL__POR,
+ [SITAR_A_RX_HPH_L_DAC_CTL] = SITAR_A_RX_HPH_L_DAC_CTL__POR,
+ [SITAR_A_RX_HPH_L_ATEST] = SITAR_A_RX_HPH_L_ATEST__POR,
+ [SITAR_A_RX_HPH_L_STATUS] = SITAR_A_RX_HPH_L_STATUS__POR,
+ [SITAR_A_RX_HPH_R_GAIN] = SITAR_A_RX_HPH_R_GAIN__POR,
+ [SITAR_A_RX_HPH_R_TEST] = SITAR_A_RX_HPH_R_TEST__POR,
+ [SITAR_A_RX_HPH_R_PA_CTL] = SITAR_A_RX_HPH_R_PA_CTL__POR,
+ [SITAR_A_RX_HPH_R_DAC_CTL] = SITAR_A_RX_HPH_R_DAC_CTL__POR,
+ [SITAR_A_RX_HPH_R_ATEST] = SITAR_A_RX_HPH_R_ATEST__POR,
+ [SITAR_A_RX_HPH_R_STATUS] = SITAR_A_RX_HPH_R_STATUS__POR,
+ [SITAR_A_RX_EAR_BIAS_PA] = SITAR_A_RX_EAR_BIAS_PA__POR,
+ [SITAR_A_RX_EAR_BIAS_CMBUFF] = SITAR_A_RX_EAR_BIAS_CMBUFF__POR,
+ [SITAR_A_RX_EAR_EN] = SITAR_A_RX_EAR_EN__POR,
+ [SITAR_A_RX_EAR_GAIN] = SITAR_A_RX_EAR_GAIN__POR,
+ [SITAR_A_RX_EAR_CMBUFF] = SITAR_A_RX_EAR_CMBUFF__POR,
+ [SITAR_A_RX_EAR_ICTL] = SITAR_A_RX_EAR_ICTL__POR,
+ [SITAR_A_RX_EAR_CCOMP] = SITAR_A_RX_EAR_CCOMP__POR,
+ [SITAR_A_RX_EAR_VCM] = SITAR_A_RX_EAR_VCM__POR,
+ [SITAR_A_RX_EAR_CNP] = SITAR_A_RX_EAR_CNP__POR,
+ [SITAR_A_RX_EAR_ATEST] = SITAR_A_RX_EAR_ATEST__POR,
+ [SITAR_A_RX_EAR_STATUS] = SITAR_A_RX_EAR_STATUS__POR,
+ [SITAR_A_RX_LINE_BIAS_PA] = SITAR_A_RX_LINE_BIAS_PA__POR,
+ [SITAR_A_RX_LINE_BIAS_LDO] = SITAR_A_RX_LINE_BIAS_LDO__POR,
+ [SITAR_A_RX_LINE_BIAS_CNP1] = SITAR_A_RX_LINE_BIAS_CNP1__POR,
+ [SITAR_A_RX_LINE_COM] = SITAR_A_RX_LINE_COM__POR,
+ [SITAR_A_RX_LINE_CNP_EN] = SITAR_A_RX_LINE_CNP_EN__POR,
+ [SITAR_A_RX_LINE_CNP_WG_CTL] = SITAR_A_RX_LINE_CNP_WG_CTL__POR,
+ [SITAR_A_RX_LINE_CNP_WG_TIME] = SITAR_A_RX_LINE_CNP_WG_TIME__POR,
+ [SITAR_A_RX_LINE_1_GAIN] = SITAR_A_RX_LINE_1_GAIN__POR,
+ [SITAR_A_RX_LINE_1_TEST] = SITAR_A_RX_LINE_1_TEST__POR,
+ [SITAR_A_RX_LINE_1_DAC_CTL] = SITAR_A_RX_LINE_1_DAC_CTL__POR,
+ [SITAR_A_RX_LINE_1_STATUS] = SITAR_A_RX_LINE_1_STATUS__POR,
+ [SITAR_A_RX_LINE_2_GAIN] = SITAR_A_RX_LINE_2_GAIN__POR,
+ [SITAR_A_RX_LINE_2_TEST] = SITAR_A_RX_LINE_2_TEST__POR,
+ [SITAR_A_RX_LINE_2_DAC_CTL] = SITAR_A_RX_LINE_2_DAC_CTL__POR,
+ [SITAR_A_RX_LINE_2_STATUS] = SITAR_A_RX_LINE_2_STATUS__POR,
+ [SITAR_A_RX_LINE_BIAS_CNP2] = SITAR_A_RX_LINE_BIAS_CNP2__POR,
+ [SITAR_A_RX_LINE_OCP_CTL] = SITAR_A_RX_LINE_OCP_CTL__POR,
+ [SITAR_A_RX_LINE_1_PA_CTL] = SITAR_A_RX_LINE_1_PA_CTL__POR,
+ [SITAR_A_RX_LINE_2_PA_CTL] = SITAR_A_RX_LINE_2_PA_CTL__POR,
+ [SITAR_A_RX_LINE_CNP_DBG] = SITAR_A_RX_LINE_CNP_DBG__POR,
+ [SITAR_A_MBHC_HPH] = SITAR_A_MBHC_HPH__POR,
+ [SITAR_A_RC_OSC_FREQ] = SITAR_A_RC_OSC_FREQ__POR,
+ [SITAR_A_RC_OSC_TEST] = SITAR_A_RC_OSC_TEST__POR,
+ [SITAR_A_RC_OSC_STATUS] = SITAR_A_RC_OSC_STATUS__POR,
+ [SITAR_A_RC_OSC_TUNER] = SITAR_A_RC_OSC_TUNER__POR,
+ [SITAR_A_CDC_ANC1_CTL] = SITAR_A_CDC_ANC1_CTL__POR,
+ [SITAR_A_CDC_ANC1_SHIFT] = SITAR_A_CDC_ANC1_SHIFT__POR,
+ [SITAR_A_CDC_ANC1_IIR_B1_CTL] = SITAR_A_CDC_ANC1_IIR_B1_CTL__POR,
+ [SITAR_A_CDC_ANC1_IIR_B2_CTL] = SITAR_A_CDC_ANC1_IIR_B2_CTL__POR,
+ [SITAR_A_CDC_ANC1_IIR_B3_CTL] = SITAR_A_CDC_ANC1_IIR_B3_CTL__POR,
+ [SITAR_A_CDC_ANC1_IIR_B4_CTL] = SITAR_A_CDC_ANC1_IIR_B4_CTL__POR,
+ [SITAR_A_CDC_ANC1_LPF_B1_CTL] = SITAR_A_CDC_ANC1_LPF_B1_CTL__POR,
+ [SITAR_A_CDC_ANC1_LPF_B2_CTL] = SITAR_A_CDC_ANC1_LPF_B2_CTL__POR,
+ [SITAR_A_CDC_ANC1_LPF_B3_CTL] = SITAR_A_CDC_ANC1_LPF_B3_CTL__POR,
+ [SITAR_A_CDC_ANC1_SPARE] = SITAR_A_CDC_ANC1_SPARE__POR,
+ [SITAR_A_CDC_ANC1_SMLPF_CTL] = SITAR_A_CDC_ANC1_SMLPF_CTL__POR,
+ [SITAR_A_CDC_ANC1_DCFLT_CTL] = SITAR_A_CDC_ANC1_DCFLT_CTL__POR,
+ [SITAR_A_CDC_TX1_VOL_CTL_TIMER] = SITAR_A_CDC_TX1_VOL_CTL_TIMER__POR,
+ [SITAR_A_CDC_TX1_VOL_CTL_GAIN] = SITAR_A_CDC_TX1_VOL_CTL_GAIN__POR,
+ [SITAR_A_CDC_TX1_VOL_CTL_CFG] = SITAR_A_CDC_TX1_VOL_CTL_CFG__POR,
+ [SITAR_A_CDC_TX1_MUX_CTL] = SITAR_A_CDC_TX1_MUX_CTL__POR,
+ [SITAR_A_CDC_TX1_CLK_FS_CTL] = SITAR_A_CDC_TX1_CLK_FS_CTL__POR,
+ [SITAR_A_CDC_TX1_DMIC_CTL] = SITAR_A_CDC_TX1_DMIC_CTL__POR,
+ [SITAR_A_CDC_SRC1_PDA_CFG] = SITAR_A_CDC_SRC1_PDA_CFG__POR,
+ [SITAR_A_CDC_SRC1_FS_CTL] = SITAR_A_CDC_SRC1_FS_CTL__POR,
+ [SITAR_A_CDC_RX1_B1_CTL] = SITAR_A_CDC_RX1_B1_CTL__POR,
+ [SITAR_A_CDC_RX1_B2_CTL] = SITAR_A_CDC_RX1_B2_CTL__POR,
+ [SITAR_A_CDC_RX1_B3_CTL] = SITAR_A_CDC_RX1_B3_CTL__POR,
+ [SITAR_A_CDC_RX1_B4_CTL] = SITAR_A_CDC_RX1_B4_CTL__POR,
+ [SITAR_A_CDC_RX1_B5_CTL] = SITAR_A_CDC_RX1_B5_CTL__POR,
+ [SITAR_A_CDC_RX1_B6_CTL] = SITAR_A_CDC_RX1_B6_CTL__POR,
+ [SITAR_A_CDC_RX1_VOL_CTL_B1_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+ [SITAR_A_CDC_RX1_VOL_CTL_B2_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+ [SITAR_A_CDC_CLK_ANC_RESET_CTL] = SITAR_A_CDC_CLK_ANC_RESET_CTL__POR,
+ [SITAR_A_CDC_CLK_RX_RESET_CTL] = SITAR_A_CDC_CLK_RX_RESET_CTL__POR,
+ [SITAR_A_CDC_CLK_TX_RESET_B1_CTL] =
+ SITAR_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+ [SITAR_A_CDC_CLK_TX_RESET_B2_CTL] =
+ SITAR_A_CDC_CLK_TX_RESET_B2_CTL__POR,
+ [SITAR_A_CDC_CLK_DMIC_CTL] = SITAR_A_CDC_CLK_DMIC_CTL__POR,
+ [SITAR_A_CDC_CLK_RX_I2S_CTL] = SITAR_A_CDC_CLK_RX_I2S_CTL__POR,
+ [SITAR_A_CDC_CLK_TX_I2S_CTL] = SITAR_A_CDC_CLK_TX_I2S_CTL__POR,
+ [SITAR_A_CDC_CLK_OTHR_RESET_CTL] = SITAR_A_CDC_CLK_OTHR_RESET_CTL__POR,
+ [SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+ SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+ [SITAR_A_CDC_CLK_OTHR_CTL] = SITAR_A_CDC_CLK_OTHR_CTL__POR,
+ [SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL] =
+ SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL__POR,
+ [SITAR_A_CDC_CLK_ANC_CLK_EN_CTL] = SITAR_A_CDC_CLK_ANC_CLK_EN_CTL__POR,
+ [SITAR_A_CDC_CLK_RX_B1_CTL] = SITAR_A_CDC_CLK_RX_B1_CTL__POR,
+ [SITAR_A_CDC_CLK_RX_B2_CTL] = SITAR_A_CDC_CLK_RX_B2_CTL__POR,
+ [SITAR_A_CDC_CLK_MCLK_CTL] = SITAR_A_CDC_CLK_MCLK_CTL__POR,
+ [SITAR_A_CDC_CLK_PDM_CTL] = SITAR_A_CDC_CLK_PDM_CTL__POR,
+ [SITAR_A_CDC_CLK_SD_CTL] = SITAR_A_CDC_CLK_SD_CTL__POR,
+ [SITAR_A_CDC_CLK_LP_CTL] = SITAR_A_CDC_CLK_LP_CTL__POR,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL] =
+ SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL__POR,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL] =
+ SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL__POR,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL] =
+ SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL__POR,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL] =
+ SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL__POR,
+ [SITAR_A_CDC_CLSG_GAIN_THRESH_CTL] =
+ SITAR_A_CDC_CLSG_GAIN_THRESH_CTL__POR,
+ [SITAR_A_CDC_CLSG_TIMER_B1_CFG] = SITAR_A_CDC_CLSG_TIMER_B1_CFG__POR,
+ [SITAR_A_CDC_CLSG_TIMER_B2_CFG] = SITAR_A_CDC_CLSG_TIMER_B2_CFG__POR,
+ [SITAR_A_CDC_CLSG_CTL] = SITAR_A_CDC_CLSG_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B1_CTL] = SITAR_A_CDC_IIR1_GAIN_B1_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B2_CTL] = SITAR_A_CDC_IIR1_GAIN_B2_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B3_CTL] = SITAR_A_CDC_IIR1_GAIN_B3_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B4_CTL] = SITAR_A_CDC_IIR1_GAIN_B4_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B5_CTL] = SITAR_A_CDC_IIR1_GAIN_B5_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B6_CTL] = SITAR_A_CDC_IIR1_GAIN_B6_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B7_CTL] = SITAR_A_CDC_IIR1_GAIN_B7_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_B8_CTL] = SITAR_A_CDC_IIR1_GAIN_B8_CTL__POR,
+ [SITAR_A_CDC_IIR1_CTL] = SITAR_A_CDC_IIR1_CTL__POR,
+ [SITAR_A_CDC_IIR1_GAIN_TIMER_CTL] =
+ SITAR_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+ [SITAR_A_CDC_IIR1_COEF_B1_CTL] = SITAR_A_CDC_IIR1_COEF_B1_CTL__POR,
+ [SITAR_A_CDC_IIR1_COEF_B2_CTL] = SITAR_A_CDC_IIR1_COEF_B2_CTL__POR,
+ [SITAR_A_CDC_IIR1_COEF_B3_CTL] = SITAR_A_CDC_IIR1_COEF_B3_CTL__POR,
+ [SITAR_A_CDC_IIR1_COEF_B4_CTL] = SITAR_A_CDC_IIR1_COEF_B4_CTL__POR,
+ [SITAR_A_CDC_IIR1_COEF_B5_CTL] = SITAR_A_CDC_IIR1_COEF_B5_CTL__POR,
+ [SITAR_A_CDC_TOP_GAIN_UPDATE] = SITAR_A_CDC_TOP_GAIN_UPDATE__POR,
+ [SITAR_A_CDC_TOP_RDAC_DOUT_CTL] = SITAR_A_CDC_TOP_RDAC_DOUT_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B1_CTL] = SITAR_A_CDC_DEBUG_B1_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B2_CTL] = SITAR_A_CDC_DEBUG_B2_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B3_CTL] = SITAR_A_CDC_DEBUG_B3_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B4_CTL] = SITAR_A_CDC_DEBUG_B4_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B5_CTL] = SITAR_A_CDC_DEBUG_B5_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B6_CTL] = SITAR_A_CDC_DEBUG_B6_CTL__POR,
+ [SITAR_A_CDC_DEBUG_B7_CTL] = SITAR_A_CDC_DEBUG_B7_CTL__POR,
+ [SITAR_A_CDC_COMP1_B1_CTL] = SITAR_A_CDC_COMP1_B1_CTL__POR,
+ [SITAR_A_CDC_COMP1_B2_CTL] = SITAR_A_CDC_COMP1_B2_CTL__POR,
+ [SITAR_A_CDC_COMP1_B3_CTL] = SITAR_A_CDC_COMP1_B3_CTL__POR,
+ [SITAR_A_CDC_COMP1_B4_CTL] = SITAR_A_CDC_COMP1_B4_CTL__POR,
+ [SITAR_A_CDC_COMP1_B5_CTL] = SITAR_A_CDC_COMP1_B5_CTL__POR,
+ [SITAR_A_CDC_COMP1_B6_CTL] = SITAR_A_CDC_COMP1_B6_CTL__POR,
+ [SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS] =
+ SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
+ [SITAR_A_CDC_COMP1_FS_CFG] = SITAR_A_CDC_COMP1_FS_CFG__POR,
+ [SITAR_A_CDC_CONN_RX1_B1_CTL] = SITAR_A_CDC_CONN_RX1_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_RX1_B2_CTL] = SITAR_A_CDC_CONN_RX1_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_RX1_B3_CTL] = SITAR_A_CDC_CONN_RX1_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_RX2_B1_CTL] = SITAR_A_CDC_CONN_RX2_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_RX2_B2_CTL] = SITAR_A_CDC_CONN_RX2_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_RX2_B3_CTL] = SITAR_A_CDC_CONN_RX2_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_RX3_B1_CTL] = SITAR_A_CDC_CONN_RX3_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_RX3_B2_CTL] = SITAR_A_CDC_CONN_RX3_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_RX3_B3_CTL] = SITAR_A_CDC_CONN_RX3_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_ANC_B1_CTL] = SITAR_A_CDC_CONN_ANC_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_ANC_B2_CTL] = SITAR_A_CDC_CONN_ANC_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_B1_CTL] = SITAR_A_CDC_CONN_TX_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_B2_CTL] = SITAR_A_CDC_CONN_TX_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ1_B1_CTL] = SITAR_A_CDC_CONN_EQ1_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ1_B2_CTL] = SITAR_A_CDC_CONN_EQ1_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ1_B3_CTL] = SITAR_A_CDC_CONN_EQ1_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ1_B4_CTL] = SITAR_A_CDC_CONN_EQ1_B4_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ2_B1_CTL] = SITAR_A_CDC_CONN_EQ2_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ2_B2_CTL] = SITAR_A_CDC_CONN_EQ2_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ2_B3_CTL] = SITAR_A_CDC_CONN_EQ2_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_EQ2_B4_CTL] = SITAR_A_CDC_CONN_EQ2_B4_CTL__POR,
+ [SITAR_A_CDC_CONN_SRC1_B1_CTL] = SITAR_A_CDC_CONN_SRC1_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_SRC1_B2_CTL] = SITAR_A_CDC_CONN_SRC1_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_SRC2_B1_CTL] = SITAR_A_CDC_CONN_SRC2_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_SRC2_B2_CTL] = SITAR_A_CDC_CONN_SRC2_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_SB_B1_CTL] = SITAR_A_CDC_CONN_TX_SB_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_SB_B2_CTL] = SITAR_A_CDC_CONN_TX_SB_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_SB_B3_CTL] = SITAR_A_CDC_CONN_TX_SB_B3_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_SB_B4_CTL] = SITAR_A_CDC_CONN_TX_SB_B4_CTL__POR,
+ [SITAR_A_CDC_CONN_TX_SB_B5_CTL] = SITAR_A_CDC_CONN_TX_SB_B5_CTL__POR,
+ [SITAR_A_CDC_CONN_RX_SB_B1_CTL] = SITAR_A_CDC_CONN_RX_SB_B1_CTL__POR,
+ [SITAR_A_CDC_CONN_RX_SB_B2_CTL] = SITAR_A_CDC_CONN_RX_SB_B2_CTL__POR,
+ [SITAR_A_CDC_CONN_CLSG_CTL] = SITAR_A_CDC_CONN_CLSG_CTL__POR,
+ [SITAR_A_CDC_CONN_SPARE] = SITAR_A_CDC_CONN_SPARE__POR,
+ [SITAR_A_CDC_MBHC_EN_CTL] = SITAR_A_CDC_MBHC_EN_CTL__POR,
+ [SITAR_A_CDC_MBHC_FIR_B1_CFG] = SITAR_A_CDC_MBHC_FIR_B1_CFG__POR,
+ [SITAR_A_CDC_MBHC_FIR_B2_CFG] = SITAR_A_CDC_MBHC_FIR_B2_CFG__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B1_CTL] = SITAR_A_CDC_MBHC_TIMER_B1_CTL__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B2_CTL] = SITAR_A_CDC_MBHC_TIMER_B2_CTL__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B3_CTL] = SITAR_A_CDC_MBHC_TIMER_B3_CTL__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B4_CTL] = SITAR_A_CDC_MBHC_TIMER_B4_CTL__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B5_CTL] = SITAR_A_CDC_MBHC_TIMER_B5_CTL__POR,
+ [SITAR_A_CDC_MBHC_TIMER_B6_CTL] = SITAR_A_CDC_MBHC_TIMER_B6_CTL__POR,
+ [SITAR_A_CDC_MBHC_B1_STATUS] = SITAR_A_CDC_MBHC_B1_STATUS__POR,
+ [SITAR_A_CDC_MBHC_B2_STATUS] = SITAR_A_CDC_MBHC_B2_STATUS__POR,
+ [SITAR_A_CDC_MBHC_B3_STATUS] = SITAR_A_CDC_MBHC_B3_STATUS__POR,
+ [SITAR_A_CDC_MBHC_B4_STATUS] = SITAR_A_CDC_MBHC_B4_STATUS__POR,
+ [SITAR_A_CDC_MBHC_B5_STATUS] = SITAR_A_CDC_MBHC_B5_STATUS__POR,
+ [SITAR_A_CDC_MBHC_B1_CTL] = SITAR_A_CDC_MBHC_B1_CTL__POR,
+ [SITAR_A_CDC_MBHC_B2_CTL] = SITAR_A_CDC_MBHC_B2_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B1_CTL] = SITAR_A_CDC_MBHC_VOLT_B1_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B2_CTL] = SITAR_A_CDC_MBHC_VOLT_B2_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B3_CTL] = SITAR_A_CDC_MBHC_VOLT_B3_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B4_CTL] = SITAR_A_CDC_MBHC_VOLT_B4_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B5_CTL] = SITAR_A_CDC_MBHC_VOLT_B5_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B6_CTL] = SITAR_A_CDC_MBHC_VOLT_B6_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B7_CTL] = SITAR_A_CDC_MBHC_VOLT_B7_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B8_CTL] = SITAR_A_CDC_MBHC_VOLT_B8_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B9_CTL] = SITAR_A_CDC_MBHC_VOLT_B9_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B10_CTL] = SITAR_A_CDC_MBHC_VOLT_B10_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B11_CTL] = SITAR_A_CDC_MBHC_VOLT_B11_CTL__POR,
+ [SITAR_A_CDC_MBHC_VOLT_B12_CTL] = SITAR_A_CDC_MBHC_VOLT_B12_CTL__POR,
+ [SITAR_A_CDC_MBHC_CLK_CTL] = SITAR_A_CDC_MBHC_CLK_CTL__POR,
+ [SITAR_A_CDC_MBHC_INT_CTL] = SITAR_A_CDC_MBHC_INT_CTL__POR,
+ [SITAR_A_CDC_MBHC_DEBUG_CTL] = SITAR_A_CDC_MBHC_DEBUG_CTL__POR,
+ [SITAR_A_CDC_MBHC_SPARE] = SITAR_A_CDC_MBHC_SPARE__POR,
+};
+
+const u8 sitar_reg_readable[SITAR_CACHE_SIZE] = {
+ [WCD9XXX_A_CHIP_CTL] = 1,
+ [WCD9XXX_A_CHIP_STATUS] = 1,
+ [WCD9XXX_A_CHIP_ID_BYTE_0] = 1,
+ [WCD9XXX_A_CHIP_ID_BYTE_1] = 1,
+ [WCD9XXX_A_CHIP_ID_BYTE_2] = 1,
+ [WCD9XXX_A_CHIP_ID_BYTE_3] = 1,
+ [WCD9XXX_A_CHIP_VERSION] = 1,
+ [WCD9XXX_A_SB_VERSION] = 1,
+ [WCD9XXX_A_SLAVE_ID_1] = 1,
+ [WCD9XXX_A_SLAVE_ID_2] = 1,
+ [WCD9XXX_A_SLAVE_ID_3] = 1,
+ [SITAR_A_PIN_CTL_OE0] = 1,
+ [SITAR_A_PIN_CTL_OE1] = 1,
+ [SITAR_A_PIN_CTL_DATA0] = 1,
+ [SITAR_A_PIN_CTL_DATA1] = 1,
+ [SITAR_A_HDRIVE_GENERIC] = 1,
+ [SITAR_A_HDRIVE_OVERRIDE] = 1,
+ [SITAR_A_ANA_CSR_WAIT_STATE] = 1,
+ [SITAR_A_PROCESS_MONITOR_CTL0] = 1,
+ [SITAR_A_PROCESS_MONITOR_CTL1] = 1,
+ [SITAR_A_PROCESS_MONITOR_CTL2] = 1,
+ [SITAR_A_PROCESS_MONITOR_CTL3] = 1,
+ [SITAR_A_QFUSE_CTL] = 1,
+ [SITAR_A_QFUSE_STATUS] = 1,
+ [SITAR_A_QFUSE_DATA_OUT0] = 1,
+ [SITAR_A_QFUSE_DATA_OUT1] = 1,
+ [SITAR_A_QFUSE_DATA_OUT2] = 1,
+ [SITAR_A_QFUSE_DATA_OUT3] = 1,
+ [SITAR_A_CDC_CTL] = 1,
+ [SITAR_A_LEAKAGE_CTL] = 1,
+ [SITAR_A_INTR_MODE] = 1,
+ [SITAR_A_INTR_MASK0] = 1,
+ [SITAR_A_INTR_MASK1] = 1,
+ [SITAR_A_INTR_MASK2] = 1,
+ [SITAR_A_INTR_STATUS0] = 1,
+ [SITAR_A_INTR_STATUS1] = 1,
+ [SITAR_A_INTR_STATUS2] = 1,
+ [SITAR_A_INTR_LEVEL0] = 1,
+ [SITAR_A_INTR_LEVEL1] = 1,
+ [SITAR_A_INTR_LEVEL2] = 1,
+ [SITAR_A_INTR_TEST0] = 1,
+ [SITAR_A_INTR_TEST1] = 1,
+ [SITAR_A_INTR_TEST2] = 1,
+ [SITAR_A_INTR_SET0] = 1,
+ [SITAR_A_INTR_SET1] = 1,
+ [SITAR_A_INTR_SET2] = 1,
+ [SITAR_A_CDC_TX_I2S_SCK_MODE] = 1,
+ [SITAR_A_CDC_TX_I2S_WS_MODE] = 1,
+ [SITAR_A_CDC_DMIC_DATA0_MODE] = 1,
+ [SITAR_A_CDC_DMIC_CLK0_MODE] = 1,
+ [SITAR_A_CDC_DMIC_DATA1_MODE] = 1,
+ [SITAR_A_CDC_DMIC_CLK1_MODE] = 1,
+ [SITAR_A_CDC_TX_I2S_SD0_MODE] = 1,
+ [SITAR_A_CDC_INTR_MODE] = 1,
+ [SITAR_A_CDC_RX_I2S_SD0_MODE] = 1,
+ [SITAR_A_CDC_RX_I2S_SD1_MODE] = 1,
+ [SITAR_A_BIAS_REF_CTL] = 1,
+ [SITAR_A_BIAS_CENTRAL_BG_CTL] = 1,
+ [SITAR_A_BIAS_PRECHRG_CTL] = 1,
+ [SITAR_A_BIAS_CURR_CTL_1] = 1,
+ [SITAR_A_BIAS_CURR_CTL_2] = 1,
+ [SITAR_A_BIAS_OSC_BG_CTL] = 1,
+ [SITAR_A_CLK_BUFF_EN1] = 1,
+ [SITAR_A_CLK_BUFF_EN2] = 1,
+ [SITAR_A_LDO_H_MODE_1] = 1,
+ [SITAR_A_LDO_H_MODE_2] = 1,
+ [SITAR_A_LDO_H_LOOP_CTL] = 1,
+ [SITAR_A_LDO_H_COMP_1] = 1,
+ [SITAR_A_LDO_H_COMP_2] = 1,
+ [SITAR_A_LDO_H_BIAS_1] = 1,
+ [SITAR_A_LDO_H_BIAS_2] = 1,
+ [SITAR_A_LDO_H_BIAS_3] = 1,
+ [SITAR_A_MICB_CFILT_1_CTL] = 1,
+ [SITAR_A_MICB_CFILT_1_VAL] = 1,
+ [SITAR_A_MICB_CFILT_1_PRECHRG] = 1,
+ [SITAR_A_MICB_1_CTL] = 1,
+ [SITAR_A_MICB_1_INT_RBIAS] = 1,
+ [SITAR_A_MICB_1_MBHC] = 1,
+ [SITAR_A_MICB_CFILT_2_CTL] = 1,
+ [SITAR_A_MICB_CFILT_2_VAL] = 1,
+ [SITAR_A_MICB_CFILT_2_PRECHRG] = 1,
+ [SITAR_A_MICB_2_CTL] = 1,
+ [SITAR_A_MICB_2_INT_RBIAS] = 1,
+ [SITAR_A_MICB_2_MBHC] = 1,
+ [SITAR_A_TX_COM_BIAS] = 1,
+ [SITAR_A_MBHC_SCALING_MUX_1] = 1,
+ [SITAR_A_MBHC_SCALING_MUX_2] = 1,
+ [SITAR_A_TX_SUP_SWITCH_CTRL_1] = 1,
+ [SITAR_A_TX_SUP_SWITCH_CTRL_2] = 1,
+ [SITAR_A_TX_1_2_EN] = 1,
+ [SITAR_A_TX_1_2_TEST_EN] = 1,
+ [SITAR_A_TX_1_2_ADC_CH1] = 1,
+ [SITAR_A_TX_1_2_ADC_CH2] = 1,
+ [SITAR_A_TX_1_2_ATEST_REFCTRL] = 1,
+ [SITAR_A_TX_1_2_TEST_CTL] = 1,
+ [SITAR_A_TX_1_2_TEST_BLOCK_EN] = 1,
+ [SITAR_A_TX_1_2_TXFE_CLKDIV] = 1,
+ [SITAR_A_TX_1_2_SAR_ERR_CH1] = 1,
+ [SITAR_A_TX_1_2_SAR_ERR_CH2] = 1,
+ [SITAR_A_TX_3_EN] = 1,
+ [SITAR_A_TX_3_TEST_EN] = 1,
+ [SITAR_A_TX_3_ADC] = 1,
+ [SITAR_A_TX_3_MBHC_ATEST_REFCTRL] = 1,
+ [SITAR_A_TX_3_TEST_CTL] = 1,
+ [SITAR_A_TX_3_TEST_BLOCK_EN] = 1,
+ [SITAR_A_TX_3_TXFE_CKDIV] = 1,
+ [SITAR_A_TX_3_SAR_ERR] = 1,
+ [SITAR_A_TX_4_MBHC_EN] = 1,
+ [SITAR_A_TX_4_MBHC_ADC] = 1,
+ [SITAR_A_TX_4_MBHC_TEST_CTL] = 1,
+ [SITAR_A_TX_4_MBHC_SAR_ERR] = 1,
+ [SITAR_A_TX_4_TXFE_CLKDIV] = 1,
+ [SITAR_A_AUX_COM_CTL] = 1,
+ [SITAR_A_AUX_COM_ATEST] = 1,
+ [SITAR_A_AUX_L_EN] = 1,
+ [SITAR_A_AUX_L_GAIN] = 1,
+ [SITAR_A_AUX_L_PA_CONN] = 1,
+ [SITAR_A_AUX_L_PA_CONN_INV] = 1,
+ [SITAR_A_AUX_R_EN] = 1,
+ [SITAR_A_AUX_R_GAIN] = 1,
+ [SITAR_A_AUX_R_PA_CONN] = 1,
+ [SITAR_A_AUX_R_PA_CONN_INV] = 1,
+ [SITAR_A_CP_EN] = 1,
+ [SITAR_A_CP_CLK] = 1,
+ [SITAR_A_CP_STATIC] = 1,
+ [SITAR_A_CP_DCC1] = 1,
+ [SITAR_A_CP_DCC3] = 1,
+ [SITAR_A_CP_ATEST] = 1,
+ [SITAR_A_CP_DTEST] = 1,
+ [SITAR_A_RX_COM_TIMER_DIV] = 1,
+ [SITAR_A_RX_COM_OCP_CTL] = 1,
+ [SITAR_A_RX_COM_OCP_COUNT] = 1,
+ [SITAR_A_RX_COM_DAC_CTL] = 1,
+ [SITAR_A_RX_COM_BIAS] = 1,
+ [SITAR_A_RX_HPH_BIAS_PA] = 1,
+ [SITAR_A_RX_HPH_BIAS_LDO] = 1,
+ [SITAR_A_RX_HPH_BIAS_CNP] = 1,
+ [SITAR_A_RX_HPH_BIAS_WG] = 1,
+ [SITAR_A_RX_HPH_OCP_CTL] = 1,
+ [SITAR_A_RX_HPH_CNP_EN] = 1,
+ [SITAR_A_RX_HPH_CNP_WG_CTL] = 1,
+ [SITAR_A_RX_HPH_CNP_WG_TIME] = 1,
+ [SITAR_A_RX_HPH_L_GAIN] = 1,
+ [SITAR_A_RX_HPH_L_TEST] = 1,
+ [SITAR_A_RX_HPH_L_PA_CTL] = 1,
+ [SITAR_A_RX_HPH_L_DAC_CTL] = 1,
+ [SITAR_A_RX_HPH_L_ATEST] = 1,
+ [SITAR_A_RX_HPH_L_STATUS] = 1,
+ [SITAR_A_RX_HPH_R_GAIN] = 1,
+ [SITAR_A_RX_HPH_R_TEST] = 1,
+ [SITAR_A_RX_HPH_R_PA_CTL] = 1,
+ [SITAR_A_RX_HPH_R_DAC_CTL] = 1,
+ [SITAR_A_RX_HPH_R_ATEST] = 1,
+ [SITAR_A_RX_HPH_R_STATUS] = 1,
+ [SITAR_A_RX_EAR_BIAS_PA] = 1,
+ [SITAR_A_RX_EAR_BIAS_CMBUFF] = 1,
+ [SITAR_A_RX_EAR_EN] = 1,
+ [SITAR_A_RX_EAR_GAIN] = 1,
+ [SITAR_A_RX_EAR_CMBUFF] = 1,
+ [SITAR_A_RX_EAR_ICTL] = 1,
+ [SITAR_A_RX_EAR_CCOMP] = 1,
+ [SITAR_A_RX_EAR_VCM] = 1,
+ [SITAR_A_RX_EAR_CNP] = 1,
+ [SITAR_A_RX_EAR_ATEST] = 1,
+ [SITAR_A_RX_EAR_STATUS] = 1,
+ [SITAR_A_RX_LINE_BIAS_PA] = 1,
+ [SITAR_A_RX_LINE_BIAS_LDO] = 1,
+ [SITAR_A_RX_LINE_BIAS_CNP1] = 1,
+ [SITAR_A_RX_LINE_COM] = 1,
+ [SITAR_A_RX_LINE_CNP_EN] = 1,
+ [SITAR_A_RX_LINE_CNP_WG_CTL] = 1,
+ [SITAR_A_RX_LINE_CNP_WG_TIME] = 1,
+ [SITAR_A_RX_LINE_1_GAIN] = 1,
+ [SITAR_A_RX_LINE_1_TEST] = 1,
+ [SITAR_A_RX_LINE_1_DAC_CTL] = 1,
+ [SITAR_A_RX_LINE_1_STATUS] = 1,
+ [SITAR_A_RX_LINE_2_GAIN] = 1,
+ [SITAR_A_RX_LINE_2_TEST] = 1,
+ [SITAR_A_RX_LINE_2_DAC_CTL] = 1,
+ [SITAR_A_RX_LINE_2_STATUS] = 1,
+ [SITAR_A_RX_LINE_BIAS_CNP2] = 1,
+ [SITAR_A_RX_LINE_OCP_CTL] = 1,
+ [SITAR_A_RX_LINE_1_PA_CTL] = 1,
+ [SITAR_A_RX_LINE_2_PA_CTL] = 1,
+ [SITAR_A_RX_LINE_CNP_DBG] = 1,
+ [SITAR_A_MBHC_HPH] = 1,
+ [SITAR_A_RC_OSC_FREQ] = 1,
+ [SITAR_A_RC_OSC_TEST] = 1,
+ [SITAR_A_RC_OSC_STATUS] = 1,
+ [SITAR_A_RC_OSC_TUNER] = 1,
+ [SITAR_A_CDC_ANC1_CTL] = 1,
+ [SITAR_A_CDC_ANC1_SHIFT] = 1,
+ [SITAR_A_CDC_ANC1_IIR_B1_CTL] = 1,
+ [SITAR_A_CDC_ANC1_IIR_B2_CTL] = 1,
+ [SITAR_A_CDC_ANC1_IIR_B3_CTL] = 1,
+ [SITAR_A_CDC_ANC1_IIR_B4_CTL] = 1,
+ [SITAR_A_CDC_ANC1_LPF_B1_CTL] = 1,
+ [SITAR_A_CDC_ANC1_LPF_B2_CTL] = 1,
+ [SITAR_A_CDC_ANC1_LPF_B3_CTL] = 1,
+ [SITAR_A_CDC_ANC1_SPARE] = 1,
+ [SITAR_A_CDC_ANC1_SMLPF_CTL] = 1,
+ [SITAR_A_CDC_ANC1_DCFLT_CTL] = 1,
+ [SITAR_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+ [SITAR_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+ [SITAR_A_CDC_TX1_VOL_CTL_CFG] = 1,
+ [SITAR_A_CDC_TX1_MUX_CTL] = 1,
+ [SITAR_A_CDC_TX1_CLK_FS_CTL] = 1,
+ [SITAR_A_CDC_TX1_DMIC_CTL] = 1,
+ [SITAR_A_CDC_SRC1_PDA_CFG] = 1,
+ [SITAR_A_CDC_SRC1_FS_CTL] = 1,
+ [SITAR_A_CDC_RX1_B1_CTL] = 1,
+ [SITAR_A_CDC_RX1_B2_CTL] = 1,
+ [SITAR_A_CDC_RX1_B3_CTL] = 1,
+ [SITAR_A_CDC_RX1_B4_CTL] = 1,
+ [SITAR_A_CDC_RX1_B5_CTL] = 1,
+ [SITAR_A_CDC_RX1_B6_CTL] = 1,
+ [SITAR_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+ [SITAR_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+ [SITAR_A_CDC_CLK_ANC_RESET_CTL] = 1,
+ [SITAR_A_CDC_CLK_RX_RESET_CTL] = 1,
+ [SITAR_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+ [SITAR_A_CDC_CLK_TX_RESET_B2_CTL] = 1,
+ [SITAR_A_CDC_CLK_DMIC_CTL] = 1,
+ [SITAR_A_CDC_CLK_RX_I2S_CTL] = 1,
+ [SITAR_A_CDC_CLK_TX_I2S_CTL] = 1,
+ [SITAR_A_CDC_CLK_OTHR_RESET_CTL] = 1,
+ [SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+ [SITAR_A_CDC_CLK_OTHR_CTL] = 1,
+ [SITAR_A_CDC_CLK_RDAC_CLK_EN_CTL] = 1,
+ [SITAR_A_CDC_CLK_ANC_CLK_EN_CTL] = 1,
+ [SITAR_A_CDC_CLK_RX_B1_CTL] = 1,
+ [SITAR_A_CDC_CLK_RX_B2_CTL] = 1,
+ [SITAR_A_CDC_CLK_MCLK_CTL] = 1,
+ [SITAR_A_CDC_CLK_PDM_CTL] = 1,
+ [SITAR_A_CDC_CLK_SD_CTL] = 1,
+ [SITAR_A_CDC_CLK_LP_CTL] = 1,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B1_CTL] = 1,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B2_CTL] = 1,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL] = 1,
+ [SITAR_A_CDC_CLSG_FREQ_THRESH_B4_CTL] = 1,
+ [SITAR_A_CDC_CLSG_GAIN_THRESH_CTL] = 1,
+ [SITAR_A_CDC_CLSG_TIMER_B1_CFG] = 1,
+ [SITAR_A_CDC_CLSG_TIMER_B2_CFG] = 1,
+ [SITAR_A_CDC_CLSG_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+ [SITAR_A_CDC_IIR1_CTL] = 1,
+ [SITAR_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+ [SITAR_A_CDC_IIR1_COEF_B1_CTL] = 1,
+ [SITAR_A_CDC_IIR1_COEF_B2_CTL] = 1,
+ [SITAR_A_CDC_IIR1_COEF_B3_CTL] = 1,
+ [SITAR_A_CDC_IIR1_COEF_B4_CTL] = 1,
+ [SITAR_A_CDC_IIR1_COEF_B5_CTL] = 1,
+ [SITAR_A_CDC_TOP_GAIN_UPDATE] = 1,
+ [SITAR_A_CDC_TOP_RDAC_DOUT_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B1_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B2_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B3_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B4_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B5_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B6_CTL] = 1,
+ [SITAR_A_CDC_DEBUG_B7_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B1_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B2_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B3_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B4_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B5_CTL] = 1,
+ [SITAR_A_CDC_COMP1_B6_CTL] = 1,
+ [SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS] = 1,
+ [SITAR_A_CDC_COMP1_FS_CFG] = 1,
+ [SITAR_A_CDC_CONN_RX1_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX1_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX1_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX2_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX2_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX2_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX3_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX3_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX3_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_ANC_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_ANC_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ1_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ1_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ1_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ1_B4_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ2_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ2_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ2_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_EQ2_B4_CTL] = 1,
+ [SITAR_A_CDC_CONN_SRC1_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_SRC1_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_SRC2_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_SRC2_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_SB_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_SB_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_SB_B3_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_SB_B4_CTL] = 1,
+ [SITAR_A_CDC_CONN_TX_SB_B5_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX_SB_B1_CTL] = 1,
+ [SITAR_A_CDC_CONN_RX_SB_B2_CTL] = 1,
+ [SITAR_A_CDC_CONN_CLSG_CTL] = 1,
+ [SITAR_A_CDC_CONN_SPARE] = 1,
+ [SITAR_A_CDC_MBHC_EN_CTL] = 1,
+ [SITAR_A_CDC_MBHC_FIR_B1_CFG] = 1,
+ [SITAR_A_CDC_MBHC_FIR_B2_CFG] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+ [SITAR_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+ [SITAR_A_CDC_MBHC_B1_STATUS] = 1,
+ [SITAR_A_CDC_MBHC_B2_STATUS] = 1,
+ [SITAR_A_CDC_MBHC_B3_STATUS] = 1,
+ [SITAR_A_CDC_MBHC_B4_STATUS] = 1,
+ [SITAR_A_CDC_MBHC_B5_STATUS] = 1,
+ [SITAR_A_CDC_MBHC_B1_CTL] = 1,
+ [SITAR_A_CDC_MBHC_B2_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+ [SITAR_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+ [SITAR_A_CDC_MBHC_CLK_CTL] = 1,
+ [SITAR_A_CDC_MBHC_INT_CTL] = 1,
+ [SITAR_A_CDC_MBHC_DEBUG_CTL] = 1,
+ [SITAR_A_CDC_MBHC_SPARE] = 1,
+};
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
new file mode 100644
index 0000000..1d93d7a
--- /dev/null
+++ b/sound/soc/codecs/wcd9304.c
@@ -0,0 +1,3593 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9304_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/jack.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include "wcd9304.h"
+
+#define WCD9304_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
+ SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_48000)
+
+#define NUM_DECIMATORS 4
+#define NUM_INTERPOLATORS 3
+#define BITS_PER_REG 8
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define NUM_CODEC_DAIS 2
+
+struct sitar_codec_dai_data {
+ u32 rate;
+ u32 *ch_num;
+ u32 ch_act;
+ u32 ch_tot;
+};
+#define SITAR_CFILT_FAST_MODE 0x00
+#define SITAR_CFILT_SLOW_MODE 0x40
+
+
+#define SITAR_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
+
+#define SITAR_I2S_MASTER_MODE_MASK 0x08
+
+#define SITAR_OCP_ATTEMPT 1
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver sitar_dai[];
+static int sitar_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+
+enum sitar_bandgap_type {
+ SITAR_BANDGAP_OFF = 0,
+ SITAR_BANDGAP_AUDIO_MODE,
+ SITAR_BANDGAP_MBHC_MODE,
+};
+
+struct mbhc_micbias_regs {
+ u16 cfilt_val;
+ u16 cfilt_ctl;
+ u16 mbhc_reg;
+ u16 int_rbias;
+ u16 ctl_reg;
+ u8 cfilt_sel;
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR1 = 0,
+ IIR2,
+ IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+/* Flags to track of PA and DAC state.
+ * PA and DAC should be tracked separately as AUXPGA loopback requires
+ * only PA to be turned on without DAC being on. */
+enum sitar_priv_ack_flags {
+ SITAR_HPHL_PA_OFF_ACK = 0,
+ SITAR_HPHR_PA_OFF_ACK,
+ SITAR_HPHL_DAC_OFF_ACK,
+ SITAR_HPHR_DAC_OFF_ACK
+};
+
+struct sitar_priv {
+ struct snd_soc_codec *codec;
+ u32 adc_count;
+ u32 cfilt1_cnt;
+ u32 cfilt2_cnt;
+ u32 cfilt3_cnt;
+ u32 rx_bias_count;
+ enum sitar_bandgap_type bandgap_type;
+ bool mclk_enabled;
+ bool clock_active;
+ bool config_mode_active;
+ bool mbhc_polling_active;
+ bool fake_insert_context;
+ int buttons_pressed;
+
+ struct sitar_mbhc_calibration *calibration;
+
+ struct snd_soc_jack *headset_jack;
+ struct snd_soc_jack *button_jack;
+
+ struct wcd9xxx_pdata *pdata;
+ u32 anc_slot;
+
+ bool no_mic_headset_override;
+ /* Delayed work to report long button press */
+ struct delayed_work btn0_dwork;
+
+ struct mbhc_micbias_regs mbhc_bias_regs;
+ u8 cfilt_k_value;
+ bool mbhc_micbias_switched;
+
+ /* track PA/DAC state */
+ unsigned long hph_pa_dac_state;
+
+ /*track sitar interface type*/
+ u8 intf_type;
+
+ u32 hph_status; /* track headhpone status */
+ /* define separate work for left and right headphone OCP to avoid
+ * additional checking on which OCP event to report so no locking
+ * to ensure synchronization is required
+ */
+ struct work_struct hphlocp_work; /* reporting left hph ocp off */
+ struct work_struct hphrocp_work; /* reporting right hph ocp off */
+
+ /* pm_cnt holds number of sleep lock holders + 1
+ * so if pm_cnt is 1 system is sleep-able. */
+ atomic_t pm_cnt;
+ wait_queue_head_t pm_wq;
+
+ u8 hphlocp_cnt; /* headphone left ocp retry */
+ u8 hphrocp_cnt; /* headphone right ocp retry */
+ /* num of slim ports required */
+ struct sitar_codec_dai_data dai[NUM_CODEC_DAIS];
+};
+
+#ifdef CONFIG_DEBUG_FS
+struct sitar_priv *debug_sitar_priv;
+#endif
+
+
+static int sitar_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ear_pa_gain = snd_soc_read(codec, SITAR_A_RX_EAR_GAIN);
+
+ ear_pa_gain = ear_pa_gain >> 5;
+
+ if (ear_pa_gain == 0x00) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (ear_pa_gain == 0x04) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return -EINVAL;
+ }
+
+ pr_err("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+ return 0;
+}
+
+static int sitar_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ ear_pa_gain = 0x00;
+ break;
+ case 1:
+ ear_pa_gain = 0x80;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_write(codec, SITAR_A_RX_EAR_GAIN, ear_pa_gain);
+ return 0;
+}
+
+static int sitar_get_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_read(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+ (1 << band_idx);
+
+ pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int sitar_put_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ /* Mask first 5 bits, 6-8 are reserved */
+ snd_soc_update_bits(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx),
+ (1 << band_idx), (value << band_idx));
+
+ pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx, value);
+ return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx)
+{
+ /* Address does not automatically update if reading */
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+ 0x1F, band_idx * BAND_MAX + coeff_idx);
+
+ /* Mask bits top 2 bits since they are reserved */
+ return ((snd_soc_read(codec,
+ (SITAR_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24) |
+ (snd_soc_read(codec,
+ (SITAR_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx)) << 16) |
+ (snd_soc_read(codec,
+ (SITAR_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx)) << 8) |
+ (snd_soc_read(codec,
+ (SITAR_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx)))) &
+ 0x3FFFFFFF;
+}
+
+static int sitar_get_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+ ucontrol->value.integer.value[1] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+ ucontrol->value.integer.value[2] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+ ucontrol->value.integer.value[3] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+ ucontrol->value.integer.value[4] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+ pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[1],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[2],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[3],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[4]);
+ return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx, uint32_t value)
+{
+ /* Mask top 3 bits, 6-8 are reserved */
+ /* Update address manually each time */
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+ 0x1F, band_idx * BAND_MAX + coeff_idx);
+
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+ 0x3F, (value >> 24) & 0x3F);
+
+ /* Isolate 8bits at a time */
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx),
+ 0xFF, (value >> 16) & 0xFF);
+
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx),
+ 0xFF, (value >> 8) & 0xFF);
+
+ snd_soc_update_bits(codec,
+ (SITAR_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx),
+ 0xFF, value & 0xFF);
+}
+
+static int sitar_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+ ucontrol->value.integer.value[0]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+ ucontrol->value.integer.value[1]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+ ucontrol->value.integer.value[2]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+ ucontrol->value.integer.value[3]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+ ucontrol->value.integer.value[4]);
+
+ pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+ return 0;
+}
+
+static const char *sitar_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum sitar_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, sitar_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char *cf_text[] = {
+ "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
+
+static const struct snd_kcontrol_new sitar_snd_controls[] = {
+
+ SOC_ENUM_EXT("EAR PA Gain", sitar_ear_pa_gain_enum[0],
+ sitar_pa_gain_get, sitar_pa_gain_put),
+
+ SOC_SINGLE_TLV("LINEOUT1 Volume", SITAR_A_RX_LINE_1_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", SITAR_A_RX_LINE_2_GAIN, 0, 12, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("HPHL Volume", SITAR_A_RX_HPH_L_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", SITAR_A_RX_HPH_R_GAIN, 0, 12, 1,
+ line_gain),
+
+ SOC_SINGLE_S8_TLV("RX1 Digital Volume", SITAR_A_CDC_RX1_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("DEC1 Volume", SITAR_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", SITAR_A_CDC_IIR1_GAIN_B1_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", SITAR_A_CDC_IIR1_GAIN_B2_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", SITAR_A_CDC_IIR1_GAIN_B3_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", SITAR_A_CDC_IIR1_GAIN_B4_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_TLV("ADC1 Volume", SITAR_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", SITAR_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+
+ SOC_SINGLE("MICBIAS1 CAPLESS Switch", SITAR_A_MICB_1_CTL, 4, 1, 1),
+ SOC_SINGLE("MICBIAS2 CAPLESS Switch", SITAR_A_MICB_2_CTL, 4, 1, 1),
+
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+
+ SOC_SINGLE("TX1 HPF Switch", SITAR_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+
+ SOC_SINGLE("RX1 HPF Switch", SITAR_A_CDC_RX1_B5_CTL, 2, 1, 0),
+
+ SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+
+ SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+ sitar_get_iir_enable_audio_mixer, sitar_put_iir_enable_audio_mixer),
+
+ SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+ sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+};
+
+static const char *rx_mix1_text[] = {
+ "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+ "RX5"
+};
+
+static const char *rx_dac1_text[] = {
+ "ZERO", "RX1", "RX2"
+};
+
+static const char *rx_dac2_text[] = {
+ "ZERO", "RX1",
+};
+
+static const char *rx_dac3_text[] = {
+ "ZERO", "RX1", "RX1_INV", "RX2"
+};
+
+static const char *rx_dac4_text[] = {
+ "ZERO", "ON"
+};
+
+static const char *sb_tx1_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC1"
+};
+
+static const char *sb_tx2_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC2"
+};
+
+static const char *sb_tx3_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC3"
+};
+
+static const char *sb_tx5_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC5"
+};
+
+static const char *dec1_mux_text[] = {
+ "ZERO", "DMIC1", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC4", "ANCFB1",
+};
+
+static const char *dec2_mux_text[] = {
+ "ZERO", "DMIC2", "ADC1", "ADC2", "ADC3", "MBADC", "DMIC3", "ANCFB2",
+};
+
+static const char *dec3_mux_text[] = {
+ "ZERO", "DMIC2", "DMIC3", "DMIC4", "ADC1", "ADC2", "ADC3", "MBADC",
+};
+
+static const char *dec4_mux_text[] = {
+ "ZERO", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "ADC1", "ADC2", "ADC3",
+};
+
+static const char *iir1_inp1_text[] = {
+ "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "ZERO", "ZERO", "ZERO",
+ "ZERO", "ZERO", "ZERO", "RX1", "RX2", "RX3", "RX4", "RX5",
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX1_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX1_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX2_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX2_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX3_B1_CTL, 0, 10, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_RX3_B1_CTL, 4, 10, rx_mix1_text);
+
+static const struct soc_enum rx_dac1_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 6, 3, rx_dac1_text);
+
+static const struct soc_enum rx_dac2_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 4, 2, rx_dac2_text);
+
+static const struct soc_enum rx_dac3_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 2, 4, rx_dac3_text);
+
+static const struct soc_enum rx_dac4_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_TOP_RDAC_DOUT_CTL, 0, 2, rx_dac4_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
+
+static const struct soc_enum sb_tx3_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+
+static const struct soc_enum sb_tx2_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+
+static const struct soc_enum sb_tx1_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+
+static const struct soc_enum dec1_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 0, 8, dec1_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 2, 8, dec2_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 4, 8, dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 6, 8, dec4_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_EQ1_B1_CTL, 0, 16, iir1_inp1_text);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_dac1_mux =
+ SOC_DAPM_ENUM("RX1 DAC Mux", rx_dac1_enum);
+
+static const struct snd_kcontrol_new rx_dac2_mux =
+ SOC_DAPM_ENUM("RX2 DAC Mux", rx_dac2_enum);
+
+static const struct snd_kcontrol_new rx_dac3_mux =
+ SOC_DAPM_ENUM("RX3 DAC Mux", rx_dac3_enum);
+
+static const struct snd_kcontrol_new rx_dac4_mux =
+ SOC_DAPM_ENUM("RX4 DAC Mux", rx_dac4_enum);
+
+static const struct snd_kcontrol_new sb_tx5_mux =
+ SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx3_mux =
+ SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx2_mux =
+ SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx1_mux =
+ SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
+
+static const struct snd_kcontrol_new dec1_mux =
+ SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+ SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+ SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+ SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const struct snd_kcontrol_new dac1_switch[] = {
+ SOC_DAPM_SINGLE("Switch", SITAR_A_RX_EAR_EN, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphl_switch[] = {
+ SOC_DAPM_SINGLE("Switch", SITAR_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+static void sitar_codec_enable_adc_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s %d\n", __func__, enable);
+
+ if (enable) {
+ sitar->adc_count++;
+ snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
+
+ } else {
+ sitar->adc_count--;
+ if (!sitar->adc_count) {
+ if (!sitar->mbhc_polling_active)
+ snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS,
+ 0xE0, 0x0);
+ }
+ }
+}
+
+static int sitar_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 adc_reg;
+
+ pr_err("%s %d\n", __func__, event);
+
+ if (w->reg == SITAR_A_TX_1_2_EN)
+ adc_reg = SITAR_A_TX_1_2_TEST_CTL;
+ else {
+ pr_err("%s: Error, invalid adc register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ sitar_codec_enable_adc_block(codec, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, adc_reg, 1 << w->shift,
+ 1 << w->shift);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, adc_reg, 1 << w->shift, 0x00);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, adc_reg, 0x08, 0x08);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ sitar_codec_enable_adc_block(codec, 0);
+ break;
+ }
+ return 0;
+}
+
+static int sitar_codec_enable_lineout(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 lineout_gain_reg;
+
+ pr_err("%s %d %s\n", __func__, event, w->name);
+
+ switch (w->shift) {
+ case 0:
+ lineout_gain_reg = SITAR_A_RX_LINE_1_GAIN;
+ break;
+ case 1:
+ lineout_gain_reg = SITAR_A_RX_LINE_2_GAIN;
+ break;
+ default:
+ pr_err("%s: Error, incorrect lineout register value\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ pr_err("%s: sleeping 16 ms after %s PA turn on\n",
+ __func__, w->name);
+ usleep_range(16000, 16000);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int sitar_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
+ u8 dmic_clk_sel, dmic_clk_en;
+ unsigned int dmic;
+ int ret;
+
+ ret = kstrtouint(strpbrk(w->name, "12"), 10, &dmic);
+ if (ret < 0) {
+ pr_err("%s: Invalid DMIC line on the codec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 1:
+ case 2:
+ dmic_clk_sel = 0x02;
+ dmic_clk_en = 0x01;
+ break;
+ case 3:
+ case 4:
+ dmic_clk_sel = 0x08;
+ dmic_clk_en = 0x04;
+ break;
+
+ break;
+
+ default:
+ pr_err("%s: Invalid DMIC Selection\n", __func__);
+ return -EINVAL;
+ }
+
+ tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
+ tx_dmic_ctl_reg = SITAR_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
+
+ pr_err("%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+ dmic_clk_sel, dmic_clk_sel);
+
+ snd_soc_update_bits(codec, tx_dmic_ctl_reg, 0x1, 0x1);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+ dmic_clk_en, dmic_clk_en);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
+ dmic_clk_en, 0);
+ break;
+ }
+ return 0;
+}
+
+
+static void sitar_codec_disable_button_presses(struct snd_soc_codec *codec)
+{
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
+}
+
+static void sitar_codec_start_hs_polling(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
+ wcd9xxx_enable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+ if (!sitar->no_mic_headset_override) {
+ wcd9xxx_enable_irq(codec->control_data,
+ SITAR_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_enable_irq(codec->control_data,
+ SITAR_IRQ_MBHC_RELEASE);
+ } else {
+ sitar_codec_disable_button_presses(codec);
+ }
+}
+
+static void sitar_codec_pause_hs_polling(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+ if (!sitar->no_mic_headset_override) {
+ wcd9xxx_disable_irq(codec->control_data,
+ SITAR_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(codec->control_data,
+ SITAR_IRQ_MBHC_RELEASE);
+ }
+}
+
+static void sitar_codec_switch_cfilt_mode(struct snd_soc_codec *codec,
+ int mode)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ u8 reg_mode_val, cur_mode_val;
+ bool mbhc_was_polling = false;
+
+ if (mode)
+ reg_mode_val = SITAR_CFILT_FAST_MODE;
+ else
+ reg_mode_val = SITAR_CFILT_SLOW_MODE;
+
+ cur_mode_val = snd_soc_read(codec,
+ sitar->mbhc_bias_regs.cfilt_ctl) & 0x40;
+
+ if (cur_mode_val != reg_mode_val) {
+ if (sitar->mbhc_polling_active) {
+ sitar_codec_pause_hs_polling(codec);
+ mbhc_was_polling = true;
+ }
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
+ if (mbhc_was_polling)
+ sitar_codec_start_hs_polling(codec);
+ pr_err("%s: CFILT mode change (%x to %x)\n", __func__,
+ cur_mode_val, reg_mode_val);
+ } else {
+ pr_err("%s: CFILT Value is already %x\n",
+ __func__, cur_mode_val);
+ }
+}
+
+static void sitar_codec_update_cfilt_usage(struct snd_soc_codec *codec,
+ u8 cfilt_sel, int inc)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ u32 *cfilt_cnt_ptr = NULL;
+ u16 micb_cfilt_reg;
+
+ switch (cfilt_sel) {
+ case SITAR_CFILT1_SEL:
+ cfilt_cnt_ptr = &sitar->cfilt1_cnt;
+ micb_cfilt_reg = SITAR_A_MICB_CFILT_1_CTL;
+ break;
+ case SITAR_CFILT2_SEL:
+ cfilt_cnt_ptr = &sitar->cfilt2_cnt;
+ micb_cfilt_reg = SITAR_A_MICB_CFILT_2_CTL;
+ break;
+ default:
+ return; /* should not happen */
+ }
+
+ if (inc) {
+ if (!(*cfilt_cnt_ptr)++) {
+ /* Switch CFILT to slow mode if MBHC CFILT being used */
+ if (cfilt_sel == sitar->mbhc_bias_regs.cfilt_sel)
+ sitar_codec_switch_cfilt_mode(codec, 0);
+
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
+ }
+ } else {
+ /* check if count not zero, decrement
+ * then check if zero, go ahead disable cfilter
+ */
+ if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
+
+ /* Switch CFILT to fast mode if MBHC CFILT being used */
+ if (cfilt_sel == sitar->mbhc_bias_regs.cfilt_sel)
+ sitar_codec_switch_cfilt_mode(codec, 1);
+ }
+ }
+}
+
+static int sitar_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
+{
+ int rc = -EINVAL;
+ unsigned min_mv, max_mv;
+
+ switch (ldoh_v) {
+ case SITAR_LDOH_1P95_V:
+ min_mv = 160;
+ max_mv = 1800;
+ break;
+ case SITAR_LDOH_2P35_V:
+ min_mv = 200;
+ max_mv = 2200;
+ break;
+ case SITAR_LDOH_2P75_V:
+ min_mv = 240;
+ max_mv = 2600;
+ break;
+ case SITAR_LDOH_2P85_V:
+ min_mv = 250;
+ max_mv = 2700;
+ break;
+ default:
+ goto done;
+ }
+
+ if (cfilt_mv < min_mv || cfilt_mv > max_mv)
+ goto done;
+
+ for (rc = 4; rc <= 44; rc++) {
+ min_mv = max_mv * (rc) / 44;
+ if (min_mv >= cfilt_mv) {
+ rc -= 4;
+ break;
+ }
+ }
+done:
+ return rc;
+}
+
+static bool sitar_is_hph_pa_on(struct snd_soc_codec *codec)
+{
+ u8 hph_reg_val = 0;
+ hph_reg_val = snd_soc_read(codec, SITAR_A_RX_HPH_CNP_EN);
+
+ return (hph_reg_val & 0x30) ? true : false;
+}
+
+static bool sitar_is_hph_dac_on(struct snd_soc_codec *codec, int left)
+{
+ u8 hph_reg_val = 0;
+ if (left)
+ hph_reg_val = snd_soc_read(codec,
+ SITAR_A_RX_HPH_L_DAC_CTL);
+ else
+ hph_reg_val = snd_soc_read(codec,
+ SITAR_A_RX_HPH_R_DAC_CTL);
+
+ return (hph_reg_val & 0xC0) ? true : false;
+}
+
+static void sitar_codec_switch_micbias(struct snd_soc_codec *codec,
+ int vddio_switch)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ int cfilt_k_val;
+ bool mbhc_was_polling = false;
+
+ switch (vddio_switch) {
+ case 1:
+ if (sitar->mbhc_polling_active) {
+
+ sitar_codec_pause_hs_polling(codec);
+ /* Enable Mic Bias switch to VDDIO */
+ sitar->cfilt_k_value = snd_soc_read(codec,
+ sitar->mbhc_bias_regs.cfilt_val);
+ cfilt_k_val = sitar_find_k_value(
+ sitar->pdata->micbias.ldoh_v, 1800);
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.cfilt_val,
+ 0xFC, (cfilt_k_val << 2));
+
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x80);
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
+ sitar_codec_start_hs_polling(codec);
+
+ sitar->mbhc_micbias_switched = true;
+ pr_err("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
+ __func__);
+ }
+ break;
+
+ case 0:
+ if (sitar->mbhc_micbias_switched) {
+ if (sitar->mbhc_polling_active) {
+ sitar_codec_pause_hs_polling(codec);
+ mbhc_was_polling = true;
+ }
+ /* Disable Mic Bias switch to VDDIO */
+ if (sitar->cfilt_k_value != 0)
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.cfilt_val, 0XFC,
+ sitar->cfilt_k_value);
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.mbhc_reg, 0x10, 0x00);
+
+ if (mbhc_was_polling)
+ sitar_codec_start_hs_polling(codec);
+
+ sitar->mbhc_micbias_switched = false;
+ pr_err("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
+ __func__);
+ }
+ break;
+ }
+}
+
+static int sitar_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ u16 micb_int_reg;
+ int micb_line;
+ u8 cfilt_sel_val = 0;
+ char *internal1_text = "Internal1";
+ char *internal2_text = "Internal2";
+
+ pr_err("%s %d\n", __func__, event);
+ switch (w->reg) {
+ case SITAR_A_MICB_1_CTL:
+ micb_int_reg = SITAR_A_MICB_1_INT_RBIAS;
+ cfilt_sel_val = sitar->pdata->micbias.bias1_cfilt_sel;
+ micb_line = SITAR_MICBIAS1;
+ break;
+ case SITAR_A_MICB_2_CTL:
+ micb_int_reg = SITAR_A_MICB_2_INT_RBIAS;
+ cfilt_sel_val = sitar->pdata->micbias.bias2_cfilt_sel;
+ micb_line = SITAR_MICBIAS2;
+ break;
+ default:
+ pr_err("%s: Error, invalid micbias register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Decide whether to switch the micbias for MBHC */
+ if ((w->reg == sitar->mbhc_bias_regs.ctl_reg)
+ && sitar->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 0);
+
+ snd_soc_update_bits(codec, w->reg, 0x1E, 0x0A);
+ sitar_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0xFF, 0xA4);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (sitar->mbhc_polling_active &&
+ (sitar->calibration->bias == micb_line)) {
+ sitar_codec_pause_hs_polling(codec);
+ sitar_codec_start_hs_polling(codec);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+
+ if ((w->reg == sitar->mbhc_bias_regs.ctl_reg)
+ && sitar_is_hph_pa_on(codec))
+ sitar_codec_switch_micbias(codec, 1);
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
+ sitar_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static int sitar_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 dec_reset_reg;
+
+ pr_err("%s %d\n", __func__, event);
+
+ if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
+ dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
+ else {
+ pr_err("%s: Error, incorrect dec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
+ 1 << w->shift);
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+ break;
+ }
+ return 0;
+}
+
+static int sitar_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_err("%s %d %s\n", __func__, event, w->name);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
+ break;
+ }
+ return 0;
+}
+
+static int sitar_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(1000, 1000);
+ pr_debug("LDO_H\n");
+ break;
+ }
+ return 0;
+}
+
+static void sitar_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ if (enable) {
+ sitar->rx_bias_count++;
+ if (sitar->rx_bias_count == 1)
+ snd_soc_update_bits(codec, SITAR_A_RX_COM_BIAS,
+ 0x80, 0x80);
+ } else {
+ sitar->rx_bias_count--;
+ if (!sitar->rx_bias_count)
+ snd_soc_update_bits(codec, SITAR_A_RX_COM_BIAS,
+ 0x80, 0x00);
+ }
+}
+
+static int sitar_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_err("%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ sitar_enable_rx_bias(codec, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ sitar_enable_rx_bias(codec, 0);
+ break;
+ }
+ return 0;
+}
+static int sitar_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_err("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static void sitar_snd_soc_jack_report(struct sitar_priv *sitar,
+ struct snd_soc_jack *jack, int status,
+ int mask)
+{
+ /* XXX: wake_lock_timeout()? */
+ snd_soc_jack_report(jack, status, mask);
+}
+
+static void hphocp_off_report(struct sitar_priv *sitar,
+ u32 jack_status, int irq)
+{
+ struct snd_soc_codec *codec;
+
+ if (sitar) {
+ pr_info("%s: clear ocp status %x\n", __func__, jack_status);
+ codec = sitar->codec;
+ sitar->hph_status &= ~jack_status;
+ if (sitar->headset_jack)
+ sitar_snd_soc_jack_report(sitar, sitar->headset_jack,
+ sitar->hph_status,
+ SITAR_JACK_MASK);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ /* reset retry counter as PA is turned off signifying
+ * start of new OCP detection session
+ */
+ if (SITAR_IRQ_HPH_PA_OCPL_FAULT)
+ sitar->hphlocp_cnt = 0;
+ else
+ sitar->hphrocp_cnt = 0;
+ wcd9xxx_enable_irq(codec->control_data, irq);
+ } else {
+ pr_err("%s: Bad sitar private data\n", __func__);
+ }
+}
+
+static void hphlocp_off_report(struct work_struct *work)
+{
+ struct sitar_priv *sitar = container_of(work, struct sitar_priv,
+ hphlocp_work);
+ hphocp_off_report(sitar, SND_JACK_OC_HPHL, SITAR_IRQ_HPH_PA_OCPL_FAULT);
+}
+
+static void hphrocp_off_report(struct work_struct *work)
+{
+ struct sitar_priv *sitar = container_of(work, struct sitar_priv,
+ hphrocp_work);
+ hphocp_off_report(sitar, SND_JACK_OC_HPHR, SITAR_IRQ_HPH_PA_OCPR_FAULT);
+}
+
+static int sitar_hph_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ u8 mbhc_micb_ctl_val;
+ pr_err("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mbhc_micb_ctl_val = snd_soc_read(codec,
+ sitar->mbhc_bias_regs.ctl_reg);
+
+ if (!(mbhc_micb_ctl_val & 0x80)
+ && !sitar->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 1);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ /* schedule work is required because at the time HPH PA DAPM
+ * event callback is called by DAPM framework, CODEC dapm mutex
+ * would have been locked while snd_soc_jack_report also
+ * attempts to acquire same lock.
+ */
+ if (w->shift == 5) {
+ clear_bit(SITAR_HPHL_PA_OFF_ACK,
+ &sitar->hph_pa_dac_state);
+ clear_bit(SITAR_HPHL_DAC_OFF_ACK,
+ &sitar->hph_pa_dac_state);
+ if (sitar->hph_status & SND_JACK_OC_HPHL)
+ schedule_work(&sitar->hphlocp_work);
+ } else if (w->shift == 4) {
+ clear_bit(SITAR_HPHR_PA_OFF_ACK,
+ &sitar->hph_pa_dac_state);
+ clear_bit(SITAR_HPHR_DAC_OFF_ACK,
+ &sitar->hph_pa_dac_state);
+ if (sitar->hph_status & SND_JACK_OC_HPHR)
+ schedule_work(&sitar->hphrocp_work);
+ }
+
+ if (sitar->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 0);
+
+ pr_err("%s: sleep 10 ms after %s PA disable.\n", __func__,
+ w->name);
+ usleep_range(10000, 10000);
+
+ break;
+ }
+ return 0;
+}
+
+static void sitar_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
+ struct mbhc_micbias_regs *micbias_regs)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ struct sitar_mbhc_calibration *calibration = sitar->calibration;
+ unsigned int cfilt;
+
+ switch (calibration->bias) {
+ case SITAR_MICBIAS1:
+ cfilt = sitar->pdata->micbias.bias1_cfilt_sel;
+ micbias_regs->mbhc_reg = SITAR_A_MICB_1_MBHC;
+ micbias_regs->int_rbias = SITAR_A_MICB_1_INT_RBIAS;
+ micbias_regs->ctl_reg = SITAR_A_MICB_1_CTL;
+ break;
+ case SITAR_MICBIAS2:
+ cfilt = sitar->pdata->micbias.bias2_cfilt_sel;
+ micbias_regs->mbhc_reg = SITAR_A_MICB_2_MBHC;
+ micbias_regs->int_rbias = SITAR_A_MICB_2_INT_RBIAS;
+ micbias_regs->ctl_reg = SITAR_A_MICB_2_CTL;
+ break;
+ default:
+ /* Should never reach here */
+ pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
+ return;
+ }
+
+ micbias_regs->cfilt_sel = cfilt;
+
+ switch (cfilt) {
+ case SITAR_CFILT1_SEL:
+ micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_1_VAL;
+ micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_1_CTL;
+ break;
+ case SITAR_CFILT2_SEL:
+ micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_2_VAL;
+ micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_2_CTL;
+ break;
+ }
+}
+
+static int sitar_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_err("%s %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
+ 0x01);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x08);
+ usleep_range(200, 200);
+ snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x10, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
+ 0x10);
+ usleep_range(20, 20);
+ snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x08, 0x08);
+ snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x10, 0x10);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLSG_CTL, 0x08, 0x00);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x01,
+ 0x00);
+ snd_soc_update_bits(codec, SITAR_A_CP_STATIC, 0x08, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget sitar_dapm_i2s_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", SITAR_A_CDC_CLK_RX_I2S_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", SITAR_A_CDC_CLK_TX_I2S_CTL, 4,
+ 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget sitar_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+
+ SND_SOC_DAPM_PGA("EAR PA", SITAR_A_RX_EAR_EN, 4, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("DAC1", SITAR_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch)),
+ SND_SOC_DAPM_SUPPLY("EAR DRIVER", SITAR_A_RX_EAR_EN, 3, 0, NULL, 0),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, sitar_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, sitar_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIM RX4", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIM RX5", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+
+ /* Headphone */
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL", SITAR_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+ sitar_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("HPHL DAC", SITAR_A_RX_HPH_L_DAC_CTL, 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+ SND_SOC_DAPM_PGA_E("HPHR", SITAR_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+ sitar_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, SITAR_A_RX_HPH_R_DAC_CTL, 7, 0,
+ sitar_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", SITAR_A_RX_LINE_CNP_EN, 0, 0, NULL,
+ 0, sitar_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", SITAR_A_RX_LINE_CNP_EN, 1, 0, NULL,
+ 0, sitar_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+ 0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+ 0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MIXER_E("RX3 MIX1", SITAR_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+ 0, sitar_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX("DAC1 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac1_mux),
+ SND_SOC_DAPM_MUX("DAC2 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac2_mux),
+ SND_SOC_DAPM_MUX("DAC3 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac3_mux),
+ SND_SOC_DAPM_MUX("DAC4 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac4_mux),
+
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", SITAR_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", SITAR_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX3 CHAIN", SITAR_A_CDC_RX3_B6_CTL, 5, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+
+ SND_SOC_DAPM_SUPPLY("CP", SITAR_A_CP_EN, 0, 0,
+ sitar_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+ sitar_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("LDO_H", SITAR_A_LDO_H_MODE_1, 7, 0,
+ sitar_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+ /* TX */
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", SITAR_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+ 0),
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SITAR_A_MICB_1_CTL, 7, 0,
+ sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", SITAR_A_MICB_1_CTL, 7, 0,
+ sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SITAR_A_MICB_2_CTL, 7, 0,
+ sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", SITAR_A_MICB_2_CTL, 7, 0,
+ sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", SITAR_A_MICB_2_CTL, 7, 0,
+ sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, SITAR_A_TX_1_2_EN, 7, 0,
+ sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, SITAR_A_TX_1_2_EN, 3, 0,
+ sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
+ SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
+ SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, sitar_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, sitar_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, sitar_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR1", SITAR_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR PA"},
+ {"EAR PA", "NULL", "DAC1"},
+ {"DAC1", "Switch", "DAC1 MUX"},
+ {"DAC1", NULL, "CP"},
+ {"DAC1", NULL, "EAR DRIVER"},
+
+ {"LINEOUT1", NULL, "CP"},
+ {"LINEOUT2", NULL, "CP"},
+
+ {"LINEOUT2", NULL, "LINEOUT2 PA"},
+ {"LINEOUT2 PA", "NULL", "DAC3 MUX"},
+
+ {"LINEOUT1", NULL, "LINEOUT1 PA"},
+ {"LINEOUT1 PA", "NULL", "DAC2 MUX"},
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL"},
+ {"HEADPHONE", NULL, "HPHR"},
+
+ {"HPHL", NULL, "HPHL DAC"},
+ {"HPHL DAC", NULL, "DAC4 MUX"},
+ {"HPHR", NULL, "HPHR DAC"},
+ {"HPHL DAC", NULL, "RX3 MIX1"},
+
+ {"DAC1 MUX", "RX1", "RX1 CHAIN"},
+ {"DAC2 MUX", "RX1", "RX1 CHAIN"},
+ {"DAC3 MUX", "RX1", "RX1 CHAIN"},
+ {"DAC3 MUX", "RX1_INV", "RX1 CHAIN"},
+ {"DAC3 MUX", "RX2", "RX2 MIX1"},
+ {"DAC4 MUX", "ON", "RX2 MIX1"},
+
+ {"RX1 CHAIN", NULL, "RX1 MIX1"},
+
+ {"CP", NULL, "RX_BIAS"},
+
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+
+ /* SLIMBUS Connections */
+
+ /* Slimbus port 5 is non functional in Sitar 1.0 */
+ {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP2", "IIR1", "IIR1"},
+
+
+ /* TX */
+ {"SLIM TX1", NULL, "SLIM TX1 MUX"},
+ {"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
+
+ {"SLIM TX2", NULL, "SLIM TX2 MUX"},
+ {"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
+
+ {"SLIM TX1", NULL, "SLIM TX1 MUX"},
+ {"SLIM TX2", NULL, "SLIM TX2 MUX"},
+ {"SLIM TX3", NULL, "SLIM TX3 MUX"},
+
+ {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+
+ /* Decimator Inputs */
+ {"DEC1 MUX", "DMIC1", "DMIC1"},
+ {"DEC1 MUX", "DMIC4", "DMIC4"},
+ {"DEC1 MUX", "ADC1", "ADC1"},
+ {"DEC1 MUX", "ADC2", "ADC2"},
+
+ {"DEC2 MUX", "DMIC2", "DMIC2"},
+ {"DEC2 MUX", "DMIC3", "DMIC3"},
+ {"DEC2 MUX", "ADC1", "ADC1"},
+ {"DEC2 MUX", "ADC2", "ADC2"},
+
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC3 MUX", "ADC1", "ADC1"},
+ {"DEC3 MUX", "ADC2", "ADC2"},
+ {"DEC3 MUX", "DMIC2", "DMIC2"},
+ {"DEC3 MUX", "DMIC3", "DMIC4"},
+
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
+ {"DEC4 MUX", "ADC1", "ADC1"},
+ {"DEC4 MUX", "ADC2", "ADC2"},
+ {"DEC4 MUX", "DMIC3", "DMIC3"},
+ {"DEC4 MUX", "DMIC2", "DMIC2"},
+ {"DEC4 MUX", "DMIC1", "DMIC1"},
+
+ /* ADC Connections */
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2", NULL, "AMIC2"},
+
+ /* IIR */
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"MIC BIAS1 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS1 External", NULL, "LDO_H"},
+ {"MIC BIAS2 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS2 External", NULL, "LDO_H"},
+};
+
+static int sitar_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ return sitar_reg_readable[reg];
+}
+
+static int sitar_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ /* Registers lower than 0x100 are top level registers which can be
+ * written by the Sitar core driver.
+ */
+
+ if ((reg >= SITAR_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+ return 1;
+
+ /* IIR Coeff registers are not cacheable */
+ if ((reg >= SITAR_A_CDC_IIR1_COEF_B1_CTL) &&
+ (reg <= SITAR_A_CDC_IIR1_COEF_B5_CTL))
+ return 1;
+
+ return 0;
+}
+
+#define SITAR_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+static int sitar_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+
+ BUG_ON(reg > SITAR_MAX_REGISTER);
+
+ if (!sitar_volatile(codec, reg)) {
+ ret = snd_soc_cache_write(codec, reg, value);
+ if (ret != 0)
+ dev_err(codec->dev, "Cache write to %x failed: %d\n",
+ reg, ret);
+ }
+
+ return wcd9xxx_reg_write(codec->control_data, reg, value);
+}
+static unsigned int sitar_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned int val;
+ int ret;
+
+ BUG_ON(reg > SITAR_MAX_REGISTER);
+
+ if (!sitar_volatile(codec, reg) && sitar_readable(codec, reg) &&
+ reg < codec->driver->reg_cache_size) {
+ ret = snd_soc_cache_read(codec, reg, &val);
+ if (ret >= 0) {
+ return val;
+ } else
+ dev_err(codec->dev, "Cache read from %x failed: %d\n",
+ reg, ret);
+ }
+
+ val = wcd9xxx_reg_read(codec->control_data, reg);
+ return val;
+}
+
+static void sitar_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
+{
+
+ snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x0C, 0x61);
+ snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
+ usleep_range(1000, 1000);
+ snd_soc_write(codec, SITAR_A_BIAS_REF_CTL, 0x1C);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x04,
+ 0x04);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x01);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+}
+
+static void sitar_codec_enable_bandgap(struct snd_soc_codec *codec,
+ enum sitar_bandgap_type choice)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ /* TODO lock resources accessed by audio streams and threaded
+ * interrupt handlers
+ */
+
+ pr_err("%s, choice is %d, current is %d\n", __func__, choice,
+ sitar->bandgap_type);
+
+ if (sitar->bandgap_type == choice)
+ return;
+
+ if ((sitar->bandgap_type == SITAR_BANDGAP_OFF) &&
+ (choice == SITAR_BANDGAP_AUDIO_MODE)) {
+ sitar_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == SITAR_BANDGAP_MBHC_MODE) {
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x2,
+ 0x2);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x4,
+ 0x4);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x1);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+ } else if ((sitar->bandgap_type == SITAR_BANDGAP_MBHC_MODE) &&
+ (choice == SITAR_BANDGAP_AUDIO_MODE)) {
+ snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
+ usleep_range(100, 100);
+ sitar_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == SITAR_BANDGAP_OFF) {
+ snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
+ } else {
+ pr_err("%s: Error, Invalid bandgap settings\n", __func__);
+ }
+ sitar->bandgap_type = choice;
+}
+
+
+static int sitar_codec_enable_clock_block(struct snd_soc_codec *codec,
+ int config_mode)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s\n", __func__);
+
+ if (config_mode) {
+ snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x00);
+ snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
+ snd_soc_write(codec, SITAR_A_CLK_BUFF_EN1, 0x0D);
+ usleep_range(1000, 1000);
+ } else
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
+
+
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
+ usleep_range(50, 50);
+ sitar->clock_active = true;
+ return 0;
+}
+static void sitar_codec_disable_clock_block(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ pr_err("%s\n", __func__);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
+ ndelay(160);
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x00);
+ sitar->clock_active = false;
+}
+
+static void sitar_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
+{
+ /* TODO store register values in calibration */
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B5_CTL, 0x20);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B6_CTL, 0xFF);
+
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B10_CTL, 0xFF);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B9_CTL, 0x20);
+
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL, 0xF8);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
+
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 3);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B2_CTL, 9);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B3_CTL, 30);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B6_CTL, 120);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 0x78, 0x58);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_B2_CTL, 11);
+}
+
+static int sitar_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ pr_err("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+
+ return 0;
+}
+
+static void sitar_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ pr_err("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+}
+
+int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ pr_err("%s() mclk_enable = %u\n", __func__, mclk_enable);
+
+ if (mclk_enable) {
+ sitar->mclk_enabled = true;
+
+ if (sitar->mbhc_polling_active && (sitar->mclk_enabled)) {
+ sitar_codec_pause_hs_polling(codec);
+ sitar_codec_enable_bandgap(codec,
+ SITAR_BANDGAP_AUDIO_MODE);
+ sitar_codec_enable_clock_block(codec, 0);
+ sitar_codec_calibrate_hs_polling(codec);
+ sitar_codec_start_hs_polling(codec);
+ } else {
+ sitar_codec_enable_bandgap(codec,
+ SITAR_BANDGAP_AUDIO_MODE);
+ sitar_codec_enable_clock_block(codec, 0);
+ }
+ } else {
+
+ if (!sitar->mclk_enabled) {
+ pr_err("Error, MCLK already diabled\n");
+ return -EINVAL;
+ }
+ sitar->mclk_enabled = false;
+
+ if (sitar->mbhc_polling_active) {
+ if (!sitar->mclk_enabled) {
+ sitar_codec_pause_hs_polling(codec);
+ sitar_codec_enable_bandgap(codec,
+ SITAR_BANDGAP_MBHC_MODE);
+ sitar_enable_rx_bias(codec, 1);
+ sitar_codec_enable_clock_block(codec, 1);
+ sitar_codec_calibrate_hs_polling(codec);
+ sitar_codec_start_hs_polling(codec);
+ }
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1,
+ 0x05, 0x01);
+ } else {
+ sitar_codec_disable_clock_block(codec);
+ sitar_codec_enable_bandgap(codec,
+ SITAR_BANDGAP_OFF);
+ }
+ }
+ return 0;
+}
+
+static int sitar_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ pr_err("%s\n", __func__);
+ return 0;
+}
+
+static int sitar_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ u8 val = 0;
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+
+ pr_err("%s\n", __func__);
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* CPU is master */
+ if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(dai->codec,
+ SITAR_A_CDC_CLK_TX_I2S_CTL,
+ SITAR_I2S_MASTER_MODE_MASK, 0);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(dai->codec,
+ SITAR_A_CDC_CLK_RX_I2S_CTL,
+ SITAR_I2S_MASTER_MODE_MASK, 0);
+ }
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* CPU is slave */
+ if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ val = SITAR_I2S_MASTER_MODE_MASK;
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(dai->codec,
+ SITAR_A_CDC_CLK_TX_I2S_CTL, val, val);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(dai->codec,
+ SITAR_A_CDC_CLK_RX_I2S_CTL, val, val);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+static int sitar_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+ u32 i = 0;
+ if (!tx_slot && !rx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: DAI-ID %x %d %d\n", __func__, dai->id, tx_num, rx_num);
+
+ if (dai->id == AIF1_PB) {
+ for (i = 0; i < rx_num; i++) {
+ sitar->dai[dai->id - 1].ch_num[i] = rx_slot[i];
+ sitar->dai[dai->id - 1].ch_act = 0;
+ sitar->dai[dai->id - 1].ch_tot = rx_num;
+ }
+ } else if (dai->id == AIF1_CAP) {
+ for (i = 0; i < tx_num; i++) {
+ sitar->dai[dai->id - 1].ch_num[i] = tx_slot[i];
+ sitar->dai[dai->id - 1].ch_act = 0;
+ sitar->dai[dai->id - 1].ch_tot = tx_num;
+ }
+ }
+ return 0;
+}
+
+static int sitar_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ struct wcd9xxx *sitar = dev_get_drvdata(dai->codec->control_data);
+
+ u32 cnt = 0;
+ u32 tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+ if (!rx_slot && !tx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
+ /* for virtual port, codec driver needs to do
+ * housekeeping, for now should be ok
+ */
+ wcd9xxx_get_channel(sitar, rx_ch, tx_ch);
+ if (dai->id == AIF1_PB) {
+ *rx_num = sitar_dai[dai->id - 1].playback.channels_max;
+ while (cnt < *rx_num) {
+ rx_slot[cnt] = rx_ch[cnt];
+ cnt++;
+ }
+ } else if (dai->id == AIF1_CAP) {
+ *tx_num = sitar_dai[dai->id - 1].capture.channels_max;
+ while (cnt < *tx_num) {
+ tx_slot[cnt] = tx_ch[6 + cnt];
+ cnt++;
+ }
+ }
+ return 0;
+}
+
+static int sitar_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
+ u8 path, shift;
+ u16 tx_fs_reg, rx_fs_reg;
+ u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
+
+ pr_err("%s: DAI-ID %x\n", __func__, dai->id);
+
+ switch (params_rate(params)) {
+ case 8000:
+ tx_fs_rate = 0x00;
+ rx_fs_rate = 0x00;
+ break;
+ case 16000:
+ tx_fs_rate = 0x01;
+ rx_fs_rate = 0x20;
+ break;
+ case 32000:
+ tx_fs_rate = 0x02;
+ rx_fs_rate = 0x40;
+ break;
+ case 48000:
+ tx_fs_rate = 0x03;
+ rx_fs_rate = 0x60;
+ break;
+ default:
+ pr_err("%s: Invalid sampling rate %d\n", __func__,
+ params_rate(params));
+ return -EINVAL;
+ }
+
+
+ /**
+ * If current dai is a tx dai, set sample rate to
+ * all the txfe paths that are currently not active
+ */
+ if (dai->id == AIF1_CAP) {
+
+ tx_state = snd_soc_read(codec,
+ SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL);
+
+ for (path = 1, shift = 0;
+ path <= NUM_DECIMATORS; path++, shift++) {
+
+ if (!(tx_state & (1 << shift))) {
+ tx_fs_reg = SITAR_A_CDC_TX1_CLK_FS_CTL
+ + (BITS_PER_REG*(path-1));
+ snd_soc_update_bits(codec, tx_fs_reg,
+ 0x03, tx_fs_rate);
+ }
+ }
+ if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ SITAR_A_CDC_CLK_TX_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ SITAR_A_CDC_CLK_TX_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ pr_err("invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_TX_I2S_CTL,
+ 0x03, tx_fs_rate);
+ }
+ } else {
+ sitar->dai[dai->id - 1].rate = params_rate(params);
+ }
+
+ /**
+ * TODO: Need to handle case where same RX chain takes 2 or more inputs
+ * with varying sample rates
+ */
+
+ /**
+ * If current dai is a rx dai, set sample rate to
+ * all the rx paths that are currently not active
+ */
+ if (dai->id == AIF1_PB) {
+
+ rx_state = snd_soc_read(codec,
+ SITAR_A_CDC_CLK_RX_B1_CTL);
+
+ for (path = 1, shift = 0;
+ path <= NUM_INTERPOLATORS; path++, shift++) {
+
+ if (!(rx_state & (1 << shift))) {
+ rx_fs_reg = SITAR_A_CDC_RX1_B5_CTL
+ + (BITS_PER_REG*(path-1));
+ snd_soc_update_bits(codec, rx_fs_reg,
+ 0xE0, rx_fs_rate);
+ }
+ }
+ if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ SITAR_A_CDC_CLK_RX_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ SITAR_A_CDC_CLK_RX_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ pr_err("invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, SITAR_A_CDC_CLK_RX_I2S_CTL,
+ 0x03, (rx_fs_rate >> 0x05));
+ }
+ } else {
+ sitar->dai[dai->id - 1].rate = params_rate(params);
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops sitar_dai_ops = {
+ .startup = sitar_startup,
+ .shutdown = sitar_shutdown,
+ .hw_params = sitar_hw_params,
+ .set_sysclk = sitar_set_dai_sysclk,
+ .set_fmt = sitar_set_dai_fmt,
+ .set_channel_map = sitar_set_channel_map,
+ .get_channel_map = sitar_get_channel_map,
+};
+
+static struct snd_soc_dai_driver sitar_dai[] = {
+ {
+ .name = "sitar_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = WCD9304_RATES,
+ .formats = SITAR_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &sitar_dai_ops,
+ },
+ {
+ .name = "sitar_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = WCD9304_RATES,
+ .formats = SITAR_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &sitar_dai_ops,
+ },
+};
+
+static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct wcd9xxx *sitar;
+ struct snd_soc_codec *codec = w->codec;
+ struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
+ u32 j = 0;
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ sitar = codec->control_data;
+ /* Execute the callback only if interface type is slimbus */
+ if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+ if (sitar_dai[j].id == AIF1_CAP)
+ continue;
+ if (!strncmp(w->sname,
+ sitar_dai[j].playback.stream_name, 13)) {
+ ++sitar_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (sitar_p->dai[j].ch_act == sitar_p->dai[j].ch_tot)
+ wcd9xxx_cfg_slim_sch_rx(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot,
+ sitar_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+ if (sitar_dai[j].id == AIF1_CAP)
+ continue;
+ if (!strncmp(w->sname,
+ sitar_dai[j].playback.stream_name, 13)) {
+ --sitar_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!sitar_p->dai[j].ch_act) {
+ wcd9xxx_close_slim_sch_rx(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot);
+ sitar_p->dai[j].rate = 0;
+ memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
+ sitar_p->dai[j].ch_tot));
+ sitar_p->dai[j].ch_tot = 0;
+ }
+ }
+ return 0;
+}
+
+static int sitar_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct wcd9xxx *sitar;
+ struct snd_soc_codec *codec = w->codec;
+ struct sitar_priv *sitar_p = snd_soc_codec_get_drvdata(codec);
+ /* index to the DAI ID, for now hardcoding */
+ u32 j = 0;
+
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ sitar = codec->control_data;
+
+ /* Execute the callback only if interface type is slimbus */
+ if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+ if (sitar_dai[j].id == AIF1_PB)
+ continue;
+ if (!strncmp(w->sname,
+ sitar_dai[j].capture.stream_name, 13)) {
+ ++sitar_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (sitar_p->dai[j].ch_act == sitar_p->dai[j].ch_tot)
+ wcd9xxx_cfg_slim_sch_tx(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot,
+ sitar_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
+ if (sitar_dai[j].id == AIF1_PB)
+ continue;
+ if (!strncmp(w->sname,
+ sitar_dai[j].capture.stream_name, 13)) {
+ --sitar_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!sitar_p->dai[j].ch_act) {
+ wcd9xxx_close_slim_sch_tx(sitar,
+ sitar_p->dai[j].ch_num,
+ sitar_p->dai[j].ch_tot);
+ sitar_p->dai[j].rate = 0;
+ memset(sitar_p->dai[j].ch_num, 0, (sizeof(u32)*
+ sitar_p->dai[j].ch_tot));
+ sitar_p->dai[j].ch_tot = 0;
+ }
+ }
+ return 0;
+}
+
+
+static short sitar_codec_read_sta_result(struct snd_soc_codec *codec)
+{
+ u8 bias_msb, bias_lsb;
+ short bias_value;
+
+ bias_msb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B3_STATUS);
+ bias_lsb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B2_STATUS);
+ bias_value = (bias_msb << 8) | bias_lsb;
+ return bias_value;
+}
+
+static short sitar_codec_read_dce_result(struct snd_soc_codec *codec)
+{
+ u8 bias_msb, bias_lsb;
+ short bias_value;
+
+ bias_msb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B5_STATUS);
+ bias_lsb = snd_soc_read(codec, SITAR_A_CDC_MBHC_B4_STATUS);
+ bias_value = (bias_msb << 8) | bias_lsb;
+ return bias_value;
+}
+
+static short sitar_codec_measure_micbias_voltage(struct snd_soc_codec *codec,
+ int dce)
+{
+ short bias_value;
+
+ if (dce) {
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
+ usleep_range(60000, 60000);
+ bias_value = sitar_codec_read_dce_result(codec);
+ } else {
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ usleep_range(5000, 5000);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
+ usleep_range(50, 50);
+ bias_value = sitar_codec_read_sta_result(codec);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x0);
+ }
+
+ pr_err("read microphone bias value %x\n", bias_value);
+ return bias_value;
+}
+
+static short sitar_codec_setup_hs_polling(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ struct sitar_mbhc_calibration *calibration = sitar->calibration;
+ short bias_value;
+ u8 cfilt_mode;
+
+ if (!calibration) {
+ pr_err("Error, no sitar calibration\n");
+ return -ENODEV;
+ }
+
+ sitar->mbhc_polling_active = true;
+
+ if (!sitar->mclk_enabled) {
+ sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_MBHC_MODE);
+ sitar_enable_rx_bias(codec, 1);
+ sitar_codec_enable_clock_block(codec, 1);
+ }
+
+ snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x01);
+
+ snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
+
+ /* Make sure CFILT is in fast mode, save current mode */
+ cfilt_mode = snd_soc_read(codec,
+ sitar->mbhc_bias_regs.cfilt_ctl);
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
+ 0x70, 0x00);
+
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+ snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x6);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+
+ sitar_codec_calibrate_hs_polling(codec);
+
+ bias_value = sitar_codec_measure_micbias_voltage(codec, 0);
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.cfilt_ctl, 0x40, cfilt_mode);
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x13, 0x00);
+
+ return bias_value;
+}
+
+static int sitar_codec_enable_hs_detect(struct snd_soc_codec *codec,
+ int insertion)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ struct sitar_mbhc_calibration *calibration = sitar->calibration;
+ int central_bias_enabled = 0;
+ u8 wg_time;
+
+ if (!calibration) {
+ pr_err("Error, no sitar calibration\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0);
+
+ if (insertion) {
+ /* Make sure mic bias and Mic line schmitt trigger
+ * are turned OFF
+ */
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.ctl_reg,
+ 0x81, 0x01);
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+ 0x90, 0x00);
+ wg_time = snd_soc_read(codec, SITAR_A_RX_HPH_CNP_WG_TIME) ;
+ wg_time += 1;
+
+ /* Enable HPH Schmitt Trigger */
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x11, 0x11);
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x0C,
+ calibration->hph_current << 2);
+
+ /* Turn off HPH PAs and DAC's during insertion detection to
+ * avoid false insertion interrupts
+ */
+ if (sitar->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 0);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_L_DAC_CTL,
+ 0xC0, 0x00);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_R_DAC_CTL,
+ 0xC0, 0x00);
+ usleep_range(wg_time * 1000, wg_time * 1000);
+
+ /* setup for insetion detection */
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x02, 0x02);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0);
+ } else {
+ /* Make sure the HPH schmitt trigger is OFF */
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12, 0x00);
+
+ /* enable the mic line schmitt trigger */
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg, 0x60,
+ calibration->mic_current << 5);
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ usleep_range(calibration->mic_pid, calibration->mic_pid);
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x10);
+
+ /* Setup for low power removal detection */
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
+ }
+
+ if (snd_soc_read(codec, SITAR_A_CDC_MBHC_B1_CTL) & 0x4) {
+ if (!(sitar->clock_active)) {
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
+ 0x06, 0);
+ usleep_range(calibration->shutdown_plug_removal,
+ calibration->shutdown_plug_removal);
+ } else
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
+ 0x06, 0);
+ }
+
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.int_rbias, 0x80, 0);
+
+ /* If central bandgap disabled */
+ if (!(snd_soc_read(codec, SITAR_A_PIN_CTL_OE1) & 1)) {
+ snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE1, 0x3, 0x3);
+ usleep_range(calibration->bg_fast_settle,
+ calibration->bg_fast_settle);
+ central_bias_enabled = 1;
+ }
+
+ /* If LDO_H disabled */
+ if (snd_soc_read(codec, SITAR_A_PIN_CTL_OE0) & 0x80) {
+ snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x10, 0);
+ snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0x80);
+ usleep_range(calibration->tldoh, calibration->tldoh);
+ snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0);
+
+ if (central_bias_enabled)
+ snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE1, 0x1, 0);
+ }
+
+ wcd9xxx_enable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+ return 0;
+}
+
+
+static void sitar_lock_sleep(struct sitar_priv *sitar)
+{
+ int ret;
+ while (!(ret = wait_event_timeout(sitar->pm_wq,
+ atomic_inc_not_zero(&sitar->pm_cnt),
+ 2 * HZ))) {
+ pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
+ __func__, ret, atomic_read(&sitar->pm_cnt));
+ WARN_ON_ONCE(1);
+ }
+}
+
+static void sitar_unlock_sleep(struct sitar_priv *sitar)
+{
+ atomic_dec(&sitar->pm_cnt);
+ wake_up(&sitar->pm_wq);
+}
+
+
+static void btn0_lpress_fn(struct work_struct *work)
+{
+ struct delayed_work *delayed_work;
+ struct sitar_priv *sitar;
+
+ pr_err("%s:\n", __func__);
+
+ delayed_work = to_delayed_work(work);
+ sitar = container_of(delayed_work, struct sitar_priv, btn0_dwork);
+
+ if (sitar) {
+ if (sitar->button_jack) {
+ pr_err("%s: Reporting long button press event\n",
+ __func__);
+ sitar_snd_soc_jack_report(sitar, sitar->button_jack,
+ SND_JACK_BTN_0,
+ SND_JACK_BTN_0);
+ }
+ } else {
+ pr_err("%s: Bad sitar private data\n", __func__);
+ }
+
+ sitar_unlock_sleep(sitar);
+}
+
+int sitar_hs_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
+ struct sitar_mbhc_calibration *calibration)
+{
+ struct sitar_priv *sitar;
+ int rc;
+
+ if (!codec || !calibration) {
+ pr_err("Error: no codec or calibration\n");
+ return -EINVAL;
+ }
+ sitar = snd_soc_codec_get_drvdata(codec);
+ sitar->headset_jack = headset_jack;
+ sitar->button_jack = button_jack;
+ sitar->calibration = calibration;
+ sitar_get_mbhc_micbias_regs(codec, &sitar->mbhc_bias_regs);
+
+ /* Put CFILT in fast mode by default */
+ snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
+ 0x40, SITAR_CFILT_FAST_MODE);
+
+ INIT_DELAYED_WORK(&sitar->btn0_dwork, btn0_lpress_fn);
+ INIT_WORK(&sitar->hphlocp_work, hphlocp_off_report);
+ INIT_WORK(&sitar->hphrocp_work, hphrocp_off_report);
+ rc = sitar_codec_enable_hs_detect(codec, 1);
+
+ if (!IS_ERR_VALUE(rc)) {
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ wcd9xxx_enable_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT);
+ wcd9xxx_enable_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPR_FAULT);
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(sitar_hs_detect);
+
+static irqreturn_t sitar_dce_handler(int irq, void *data)
+{
+ struct sitar_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ short bias_value;
+
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+ sitar_lock_sleep(priv);
+
+ bias_value = sitar_codec_read_dce_result(codec);
+ pr_err("%s: button press interrupt, bias value(DCE Read)=%d\n",
+ __func__, bias_value);
+
+ bias_value = sitar_codec_read_sta_result(codec);
+ pr_err("%s: button press interrupt, bias value(STA Read)=%d\n",
+ __func__, bias_value);
+ /*
+ * TODO: If button pressed is not button 0,
+ * report the button press event immediately.
+ */
+ priv->buttons_pressed |= SND_JACK_BTN_0;
+
+ msleep(100);
+
+ if (schedule_delayed_work(&priv->btn0_dwork,
+ msecs_to_jiffies(400)) == 0) {
+ WARN(1, "Button pressed twice without release event\n");
+ sitar_unlock_sleep(priv);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_release_handler(int irq, void *data)
+{
+ struct sitar_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ int ret, mic_voltage;
+
+ pr_err("%s\n", __func__);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+ sitar_lock_sleep(priv);
+
+ mic_voltage = sitar_codec_read_dce_result(codec);
+ pr_err("%s: Microphone Voltage on release(DCE Read) = %d\n",
+ __func__, mic_voltage);
+
+ if (priv->buttons_pressed & SND_JACK_BTN_0) {
+ ret = cancel_delayed_work(&priv->btn0_dwork);
+
+ if (ret == 0) {
+
+ pr_err("%s: Reporting long button release event\n",
+ __func__);
+ if (priv->button_jack) {
+ sitar_snd_soc_jack_report(priv,
+ priv->button_jack, 0,
+ SND_JACK_BTN_0);
+ }
+
+ } else {
+ /* if scheduled btn0_dwork is canceled from here,
+ * we have to unlock from here instead btn0_work */
+ sitar_unlock_sleep(priv);
+ mic_voltage =
+ sitar_codec_measure_micbias_voltage(codec, 0);
+ pr_err("%s: Mic Voltage on release(new STA) = %d\n",
+ __func__, mic_voltage);
+
+ if (mic_voltage < -2000 || mic_voltage > -670) {
+ pr_err("%s: Fake buttton press interrupt\n",
+ __func__);
+ } else {
+
+ if (priv->button_jack) {
+ pr_err("%s:reporting short button press and release\n",
+ __func__);
+
+ sitar_snd_soc_jack_report(priv,
+ priv->button_jack,
+ SND_JACK_BTN_0, SND_JACK_BTN_0);
+ sitar_snd_soc_jack_report(priv,
+ priv->button_jack,
+ 0, SND_JACK_BTN_0);
+ }
+ }
+ }
+
+ priv->buttons_pressed &= ~SND_JACK_BTN_0;
+ }
+
+ sitar_codec_start_hs_polling(codec);
+ sitar_unlock_sleep(priv);
+ return IRQ_HANDLED;
+}
+
+static void sitar_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ struct sitar_mbhc_calibration *calibration = sitar->calibration;
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
+
+ snd_soc_update_bits(codec,
+ sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+ usleep_range(calibration->shutdown_plug_removal,
+ calibration->shutdown_plug_removal);
+
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
+
+ snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x00);
+}
+
+static void sitar_codec_shutdown_hs_polling(struct snd_soc_codec *codec)
+{
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+ sitar_codec_shutdown_hs_removal_detect(codec);
+
+ if (!sitar->mclk_enabled) {
+ snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0x00);
+ sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_AUDIO_MODE);
+ sitar_codec_enable_clock_block(codec, 0);
+ }
+
+ sitar->mbhc_polling_active = false;
+}
+
+static irqreturn_t sitar_hphl_ocp_irq(int irq, void *data)
+{
+ struct sitar_priv *sitar = data;
+ struct snd_soc_codec *codec;
+
+ pr_info("%s: received HPHL OCP irq\n", __func__);
+
+ if (sitar) {
+ codec = sitar->codec;
+ if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ pr_info("%s: retry\n", __func__);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ } else {
+ wcd9xxx_disable_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT);
+ sitar->hphlocp_cnt = 0;
+ sitar->hph_status |= SND_JACK_OC_HPHL;
+ if (sitar->headset_jack)
+ sitar_snd_soc_jack_report(sitar,
+ sitar->headset_jack,
+ sitar->hph_status,
+ SITAR_JACK_MASK);
+ }
+ } else {
+ pr_err("%s: Bad sitar private data\n", __func__);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_hphr_ocp_irq(int irq, void *data)
+{
+ struct sitar_priv *sitar = data;
+ struct snd_soc_codec *codec;
+
+ pr_info("%s: received HPHR OCP irq\n", __func__);
+
+ if (sitar) {
+ codec = sitar->codec;
+ if (sitar->hphrocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ pr_info("%s: retry\n", __func__);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ } else {
+ wcd9xxx_disable_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPR_FAULT);
+ sitar->hphrocp_cnt = 0;
+ sitar->hph_status |= SND_JACK_OC_HPHR;
+ if (sitar->headset_jack)
+ sitar_snd_soc_jack_report(sitar,
+ sitar->headset_jack,
+ sitar->hph_status,
+ SITAR_JACK_MASK);
+ }
+ } else {
+ pr_err("%s: Bad sitar private data\n", __func__);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void sitar_sync_hph_state(struct sitar_priv *sitar)
+{
+ if (test_and_clear_bit(SITAR_HPHR_PA_OFF_ACK,
+ &sitar->hph_pa_dac_state)) {
+ pr_err("%s: HPHR clear flag and enable PA\n", __func__);
+ snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_CNP_EN, 0x10,
+ 1 << 4);
+ }
+ if (test_and_clear_bit(SITAR_HPHL_PA_OFF_ACK,
+ &sitar->hph_pa_dac_state)) {
+ pr_err("%s: HPHL clear flag and enable PA\n", __func__);
+ snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_CNP_EN, 0x20,
+ 1 << 5);
+ }
+
+ if (test_and_clear_bit(SITAR_HPHR_DAC_OFF_ACK,
+ &sitar->hph_pa_dac_state)) {
+ pr_err("%s: HPHR clear flag and enable DAC\n", __func__);
+ snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_R_DAC_CTL,
+ 0xC0, 0xC0);
+ }
+ if (test_and_clear_bit(SITAR_HPHL_DAC_OFF_ACK,
+ &sitar->hph_pa_dac_state)) {
+ pr_err("%s: HPHL clear flag and enable DAC\n", __func__);
+ snd_soc_update_bits(sitar->codec, SITAR_A_RX_HPH_L_DAC_CTL,
+ 0xC0, 0xC0);
+ }
+}
+
+static irqreturn_t sitar_hs_insert_irq(int irq, void *data)
+{
+ struct sitar_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ int ldo_h_on, micb_cfilt_on;
+ short mic_voltage;
+ short threshold_no_mic = 0xF7F6;
+ short threshold_fake_insert = 0xFD30;
+ u8 is_removal;
+
+ pr_err("%s\n", __func__);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+ sitar_lock_sleep(priv);
+
+ is_removal = snd_soc_read(codec, SITAR_A_CDC_MBHC_INT_CTL) & 0x02;
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
+
+ /* Turn off both HPH and MIC line schmitt triggers */
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+ 0x90, 0x00);
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x13, 0x00);
+
+ if (priv->fake_insert_context) {
+ pr_err("%s: fake context interrupt, reset insertion\n",
+ __func__);
+ priv->fake_insert_context = false;
+ sitar_codec_shutdown_hs_polling(codec);
+ sitar_codec_enable_hs_detect(codec, 1);
+ return IRQ_HANDLED;
+ }
+
+
+ ldo_h_on = snd_soc_read(codec, SITAR_A_LDO_H_MODE_1) & 0x80;
+ micb_cfilt_on = snd_soc_read(codec,
+ priv->mbhc_bias_regs.cfilt_ctl) & 0x80;
+
+ if (!ldo_h_on)
+ snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
+ if (!micb_cfilt_on)
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
+ 0x80, 0x80);
+
+ usleep_range(priv->calibration->setup_plug_removal_delay,
+ priv->calibration->setup_plug_removal_delay);
+
+ if (!ldo_h_on)
+ snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x0);
+ if (!micb_cfilt_on)
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
+ 0x80, 0x0);
+
+ if (is_removal) {
+ /*
+ * If headphone is removed while playback is in progress,
+ * it is possible that micbias will be switched to VDDIO.
+ */
+ if (priv->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 0);
+ priv->hph_status &= ~SND_JACK_HEADPHONE;
+
+ /* If headphone PA is on, check if userspace receives
+ * removal event to sync-up PA's state */
+ if (sitar_is_hph_pa_on(codec)) {
+ set_bit(SITAR_HPHL_PA_OFF_ACK, &priv->hph_pa_dac_state);
+ set_bit(SITAR_HPHR_PA_OFF_ACK, &priv->hph_pa_dac_state);
+ }
+
+ if (sitar_is_hph_dac_on(codec, 1))
+ set_bit(SITAR_HPHL_DAC_OFF_ACK,
+ &priv->hph_pa_dac_state);
+ if (sitar_is_hph_dac_on(codec, 0))
+ set_bit(SITAR_HPHR_DAC_OFF_ACK,
+ &priv->hph_pa_dac_state);
+
+ if (priv->headset_jack) {
+ pr_err("%s: Reporting removal\n", __func__);
+ sitar_snd_soc_jack_report(priv, priv->headset_jack,
+ priv->hph_status,
+ SITAR_JACK_MASK);
+ }
+ sitar_codec_shutdown_hs_removal_detect(codec);
+ sitar_codec_enable_hs_detect(codec, 1);
+ sitar_unlock_sleep(priv);
+ return IRQ_HANDLED;
+ }
+
+ mic_voltage = sitar_codec_setup_hs_polling(codec);
+
+ if (mic_voltage > threshold_fake_insert) {
+ pr_err("%s: Fake insertion interrupt, mic_voltage = %x\n",
+ __func__, mic_voltage);
+
+ /* Disable HPH trigger and enable MIC line trigger */
+ snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12, 0x00);
+
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x60,
+ priv->calibration->mic_current << 5);
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ usleep_range(priv->calibration->mic_pid,
+ priv->calibration->mic_pid);
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x10);
+
+ /* Setup for insertion detection */
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0);
+ priv->fake_insert_context = true;
+ wcd9xxx_enable_irq(codec->control_data,
+ SITAR_IRQ_MBHC_INSERTION);
+ snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+
+ } else if (mic_voltage < threshold_no_mic) {
+ pr_err("%s: Headphone Detected, mic_voltage = %x\n",
+ __func__, mic_voltage);
+ priv->hph_status |= SND_JACK_HEADPHONE;
+ if (priv->headset_jack) {
+ pr_err("%s: Reporting insertion %d\n", __func__,
+ SND_JACK_HEADPHONE);
+ sitar_snd_soc_jack_report(priv, priv->headset_jack,
+ priv->hph_status,
+ SITAR_JACK_MASK);
+ }
+ sitar_codec_shutdown_hs_polling(codec);
+ sitar_codec_enable_hs_detect(codec, 0);
+ sitar_sync_hph_state(priv);
+ } else {
+ pr_err("%s: Headset detected, mic_voltage = %x\n",
+ __func__, mic_voltage);
+ priv->hph_status |= SND_JACK_HEADSET;
+ if (priv->headset_jack) {
+ pr_err("%s: Reporting insertion %d\n", __func__,
+ SND_JACK_HEADSET);
+ sitar_snd_soc_jack_report(priv, priv->headset_jack,
+ priv->hph_status,
+ SITAR_JACK_MASK);
+ }
+ sitar_codec_start_hs_polling(codec);
+ sitar_sync_hph_state(priv);
+ }
+
+ sitar_unlock_sleep(priv);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sitar_hs_remove_irq(int irq, void *data)
+{
+ struct sitar_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ short bias_value;
+
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+ sitar_lock_sleep(priv);
+
+ usleep_range(priv->calibration->shutdown_plug_removal,
+ priv->calibration->shutdown_plug_removal);
+
+ bias_value = sitar_codec_measure_micbias_voltage(codec, 1);
+ pr_err("removal interrupt, bias value is %d\n", bias_value);
+
+ if (bias_value < -90) {
+ pr_err("False alarm, headset not actually removed\n");
+ sitar_codec_start_hs_polling(codec);
+ } else {
+ /*
+ * If this removal is not false, first check the micbias
+ * switch status and switch it to LDOH if it is already
+ * switched to VDDIO.
+ */
+ if (priv->mbhc_micbias_switched)
+ sitar_codec_switch_micbias(codec, 0);
+ priv->hph_status &= ~SND_JACK_HEADSET;
+ if (priv->headset_jack) {
+ pr_err("%s: Reporting removal\n", __func__);
+ sitar_snd_soc_jack_report(priv, priv->headset_jack, 0,
+ SITAR_JACK_MASK);
+ }
+ sitar_codec_shutdown_hs_polling(codec);
+
+ sitar_codec_enable_hs_detect(codec, 1);
+ }
+
+ sitar_unlock_sleep(priv);
+ return IRQ_HANDLED;
+}
+
+
+static unsigned long slimbus_value;
+
+static irqreturn_t sitar_slimbus_irq(int irq, void *data)
+{
+ struct sitar_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ int i, j;
+ u8 val;
+
+ sitar_lock_sleep(priv);
+
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+ slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
+ SITAR_SLIM_PGD_PORT_INT_STATUS0 + i);
+ for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
+ val = wcd9xxx_interface_reg_read(codec->control_data,
+ SITAR_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
+ if (val & 0x1)
+ pr_err_ratelimited("overflow error on port %x,"
+ " value %x\n", i*8 + j, val);
+ if (val & 0x2)
+ pr_err_ratelimited("underflow error on port %x,"
+ " value %x\n", i*8 + j, val);
+ }
+ wcd9xxx_interface_reg_write(codec->control_data,
+ SITAR_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+ }
+
+ sitar_unlock_sleep(priv);
+ return IRQ_HANDLED;
+}
+
+
+static int sitar_handle_pdata(struct sitar_priv *sitar)
+{
+ struct snd_soc_codec *codec = sitar->codec;
+ struct wcd9xxx_pdata *pdata = sitar->pdata;
+ int k1, k2, rc = 0;
+ u8 leg_mode = pdata->amic_settings.legacy_mode;
+ u8 txfe_bypass = pdata->amic_settings.txfe_enable;
+ u8 txfe_buff = pdata->amic_settings.txfe_buff;
+ u8 flag = pdata->amic_settings.use_pdata;
+ u8 i = 0, j = 0;
+ u8 val_txfe = 0, value = 0;
+
+ if (!pdata) {
+ rc = -ENODEV;
+ goto done;
+ }
+
+ /* Make sure settings are correct */
+ if ((pdata->micbias.ldoh_v > SITAR_LDOH_2P85_V) ||
+ (pdata->micbias.bias1_cfilt_sel > SITAR_CFILT2_SEL) ||
+ (pdata->micbias.bias2_cfilt_sel > SITAR_CFILT2_SEL)) {
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* figure out k value */
+ k1 = sitar_find_k_value(pdata->micbias.ldoh_v,
+ pdata->micbias.cfilt1_mv);
+ k2 = sitar_find_k_value(pdata->micbias.ldoh_v,
+ pdata->micbias.cfilt2_mv);
+
+ if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2)) {
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Set voltage level and always use LDO */
+
+ snd_soc_update_bits(codec, SITAR_A_MICB_CFILT_1_VAL, 0xFC,
+ (k1 << 2));
+ snd_soc_update_bits(codec, SITAR_A_MICB_CFILT_2_VAL, 0xFC,
+ (k2 << 2));
+
+ snd_soc_update_bits(codec, SITAR_A_MICB_1_CTL, 0x60,
+ (pdata->micbias.bias1_cfilt_sel << 5));
+ snd_soc_update_bits(codec, SITAR_A_MICB_2_CTL, 0x60,
+ (pdata->micbias.bias2_cfilt_sel << 5));
+
+ for (i = 0; i < 6; j++, i += 2) {
+ if (flag & (0x01 << i)) {
+ value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
+ val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
+ val_txfe = val_txfe |
+ ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
+ snd_soc_update_bits(codec, SITAR_A_TX_1_2_EN + j * 10,
+ 0x10, value);
+ snd_soc_update_bits(codec,
+ SITAR_A_TX_1_2_TEST_EN + j * 10,
+ 0x30, val_txfe);
+ }
+ if (flag & (0x01 << (i + 1))) {
+ value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
+ val_txfe = (txfe_bypass &
+ (0x01 << (i + 1))) ? 0x02 : 0x00;
+ val_txfe |= (txfe_buff &
+ (0x01 << (i + 1))) ? 0x01 : 0x00;
+ snd_soc_update_bits(codec, SITAR_A_TX_1_2_EN + j * 10,
+ 0x01, value);
+ snd_soc_update_bits(codec,
+ SITAR_A_TX_1_2_TEST_EN + j * 10,
+ 0x03, val_txfe);
+ }
+ }
+
+ if (pdata->ocp.use_pdata) {
+ /* not defined in CODEC specification */
+ if (pdata->ocp.hph_ocp_limit == 1 ||
+ pdata->ocp.hph_ocp_limit == 5) {
+ rc = -EINVAL;
+ goto done;
+ }
+ snd_soc_update_bits(codec, SITAR_A_RX_COM_OCP_CTL,
+ 0x0F, pdata->ocp.num_attempts);
+ snd_soc_write(codec, SITAR_A_RX_COM_OCP_COUNT,
+ ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+ snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL,
+ 0xE0, (pdata->ocp.hph_ocp_limit << 5));
+ }
+done:
+ return rc;
+}
+
+static const struct sitar_reg_mask_val sitar_1_1_reg_defaults[] = {
+
+ /* Sitar 1.1 MICBIAS changes */
+ SITAR_REG_VAL(SITAR_A_MICB_1_INT_RBIAS, 0x24),
+ SITAR_REG_VAL(SITAR_A_MICB_2_INT_RBIAS, 0x24),
+
+ /* Sitar 1.1 HPH changes */
+ SITAR_REG_VAL(SITAR_A_RX_HPH_BIAS_PA, 0x57),
+ SITAR_REG_VAL(SITAR_A_RX_HPH_BIAS_LDO, 0x56),
+
+ /* Sitar 1.1 EAR PA changes */
+ SITAR_REG_VAL(SITAR_A_RX_EAR_BIAS_PA, 0xA6),
+ SITAR_REG_VAL(SITAR_A_RX_EAR_GAIN, 0x02),
+ SITAR_REG_VAL(SITAR_A_RX_EAR_VCM, 0x03),
+
+ /* Sitar 1.1 RX Changes */
+ SITAR_REG_VAL(SITAR_A_CDC_RX1_B5_CTL, 0x78),
+
+ /* Sitar 1.1 RX1 and RX2 Changes */
+ SITAR_REG_VAL(SITAR_A_CDC_RX1_B6_CTL, 0x80),
+
+ SITAR_REG_VAL(SITAR_A_CDC_CLSG_FREQ_THRESH_B3_CTL, 0x1B),
+
+};
+
+static void sitar_update_reg_defaults(struct snd_soc_codec *codec)
+{
+ u32 i;
+ for (i = 0; i < ARRAY_SIZE(sitar_1_1_reg_defaults); i++)
+ snd_soc_write(codec, sitar_1_1_reg_defaults[i].reg,
+ sitar_1_1_reg_defaults[i].val);
+
+}
+static const struct sitar_reg_mask_val sitar_codec_reg_init_val[] = {
+ /* Initialize current threshold to 350MA
+ * number of wait and run cycles to 4096
+ */
+ {SITAR_A_RX_HPH_OCP_CTL, 0xF8, 0x60},
+ {SITAR_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+ {SITAR_A_QFUSE_CTL, 0xFF, 0x03},
+
+ /* Initialize gain registers to use register gain */
+ {SITAR_A_RX_HPH_L_GAIN, 0x10, 0x10},
+ {SITAR_A_RX_HPH_R_GAIN, 0x10, 0x10},
+ {SITAR_A_RX_LINE_1_GAIN, 0x10, 0x10},
+ {SITAR_A_RX_LINE_2_GAIN, 0x10, 0x10},
+
+ /* Initialize mic biases to differential mode */
+ {SITAR_A_MICB_1_INT_RBIAS, 0x24, 0x24},
+ {SITAR_A_MICB_2_INT_RBIAS, 0x24, 0x24},
+
+ {SITAR_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
+
+ /* Use 16 bit sample size for TX1 to TX6 */
+ {SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x28},
+ {SITAR_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
+ {SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
+ {SITAR_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
+ {SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+
+ /* Use 16 bit sample size for RX */
+ {SITAR_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
+ {SITAR_A_CDC_CONN_RX_SB_B2_CTL, 0x02, 0x02},
+
+ /*enable HPF filter for TX paths */
+ {SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+};
+
+static void sitar_codec_init_reg(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(sitar_codec_reg_init_val); i++)
+ snd_soc_update_bits(codec, sitar_codec_reg_init_val[i].reg,
+ sitar_codec_reg_init_val[i].mask,
+ sitar_codec_reg_init_val[i].val);
+}
+
+static int sitar_codec_probe(struct snd_soc_codec *codec)
+{
+ struct sitar *control;
+ struct sitar_priv *sitar;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int ret = 0;
+ int i;
+ u8 sitar_version;
+ int ch_cnt;
+
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ control = codec->control_data;
+
+ sitar = kzalloc(sizeof(struct sitar_priv), GFP_KERNEL);
+ if (!sitar) {
+ dev_err(codec->dev, "Failed to allocate private data\n");
+ return -ENOMEM;
+ }
+
+ /* Make sure mbhc micbias register addresses are zeroed out */
+ memset(&sitar->mbhc_bias_regs, 0,
+ sizeof(struct mbhc_micbias_regs));
+ sitar->cfilt_k_value = 0;
+ sitar->mbhc_micbias_switched = false;
+
+ snd_soc_codec_set_drvdata(codec, sitar);
+
+ sitar->mclk_enabled = false;
+ sitar->bandgap_type = SITAR_BANDGAP_OFF;
+ sitar->clock_active = false;
+ sitar->config_mode_active = false;
+ sitar->mbhc_polling_active = false;
+ sitar->fake_insert_context = false;
+ sitar->no_mic_headset_override = false;
+ sitar->codec = codec;
+ sitar->pdata = dev_get_platdata(codec->dev->parent);
+ atomic_set(&sitar->pm_cnt, 1);
+ init_waitqueue_head(&sitar->pm_wq);
+
+ sitar_update_reg_defaults(codec);
+ sitar_codec_init_reg(codec);
+
+ ret = sitar_handle_pdata(sitar);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("%s: bad pdata\n", __func__);
+ goto err_pdata;
+ }
+
+ snd_soc_add_controls(codec, sitar_snd_controls,
+ ARRAY_SIZE(sitar_snd_controls));
+ snd_soc_dapm_new_controls(dapm, sitar_dapm_widgets,
+ ARRAY_SIZE(sitar_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
+
+ sitar_version = snd_soc_read(codec, WCD9XXX_A_CHIP_VERSION);
+ pr_info("%s : Sitar version reg 0x%2x\n", __func__, (u32)sitar_version);
+
+ sitar_version &= 0x1F;
+ pr_info("%s : Sitar version %u\n", __func__, (u32)sitar_version);
+
+ snd_soc_dapm_sync(dapm);
+
+
+ ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION,
+ sitar_hs_insert_irq, "Headset insert detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_MBHC_INSERTION);
+ goto err_insert_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
+
+ ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL,
+ sitar_hs_remove_irq, "Headset remove detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_MBHC_REMOVAL);
+ goto err_remove_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
+
+ ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL,
+ sitar_dce_handler, "DC Estimation detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_MBHC_POTENTIAL);
+ goto err_potential_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
+
+ ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE,
+ sitar_release_handler, "Button Release detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_MBHC_RELEASE);
+ goto err_release_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
+
+ ret = wcd9xxx_request_irq(codec->control_data, SITAR_IRQ_SLIMBUS,
+ sitar_slimbus_irq, "SLIMBUS Slave", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_SLIMBUS);
+ goto err_slimbus_irq;
+ }
+
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+ wcd9xxx_interface_reg_write(codec->control_data,
+ SITAR_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
+
+
+ ret = wcd9xxx_request_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT, sitar_hphl_ocp_irq,
+ "HPH_L OCP detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT);
+ goto err_hphl_ocp_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_HPH_PA_OCPL_FAULT);
+
+ ret = wcd9xxx_request_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPR_FAULT, sitar_hphr_ocp_irq,
+ "HPH_R OCP detect", sitar);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ SITAR_IRQ_HPH_PA_OCPR_FAULT);
+ goto err_hphr_ocp_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_HPH_PA_OCPR_FAULT);
+
+ for (i = 0; i < ARRAY_SIZE(sitar_dai); i++) {
+ switch (sitar_dai[i].id) {
+ case AIF1_PB:
+ ch_cnt = sitar_dai[i].playback.channels_max;
+ break;
+ case AIF1_CAP:
+ ch_cnt = sitar_dai[i].capture.channels_max;
+ break;
+ default:
+ continue;
+ }
+ sitar->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+ ch_cnt), GFP_KERNEL);
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ debug_sitar_priv = sitar;
+#endif
+
+ return ret;
+
+err_hphr_ocp_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_HPH_PA_OCPL_FAULT, sitar);
+err_hphl_ocp_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_SLIMBUS, sitar);
+err_slimbus_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_MBHC_RELEASE, sitar);
+err_release_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_MBHC_POTENTIAL, sitar);
+err_potential_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_MBHC_REMOVAL, sitar);
+err_remove_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ SITAR_IRQ_MBHC_INSERTION, sitar);
+err_insert_irq:
+err_pdata:
+ kfree(sitar);
+ return ret;
+}
+static int sitar_codec_remove(struct snd_soc_codec *codec)
+{
+ int i;
+ struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+ wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_SLIMBUS, sitar);
+ wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE, sitar);
+ wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL, sitar);
+ wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL, sitar);
+ wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION, sitar);
+ sitar_codec_disable_clock_block(codec);
+ sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_OFF);
+ for (i = 0; i < ARRAY_SIZE(sitar_dai); i++)
+ kfree(sitar->dai[i].ch_num);
+ kfree(sitar);
+ return 0;
+}
+static struct snd_soc_codec_driver soc_codec_dev_sitar = {
+ .probe = sitar_codec_probe,
+ .remove = sitar_codec_remove,
+ .read = sitar_read,
+ .write = sitar_write,
+
+ .readable_register = sitar_readable,
+ .volatile_register = sitar_volatile,
+
+ .reg_cache_size = SITAR_CACHE_SIZE,
+ .reg_cache_default = sitar_reg_defaults,
+ .reg_word_size = 1,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfs_poke;
+
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t codec_debug_write(struct file *filp,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char lbuf[32];
+ char *buf;
+ int rc;
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+ buf = (char *)lbuf;
+ debug_sitar_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
+ ? false : true;
+
+ return rc;
+}
+
+static const struct file_operations codec_debug_ops = {
+ .open = codec_debug_open,
+ .write = codec_debug_write,
+};
+#endif
+
+#ifdef CONFIG_PM
+static int sitar_suspend(struct device *dev)
+{
+ int ret = 0, cnt;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sitar_priv *sitar = platform_get_drvdata(pdev);
+
+ cnt = atomic_read(&sitar->pm_cnt);
+ if (cnt > 0) {
+ if (wait_event_timeout(sitar->pm_wq,
+ (atomic_cmpxchg(&sitar->pm_cnt, 1, 0)
+ == 1), 5 * HZ)) {
+ dev_dbg(dev, "system suspend pm_cnt %d\n",
+ atomic_read(&sitar->pm_cnt));
+ } else {
+ dev_err(dev, "%s timed out pm_cnt = %d\n",
+ __func__, atomic_read(&sitar->pm_cnt));
+ WARN_ON_ONCE(1);
+ ret = -EBUSY;
+ }
+ } else if (cnt == 0)
+ dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
+ atomic_read(&sitar->pm_cnt));
+ else {
+ WARN(1, "unexpected pm_cnt %d\n", cnt);
+ ret = -EFAULT;
+ }
+
+ return ret;
+}
+
+static int sitar_resume(struct device *dev)
+{
+ int ret = 0, cnt;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sitar_priv *sitar = platform_get_drvdata(pdev);
+
+ cnt = atomic_cmpxchg(&sitar->pm_cnt, 0, 1);
+ if (cnt == 0) {
+ dev_dbg(dev, "system resume, pm_cnt %d\n",
+ atomic_read(&sitar->pm_cnt));
+ wake_up_all(&sitar->pm_wq);
+ } else if (cnt > 0)
+ dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
+ else {
+ WARN(1, "unexpected pm_cnt %d\n", cnt);
+ ret = -EFAULT;
+ }
+
+ return ret;
+}
+
+static const struct dev_pm_ops sitar_pm_ops = {
+ .suspend = sitar_suspend,
+ .resume = sitar_resume,
+};
+#endif
+
+static int __devinit sitar_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ pr_err("%s\n", __func__);
+#ifdef CONFIG_DEBUG_FS
+ debugfs_poke = debugfs_create_file("TRRS",
+ S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
+
+#endif
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_sitar,
+ sitar_dai, ARRAY_SIZE(sitar_dai));
+ return ret;
+}
+static int __devexit sitar_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(debugfs_poke);
+#endif
+ return 0;
+}
+static struct platform_driver sitar_codec_driver = {
+ .probe = sitar_probe,
+ .remove = sitar_remove,
+ .driver = {
+ .name = "sitar_codec",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &sitar_pm_ops,
+#endif
+ },
+};
+
+static int __init sitar_codec_init(void)
+{
+ return platform_driver_register(&sitar_codec_driver);
+}
+
+static void __exit sitar_codec_exit(void)
+{
+ platform_driver_unregister(&sitar_codec_driver);
+}
+
+module_init(sitar_codec_init);
+module_exit(sitar_codec_exit);
+
+MODULE_DESCRIPTION("Sitar codec driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9304.h b/sound/soc/codecs/wcd9304.h
new file mode 100644
index 0000000..07a1ca0
--- /dev/null
+++ b/sound/soc/codecs/wcd9304.h
@@ -0,0 +1,72 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <sound/soc.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+
+#define SITAR_VERSION_1_0 0x00
+
+#define SITAR_NUM_REGISTERS 0x3E0
+#define SITAR_MAX_REGISTER (SITAR_NUM_REGISTERS-1)
+#define SITAR_CACHE_SIZE SITAR_NUM_REGISTERS
+
+#define SITAR_REG_VAL(reg, val) {reg, 0, val}
+
+/* Local to the core only */
+#define SITAR_SLIM_MAX_RX_PORTS 5
+#define SITAR_SLIM_MAX_TX_PORTS 5
+
+extern const u8 sitar_reg_readable[SITAR_CACHE_SIZE];
+extern const u8 sitar_reg_defaults[SITAR_CACHE_SIZE];
+
+enum sitar_micbias_num {
+ SITAR_MICBIAS1,
+ SITAR_MICBIAS2,
+};
+
+enum sitar_pid_current {
+ SITAR_PID_MIC_2P5_UA,
+ SITAR_PID_MIC_5_UA,
+ SITAR_PID_MIC_10_UA,
+ SITAR_PID_MIC_20_UA,
+};
+
+struct sitar_mbhc_calibration {
+ enum sitar_micbias_num bias;
+ int tldoh;
+ int bg_fast_settle;
+ enum sitar_pid_current mic_current;
+ int mic_pid;
+ enum sitar_pid_current hph_current;
+ int setup_plug_removal_delay;
+ int shutdown_plug_removal;
+};
+
+struct sitar_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+extern int sitar_hs_detect(struct snd_soc_codec *codec,
+ struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
+ struct sitar_mbhc_calibration *calibration);
+
+#ifndef anc_header_dec
+struct anc_header {
+ u32 reserved[3];
+ u32 num_anc_slots;
+};
+#define anc_header_dec
+#endif
+
+extern int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable);
diff --git a/sound/soc/codecs/wcd9310-tables.c b/sound/soc/codecs/wcd9310-tables.c
index c681771..e0ad541 100644
--- a/sound/soc/codecs/wcd9310-tables.c
+++ b/sound/soc/codecs/wcd9310-tables.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/wcd9310/registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
#include "wcd9310.h"
const u8 tabla_reg_readable[TABLA_CACHE_SIZE] = {
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 46f6461..082b29e 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -18,9 +18,10 @@
#include <linux/printk.h>
#include <linux/ratelimit.h>
#include <linux/debugfs.h>
-#include <linux/mfd/wcd9310/core.h>
-#include <linux/mfd/wcd9310/registers.h>
-#include <linux/mfd/wcd9310/pdata.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9310_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -28,6 +29,7 @@
#include <sound/tlv.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "wcd9310.h"
#define WCD9310_RATES (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000|\
@@ -171,7 +173,7 @@
struct snd_soc_jack *headset_jack;
struct snd_soc_jack *button_jack;
- struct tabla_pdata *pdata;
+ struct wcd9xxx_pdata *pdata;
u32 anc_slot;
bool no_mic_headset_override;
@@ -1319,10 +1321,12 @@
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
- tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+ wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
if (!tabla->no_mic_headset_override) {
- tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
- tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+ wcd9xxx_enable_irq(codec->control_data,
+ TABLA_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_enable_irq(codec->control_data,
+ TABLA_IRQ_MBHC_RELEASE);
} else {
tabla_codec_disable_button_presses(codec);
}
@@ -1336,11 +1340,12 @@
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
if (!tabla->no_mic_headset_override) {
- tabla_disable_irq(codec->control_data,
+ wcd9xxx_disable_irq(codec->control_data,
TABLA_IRQ_MBHC_POTENTIAL);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+ wcd9xxx_disable_irq(codec->control_data,
+ TABLA_IRQ_MBHC_RELEASE);
}
}
@@ -1767,7 +1772,7 @@
tabla->hphlocp_cnt = 0;
else
tabla->hphrocp_cnt = 0;
- tabla_enable_irq(codec->control_data, irq);
+ wcd9xxx_enable_irq(codec->control_data, irq);
} else {
pr_err("%s: Bad tabla private data\n", __func__);
}
@@ -1925,16 +1930,16 @@
static const struct snd_soc_dapm_widget tabla_1_x_dapm_widgets[] = {
SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_1_A_MICB_4_CTL, 7,
- 0, tabla_codec_enable_micbias,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_POST_PMD),
+ 0, tabla_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_widget tabla_2_higher_dapm_widgets[] = {
SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TABLA_2_A_MICB_4_CTL, 7,
- 0, tabla_codec_enable_micbias,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_POST_PMD),
+ 0, tabla_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route audio_i2s_map[] = {
@@ -2284,7 +2289,7 @@
static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg)
{
int i;
- struct tabla *tabla_core = dev_get_drvdata(ssc->dev->parent);
+ struct wcd9xxx *tabla_core = dev_get_drvdata(ssc->dev->parent);
if (TABLA_IS_1_X(tabla_core->version)) {
for (i = 0; i < ARRAY_SIZE(tabla_1_reg_readable); i++) {
@@ -2333,7 +2338,7 @@
reg, ret);
}
- return tabla_reg_write(codec->control_data, reg, value);
+ return wcd9xxx_reg_write(codec->control_data, reg, value);
}
static unsigned int tabla_read(struct snd_soc_codec *codec,
unsigned int reg)
@@ -2353,7 +2358,7 @@
reg, ret);
}
- val = tabla_reg_read(codec->control_data, reg);
+ val = wcd9xxx_reg_read(codec->control_data, reg);
return val;
}
@@ -2543,8 +2548,13 @@
static int tabla_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct wcd9xxx *tabla_core = dev_get_drvdata(dai->codec->dev->parent);
pr_debug("%s(): substream = %s stream = %d\n" , __func__,
substream->name, substream->stream);
+ if ((tabla_core != NULL) &&
+ (tabla_core->dev != NULL) &&
+ (tabla_core->dev->parent != NULL))
+ pm_runtime_get_sync(tabla_core->dev->parent);
return 0;
}
@@ -2552,8 +2562,15 @@
static void tabla_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
+ struct wcd9xxx *tabla_core = dev_get_drvdata(dai->codec->dev->parent);
pr_debug("%s(): substream = %s stream = %d\n" , __func__,
substream->name, substream->stream);
+ if ((tabla_core != NULL) &&
+ (tabla_core->dev != NULL) &&
+ (tabla_core->dev->parent != NULL)) {
+ pm_runtime_mark_last_busy(tabla_core->dev->parent);
+ pm_runtime_put(tabla_core->dev->parent);
+ }
}
int tabla_mclk_enable(struct snd_soc_codec *codec, int mclk_enable)
@@ -2622,7 +2639,7 @@
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* CPU is master */
- if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+ if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
if (dai->id == AIF1_CAP)
snd_soc_update_bits(dai->codec,
TABLA_A_CDC_CLK_TX_I2S_CTL,
@@ -2635,7 +2652,7 @@
break;
case SND_SOC_DAIFMT_CBM_CFM:
/* CPU is slave */
- if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+ if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
val = TABLA_I2S_MASTER_MODE_MASK;
if (dai->id == AIF1_CAP)
snd_soc_update_bits(dai->codec,
@@ -2685,7 +2702,7 @@
unsigned int *rx_num, unsigned int *rx_slot)
{
- struct tabla *tabla = dev_get_drvdata(dai->codec->control_data);
+ struct wcd9xxx *tabla = dev_get_drvdata(dai->codec->control_data);
u32 cnt = 0;
u32 tx_ch[SLIM_MAX_TX_PORTS];
@@ -2699,7 +2716,7 @@
/* for virtual port, codec driver needs to do
* housekeeping, for now should be ok
*/
- tabla_get_channel(tabla, rx_ch, tx_ch);
+ wcd9xxx_get_channel(tabla, rx_ch, tx_ch);
if (dai->id == AIF1_PB) {
*rx_num = tabla_dai[dai->id - 1].playback.channels_max;
while (cnt < *rx_num) {
@@ -2784,7 +2801,7 @@
0x03, tx_fs_rate);
}
}
- if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+ if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(codec,
@@ -2830,7 +2847,7 @@
0xE0, rx_fs_rate);
}
}
- if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+ if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_update_bits(codec,
@@ -2945,7 +2962,7 @@
static int tabla_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct tabla *tabla;
+ struct wcd9xxx *tabla;
struct snd_soc_codec *codec = w->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
u32 j = 0;
@@ -2953,7 +2970,7 @@
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
/* Execute the callback only if interface type is slimbus */
- if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+ if (tabla_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
return 0;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@@ -2967,10 +2984,10 @@
}
}
if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
- ret = tabla_cfg_slim_sch_rx(tabla,
- tabla_p->dai[j].ch_num,
- tabla_p->dai[j].ch_tot,
- tabla_p->dai[j].rate);
+ ret = wcd9xxx_cfg_slim_sch_rx(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ tabla_p->dai[j].rate);
break;
case SND_SOC_DAPM_POST_PMD:
for (j = 0; j < ARRAY_SIZE(tabla_dai); j++) {
@@ -2983,12 +3000,12 @@
}
}
if (!tabla_p->dai[j].ch_act) {
- ret = tabla_close_slim_sch_rx(tabla,
+ ret = wcd9xxx_close_slim_sch_rx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
- tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot));
tabla_p->dai[j].ch_tot = 0;
}
}
@@ -2998,7 +3015,7 @@
static int tabla_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct tabla *tabla;
+ struct wcd9xxx *tabla;
struct snd_soc_codec *codec = w->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
/* index to the DAI ID, for now hardcoding */
@@ -3009,7 +3026,7 @@
tabla = codec->control_data;
/* Execute the callback only if interface type is slimbus */
- if (tabla_p->intf_type != TABLA_INTERFACE_TYPE_SLIMBUS)
+ if (tabla_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
return 0;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
@@ -3024,7 +3041,7 @@
}
}
if (tabla_p->dai[j].ch_act == tabla_p->dai[j].ch_tot)
- ret = tabla_cfg_slim_sch_tx(tabla,
+ ret = wcd9xxx_cfg_slim_sch_tx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot,
tabla_p->dai[j].rate);
@@ -3041,12 +3058,12 @@
}
}
if (!tabla_p->dai[j].ch_act) {
- ret = tabla_close_slim_sch_tx(tabla,
+ ret = wcd9xxx_close_slim_sch_tx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
- tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot));
tabla_p->dai[j].ch_tot = 0;
}
}
@@ -3584,7 +3601,7 @@
snd_soc_update_bits(codec, tabla->reg_addr.micb_4_mbhc, 0x3,
tabla->micbias);
- tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+ wcd9xxx_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
return 0;
}
@@ -3655,10 +3672,10 @@
if (tabla->button_jack) {
bias_value = tabla_codec_read_sta_result(tabla->codec);
sta_mv = tabla_codec_sta_dce_v(tabla->codec, 0,
- bias_value);
+ bias_value);
bias_value = tabla_codec_read_dce_result(tabla->codec);
dce_mv = tabla_codec_sta_dce_v(tabla->codec, 1,
- bias_value);
+ bias_value);
pr_debug("%s: Reporting long button press event"
" STA: %d, DCE: %d\n", __func__,
sta_mv, dce_mv);
@@ -3670,7 +3687,6 @@
pr_err("%s: Bad tabla private data\n", __func__);
}
- tabla_unlock_sleep(core);
}
void tabla_mbhc_cal(struct snd_soc_codec *codec)
@@ -3850,7 +3866,7 @@
struct tabla_mbhc_btn_detect_cfg *btn_det;
int n;
u8 *n_cic, *gain;
- struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+ struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
tabla = snd_soc_codec_get_drvdata(codec);
generic = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration);
@@ -3998,7 +4014,7 @@
if (mclk_rate != TABLA_MCLK_RATE_12288KHZ) {
if (mclk_rate == TABLA_MCLK_RATE_9600KHZ)
pr_err("Error: clock rate %dHz is not yet supported\n",
- mclk_rate);
+ mclk_rate);
else
pr_err("Error: unsupported clock rate %d\n", mclk_rate);
return -EINVAL;
@@ -4037,9 +4053,9 @@
if (!IS_ERR_VALUE(rc)) {
snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
0x10);
- tabla_enable_irq(codec->control_data,
+ wcd9xxx_enable_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPL_FAULT);
- tabla_enable_irq(codec->control_data,
+ wcd9xxx_enable_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPR_FAULT);
}
@@ -4057,7 +4073,7 @@
btn_det = TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
v_btn_low = tabla_mbhc_cal_btn_det_mp(btn_det, TABLA_BTN_DET_V_BTN_LOW);
v_btn_high = tabla_mbhc_cal_btn_det_mp(btn_det,
- TABLA_BTN_DET_V_BTN_HIGH);
+ TABLA_BTN_DET_V_BTN_HIGH);
for (i = 0; i < btn_det->num_btn; i++) {
if ((v_btn_low[i] <= bias_mv) && (v_btn_high[i] >= bias_mv)) {
btn = i;
@@ -4115,10 +4131,10 @@
TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
short btnmeas[d->n_btn_meas + 1];
struct snd_soc_codec *codec = priv->codec;
- struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
+ struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
bias_value_dce = tabla_codec_read_dce_result(codec);
bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
@@ -4164,12 +4180,12 @@
/* XXX: assuming button 0 has the lowest micbias voltage */
if (btn == 0) {
- tabla_lock_sleep(core);
+ wcd9xxx_lock_sleep(core);
if (schedule_delayed_work(&priv->btn0_dwork,
msecs_to_jiffies(400)) == 0) {
WARN(1, "Button pressed twice without release"
"event\n");
- tabla_unlock_sleep(core);
+ wcd9xxx_unlock_sleep(core);
}
} else {
pr_debug("%s: Reporting short button %d(0x%x) press\n",
@@ -4191,10 +4207,10 @@
short mb_v;
struct tabla_priv *priv = data;
struct snd_soc_codec *codec = priv->codec;
- struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
+ struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
pr_debug("%s: enter\n", __func__);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
if (priv->buttons_pressed & SND_JACK_BTN_0) {
ret = cancel_delayed_work(&priv->btn0_dwork);
@@ -4208,7 +4224,7 @@
} else {
/* if scheduled btn0_dwork is canceled from here,
* we have to unlock from here instead btn0_work */
- tabla_unlock_sleep(core);
+ wcd9xxx_unlock_sleep(core);
mb_v = tabla_codec_sta_dce(codec, 0);
pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
__func__, mb_v,
@@ -4304,7 +4320,7 @@
snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
0x10);
} else {
- tabla_disable_irq(codec->control_data,
+ wcd9xxx_disable_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPL_FAULT);
tabla->hphlocp_cnt = 0;
tabla->hph_status |= SND_JACK_OC_HPHL;
@@ -4337,7 +4353,7 @@
snd_soc_update_bits(codec, TABLA_A_RX_HPH_OCP_CTL, 0x10,
0x10);
} else {
- tabla_disable_irq(codec->control_data,
+ wcd9xxx_disable_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPR_FAULT);
tabla->hphrocp_cnt = 0;
tabla->hph_status |= SND_JACK_OC_HPHR;
@@ -4357,26 +4373,26 @@
static void tabla_sync_hph_state(struct tabla_priv *tabla)
{
if (test_and_clear_bit(TABLA_HPHR_PA_OFF_ACK,
- &tabla->hph_pa_dac_state)) {
+ &tabla->hph_pa_dac_state)) {
pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x10,
1 << 4);
}
if (test_and_clear_bit(TABLA_HPHL_PA_OFF_ACK,
- &tabla->hph_pa_dac_state)) {
+ &tabla->hph_pa_dac_state)) {
pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_CNP_EN, 0x20,
1 << 5);
}
if (test_and_clear_bit(TABLA_HPHR_DAC_OFF_ACK,
- &tabla->hph_pa_dac_state)) {
+ &tabla->hph_pa_dac_state)) {
pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_R_DAC_CTL,
0xC0, 0xC0);
}
if (test_and_clear_bit(TABLA_HPHL_DAC_OFF_ACK,
- &tabla->hph_pa_dac_state)) {
+ &tabla->hph_pa_dac_state)) {
pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
snd_soc_update_bits(tabla->codec, TABLA_A_RX_HPH_L_DAC_CTL,
0xC0, 0xC0);
@@ -4395,7 +4411,7 @@
int mic_mv;
pr_debug("%s: enter\n", __func__);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
@@ -4406,7 +4422,7 @@
if (priv->mbhc_fake_ins_start &&
time_after(jiffies, priv->mbhc_fake_ins_start +
- msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
+ msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
pr_debug("%s: fake context interrupt, reset insertion\n",
__func__);
priv->mbhc_fake_ins_start = 0;
@@ -4482,8 +4498,8 @@
0),
mb_v, mic_mv);
if (time_after(jiffies,
- priv->mbhc_fake_ins_start +
- msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
+ priv->mbhc_fake_ins_start +
+ msecs_to_jiffies(TABLA_FAKE_INS_THRESHOLD_MS))) {
/* Disable HPH trigger and enable MIC line trigger */
snd_soc_update_bits(codec, TABLA_A_MBHC_HPH, 0x12,
0x00);
@@ -4509,7 +4525,8 @@
}
/* Setup for insertion detection */
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x2, 0);
- tabla_enable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+ wcd9xxx_enable_irq(codec->control_data,
+ TABLA_IRQ_MBHC_INSERTION);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
} else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
@@ -4559,9 +4576,9 @@
int min_us = TABLA_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
pr_debug("%s: enter, removal interrupt\n", __func__);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
usleep_range(generic->t_shutdown_plug_rem,
generic->t_shutdown_plug_rem);
@@ -4611,11 +4628,11 @@
int i, j;
u8 val;
- for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
- slimbus_value = tabla_interface_reg_read(codec->control_data,
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+ slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
- val = tabla_interface_reg_read(codec->control_data,
+ val = wcd9xxx_interface_reg_read(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
if (val & 0x1)
pr_err_ratelimited("overflow error on port %x,"
@@ -4624,7 +4641,7 @@
pr_err_ratelimited("underflow error on port %x,"
" value %x\n", i*8 + j, val);
}
- tabla_interface_reg_write(codec->control_data,
+ wcd9xxx_interface_reg_write(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
}
@@ -4635,7 +4652,7 @@
static int tabla_handle_pdata(struct tabla_priv *tabla)
{
struct snd_soc_codec *codec = tabla->codec;
- struct tabla_pdata *pdata = tabla->pdata;
+ struct wcd9xxx_pdata *pdata = tabla->pdata;
int k1, k2, k3, rc = 0;
u8 leg_mode = pdata->amic_settings.legacy_mode;
u8 txfe_bypass = pdata->amic_settings.txfe_enable;
@@ -4802,7 +4819,7 @@
static void tabla_update_reg_defaults(struct snd_soc_codec *codec)
{
u32 i;
- struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+ struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
for (i = 0; i < ARRAY_SIZE(tabla_1_1_reg_defaults); i++)
snd_soc_write(codec, tabla_1_1_reg_defaults[i].reg,
@@ -4894,7 +4911,7 @@
static void tabla_codec_init_reg(struct snd_soc_codec *codec)
{
u32 i;
- struct tabla *tabla_core = dev_get_drvdata(codec->dev->parent);
+ struct wcd9xxx *tabla_core = dev_get_drvdata(codec->dev->parent);
for (i = 0; i < ARRAY_SIZE(tabla_codec_reg_init_val); i++)
snd_soc_update_bits(codec, tabla_codec_reg_init_val[i].reg,
@@ -4918,7 +4935,7 @@
static void tabla_update_reg_address(struct tabla_priv *priv)
{
- struct tabla *tabla_core = dev_get_drvdata(priv->codec->dev->parent);
+ struct wcd9xxx *tabla_core = dev_get_drvdata(priv->codec->dev->parent);
struct tabla_reg_address *reg_addr = &priv->reg_addr;
if (TABLA_IS_1_X(tabla_core->version)) {
@@ -4934,7 +4951,7 @@
static int tabla_codec_probe(struct snd_soc_codec *codec)
{
- struct tabla *control;
+ struct wcd9xxx *control;
struct tabla_priv *tabla;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
@@ -4973,7 +4990,7 @@
tabla->no_mic_headset_override = false;
tabla->codec = codec;
tabla->pdata = dev_get_platdata(codec->dev->parent);
- tabla->intf_type = tabla_get_intf_type();
+ tabla->intf_type = wcd9xxx_get_intf_type();
tabla_update_reg_address(tabla);
tabla_update_reg_defaults(codec);
@@ -5002,7 +5019,7 @@
snd_soc_dapm_new_controls(dapm, tabla_2_higher_dapm_widgets,
ARRAY_SIZE(tabla_2_higher_dapm_widgets));
- if (tabla->intf_type == TABLA_INTERFACE_TYPE_I2C) {
+ if (tabla->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
snd_soc_dapm_new_controls(dapm, tabla_dapm_i2s_widgets,
ARRAY_SIZE(tabla_dapm_i2s_widgets));
snd_soc_dapm_add_routes(dapm, audio_i2s_map,
@@ -5018,49 +5035,49 @@
ARRAY_SIZE(tabla_2_x_lineout_2_to_4_map));
} else {
pr_err("%s : ERROR. Unsupported Tabla version 0x%2x\n",
- __func__, control->version);
+ __func__, control->version);
goto err_pdata;
}
snd_soc_dapm_sync(dapm);
- ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
+ ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION,
tabla_hs_insert_irq, "Headset insert detect", tabla);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
TABLA_IRQ_MBHC_INSERTION);
goto err_insert_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
- ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
+ ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL,
tabla_hs_remove_irq, "Headset remove detect", tabla);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
TABLA_IRQ_MBHC_REMOVAL);
goto err_remove_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
- ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
+ ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL,
tabla_dce_handler, "DC Estimation detect", tabla);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
TABLA_IRQ_MBHC_POTENTIAL);
goto err_potential_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
- ret = tabla_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
+ ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE,
tabla_release_handler, "Button Release detect", tabla);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
TABLA_IRQ_MBHC_RELEASE);
goto err_release_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
- ret = tabla_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
+ ret = wcd9xxx_request_irq(codec->control_data, TABLA_IRQ_SLIMBUS,
tabla_slimbus_irq, "SLIMBUS Slave", tabla);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
@@ -5068,11 +5085,11 @@
goto err_slimbus_irq;
}
- for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++)
- tabla_interface_reg_write(codec->control_data,
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+ wcd9xxx_interface_reg_write(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
- ret = tabla_request_irq(codec->control_data,
+ ret = wcd9xxx_request_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla_hphl_ocp_irq,
"HPH_L OCP detect", tabla);
if (ret) {
@@ -5080,9 +5097,9 @@
TABLA_IRQ_HPH_PA_OCPL_FAULT);
goto err_hphl_ocp_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT);
- ret = tabla_request_irq(codec->control_data,
+ ret = wcd9xxx_request_irq(codec->control_data,
TABLA_IRQ_HPH_PA_OCPR_FAULT, tabla_hphr_ocp_irq,
"HPH_R OCP detect", tabla);
if (ret) {
@@ -5090,7 +5107,7 @@
TABLA_IRQ_HPH_PA_OCPR_FAULT);
goto err_hphr_ocp_irq;
}
- tabla_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
+ wcd9xxx_disable_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPR_FAULT);
for (i = 0; i < ARRAY_SIZE(tabla_dai); i++) {
switch (tabla_dai[i].id) {
case AIF1_PB:
@@ -5116,17 +5133,18 @@
return ret;
err_hphr_ocp_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
+ wcd9xxx_free_irq(codec->control_data,
+ TABLA_IRQ_HPH_PA_OCPL_FAULT, tabla);
err_hphl_ocp_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
err_slimbus_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
err_release_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
err_potential_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
err_remove_irq:
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
err_insert_irq:
err_pdata:
kfree(tabla);
@@ -5136,11 +5154,11 @@
{
int i;
struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
- tabla_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
- tabla_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_SLIMBUS, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL, tabla);
+ wcd9xxx_free_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION, tabla);
tabla_codec_disable_clock_block(codec);
tabla_codec_enable_bandgap(codec, TABLA_BANDGAP_OFF);
if (tabla->mbhc_fw)
@@ -5227,10 +5245,10 @@
S_IFREG | S_IRUGO, NULL, (void *) "TRRS", &codec_debug_ops);
#endif
- if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_SLIMBUS)
+ if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
tabla_dai, ARRAY_SIZE(tabla_dai));
- else if (tabla_get_intf_type() == TABLA_INTERFACE_TYPE_I2C)
+ else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tabla,
tabla_i2s_dai, ARRAY_SIZE(tabla_i2s_dai));
return ret;
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 9c430b9..d1d0c17 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -11,7 +11,7 @@
*/
#include <sound/soc.h>
#include <sound/jack.h>
-#include <linux/mfd/wcd9310/wcd9310-slimslave.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
#define TABLA_NUM_REGISTERS 0x400
#define TABLA_MAX_REGISTER (TABLA_NUM_REGISTERS-1)
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 1ed5f74..3a2687e 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -126,6 +126,7 @@
select SND_SOC_QDSP6
select SND_SOC_MSM_STUB
select SND_SOC_WCD9310
+ select SND_SOC_WCD9304
select SND_SOC_MSM_HOSTLESS_PCM
select SND_SOC_MSM_QDSP6_HDMI_AUDIO
default n
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 6f2d651..2aef4bd 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -62,7 +62,7 @@
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
-snd-soc-msm8960-objs := msm8960.o apq8064.o
+snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o
obj-$(CONFIG_SND_SOC_MSM8960) += snd-soc-msm8960.o
# Generic MSM drivers
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index bcf6784..ff50ba6 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -727,6 +727,13 @@
return ret;
}
+static int msm_stubrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+ rtd->pmdown_time = 0;
+
+ return 0;
+}
+
static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
{
int err;
@@ -1253,6 +1260,7 @@
.no_pcm = 1,
/* .be_id = do not care */
.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .init = &msm_stubrx_init,
.ops = &msm_be_ops,
},
{
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index f0f17a9..7d99322 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -179,6 +179,7 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct compr_audio *compr = runtime->private_data;
struct msm_audio *prtd = &compr->prtd;
+ struct asm_aac_cfg aac_cfg;
int ret;
pr_debug("%s\n", __func__);
@@ -189,14 +190,33 @@
prtd->samp_rate = runtime->rate;
prtd->channel_mode = runtime->channels;
prtd->out_head = 0;
+ atomic_set(&prtd->out_count, runtime->periods);
+
if (prtd->enabled)
return 0;
- ret = q6asm_media_format_block(prtd->audio_client, compr->codec);
- if (ret < 0)
- pr_info("%s: CMD Format block failed\n", __func__);
-
- atomic_set(&prtd->out_count, runtime->periods);
+ switch (compr->info.codec_param.codec.id) {
+ case SND_AUDIOCODEC_MP3:
+ ret = q6asm_media_format_block(prtd->audio_client,
+ compr->codec);
+ if (ret < 0)
+ pr_info("%s: CMD Format block failed\n", __func__);
+ break;
+ case SND_AUDIOCODEC_AAC:
+ pr_debug("SND_AUDIOCODEC_AAC\n");
+ memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
+ aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
+ aac_cfg.format = 0x03;
+ aac_cfg.ch_cfg = runtime->channels;
+ aac_cfg.sample_rate = runtime->rate;
+ ret = q6asm_media_format_block_aac(prtd->audio_client,
+ &aac_cfg);
+ if (ret < 0)
+ pr_err("%s: CMD Format block failed\n", __func__);
+ break;
+ default:
+ return -EINVAL;
+ }
prtd->enabled = 1;
prtd->cmd_ack = 0;
@@ -250,6 +270,7 @@
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
+ compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
/* Add new codecs here */
}
@@ -504,6 +525,10 @@
pr_debug("SND_AUDIOCODEC_MP3\n");
compr->codec = FORMAT_MP3;
break;
+ case SND_AUDIOCODEC_AAC:
+ pr_debug("SND_AUDIOCODEC_AAC\n");
+ compr->codec = FORMAT_MPEG4_AAC;
+ break;
default:
pr_debug("FORMAT_LINEAR_PCM\n");
compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index 6907ded..3333344 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -14,10 +14,8 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <linux/mfd/wcd9310/core.h>
#include <linux/bitops.h>
#include <linux/slab.h>
-#include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -25,7 +23,6 @@
#include <sound/q6afe.h>
#include <sound/q6adm.h>
#include <sound/msm-dai-q6.h>
-#include <mach/clk.h>
#include <mach/msm_hdmi_audio.h>
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 070dc7b..0430f7b 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -14,7 +14,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <linux/mfd/wcd9310/core.h>
+#include <linux/mfd/wcd9xxx/core.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/clk.h>
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index b01c22c..14da1ba 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -254,6 +254,23 @@
mutex_unlock(&routing_lock);
}
+/* Check if FE/BE route is set */
+static bool msm_pcm_routing_route_is_set(u16 be_id, u16 fe_id)
+{
+ bool rc = false;
+
+ if (be_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+ /* recheck FE ID in the mixer control defined in this file */
+ pr_err("%s: bad MM ID\n", __func__);
+ return rc;
+ }
+
+ if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions))
+ rc = true;
+
+ return rc;
+}
+
static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
{
int session_type, path_type;
@@ -350,10 +367,12 @@
(struct soc_mixer_control *)kcontrol->private_value;
- if (ucontrol->value.integer.value[0]) {
+ if (ucontrol->value.integer.value[0] &&
+ msm_pcm_routing_route_is_set(mc->reg, mc->shift) == false) {
msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
- } else {
+ } else if (!ucontrol->value.integer.value[0] &&
+ msm_pcm_routing_route_is_set(mc->reg, mc->shift) == true) {
msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
}
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index 471284b..5a0f27a 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -217,6 +217,26 @@
return 0;
}
+static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ voc_get_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME));
+ return 0;
+}
+
+static int msm_voice_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_rx_device_mute(voc_get_session_id(VOICE_SESSION_NAME), mute);
+
+ return 0;
+}
+
static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
static const struct soc_enum msm_tty_mode_enum[] = {
SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -308,6 +328,9 @@
}
static struct snd_kcontrol_new msm_voice_controls[] = {
+ SOC_SINGLE_EXT("Voice Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice_rx_device_mute_get,
+ msm_voice_rx_device_mute_put),
SOC_SINGLE_EXT("Voice Tx Mute", SND_SOC_NOPM, 0, 1, 0,
msm_voice_mute_get, msm_voice_mute_put),
SOC_SINGLE_EXT("Voice Rx Volume", SND_SOC_NOPM, 0, 5, 0,
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 56b4cf5..2301472 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -108,6 +108,7 @@
uint32_t mode;
uint32_t rate_type;
uint32_t rate;
+ uint32_t dtx_mode;
uint8_t capture_start;
uint8_t playback_start;
@@ -200,6 +201,31 @@
return 0;
}
+static int msm_voip_dtx_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ voip_info.dtx_mode = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: dtx: %d\n", __func__, voip_info.dtx_mode);
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+static int msm_voip_dtx_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ mutex_lock(&voip_info.lock);
+
+ ucontrol->value.integer.value[0] = voip_info.dtx_mode;
+
+ mutex_unlock(&voip_info.lock);
+
+ return 0;
+}
+
static struct snd_kcontrol_new msm_voip_controls[] = {
SOC_SINGLE_EXT("Voip Tx Mute", SND_SOC_NOPM, 0, 1, 0,
msm_voip_mute_get, msm_voip_mute_put),
@@ -208,6 +234,8 @@
SOC_SINGLE_MULTI_EXT("Voip Mode Rate Config", SND_SOC_NOPM, 0, 23850,
0, 2, msm_voip_mode_rate_config_get,
msm_voip_mode_rate_config_put),
+ SOC_SINGLE_EXT("Voip Dtx Mode", SND_SOC_NOPM, 0, 1, 0,
+ msm_voip_dtx_mode_get, msm_voip_dtx_mode_put),
};
static int msm_pcm_voip_probe(struct snd_soc_platform *platform)
@@ -713,11 +741,13 @@
if ((prtd->play_samp_rate == 8000) &&
(prtd->cap_samp_rate == 8000))
voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_NB);
+ VSS_NETWORK_ID_VOIP_NB,
+ voip_info.dtx_mode);
else if ((prtd->play_samp_rate == 16000) &&
(prtd->cap_samp_rate == 16000))
voc_config_vocoder(media_type, rate_type,
- VSS_NETWORK_ID_VOIP_WB);
+ VSS_NETWORK_ID_VOIP_WB,
+ voip_info.dtx_mode);
else {
pr_debug("%s: Invalid rate playback %d, capture %d\n",
__func__, prtd->play_samp_rate,
diff --git a/sound/soc/msm/msm-pcm.c b/sound/soc/msm/msm-pcm.c
index bea528f..ea31985 100644
--- a/sound/soc/msm/msm-pcm.c
+++ b/sound/soc/msm/msm-pcm.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -45,8 +45,6 @@
msm_adsp_write(prtd->audrec, QDSP_uPAudRecCmdQueue, cmd, len)
int intcnt;
-static int audio_dsp_send_buffer(struct msm_audio *prtd,
- unsigned idx, unsigned len);
struct audio_frame {
uint16_t count_low;
@@ -139,12 +137,15 @@
if (prtd->ops->playback)
prtd->ops->playback(prtd);
+ if (prtd->mmap_flag)
+ break;
+
spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
if (prtd->running) {
prtd->out[idx].used = 0;
frame = prtd->out + prtd->out_tail;
if (frame->used) {
- audio_dsp_send_buffer(prtd,
+ alsa_dsp_send_buffer(prtd,
prtd->out_tail,
frame->used);
prtd->out_tail ^= 1;
@@ -414,7 +415,7 @@
spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
frame = prtd->out + prtd->out_tail;
if (frame->used && prtd->out_needed) {
- audio_dsp_send_buffer(prtd, prtd->out_tail,
+ alsa_dsp_send_buffer(prtd, prtd->out_tail,
frame->used);
prtd->out_tail ^= 1;
prtd->out_needed--;
@@ -583,7 +584,7 @@
}
EXPORT_SYMBOL(alsa_buffer_read);
-static int audio_dsp_send_buffer(struct msm_audio *prtd,
+int alsa_dsp_send_buffer(struct msm_audio *prtd,
unsigned idx, unsigned len)
{
audpp_cmd_pcm_intf_send_buffer cmd;
diff --git a/sound/soc/msm/msm-pcm.h b/sound/soc/msm/msm-pcm.h
index e7ddd30..6e1325b 100644
--- a/sound/soc/msm/msm-pcm.h
+++ b/sound/soc/msm/msm-pcm.h
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -173,11 +173,15 @@
int running;
int stopped; /* set when stopped, cleared on flush */
int eos_ack;
+ int mmap_flag;
+ int period;
};
/* platform data */
+extern int alsa_dsp_send_buffer(struct msm_audio *prtd,
+ unsigned idx, unsigned len);
extern int audio_dsp_out_enable(struct msm_audio *prtd, int yes);
extern struct snd_soc_platform_driver msm_soc_platform;
diff --git a/sound/soc/msm/msm7k-pcm.c b/sound/soc/msm/msm7k-pcm.c
index 1f36e3b..6ef924f 100644
--- a/sound/soc/msm/msm7k-pcm.c
+++ b/sound/soc/msm/msm7k-pcm.c
@@ -1,6 +1,6 @@
/* linux/sound/soc/msm/msm7k-pcm.c
*
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2012 Code Aurora Forum. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -109,18 +109,20 @@
}
static struct snd_pcm_hardware msm_pcm_playback_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED,
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED,
.formats = USE_FORMATS,
.rates = USE_RATE,
.rate_min = USE_RATE_MIN,
.rate_max = USE_RATE_MAX,
.channels_min = USE_CHANNELS_MIN,
.channels_max = USE_CHANNELS_MAX,
- .buffer_bytes_max = MAX_BUFFER_PLAYBACK_SIZE,
- .period_bytes_min = 64,
- .period_bytes_max = MAX_PERIOD_SIZE,
- .periods_min = USE_PERIODS_MIN,
- .periods_max = USE_PERIODS_MAX,
+ .buffer_bytes_max = 4800 * 2,
+ .period_bytes_min = 4800,
+ .period_bytes_max = 4800,
+ .periods_min = 2,
+ .periods_max = 2,
.fifo_size = 0,
};
@@ -151,10 +153,36 @@
.mask = 0,
};
+static void msm_pcm_enqueue_data(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ unsigned int period_size;
+
+ pr_debug("prtd->out_tail =%d mmap_flag=%d\n",
+ prtd->out_tail, prtd->mmap_flag);
+ period_size = snd_pcm_lib_period_bytes(substream);
+ alsa_dsp_send_buffer(prtd, prtd->out_tail, period_size);
+ prtd->out_tail ^= 1;
+ ++copy_count;
+ prtd->period++;
+ if (unlikely(prtd->period >= runtime->periods))
+ prtd->period = 0;
+
+}
+
static void playback_event_handler(void *data)
{
struct msm_audio *prtd = data;
snd_pcm_period_elapsed(prtd->playback_substream);
+ if (prtd->mmap_flag) {
+ if (prtd->dir == SNDRV_PCM_STREAM_CAPTURE)
+ return;
+ if (!prtd->stopped)
+ msm_pcm_enqueue_data(prtd->playback_substream);
+ else
+ prtd->out_needed++;
+ }
}
static void capture_event_handler(void *data)
@@ -177,6 +205,26 @@
prtd->out_sample_rate = runtime->rate;
prtd->out_channel_mode = runtime->channels;
+ if (prtd->enabled | !(prtd->mmap_flag))
+ return 0;
+
+ prtd->data = substream->dma_buffer.area;
+ prtd->phys = substream->dma_buffer.addr;
+ prtd->out[0].data = prtd->data + 0;
+ prtd->out[0].addr = prtd->phys + 0;
+ prtd->out[0].size = BUFSZ;
+ prtd->out[1].data = prtd->data + BUFSZ;
+ prtd->out[1].addr = prtd->phys + BUFSZ;
+ prtd->out[1].size = BUFSZ;
+
+ prtd->out[0].used = prtd->pcm_count;
+ prtd->out[1].used = prtd->pcm_count;
+
+ mutex_lock(&the_locks.lock);
+ alsa_audio_configure(prtd);
+ mutex_unlock(&the_locks.lock);
+
+
return 0;
}
@@ -231,16 +279,55 @@
static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ unsigned long flag = 0;
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ || !prtd->mmap_flag)
+ break;
+ if (!prtd->out_needed) {
+ prtd->stopped = 0;
+ break;
+ }
+ spin_lock_irqsave(&the_locks.write_dsp_lock, flag);
+ if (prtd->running == 1) {
+ if (prtd->stopped == 1) {
+ prtd->stopped = 0;
+ prtd->period = 0;
+ if (prtd->pcm_irq_pos == 0) {
+ prtd->out_tail = 0;
+ msm_pcm_enqueue_data(
+ prtd->playback_substream);
+ prtd->out_needed--;
+ } else {
+ prtd->out_tail = 1;
+ msm_pcm_enqueue_data(
+ prtd->playback_substream);
+ prtd->out_needed--;
+ }
+ if (prtd->out_needed) {
+ prtd->out_tail ^= 1;
+ msm_pcm_enqueue_data(
+ prtd->playback_substream);
+ prtd->out_needed--;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&the_locks.write_dsp_lock, flag);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ || !prtd->mmap_flag)
+ break;
+ prtd->stopped = 1;
break;
default:
ret = -EINVAL;
@@ -376,7 +463,6 @@
fbytes = frames_to_bytes(runtime, frames);
rc = alsa_send_buffer(prtd, buf, fbytes, NULL);
++copy_count;
- prtd->pcm_buf_pos += fbytes;
if (copy_count == 1) {
mutex_lock(&the_locks.lock);
alsa_audio_configure(prtd);
@@ -469,10 +555,27 @@
runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
}
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
return 0;
}
+int msm_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ prtd->out_head = 0; /* point to First buffer on startup */
+ prtd->mmap_flag = 1;
+ runtime->dma_bytes = snd_pcm_lib_period_bytes(substream)*2;
+ dma_mmap_coherent(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+ return 0;
+}
+
static struct snd_pcm_ops msm_pcm_ops = {
.open = msm_pcm_open,
.copy = msm_pcm_copy,
@@ -482,6 +585,7 @@
.prepare = msm_pcm_prepare,
.trigger = msm_pcm_trigger,
.pointer = msm_pcm_pointer,
+ .mmap = msm_pcm_mmap,
};
static int pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
new file mode 100644
index 0000000..a081253
--- /dev/null
+++ b/sound/soc/msm/msm8930.c
@@ -0,0 +1,1083 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dsp.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <asm/mach-types.h>
+#include <mach/socinfo.h>
+#include "msm-pcm-routing.h"
+#include "../codecs/wcd9304.h"
+
+/* 8930 machine driver */
+
+#define PM8921_GPIO_BASE NR_GPIO_IRQS
+#define PM8921_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8921_GPIO_BASE)
+
+#define MSM8930_SPK_ON 1
+#define MSM8930_SPK_OFF 0
+
+#define msm8930_SLIM_0_RX_MAX_CHANNELS 2
+#define msm8930_SLIM_0_TX_MAX_CHANNELS 4
+
+#define BTSCO_RATE_8KHZ 8000
+#define BTSCO_RATE_16KHZ 16000
+
+#define BOTTOM_SPK_AMP_POS 0x1
+#define BOTTOM_SPK_AMP_NEG 0x2
+#define TOP_SPK_AMP_POS 0x4
+#define TOP_SPK_AMP_NEG 0x8
+
+#define GPIO_AUX_PCM_DOUT 63
+#define GPIO_AUX_PCM_DIN 64
+#define GPIO_AUX_PCM_SYNC 65
+#define GPIO_AUX_PCM_CLK 66
+
+#define SITAR_EXT_CLK_RATE 12288000
+
+#define SITAR_MBHC_DEF_BUTTONS 3
+#define SITAR_MBHC_DEF_RLOADS 5
+
+static int msm8930_spk_control;
+static int msm8930_slim_0_rx_ch = 1;
+static int msm8930_slim_0_tx_ch = 1;
+
+static int msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm8930_btsco_ch = 1;
+
+static struct clk *codec_clk;
+static int clk_users;
+
+static int msm8930_headset_gpios_configured;
+
+static struct snd_soc_jack hs_jack;
+static struct snd_soc_jack button_jack;
+
+struct sitar_mbhc_calibration sitar_calib = {
+ .bias = SITAR_MICBIAS2,
+ .tldoh = 100,
+ .bg_fast_settle = 100,
+ .mic_current = SITAR_PID_MIC_5_UA,
+ .mic_pid = 100,
+ .hph_current = SITAR_PID_MIC_5_UA,
+ .setup_plug_removal_delay = 1000000,
+ .shutdown_plug_removal = 100000,
+};
+
+static void msm8930_ext_control(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
+ if (msm8930_spk_control == MSM8930_SPK_ON) {
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
+ snd_soc_dapm_disable_pin(dapm, "Ext Spk Right Pos");
+ }
+
+ snd_soc_dapm_sync(dapm);
+}
+
+static int msm8930_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
+ ucontrol->value.integer.value[0] = msm8930_spk_control;
+ return 0;
+}
+static int msm8930_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s()\n", __func__);
+ if (msm8930_spk_control == ucontrol->value.integer.value[0])
+ return 0;
+
+ msm8930_spk_control = ucontrol->value.integer.value[0];
+ msm8930_ext_control(codec);
+ return 1;
+}
+
+static int msm8930_spkramp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
+ /* TODO: add external speaker power amps support */
+ return 0;
+}
+int msm8930_enable_codec_ext_clk(
+ struct snd_soc_codec *codec, int enable)
+{
+ pr_debug("%s: enable = %d\n", __func__, enable);
+ if (enable) {
+ clk_users++;
+ pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+ if (clk_users != 1)
+ return 0;
+
+ if (codec_clk) {
+ clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
+ clk_enable(codec_clk);
+ sitar_mclk_enable(codec, 1);
+ } else {
+ pr_err("%s: Error setting Tabla MCLK\n", __func__);
+ clk_users--;
+ return -EINVAL;
+ }
+ } else {
+ pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+ if (clk_users == 0)
+ return 0;
+ clk_users--;
+ if (!clk_users) {
+ pr_debug("%s: disabling MCLK. clk_users = %d\n",
+ __func__, clk_users);
+ clk_disable(codec_clk);
+ sitar_mclk_enable(codec, 0);
+ }
+ }
+ return 0;
+}
+
+static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return msm8930_enable_codec_ext_clk(w->codec, 1);
+ case SND_SOC_DAPM_POST_PMD:
+ return msm8930_enable_codec_ext_clk(w->codec, 0);
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget msm8930_dapm_widgets[] = {
+
+ SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
+ msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
+ SND_SOC_DAPM_SPK("Ext Spk Right Pos", msm8930_spkramp_event),
+
+ SND_SOC_DAPM_MIC("Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+ SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+
+ SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic2", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic3", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic4", NULL),
+
+};
+
+static const struct snd_soc_dapm_route common_audio_map[] = {
+
+ {"RX_BIAS", NULL, "MCLK"},
+ {"LDO_H", NULL, "MCLK"},
+
+ {"MIC BIAS1 Internal1", NULL, "MCLK"},
+ {"MIC BIAS2 Internal1", NULL, "MCLK"},
+
+ /* Speaker path */
+ {"Ext Spk Left Pos", NULL, "LINEOUT1"},
+ {"Ext Spk Right Pos", NULL, "LINEOUT2"},
+
+
+ {"AMIC2", NULL, "MIC BIAS2 Internal1"},
+ {"MIC BIAS2 Internal1", NULL, "Headset Mic"},
+
+ /* Microphone path */
+ {"AMIC1", NULL, "MIC BIAS1 Internal1"},
+ {"MIC BIAS1 Internal1", NULL, "Handset Mic"},
+
+ {"HEADPHONE", NULL, "LDO_H"},
+
+ /**
+ * The digital Mic routes are setup considering
+ * fluid as default device.
+ */
+
+ /**
+ * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
+ * Digital Mic GM5 on CDP mainboard.
+ * Conncted to DMIC2 Input on Tabla codec.
+ */
+ {"DMIC1", NULL, "MIC BIAS1 External"},
+ {"MIC BIAS1 External", NULL, "Digital Mic1"},
+
+ /**
+ * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
+ * Digital Mic GM6 on CDP mainboard.
+ * Conncted to DMIC1 Input on Tabla codec.
+ */
+ {"DMIC2", NULL, "MIC BIAS1 External"},
+ {"MIC BIAS1 External", NULL, "Digital Mic2"},
+ /**
+ * Digital Mic3. Back Bottom Digital Mic on Fluid.
+ * Digital Mic GM1 on CDP mainboard.
+ * Conncted to DMIC4 Input on Tabla codec.
+ */
+ {"DMIC3", NULL, "MIC BIAS2 External"},
+ {"MIC BIAS2 External", NULL, "Digital Mic3"},
+
+ /**
+ * Digital Mic4. Back top Digital Mic on Fluid.
+ * Digital Mic GM2 on CDP mainboard.
+ * Conncted to DMIC3 Input on Tabla codec.
+ */
+ {"DMIC4", NULL, "MIC BIAS2 External"},
+ {"MIC BIAS2 External", NULL, "Digital Mic4"},
+
+
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *slim0_rx_ch_text[] = {"One", "Two"};
+static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+
+static const struct soc_enum msm8930_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, spk_function),
+ SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
+ SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+};
+
+static const char *btsco_rate_text[] = {"8000", "16000"};
+static const struct soc_enum msm8930_btsco_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
+};
+
+static int msm8930_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
+ msm8930_slim_0_rx_ch);
+ ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
+ return 0;
+}
+
+static int msm8930_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
+ msm8930_slim_0_rx_ch);
+ return 1;
+}
+
+static int msm8930_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
+ msm8930_slim_0_tx_ch);
+ ucontrol->value.integer.value[0] = msm8930_slim_0_tx_ch - 1;
+ return 0;
+}
+
+static int msm8930_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm8930_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm8930_slim_0_tx_ch = %d\n", __func__,
+ msm8930_slim_0_tx_ch);
+ return 1;
+}
+
+static int msm8930_btsco_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm8930_btsco_rate = %d", __func__, msm8930_btsco_rate);
+ ucontrol->value.integer.value[0] = msm8930_btsco_rate;
+ return 0;
+}
+
+static int msm8930_btsco_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+ break;
+ case 1:
+ msm8930_btsco_rate = BTSCO_RATE_16KHZ;
+ break;
+ default:
+ msm8930_btsco_rate = BTSCO_RATE_8KHZ;
+ break;
+ }
+ pr_debug("%s: msm8930_btsco_rate = %d\n", __func__, msm8930_btsco_rate);
+ return 0;
+}
+
+static const struct snd_kcontrol_new sitar_msm8930_controls[] = {
+ SOC_ENUM_EXT("Speaker Function", msm8930_enum[0], msm8930_get_spk,
+ msm8930_set_spk),
+ SOC_ENUM_EXT("SLIM_0_RX Channels", msm8930_enum[1],
+ msm8930_slim_0_rx_ch_get, msm8930_slim_0_rx_ch_put),
+ SOC_ENUM_EXT("SLIM_0_TX Channels", msm8930_enum[2],
+ msm8930_slim_0_tx_ch_get, msm8930_slim_0_tx_ch_put),
+};
+
+static const struct snd_kcontrol_new int_btsco_rate_mixer_controls[] = {
+ SOC_ENUM_EXT("Internal BTSCO SampleRate", msm8930_btsco_enum[0],
+ msm8930_btsco_rate_get, msm8930_btsco_rate_put),
+};
+
+static int msm8930_btsco_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int err = 0;
+ struct snd_soc_platform *platform = rtd->platform;
+
+ err = snd_soc_add_platform_controls(platform,
+ int_btsco_rate_mixer_controls,
+ ARRAY_SIZE(int_btsco_rate_mixer_controls));
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int msm8930_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+ pr_debug("%s: ch=%d\n", __func__,
+ msm8930_slim_0_rx_ch);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ msm8930_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+ msm8930_slim_0_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+ } else {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ msm8930_slim_0_tx_ch, tx_ch, 0 , 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map\n", __func__);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(codec_dai,
+ msm8930_slim_0_tx_ch, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set codec channel map\n",
+ __func__);
+ goto end;
+ }
+
+ }
+end:
+ return ret;
+}
+
+static int msm8930_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_debug("%s()\n", __func__);
+
+
+ rtd->pmdown_time = 0;
+
+ err = snd_soc_add_controls(codec, sitar_msm8930_controls,
+ ARRAY_SIZE(sitar_msm8930_controls));
+ if (err < 0)
+ return err;
+
+ snd_soc_dapm_new_controls(dapm, msm8930_dapm_widgets,
+ ARRAY_SIZE(msm8930_dapm_widgets));
+
+ snd_soc_dapm_add_routes(dapm, common_audio_map,
+ ARRAY_SIZE(common_audio_map));
+
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
+ snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+
+ snd_soc_dapm_sync(dapm);
+
+ err = snd_soc_jack_new(codec, "Headset Jack",
+ (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
+ &hs_jack);
+ if (err) {
+ pr_err("failed to create new jack\n");
+ return err;
+ }
+
+ err = snd_soc_jack_new(codec, "Button Jack",
+ SND_JACK_BTN_0, &button_jack);
+ if (err) {
+ pr_err("failed to create new jack\n");
+ return err;
+ }
+ codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+ sitar_hs_detect(codec, &hs_jack, &button_jack, &sitar_calib);
+ return 0;
+}
+
+static struct snd_soc_dsp_link lpa_fe_media = {
+ .playback = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+static struct snd_soc_dsp_link fe_media = {
+ .playback = true,
+ .capture = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+static struct snd_soc_dsp_link slimbus0_hl_media = {
+ .playback = true,
+ .capture = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+static struct snd_soc_dsp_link int_fm_hl_media = {
+ .playback = true,
+ .capture = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+/* bi-directional media definition for hostless PCM device */
+static struct snd_soc_dsp_link bidir_hl_media = {
+ .playback = true,
+ .capture = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+static struct snd_soc_dsp_link hdmi_rx_hl = {
+ .playback = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
+static int msm8930_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = msm8930_slim_0_rx_ch;
+
+ return 0;
+}
+
+static int msm8930_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = msm8930_slim_0_tx_ch;
+
+ return 0;
+}
+
+static int msm8930_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+
+ return 0;
+}
+
+static int msm8930_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ return 0;
+}
+
+static int msm8930_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ rate->min = rate->max = msm8930_btsco_rate;
+ channels->min = channels->max = msm8930_btsco_ch;
+
+ return 0;
+}
+static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ /* PCM only supports mono output with 8khz sample rate */
+ rate->min = rate->max = 8000;
+ channels->min = channels->max = 1;
+
+ return 0;
+}
+static int msm8930_aux_pcm_get_gpios(void)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
+ __func__, GPIO_AUX_PCM_DOUT);
+ goto fail_dout;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
+ __func__, GPIO_AUX_PCM_DIN);
+ goto fail_din;
+ }
+
+ ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
+ __func__, GPIO_AUX_PCM_SYNC);
+ goto fail_sync;
+ }
+ ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
+ if (ret < 0) {
+ pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
+ __func__, GPIO_AUX_PCM_CLK);
+ goto fail_clk;
+ }
+
+ return 0;
+
+fail_clk:
+ gpio_free(GPIO_AUX_PCM_SYNC);
+fail_sync:
+ gpio_free(GPIO_AUX_PCM_DIN);
+fail_din:
+ gpio_free(GPIO_AUX_PCM_DOUT);
+fail_dout:
+
+ return ret;
+}
+
+static int msm8930_aux_pcm_free_gpios(void)
+{
+ gpio_free(GPIO_AUX_PCM_DIN);
+ gpio_free(GPIO_AUX_PCM_DOUT);
+ gpio_free(GPIO_AUX_PCM_SYNC);
+ gpio_free(GPIO_AUX_PCM_CLK);
+
+ return 0;
+}
+static int msm8930_startup(struct snd_pcm_substream *substream)
+{
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+ return 0;
+}
+
+static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ ret = msm8930_aux_pcm_get_gpios();
+ if (ret < 0) {
+ pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+
+ pr_debug("%s(): substream = %s\n", __func__, substream->name);
+ msm8930_aux_pcm_free_gpios();
+}
+
+static void msm8930_shutdown(struct snd_pcm_substream *substream)
+{
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+}
+
+static struct snd_soc_ops msm8930_be_ops = {
+ .startup = msm8930_startup,
+ .hw_params = msm8930_hw_params,
+ .shutdown = msm8930_shutdown,
+};
+
+static struct snd_soc_ops msm8930_auxpcm_be_ops = {
+ .startup = msm8930_auxpcm_startup,
+ .shutdown = msm8930_auxpcm_shutdown,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm8930_dai[] = {
+ /* FrontEnd DAI Links */
+ {
+ .name = "MSM8930 Media1",
+ .stream_name = "MultiMedia1",
+ .cpu_dai_name = "MultiMedia1",
+ .platform_name = "msm-pcm-dsp",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ },
+ {
+ .name = "MSM8930 Media2",
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {
+ .name = "Circuit-Switch Voice",
+ .stream_name = "CS-Voice",
+ .cpu_dai_name = "CS-VOICE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_CS_VOICE,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = "MSM VoIP",
+ .stream_name = "VoIP",
+ .cpu_dai_name = "VoIP",
+ .platform_name = "msm-voip-dsp",
+ .dynamic = 1,
+ .dsp_link = &fe_media,
+ .be_id = MSM_FRONTEND_DAI_VOIP,
+ },
+ {
+ .name = "MSM8930 LPA",
+ .stream_name = "LPA",
+ .cpu_dai_name = "MultiMedia3",
+ .platform_name = "msm-pcm-lpa",
+ .dynamic = 1,
+ .dsp_link = &lpa_fe_media,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ },
+ /* Hostless PMC purpose */
+ {
+ .name = "SLIMBUS_0 Hostless",
+ .stream_name = "SLIMBUS_0 Hostless",
+ .cpu_dai_name = "SLIMBUS0_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &slimbus0_hl_media,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* .be_id = do not care */
+ },
+ {
+ .name = "INT_FM Hostless",
+ .stream_name = "INT_FM Hostless",
+ .cpu_dai_name = "INT_FM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &int_fm_hl_media,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* .be_id = do not care */
+ },
+ {
+ .name = "MSM AFE-PCM RX",
+ .stream_name = "AFE-PROXY RX",
+ .cpu_dai_name = "msm-dai-q6.241",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ },
+ {
+ .name = "MSM AFE-PCM TX",
+ .stream_name = "AFE-PROXY TX",
+ .cpu_dai_name = "msm-dai-q6.240",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ },
+ {
+ .name = "MSM8930 Compr",
+ .stream_name = "COMPR",
+ .cpu_dai_name = "MultiMedia4",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .dsp_link = &lpa_fe_media,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ },
+ {
+ .name = "AUXPCM Hostless",
+ .stream_name = "AUXPCM Hostless",
+ .cpu_dai_name = "AUXPCM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &bidir_hl_media,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ /* HDMI Hostless */
+ {
+ .name = "HDMI_RX_HOSTLESS",
+ .stream_name = "HDMI_RX_HOSTLESS",
+ .cpu_dai_name = "HDMI_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &hdmi_rx_hl,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .no_codec = 1,
+ .ignore_suspend = 1,
+ },
+ /* Backend DAI Links */
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "sitar_codec",
+ .codec_dai_name = "sitar_rx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm8930_audrx_init,
+ .be_hw_params_fixup = msm8930_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8930_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "sitar_codec",
+ .codec_dai_name = "sitar_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm8930_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8930_be_ops,
+ },
+ /* Backend BT/FM DAI Links */
+ {
+ .name = LPASS_BE_INT_BT_SCO_RX,
+ .stream_name = "Internal BT-SCO Playback",
+ .cpu_dai_name = "msm-dai-q6.12288",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .init = &msm8930_btsco_init,
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
+ },
+ {
+ .name = LPASS_BE_INT_BT_SCO_TX,
+ .stream_name = "Internal BT-SCO Capture",
+ .cpu_dai_name = "msm-dai-q6.12289",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ .be_hw_params_fixup = msm8930_btsco_be_hw_params_fixup,
+ },
+ {
+ .name = LPASS_BE_INT_FM_RX,
+ .stream_name = "Internal FM Playback",
+ .cpu_dai_name = "msm-dai-q6.12292",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_FM_RX,
+ .be_hw_params_fixup = msm8930_be_hw_params_fixup,
+ },
+ {
+ .name = LPASS_BE_INT_FM_TX,
+ .stream_name = "Internal FM Capture",
+ .cpu_dai_name = "msm-dai-q6.12293",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_FM_TX,
+ .be_hw_params_fixup = msm8930_be_hw_params_fixup,
+ },
+ /* HDMI BACK END DAI Link */
+ {
+ .name = LPASS_BE_HDMI,
+ .stream_name = "HDMI Playback",
+ .cpu_dai_name = "msm-dai-q6-hdmi.8",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_HDMI_RX,
+ .be_hw_params_fixup = msm8930_hdmi_be_hw_params_fixup,
+ },
+ /* Backend AFE DAI Links */
+ {
+ .name = LPASS_BE_AFE_PCM_RX,
+ .stream_name = "AFE Playback",
+ .cpu_dai_name = "msm-dai-q6.224",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_codec = 1,
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_TX,
+ .stream_name = "AFE Capture",
+ .cpu_dai_name = "msm-dai-q6.225",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_codec = 1,
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ },
+ /* AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_AUXPCM_RX,
+ .stream_name = "AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6.2",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+ .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+ .ops = &msm8930_auxpcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_AUXPCM_TX,
+ .stream_name = "AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6.3",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+ .be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
+ },
+ /* Incall Music BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE_PLAYBACK_TX,
+ .stream_name = "Voice Farend Playback",
+ .cpu_dai_name = "msm-dai-q6.32773",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ .be_hw_params_fixup = msm8930_be_hw_params_fixup,
+ },
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6.32772",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm8930_be_hw_params_fixup,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6.32771",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .no_codec = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm8930_be_hw_params_fixup,
+ },
+};
+
+struct snd_soc_card snd_soc_card_msm8930 = {
+ .name = "msm8930-sitar-snd-card",
+ .dai_link = msm8930_dai,
+ .num_links = ARRAY_SIZE(msm8930_dai),
+};
+
+static struct platform_device *msm8930_snd_device;
+
+static int msm8930_configure_headset_mic_gpios(void)
+{
+ int ret;
+ ret = gpio_request(80, "US_EURO_SWITCH");
+ if (ret) {
+ pr_err("%s: Failed to request gpio 80\n", __func__);
+ return ret;
+ }
+ ret = gpio_direction_output(80, 0);
+ if (ret) {
+ pr_err("%s: Unable to set direction\n", __func__);
+ gpio_free(80);
+ }
+ msm8930_headset_gpios_configured = 0;
+ return 0;
+}
+static void msm8930_free_headset_mic_gpios(void)
+{
+ if (msm8930_headset_gpios_configured)
+ gpio_free(80);
+}
+
+static int __init msm8930_audio_init(void)
+{
+ int ret;
+
+ if (!cpu_is_msm8930()) {
+ pr_err("%s: Not the right machine type\n", __func__);
+ return -ENODEV ;
+ }
+
+ msm8930_snd_device = platform_device_alloc("soc-audio", 0);
+ if (!msm8930_snd_device) {
+ pr_err("Platform device allocation failed\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(msm8930_snd_device, &snd_soc_card_msm8930);
+ ret = platform_device_add(msm8930_snd_device);
+ if (ret) {
+ platform_device_put(msm8930_snd_device);
+ return ret;
+ }
+
+ if (msm8930_configure_headset_mic_gpios()) {
+ pr_err("%s Fail to configure headset mic gpios\n", __func__);
+ msm8930_headset_gpios_configured = 0;
+ } else
+ msm8930_headset_gpios_configured = 1;
+
+ return ret;
+
+}
+module_init(msm8930_audio_init);
+
+static void __exit msm8930_audio_exit(void)
+{
+ if (!cpu_is_msm8930()) {
+ pr_err("%s: Not the right machine type\n", __func__);
+ return ;
+ }
+ msm8930_free_headset_mic_gpios();
+ platform_device_unregister(msm8930_snd_device);
+}
+module_exit(msm8930_audio_exit);
+
+MODULE_DESCRIPTION("ALSA SoC MSM8930");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index eb363e7..0854dff 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1391,7 +1391,7 @@
{
int ret;
- if (!cpu_is_msm8960() && !cpu_is_msm8930()) {
+ if (!cpu_is_msm8960()) {
pr_err("%s: Not the right machine type\n", __func__);
return -ENODEV ;
}
@@ -1455,7 +1455,7 @@
static void __exit msm8960_audio_exit(void)
{
- if (!cpu_is_msm8960() && !cpu_is_msm8930()) {
+ if (!cpu_is_msm8960()) {
pr_err("%s: Not the right machine type\n", __func__);
return ;
}
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 2710fbb..7a16a10 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -205,8 +205,10 @@
get_audproc_cal(acdb_path, &aud_cal);
/* map & cache buffers used */
- if ((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
- (aud_cal.cal_size > 0)) {
+ if (((mem_addr_audproc[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
+ (aud_cal.cal_size > 0)) ||
+ (aud_cal.cal_size > mem_addr_audproc[acdb_path].cal_size)) {
+
if (mem_addr_audproc[acdb_path].cal_paddr != 0)
adm_memory_unmap_regions(
&mem_addr_audproc[acdb_path].cal_paddr,
@@ -233,8 +235,9 @@
get_audvol_cal(acdb_path, &aud_cal);
/* map & cache buffers used */
- if ((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
- (aud_cal.cal_size > 0)) {
+ if (((mem_addr_audvol[acdb_path].cal_paddr != aud_cal.cal_paddr) &&
+ (aud_cal.cal_size > 0)) ||
+ (aud_cal.cal_size > mem_addr_audvol[acdb_path].cal_size)) {
if (mem_addr_audvol[acdb_path].cal_paddr != 0)
adm_memory_unmap_regions(
&mem_addr_audvol[acdb_path].cal_paddr,
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 59506f1..be08e25 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -37,7 +37,7 @@
static struct afe_ctl this_afe;
-static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
+static struct acdb_cal_block afe_cal_addr[MAX_AUDPROC_TYPES];
#define TIMEOUT_MS 1000
#define Q6AFE_MAX_VOLUME 0x3FFF
@@ -332,12 +332,16 @@
goto done;
}
- if (afe_cal_addr[path] != cal_block.cal_paddr) {
- if (afe_cal_addr[path] != 0)
- afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
+ if ((afe_cal_addr[path].cal_paddr != cal_block.cal_paddr) ||
+ (cal_block.cal_size > afe_cal_addr[path].cal_size)) {
+ if (afe_cal_addr[path].cal_paddr != 0)
+ afe_cmd_memory_unmap_nowait(
+ afe_cal_addr[path].cal_paddr);
+
afe_cmd_memory_map_nowait(cal_block.cal_paddr,
cal_block.cal_size);
- afe_cal_addr[path] = cal_block.cal_paddr;
+ afe_cal_addr[path].cal_paddr = cal_block.cal_paddr;
+ afe_cal_addr[path].cal_size = cal_block.cal_size;
}
afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -1565,8 +1569,9 @@
debugfs_remove(debugfs_afelb_gain);
#endif
for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
- if (afe_cal_addr[i] != 0)
- afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
+ if (afe_cal_addr[i].cal_paddr != 0)
+ afe_cmd_memory_unmap_nowait(
+ afe_cal_addr[i].cal_paddr);
}
}
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index d822af5..fe31b27 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -240,6 +240,13 @@
while (cnt >= 0) {
if (port->buf[cnt].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_unmap_kernel(port->buf[cnt].client,
+ port->buf[cnt].handle);
+ ion_free(port->buf[cnt].client,
+ port->buf[cnt].handle);
+ ion_client_destroy(port->buf[cnt].client);
+#else
pr_debug("%s:data[%p]phys[%p][%p] cnt[%d]"
"mem_buffer[%p]\n",
__func__, (void *)port->buf[cnt].data,
@@ -259,6 +266,7 @@
free_contiguous_memory_by_paddr(
port->buf[cnt].phys);
+#endif
port->buf[cnt].data = NULL;
port->buf[cnt].phys = 0;
--(port->max_buf_cnt);
@@ -295,6 +303,19 @@
}
if (port->buf[0].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
+ ion_free(port->buf[0].client, port->buf[0].handle);
+ ion_client_destroy(port->buf[0].client);
+ pr_debug("%s:data[%p]phys[%p][%p]"
+ ", client[%p] handle[%p]\n",
+ __func__,
+ (void *)port->buf[0].data,
+ (void *)port->buf[0].phys,
+ (void *)&port->buf[0].phys,
+ (void *)port->buf[0].client,
+ (void *)port->buf[0].handle);
+#else
pr_debug("%s:data[%p]phys[%p][%p]"
"mem_buffer[%p]\n",
__func__,
@@ -313,6 +334,7 @@
" failed\n", __func__);
}
free_contiguous_memory_by_paddr(port->buf[0].phys);
+#endif
}
while (cnt >= 0) {
@@ -465,6 +487,9 @@
int cnt = 0;
int rc = 0;
struct audio_buffer *buf;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ int len;
+#endif
if (!(ac) || ((dir != IN) && (dir != OUT)))
return -EINVAL;
@@ -494,6 +519,50 @@
while (cnt < bufcnt) {
if (bufsz > 0) {
if (!buf[cnt].data) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ buf[cnt].client = msm_ion_client_create
+ (UINT_MAX, "audio_client");
+ if (IS_ERR_OR_NULL((void *)
+ buf[cnt].client)) {
+ pr_err("%s: ION create client"
+ " for AUDIO failed\n",
+ __func__);
+ goto fail;
+ }
+ buf[cnt].handle = ion_alloc
+ (buf[cnt].client, bufsz, SZ_4K,
+ (0x1 << ION_AUDIO_HEAP_ID));
+ if (IS_ERR_OR_NULL((void *)
+ buf[cnt].handle)) {
+ pr_err("%s: ION memory"
+ " allocation for AUDIO failed\n",
+ __func__);
+ goto fail;
+ }
+
+ rc = ion_phys(buf[cnt].client,
+ buf[cnt].handle,
+ (ion_phys_addr_t *)
+ &buf[cnt].phys,
+ (size_t *)&len);
+ if (rc) {
+ pr_err("%s: ION Get Physical"
+ " for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto fail;
+ }
+
+ buf[cnt].data = ion_map_kernel
+ (buf[cnt].client, buf[cnt].handle,
+ 0);
+ if (IS_ERR_OR_NULL((void *)
+ buf[cnt].data)) {
+ pr_err("%s: ION memory"
+ " mapping for AUDIO failed\n", __func__);
+ goto fail;
+ }
+ memset((void *)buf[cnt].data, 0, bufsz);
+#else
unsigned int flags = 0;
buf[cnt].phys =
allocate_contiguous_ebi_nomap(bufsz,
@@ -526,16 +595,15 @@
mutex_unlock(&ac->cmd_lock);
goto fail;
}
+#endif
buf[cnt].used = 1;
buf[cnt].size = bufsz;
buf[cnt].actual_size = bufsz;
- pr_debug("%s data[%p]phys[%p][%p]"
- "mem_buffer[%p]\n",
+ pr_debug("%s data[%p]phys[%p][%p]\n",
__func__,
(void *)buf[cnt].data,
(void *)buf[cnt].phys,
- (void *)&buf[cnt].phys,
- (void *)buf[cnt].mem_buffer);
+ (void *)&buf[cnt].phys);
cnt++;
}
}
@@ -562,9 +630,12 @@
{
int cnt = 0;
int rc = 0;
- int flags = 0;
struct audio_buffer *buf;
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ int len;
+#else
+ int flags = 0;
+#endif
if (!(ac) || ((dir != IN) && (dir != OUT)))
return -EINVAL;
@@ -590,6 +661,35 @@
ac->port[dir].buf = buf;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
+ if (IS_ERR_OR_NULL((void *)buf[0].client)) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto fail;
+ }
+ buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
+ (0x1 << ION_AUDIO_HEAP_ID));
+ if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
+ pr_err("%s: ION memory allocation for AUDIO failed\n",
+ __func__);
+ goto fail;
+ }
+
+ rc = ion_phys(buf[0].client, buf[0].handle,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto fail;
+ }
+
+ buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle, 0);
+ if (IS_ERR_OR_NULL((void *) buf[0].data)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto fail;
+ }
+ memset((void *)buf[0].data, 0, (bufsz * bufcnt));
+#else
buf[0].phys = allocate_contiguous_ebi_nomap(bufsz * bufcnt,
SZ_4K);
if (!buf[0].phys) {
@@ -612,6 +712,7 @@
goto fail;
}
buf[0].data = buf[0].mem_buffer->vaddr;
+#endif
if (!buf[0].data) {
pr_err("%s:invalid vaddr,"
" iomap failed\n", __func__);
@@ -726,6 +827,9 @@
if (data->opcode == RESET_EVENTS) {
pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
data->reset_event, data->reset_proc, ac->apr);
+ if (ac->cb)
+ ac->cb(data->opcode, data->token,
+ (uint32_t *)data->payload, ac->priv);
apr_reset(ac->apr);
return 0;
}
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 532d92b..0376f34 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -662,6 +662,59 @@
return -EINVAL;
}
+static int voice_set_dtx(struct voice_data *v)
+{
+ int ret = 0;
+ void *apr_cvs;
+ u16 cvs_handle;
+ struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvs = common.apr_q6_cvs;
+
+ if (!apr_cvs) {
+ pr_err("%s: apr_cvs is NULL.\n", __func__);
+ return -EINVAL;
+ }
+
+ cvs_handle = voice_get_cvs_handle(v);
+
+ /* Set DTX */
+ cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvs_set_dtx) - APR_HDR_SIZE);
+ cvs_set_dtx.hdr.src_port = v->session_id;
+ cvs_set_dtx.hdr.dest_port = cvs_handle;
+ cvs_set_dtx.hdr.token = 0;
+ cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
+ cvs_set_dtx.dtx_mode.enable = common.mvs_info.dtx_mode;
+
+ pr_debug("%s: Setting DTX %d\n", __func__, common.mvs_info.dtx_mode);
+
+ v->cvs_state = CMD_STATUS_FAIL;
+
+ ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
+ if (ret < 0) {
+ pr_err("%s: Error %d sending SET_DTX\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ ret = wait_event_timeout(v->cvs_wait,
+ (v->cvs_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int voice_config_cvs_vocoder(struct voice_data *v)
{
int ret = 0;
@@ -753,7 +806,6 @@
}
case VSS_MEDIA_ID_AMR_NB_MODEM: {
struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate;
- struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
pr_debug("Setting AMR rate\n");
@@ -785,40 +837,15 @@
pr_err("%s: wait_event timeout\n", __func__);
goto fail;
}
- /* Disable DTX */
- pr_debug("Disabling DTX\n");
- cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_set_dtx) - APR_HDR_SIZE);
- cvs_set_dtx.hdr.src_port = v->session_id;
- cvs_set_dtx.hdr.dest_port = cvs_handle;
- cvs_set_dtx.hdr.token = 0;
- cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
- cvs_set_dtx.dtx_mode.enable = 0;
-
- v->cvs_state = CMD_STATUS_FAIL;
-
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
- if (ret < 0) {
- pr_err("%s: Error %d sending SET_DTX\n",
- __func__, ret);
+ ret = voice_set_dtx(v);
+ if (ret < 0)
goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
+
break;
}
case VSS_MEDIA_ID_AMR_WB_MODEM: {
struct cvs_set_amrwb_enc_rate_cmd cvs_set_amrwb_rate;
- struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
pr_debug("Setting AMR WB rate\n");
@@ -851,70 +878,18 @@
pr_err("%s: wait_event timeout\n", __func__);
goto fail;
}
- /* Disable DTX */
- pr_debug("Disabling DTX\n");
- cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_set_dtx) - APR_HDR_SIZE);
- cvs_set_dtx.hdr.src_port = v->session_id;
- cvs_set_dtx.hdr.dest_port = cvs_handle;
- cvs_set_dtx.hdr.token = 0;
- cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
- cvs_set_dtx.dtx_mode.enable = 0;
-
- v->cvs_state = CMD_STATUS_FAIL;
-
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
- if (ret < 0) {
- pr_err("%s: Error %d sending SET_DTX\n",
- __func__, ret);
+ ret = voice_set_dtx(v);
+ if (ret < 0)
goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
+
break;
}
case VSS_MEDIA_ID_G729:
case VSS_MEDIA_ID_G711_ALAW:
case VSS_MEDIA_ID_G711_MULAW: {
- struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
- /* Disable DTX */
- pr_debug("Disabling DTX\n");
+ ret = voice_set_dtx(v);
- cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_set_dtx) - APR_HDR_SIZE);
- cvs_set_dtx.hdr.src_port = v->session_id;
- cvs_set_dtx.hdr.dest_port = cvs_handle;
- cvs_set_dtx.hdr.token = 0;
- cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
- cvs_set_dtx.dtx_mode.enable = 0;
-
- v->cvs_state = CMD_STATUS_FAIL;
-
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
- if (ret < 0) {
- pr_err("%s: Error %d sending SET_DTX\n",
- __func__, ret);
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
break;
}
default:
@@ -2307,6 +2282,51 @@
return -EINVAL;
}
+static int voice_send_rx_device_mute_cmd(struct voice_data *v)
+{
+ struct cvp_set_mute_cmd cvp_mute_cmd;
+ int ret = 0;
+ void *apr_cvp;
+ u16 cvp_handle;
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvp = common.apr_q6_cvp;
+
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ cvp_handle = voice_get_cvp_handle(v);
+
+ cvp_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_mute_cmd) - APR_HDR_SIZE);
+ cvp_mute_cmd.hdr.src_port = v->session_id;
+ cvp_mute_cmd.hdr.dest_port = cvp_handle;
+ cvp_mute_cmd.hdr.token = 0;
+ cvp_mute_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_MUTE;
+ cvp_mute_cmd.cvp_set_mute.direction = 1;
+ cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+ v->cvp_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_mute_cmd);
+ if (ret < 0) {
+ pr_err("Fail in sending RX device mute cmd\n");
+ return -EINVAL;
+ }
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int voice_send_vol_index_cmd(struct voice_data *v)
{
struct cvp_set_rx_volume_index_cmd cvp_vol_cmd;
@@ -2908,6 +2928,49 @@
return ret;
}
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ if (v == NULL) {
+ pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+
+ v->dev_rx.mute = mute;
+
+ if (v->voc_state == VOC_RUN)
+ ret = voice_send_rx_device_mute_cmd(v);
+
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
+int voc_get_rx_device_mute(uint16_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ if (v == NULL) {
+ pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
+
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+
+ ret = v->dev_rx.mute;
+
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
int voc_set_tty_mode(uint16_t session_id, uint8_t tty_mode)
{
struct voice_data *v = voice_get_session(session_id);
@@ -3236,11 +3299,13 @@
void voc_config_vocoder(uint32_t media_type,
uint32_t rate,
- uint32_t network_type)
+ uint32_t network_type,
+ uint32_t dtx_mode)
{
common.mvs_info.media_type = media_type;
common.mvs_info.rate = rate;
common.mvs_info.network_type = network_type;
+ common.mvs_info.dtx_mode = dtx_mode;
}
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
@@ -3594,6 +3659,7 @@
/* initialize dev_rx and dev_tx */
common.voice[i].dev_rx.volume = common.default_vol_val;
+ common.voice[i].dev_rx.mute = 0;
common.voice[i].dev_tx.mute = common.default_mute_val;
common.voice[i].dev_tx.port_id = 1;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 2dc08d6..0edf1c9 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -637,6 +637,8 @@
#define VSS_MEDIA_ID_G729 0x00010FD0
/* G.729AB (contains two 10ms vocoder frames. */
+#define VSS_IVOCPROC_CMD_SET_MUTE 0x000110EF
+
#define VOICE_CMD_SET_PARAM 0x00011006
#define VOICE_CMD_GET_PARAM 0x00011007
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
@@ -729,6 +731,22 @@
/* Size of the volume calibration table in bytes. */
} __packed;
+struct vss_ivocproc_cmd_set_mute_t {
+ uint16_t direction;
+ /*
+ * 0 : TX only.
+ * 1 : RX only.
+ * 2 : TX and Rx.
+ */
+ uint16_t mute_flag;
+ /*
+ * Mute, un-mute.
+ *
+ * 0 : Disable.
+ * 1 : Enable.
+ */
+} __packed;
+
struct cvp_create_full_ctl_session_cmd {
struct apr_hdr hdr;
struct vss_ivocproc_cmd_create_full_control_session_t cvp_session;
@@ -770,6 +788,11 @@
struct apr_hdr hdr;
} __packed;
+struct cvp_set_mute_cmd {
+ struct apr_hdr hdr;
+ struct vss_ivocproc_cmd_set_mute_t cvp_set_mute;
+} __packed;
+
/* CB for up-link packets. */
typedef void (*ul_cb_fn)(uint8_t *voc_pkt,
uint32_t pkt_len,
@@ -785,6 +808,7 @@
uint32_t media_type;
uint32_t rate;
uint32_t network_type;
+ uint32_t dtx_mode;
ul_cb_fn ul_cb;
dl_cb_fn dl_cb;
void *private_data;
@@ -876,7 +900,8 @@
void voc_config_vocoder(uint32_t media_type,
uint32_t rate,
- uint32_t network_type);
+ uint32_t network_type,
+ uint32_t dtx_mode);
enum {
DEV_RX = 0,
@@ -902,6 +927,8 @@
uint32_t dev_type);
int voc_set_rx_vol_index(uint16_t session_id, uint32_t dir, uint32_t voc_idx);
int voc_set_tx_mute(uint16_t session_id, uint32_t dir, uint32_t mute);
+int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute);
+int voc_get_rx_device_mute(uint16_t session_id);
int voc_disable_cvp(uint16_t session_id);
int voc_enable_cvp(uint16_t session_id);
int voc_set_route_flag(uint16_t session_id, uint8_t path_dir, uint8_t set);